Ticket #19881: 19881.patch
File 19881.patch, 33.2 KB (added by , 13 years ago) |
---|
-
wp-includes/js/imgareaselect/jquery.imgareaselect.dev.js
1 1 /* 2 2 * imgAreaSelect jQuery plugin 3 * version 0.9. 63 * version 0.9.8 4 4 * 5 5 * Copyright (c) 2008-2011 Michal Wojciechowski (odyniec.net) 6 6 * … … 13 13 14 14 (function($) { 15 15 16 /* 17 * Math functions will be used extensively, so it's convenient to make a few 18 * shortcuts 19 */ 16 20 var abs = Math.abs, 17 21 max = Math.max, 18 22 min = Math.min, 19 23 round = Math.round; 20 24 25 /** 26 * Create a new HTML div element 27 * 28 * @return A jQuery object representing the new element 29 */ 21 30 function div() { 22 31 return $('<div/>'); 23 32 } 24 33 34 /** 35 * imgAreaSelect initialization 36 * 37 * @param img 38 * A HTML image element to attach the plugin to 39 * @param options 40 * An options object 41 */ 25 42 $.imgAreaSelect = function (img, options) { 26 43 var 27 44 /* jQuery object representing the image */ 28 45 $img = $(img), 29 46 47 /* Has the image finished loading? */ 30 48 imgLoaded, 31 49 50 /* Plugin elements */ 51 52 /* Container box */ 32 53 $box = div(), 54 /* Selection area */ 33 55 $area = div(), 56 /* Border (four divs) */ 34 57 $border = div().add(div()).add(div()).add(div()), 58 /* Outer area (four divs) */ 35 59 $outer = div().add(div()).add(div()).add(div()), 60 /* Handles (empty by default, initialized in setOptions()) */ 36 61 $handles = $([]), 37 62 63 /* 64 * Additional element to work around a cursor problem in Opera 65 * (explained later) 66 */ 38 67 $areaOpera, 39 68 69 /* Image position (relative to viewport) */ 40 70 left, top, 41 71 72 /* Image offset (as returned by .offset()) */ 42 73 imgOfs = { left: 0, top: 0 }, 43 74 75 /* Image dimensions (as returned by .width() and .height()) */ 44 76 imgWidth, imgHeight, 45 77 78 /* 79 * jQuery object representing the parent element that the plugin 80 * elements are appended to 81 */ 46 82 $parent, 47 83 84 /* Parent element offset (as returned by .offset()) */ 48 85 parOfs = { left: 0, top: 0 }, 49 86 87 /* Base z-index for plugin elements */ 50 88 zIndex = 0, 51 89 90 /* Plugin elements position */ 52 91 position = 'absolute', 53 92 93 /* X/Y coordinates of the starting point for move/resize operations */ 54 94 startX, startY, 55 95 96 /* Horizontal and vertical scaling factors */ 56 97 scaleX, scaleY, 57 98 58 resizeMargin = 10, 59 99 /* Current resize mode ("nw", "se", etc.) */ 60 100 resize, 61 101 102 /* Selection area constraints */ 62 103 minWidth, minHeight, maxWidth, maxHeight, 63 104 105 /* Aspect ratio to maintain (floating point number) */ 64 106 aspectRatio, 65 107 108 /* Are the plugin elements currently displayed? */ 66 109 shown, 67 110 111 /* Current selection (relative to parent element) */ 68 112 x1, y1, x2, y2, 69 113 114 /* Current selection (relative to scaled image) */ 70 115 selection = { x1: 0, y1: 0, x2: 0, y2: 0, width: 0, height: 0 }, 71 116 117 /* Document element */ 72 118 docElem = document.documentElement, 73 119 120 /* Various helper variables used throughout the code */ 74 121 $p, d, i, o, w, h, adjusted; 75 122 123 /* 124 * Translate selection coordinates (relative to scaled image) to viewport 125 * coordinates (relative to parent element) 126 */ 127 128 /** 129 * Translate selection X to viewport X 130 * 131 * @param x 132 * Selection X 133 * @return Viewport X 134 */ 76 135 function viewX(x) { 77 136 return x + imgOfs.left - parOfs.left; 78 137 } 79 138 139 /** 140 * Translate selection Y to viewport Y 141 * 142 * @param y 143 * Selection Y 144 * @return Viewport Y 145 */ 80 146 function viewY(y) { 81 147 return y + imgOfs.top - parOfs.top; 82 148 } 83 149 150 /* 151 * Translate viewport coordinates to selection coordinates 152 */ 153 154 /** 155 * Translate viewport X to selection X 156 * 157 * @param x 158 * Viewport X 159 * @return Selection X 160 */ 84 161 function selX(x) { 85 162 return x - imgOfs.left + parOfs.left; 86 163 } 87 164 165 /** 166 * Translate viewport Y to selection Y 167 * 168 * @param y 169 * Viewport Y 170 * @return Selection Y 171 */ 88 172 function selY(y) { 89 173 return y - imgOfs.top + parOfs.top; 90 174 } 91 175 176 /* 177 * Translate event coordinates (relative to document) to viewport 178 * coordinates 179 */ 180 181 /** 182 * Get event X and translate it to viewport X 183 * 184 * @param event 185 * The event object 186 * @return Viewport X 187 */ 92 188 function evX(event) { 93 189 return event.pageX - parOfs.left; 94 190 } 95 191 192 /** 193 * Get event Y and translate it to viewport Y 194 * 195 * @param event 196 * The event object 197 * @return Viewport Y 198 */ 96 199 function evY(event) { 97 200 return event.pageY - parOfs.top; 98 201 } 99 202 203 /** 204 * Get the current selection 205 * 206 * @param noScale 207 * If set to <code>true</code>, scaling is not applied to the 208 * returned selection 209 * @return Selection object 210 */ 100 211 function getSelection(noScale) { 101 212 var sx = noScale || scaleX, sy = noScale || scaleY; 102 213 … … 108 219 height: round(selection.y2 * sy) - round(selection.y1 * sy) }; 109 220 } 110 221 222 /** 223 * Set the current selection 224 * 225 * @param x1 226 * X coordinate of the upper left corner of the selection area 227 * @param y1 228 * Y coordinate of the upper left corner of the selection area 229 * @param x2 230 * X coordinate of the lower right corner of the selection area 231 * @param y2 232 * Y coordinate of the lower right corner of the selection area 233 * @param noScale 234 * If set to <code>true</code>, scaling is not applied to the 235 * new selection 236 */ 111 237 function setSelection(x1, y1, x2, y2, noScale) { 112 238 var sx = noScale || scaleX, sy = noScale || scaleY; 113 239 … … 122 248 selection.height = selection.y2 - selection.y1; 123 249 } 124 250 251 /** 252 * Recalculate image and parent offsets 253 */ 125 254 function adjust() { 255 /* 256 * Do not adjust if image width is not a positive number. This might 257 * happen when imgAreaSelect is put on a parent element which is then 258 * hidden. 259 */ 126 260 if (!$img.width()) 127 261 return; 128 262 263 /* 264 * Get image offset. The .offset() method returns float values, so they 265 * need to be rounded. 266 */ 129 267 imgOfs = { left: round($img.offset().left), top: round($img.offset().top) }; 130 268 269 /* Get image dimensions */ 131 270 imgWidth = $img.innerWidth(); 132 271 imgHeight = $img.innerHeight(); 133 272 134 273 imgOfs.top += ($img.outerHeight() - imgHeight) >> 1; 135 274 imgOfs.left += ($img.outerWidth() - imgWidth) >> 1; 136 275 137 minWidth = options.minWidth || 0; 138 minHeight = options.minHeight || 0; 139 maxWidth = min(options.maxWidth || 1<<24, imgWidth); 140 maxHeight = min(options.maxHeight || 1<<24, imgHeight); 276 /* Set minimum and maximum selection area dimensions */ 277 minWidth = round(options.minWidth / scaleX) || 0; 278 minHeight = round(options.minHeight / scaleY) || 0; 279 maxWidth = round(min(options.maxWidth / scaleX || 1<<24, imgWidth)); 280 maxHeight = round(min(options.maxHeight / scaleY || 1<<24, imgHeight)); 141 281 282 /* 283 * Workaround for jQuery 1.3.2 incorrect offset calculation, originally 284 * observed in Safari 3. Firefox 2 is also affected. 285 */ 142 286 if ($().jquery == '1.3.2' && position == 'fixed' && 143 287 !docElem['getBoundingClientRect']) 144 288 { … … 146 290 imgOfs.left += max(document.body.scrollLeft, docElem.scrollLeft); 147 291 } 148 292 149 parOfs = $.inArray($parent.css('position'), ['absolute', 'relative']) + 1 ? 293 /* Determine parent element offset */ 294 parOfs = /absolute|relative/.test($parent.css('position')) ? 150 295 { left: round($parent.offset().left) - $parent.scrollLeft(), 151 296 top: round($parent.offset().top) - $parent.scrollTop() } : 152 297 position == 'fixed' ? … … 156 301 left = viewX(0); 157 302 top = viewY(0); 158 303 304 /* 305 * Check if selection area is within image boundaries, adjust if 306 * necessary 307 */ 159 308 if (selection.x2 > imgWidth || selection.y2 > imgHeight) 160 309 doResize(); 161 310 } 162 311 312 /** 313 * Update plugin elements 314 * 315 * @param resetKeyPress 316 * If set to <code>false</code>, this instance's keypress 317 * event handler is not activated 318 */ 163 319 function update(resetKeyPress) { 320 /* If plugin elements are hidden, do nothing */ 164 321 if (!shown) return; 165 322 323 /* 324 * Set the position and size of the container box and the selection area 325 * inside it 326 */ 166 327 $box.css({ left: viewX(selection.x1), top: viewY(selection.y1) }) 167 328 .add($area).width(w = selection.width).height(h = selection.height); 168 329 330 /* 331 * Reset the position of selection area, borders, and handles (IE6/IE7 332 * position them incorrectly if we don't do this) 333 */ 169 334 $area.add($border).add($handles).css({ left: 0, top: 0 }); 170 335 336 /* Set border dimensions */ 171 337 $border 172 338 .width(max(w - $border.outerWidth() + $border.innerWidth(), 0)) 173 339 .height(max(h - $border.outerHeight() + $border.innerHeight(), 0)); 174 340 341 /* Arrange the outer area elements */ 175 342 $($outer[0]).css({ left: left, top: top, 176 343 width: selection.x1, height: imgHeight }); 177 344 $($outer[1]).css({ left: left + selection.x1, top: top, … … 184 351 w -= $handles.outerWidth(); 185 352 h -= $handles.outerHeight(); 186 353 354 /* Arrange handles */ 187 355 switch ($handles.length) { 188 356 case 8: 189 357 $($handles[4]).css({ left: w >> 1 }); … … 196 364 } 197 365 198 366 if (resetKeyPress !== false) { 367 /* 368 * Need to reset the document keypress event handler -- unbind the 369 * current handler 370 */ 199 371 if ($.imgAreaSelect.keyPress != docKeyPress) 200 372 $(document).unbind($.imgAreaSelect.keyPress, 201 373 $.imgAreaSelect.onKeyPress); 202 374 203 375 if (options.keys) 376 /* 377 * Set the document keypress event handler to this instance's 378 * docKeyPress() function 379 */ 204 380 $(document)[$.imgAreaSelect.keyPress]( 205 381 $.imgAreaSelect.onKeyPress = docKeyPress); 206 382 } 207 383 384 /* 385 * Internet Explorer displays 1px-wide dashed borders incorrectly by 386 * filling the spaces between dashes with white. Toggling the margin 387 * property between 0 and "auto" fixes this in IE6 and IE7 (IE8 is still 388 * broken). This workaround is not perfect, as it requires setTimeout() 389 * and thus causes the border to flicker a bit, but I haven't found a 390 * better solution. 391 * 392 * Note: This only happens with CSS borders, set with the borderWidth, 393 * borderOpacity, borderColor1, and borderColor2 options (which are now 394 * deprecated). Borders created with GIF background images are fine. 395 */ 208 396 if ($.browser.msie && $border.outerWidth() - $border.innerWidth() == 2) { 209 397 $border.css('margin', 0); 210 398 setTimeout(function () { $border.css('margin', 'auto'); }, 0); 211 399 } 212 400 } 213 401 402 /** 403 * Do the complete update sequence: recalculate offsets, update the 404 * elements, and set the correct values of x1, y1, x2, and y2. 405 * 406 * @param resetKeyPress 407 * If set to <code>false</code>, this instance's keypress 408 * event handler is not activated 409 */ 214 410 function doUpdate(resetKeyPress) { 215 411 adjust(); 216 412 update(resetKeyPress); … … 218 414 x2 = viewX(selection.x2); y2 = viewY(selection.y2); 219 415 } 220 416 417 /** 418 * Hide or fade out an element (or multiple elements) 419 * 420 * @param $elem 421 * A jQuery object containing the element(s) to hide/fade out 422 * @param fn 423 * Callback function to be called when fadeOut() completes 424 */ 221 425 function hide($elem, fn) { 222 426 options.fadeSpeed ? $elem.fadeOut(options.fadeSpeed, fn) : $elem.hide(); 223 224 427 } 225 428 429 /** 430 * Selection area mousemove event handler 431 * 432 * @param event 433 * The event object 434 */ 226 435 function areaMouseMove(event) { 227 436 var x = selX(evX(event)) - selection.x1, 228 437 y = selY(evY(event)) - selection.y1; … … 234 443 $box.one('mouseout', function () { adjusted = false; }); 235 444 } 236 445 446 /* Clear the resize mode */ 237 447 resize = ''; 238 448 239 449 if (options.resizable) { 450 /* 451 * Check if the mouse pointer is over the resize margin area and set 452 * the resize mode accordingly 453 */ 240 454 if (y <= options.resizeMargin) 241 455 resize = 'n'; 242 456 else if (y >= selection.height - options.resizeMargin) … … 253 467 $areaOpera.toggle(); 254 468 } 255 469 470 /** 471 * Document mouseup event handler 472 * 473 * @param event 474 * The event object 475 */ 256 476 function docMouseUp(event) { 477 /* Set back the default cursor */ 257 478 $('body').css('cursor', ''); 479 /* 480 * If autoHide is enabled, or if the selection has zero width/height, 481 * hide the selection and the outer area 482 */ 258 483 if (options.autoHide || selection.width * selection.height == 0) 259 484 hide($box.add($outer), function () { $(this).hide(); }); 260 485 … … 264 489 options.onSelectEnd(img, getSelection()); 265 490 } 266 491 492 /** 493 * Selection area mousedown event handler 494 * 495 * @param event 496 * The event object 497 * @return false 498 */ 267 499 function areaMouseDown(event) { 268 500 if (event.which != 1) return false; 269 501 270 502 adjust(); 271 503 272 504 if (resize) { 505 /* Resize mode is in effect */ 273 506 $('body').css('cursor', resize + '-resize'); 274 507 275 508 x1 = viewX(selection[/w/.test(resize) ? 'x2' : 'x1']); … … 299 532 return false; 300 533 } 301 534 535 /** 536 * Adjust the x2/y2 coordinates to maintain aspect ratio (if defined) 537 * 538 * @param xFirst 539 * If set to <code>true</code>, calculate x2 first. Otherwise, 540 * calculate y2 first. 541 */ 302 542 function fixAspectRatio(xFirst) { 303 543 if (aspectRatio) 304 544 if (xFirst) { 305 545 x2 = max(left, min(left + imgWidth, 306 546 x1 + abs(y2 - y1) * aspectRatio * (x2 > x1 || -1))); 307 308 547 y2 = round(max(top, min(top + imgHeight, 309 548 y1 + abs(x2 - x1) / aspectRatio * (y2 > y1 || -1)))); 310 549 x2 = round(x2); … … 318 557 } 319 558 } 320 559 560 /** 561 * Resize the selection area respecting the minimum/maximum dimensions and 562 * aspect ratio 563 */ 321 564 function doResize() { 565 /* 566 * Make sure the top left corner of the selection area stays within 567 * image boundaries (it might not if the image source was dynamically 568 * changed). 569 */ 322 570 x1 = min(x1, left + imgWidth); 323 571 y1 = min(y1, top + imgHeight); 324 572 325 573 if (abs(x2 - x1) < minWidth) { 574 /* Selection width is smaller than minWidth */ 326 575 x2 = x1 - minWidth * (x2 < x1 || -1); 327 576 328 577 if (x2 < left) … … 332 581 } 333 582 334 583 if (abs(y2 - y1) < minHeight) { 584 /* Selection height is smaller than minHeight */ 335 585 y2 = y1 - minHeight * (y2 < y1 || -1); 336 586 337 587 if (y2 < top) … … 346 596 fixAspectRatio(abs(x2 - x1) < abs(y2 - y1) * aspectRatio); 347 597 348 598 if (abs(x2 - x1) > maxWidth) { 599 /* Selection width is greater than maxWidth */ 349 600 x2 = x1 - maxWidth * (x2 < x1 || -1); 350 601 fixAspectRatio(); 351 602 } 352 603 353 604 if (abs(y2 - y1) > maxHeight) { 605 /* Selection height is greater than maxHeight */ 354 606 y2 = y1 - maxHeight * (y2 < y1 || -1); 355 607 fixAspectRatio(true); 356 608 } … … 364 616 options.onSelectChange(img, getSelection()); 365 617 } 366 618 619 /** 620 * Mousemove event handler triggered when the user is selecting an area 621 * 622 * @param event 623 * The event object 624 * @return false 625 */ 367 626 function selectingMouseMove(event) { 368 x2 = resize == '' || /w|e/.test(resize) || aspectRatio ? evX(event) : viewX(selection.x2);369 y2 = resize == '' || /n|s/.test(resize) || aspectRatio ? evY(event) : viewY(selection.y2);627 x2 = /w|e|^$/.test(resize) || aspectRatio ? evX(event) : viewX(selection.x2); 628 y2 = /n|s|^$/.test(resize) || aspectRatio ? evY(event) : viewY(selection.y2); 370 629 371 630 doResize(); 372 631 373 632 return false; 374 375 633 } 376 634 635 /** 636 * Move the selection area 637 * 638 * @param newX1 639 * New viewport X1 640 * @param newY1 641 * New viewport Y1 642 */ 377 643 function doMove(newX1, newY1) { 378 644 x2 = (x1 = newX1) + selection.width; 379 645 y2 = (y1 = newY1) + selection.height; … … 386 652 options.onSelectChange(img, getSelection()); 387 653 } 388 654 655 /** 656 * Mousemove event handler triggered when the selection area is being moved 657 * 658 * @param event 659 * The event object 660 * @return false 661 */ 389 662 function movingMouseMove(event) { 390 663 x1 = max(left, min(startX + evX(event), left + imgWidth - selection.width)); 391 664 y1 = max(top, min(startY + evY(event), top + imgHeight - selection.height)); … … 393 666 doMove(x1, y1); 394 667 395 668 event.preventDefault(); 396 397 669 return false; 398 670 } 399 671 672 /** 673 * Start selection 674 */ 400 675 function startSelection() { 401 676 $(document).unbind('mousemove', startSelection); 402 677 adjust(); 403 678 404 679 x2 = x1; 405 680 y2 = y1; 406 407 681 doResize(); 408 682 409 683 resize = ''; 410 684 411 if ($outer.is(':not(:visible)')) 685 if (!$outer.is(':visible')) 686 /* Show the plugin elements */ 412 687 $box.add($outer).hide().fadeIn(options.fadeSpeed||0); 413 688 414 689 shown = true; … … 420 695 options.onSelectStart(img, getSelection()); 421 696 } 422 697 698 /** 699 * Cancel selection 700 */ 423 701 function cancelSelection() { 424 702 $(document).unbind('mousemove', startSelection) 425 703 .unbind('mouseup', cancelSelection); … … 427 705 428 706 setSelection(selX(x1), selY(y1), selX(x1), selY(y1)); 429 707 430 options.onSelectChange(img, getSelection()); 431 options.onSelectEnd(img, getSelection()); 708 /* If this is an API call, callback functions should not be triggered */ 709 if (!this instanceof $.imgAreaSelect) { 710 options.onSelectChange(img, getSelection()); 711 options.onSelectEnd(img, getSelection()); 712 } 432 713 } 433 714 715 /** 716 * Image mousedown event handler 717 * 718 * @param event 719 * The event object 720 * @return false 721 */ 434 722 function imgMouseDown(event) { 723 /* Ignore the event if animation is in progress */ 435 724 if (event.which != 1 || $outer.is(':animated')) return false; 436 725 437 726 adjust(); 438 727 startX = x1 = evX(event); 439 728 startY = y1 = evY(event); 440 729 730 /* Selection will start when the mouse is moved */ 441 731 $(document).mousemove(startSelection).mouseup(cancelSelection); 442 732 443 733 return false; 444 734 } 445 735 736 /** 737 * Window resize event handler 738 */ 446 739 function windowResize() { 447 740 doUpdate(false); 448 741 } 449 742 743 /** 744 * Image load event handler. This is the final part of the initialization 745 * process. 746 */ 450 747 function imgLoad() { 451 748 imgLoaded = true; 452 749 750 /* Set options */ 453 751 setOptions(options = $.extend({ 454 752 classPrefix: 'imgareaselect', 455 753 movable: true, … … 471 769 $box.add($outer).hide().fadeIn(options.fadeSpeed||0); 472 770 } 473 771 772 /* 773 * Call the onInit callback. The setTimeout() call is used to ensure 774 * that the plugin has been fully initialized and the object instance is 775 * available (so that it can be obtained in the callback). 776 */ 474 777 setTimeout(function () { options.onInit(img, getSelection()); }, 0); 475 778 } 476 779 780 /** 781 * Document keypress event handler 782 * 783 * @param event 784 * The event object 785 * @return false 786 */ 477 787 var docKeyPress = function(event) { 478 788 var k = options.keys, d, t, key = event.keyCode; 479 789 … … 486 796 (k.ctrl == 'resize' && event.ctrlKey) || 487 797 (k.alt == 'resize' && (event.altKey || event.originalEvent.altKey))) 488 798 { 799 /* Resize selection */ 800 489 801 switch (key) { 490 802 case 37: 803 /* Left */ 491 804 d = -d; 492 805 case 39: 806 /* Right */ 493 807 t = max(x1, x2); 494 808 x1 = min(x1, x2); 495 809 x2 = max(t + d, x1); 496 810 fixAspectRatio(); 497 811 break; 498 812 case 38: 813 /* Up */ 499 814 d = -d; 500 815 case 40: 816 /* Down */ 501 817 t = max(y1, y2); 502 818 y1 = min(y1, y2); 503 819 y2 = max(t + d, y1); … … 510 826 doResize(); 511 827 } 512 828 else { 829 /* Move selection */ 830 513 831 x1 = min(x1, x2); 514 832 y1 = min(y1, y2); 515 833 516 834 switch (key) { 517 835 case 37: 836 /* Left */ 518 837 doMove(max(x1 - d, left), y1); 519 838 break; 520 839 case 38: 840 /* Up */ 521 841 doMove(x1, max(y1 - d, top)); 522 842 break; 523 843 case 39: 844 /* Right */ 524 845 doMove(x1 + min(d, imgWidth - selX(x2)), y1); 525 846 break; 526 847 case 40: 848 /* Down */ 527 849 doMove(x1, y1 + min(d, imgHeight - selY(y2))); 528 850 break; 529 851 default: … … 534 856 return false; 535 857 }; 536 858 859 /** 860 * Apply style options to plugin element (or multiple elements) 861 * 862 * @param $elem 863 * A jQuery object representing the element(s) to style 864 * @param props 865 * An object that maps option names to corresponding CSS 866 * properties 867 */ 537 868 function styleOptions($elem, props) { 538 869 for (option in props) 539 870 if (options[option] !== undefined) 540 871 $elem.css(props[option], options[option]); 541 872 } 542 873 874 /** 875 * Set plugin options 876 * 877 * @param newOptions 878 * The new options object 879 */ 543 880 function setOptions(newOptions) { 544 881 if (newOptions.parent) 545 882 ($parent = $(newOptions.parent)).append($box.add($outer)); 546 883 884 /* Merge the new options with the existing ones */ 547 885 $.extend(options, newOptions); 548 886 549 887 adjust(); 550 888 551 889 if (newOptions.handles != null) { 890 /* Recreate selection area handles */ 552 891 $handles.remove(); 553 892 $handles = $([]); 554 893 … … 557 896 while (i--) 558 897 $handles = $handles.add(div()); 559 898 899 /* Add a class to handles and set the CSS properties */ 560 900 $handles.addClass(options.classPrefix + '-handle').css({ 561 901 position: 'absolute', 902 /* 903 * The font-size property needs to be set to zero, otherwise 904 * Internet Explorer makes the handles too large 905 */ 562 906 fontSize: 0, 563 907 zIndex: zIndex + 1 || 1 564 908 }); 565 909 910 /* 911 * If handle width/height has not been set with CSS rules, set the 912 * default 5px 913 */ 566 914 if (!parseInt($handles.css('width')) >= 0) 567 915 $handles.width(5).height(5); 568 916 917 /* 918 * If the borderWidth option is in use, add a solid border to 919 * handles 920 */ 569 921 if (o = options.borderWidth) 570 922 $handles.css({ borderWidth: o, borderStyle: 'solid' }); 571 923 924 /* Apply other style options */ 572 925 styleOptions($handles, { borderColor1: 'border-color', 573 926 borderColor2: 'background-color', 574 927 borderOpacity: 'opacity' }); 575 928 } 576 929 930 /* Calculate scale factors */ 577 931 scaleX = options.imageWidth / imgWidth || 1; 578 932 scaleY = options.imageHeight / imgHeight || 1; 579 933 934 /* Set selection */ 580 935 if (newOptions.x1 != null) { 581 936 setSelection(newOptions.x1, newOptions.y1, newOptions.x2, 582 937 newOptions.y2); … … 584 939 } 585 940 586 941 if (newOptions.keys) 942 /* Enable keyboard support */ 587 943 options.keys = $.extend({ shift: 1, ctrl: 'resize' }, 588 944 newOptions.keys); 589 945 946 /* Add classes to plugin elements */ 590 947 $outer.addClass(options.classPrefix + '-outer'); 591 948 $area.addClass(options.classPrefix + '-selection'); 592 949 for (i = 0; i++ < 4;) 593 950 $($border[i-1]).addClass(options.classPrefix + '-border' + i); 594 951 952 /* Apply style options */ 595 953 styleOptions($area, { selectionColor: 'background-color', 596 954 selectionOpacity: 'opacity' }); 597 955 styleOptions($border, { borderOpacity: 'opacity', … … 603 961 if (o = options.borderColor2) 604 962 $($border[1]).css({ borderStyle: 'dashed', borderColor: o }); 605 963 964 /* Append all the selection area elements to the container box */ 606 965 $box.append($area.add($border).add($areaOpera).add($handles)); 607 966 608 967 if ($.browser.msie) { 609 if (o = $outer.css('filter').match(/opacity=( [0-9]+)/))968 if (o = $outer.css('filter').match(/opacity=(\d+)/)) 610 969 $outer.css('opacity', o[1]/100); 611 if (o = $border.css('filter').match(/opacity=( [0-9]+)/))970 if (o = $border.css('filter').match(/opacity=(\d+)/)) 612 971 $border.css('opacity', o[1]/100); 613 972 } 614 973 … … 620 979 doUpdate(); 621 980 } 622 981 982 /* Calculate the aspect ratio factor */ 623 983 aspectRatio = (d = (options.aspectRatio || '').split(/:/))[0] / d[1]; 624 984 625 985 $img.add($outer).unbind('mousedown', imgMouseDown); 626 986 627 987 if (options.disable || options.enable === false) { 988 /* Disable the plugin */ 628 989 $box.unbind('mousemove', areaMouseMove).unbind('mousedown', areaMouseDown); 629 990 $(window).unbind('resize', windowResize); 630 991 } 631 992 else { 632 993 if (options.enable || options.disable === false) { 994 /* Enable the plugin */ 633 995 if (options.resizable || options.movable) 634 996 $box.mousemove(areaMouseMove).mousedown(areaMouseDown); 635 997 … … 643 1005 options.enable = options.disable = undefined; 644 1006 } 645 1007 1008 /** 1009 * Remove plugin completely 1010 */ 646 1011 this.remove = function () { 1012 /* 1013 * Call setOptions with { disable: true } to unbind the event handlers 1014 */ 647 1015 setOptions({ disable: true }); 648 1016 $box.add($outer).remove(); 649 1017 }; 650 1018 1019 /* 1020 * Public API 1021 */ 1022 1023 /** 1024 * Get current options 1025 * 1026 * @return An object containing the set of options currently in use 1027 */ 651 1028 this.getOptions = function () { return options; }; 652 1029 1030 /** 1031 * Set plugin options 1032 * 1033 * @param newOptions 1034 * The new options object 1035 */ 653 1036 this.setOptions = setOptions; 654 1037 1038 /** 1039 * Get the current selection 1040 * 1041 * @param noScale 1042 * If set to <code>true</code>, scaling is not applied to the 1043 * returned selection 1044 * @return Selection object 1045 */ 655 1046 this.getSelection = getSelection; 656 1047 1048 /** 1049 * Set the current selection 1050 * 1051 * @param x1 1052 * X coordinate of the upper left corner of the selection area 1053 * @param y1 1054 * Y coordinate of the upper left corner of the selection area 1055 * @param x2 1056 * X coordinate of the lower right corner of the selection area 1057 * @param y2 1058 * Y coordinate of the lower right corner of the selection area 1059 * @param noScale 1060 * If set to <code>true</code>, scaling is not applied to the 1061 * new selection 1062 */ 657 1063 this.setSelection = setSelection; 658 1064 1065 /** 1066 * Cancel selection 1067 */ 1068 this.cancelSelection = cancelSelection; 1069 1070 /** 1071 * Update plugin elements 1072 * 1073 * @param resetKeyPress 1074 * If set to <code>false</code>, this instance's keypress 1075 * event handler is not activated 1076 */ 659 1077 this.update = doUpdate; 660 1078 1079 /* 1080 * Traverse the image's parent elements (up to <body>) and find the 1081 * highest z-index 1082 */ 661 1083 $p = $img; 662 1084 663 1085 while ($p.length) { 664 1086 zIndex = max(zIndex, 665 1087 !isNaN($p.css('z-index')) ? $p.css('z-index') : zIndex); 1088 /* Also check if any of the ancestor elements has fixed position */ 666 1089 if ($p.css('position') == 'fixed') 667 1090 position = 'fixed'; 668 1091 669 1092 $p = $p.parent(':not(body)'); 670 1093 } 671 1094 1095 /* 1096 * If z-index is given as an option, it overrides the one found by the 1097 * above loop 1098 */ 672 1099 zIndex = options.zIndex || zIndex; 673 1100 674 1101 if ($.browser.msie) 675 1102 $img.attr('unselectable', 'on'); 676 1103 1104 /* 1105 * In MSIE and WebKit, we need to use the keydown event instead of keypress 1106 */ 677 1107 $.imgAreaSelect.keyPress = $.browser.msie || 678 1108 $.browser.safari ? 'keydown' : 'keypress'; 679 1109 1110 /* 1111 * There is a bug affecting the CSS cursor property in Opera (observed in 1112 * versions up to 10.00) that prevents the cursor from being updated unless 1113 * the mouse leaves and enters the element again. To trigger the mouseover 1114 * event, we're adding an additional div to $box and we're going to toggle 1115 * it when mouse moves inside the selection area. 1116 */ 680 1117 if ($.browser.opera) 681 1118 $areaOpera = div().css({ width: '100%', height: '100%', 682 1119 position: 'absolute', zIndex: zIndex + 2 || 2 }); 683 1120 1121 /* 1122 * We initially set visibility to "hidden" as a workaround for a weird 1123 * behaviour observed in Google Chrome 1.0.154.53 (on Windows XP). Normally 1124 * we would just set display to "none", but, for some reason, if we do so 1125 * then Chrome refuses to later display the element with .show() or 1126 * .fadeIn(). 1127 */ 684 1128 $box.add($outer).css({ visibility: 'hidden', position: position, 685 1129 overflow: 'hidden', zIndex: zIndex || '0' }); 686 1130 $box.css({ zIndex: zIndex + 2 || 2 }); 687 1131 $area.add($border).css({ position: 'absolute', fontSize: 0 }); 688 1132 1133 /* 1134 * If the image has been fully loaded, or if it is not really an image (eg. 1135 * a div), call imgLoad() immediately; otherwise, bind it to be called once 1136 * on image load event. 1137 */ 689 1138 img.complete || img.readyState == 'complete' || !$img.is('img') ? 690 1139 imgLoad() : $img.one('load', imgLoad); 691 1140 692 if ($.browser.msie && $.browser.version >= 9) 1141 /* 1142 * MSIE 9.0 doesn't always fire the image load event -- resetting the src 1143 * attribute seems to trigger it. The check is for version 7 and above to 1144 * accommodate for MSIE 9 running in compatibility mode. 1145 */ 1146 if ($.browser.msie && $.browser.version >= 7) 693 1147 img.src = img.src; 694 1148 }; 695 1149 1150 /** 1151 * Invoke imgAreaSelect on a jQuery object containing the image(s) 1152 * 1153 * @param options 1154 * Options object 1155 * @return The jQuery object or a reference to imgAreaSelect instance (if the 1156 * <code>instance</code> option was specified) 1157 */ 696 1158 $.fn.imgAreaSelect = function (options) { 697 1159 options = options || {}; 698 1160 699 1161 this.each(function () { 1162 /* Is there already an imgAreaSelect instance bound to this element? */ 700 1163 if ($(this).data('imgAreaSelect')) { 1164 /* Yes there is -- is it supposed to be removed? */ 701 1165 if (options.remove) { 1166 /* Remove the plugin */ 702 1167 $(this).data('imgAreaSelect').remove(); 703 1168 $(this).removeData('imgAreaSelect'); 704 1169 } 705 1170 else 1171 /* Reset options */ 706 1172 $(this).data('imgAreaSelect').setOptions(options); 707 1173 } 708 1174 else if (!options.remove) { 1175 /* No exising instance -- create a new one */ 1176 1177 /* 1178 * If neither the "enable" nor the "disable" option is present, add 1179 * "enable" as the default 1180 */ 709 1181 if (options.enable === undefined && options.disable === undefined) 710 1182 options.enable = true; 711 1183 … … 714 1186 }); 715 1187 716 1188 if (options.instance) 1189 /* 1190 * Return the imgAreaSelect instance bound to the first element in the 1191 * set 1192 */ 717 1193 return $(this).data('imgAreaSelect'); 718 1194 719 1195 return this; 720 1196 }; 721 1197 722 })(jQuery); 1198 })(jQuery); 1199 No newline at end of file