| 37 | | // Sanitize some options {{{ |
| 38 | | var obj = obj, opt = opt; |
| | 38 | // Internal Methods {{{ |
| | 39 | function px(n) { |
| | 40 | return n + 'px'; |
| | 41 | } |
| | 42 | function cssClass(cl) { |
| | 43 | return options.baseClass + '-' + cl; |
| | 44 | } |
| | 45 | function supportsColorFade() { |
| | 46 | return $.fx.step.hasOwnProperty('backgroundColor'); |
| | 47 | } |
| | 48 | function getPos(obj) //{{{ |
| | 49 | { |
| | 50 | var pos = $(obj).offset(); |
| | 51 | return [pos.left, pos.top]; |
| | 52 | } |
| | 53 | //}}} |
| | 54 | function mouseAbs(e) //{{{ |
| | 55 | { |
| | 56 | return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])]; |
| | 57 | } |
| | 58 | //}}} |
| | 59 | function setOptions(opt) //{{{ |
| | 60 | { |
| | 61 | if (typeof(opt) !== 'object') opt = {}; |
| | 62 | options = $.extend(options, opt); |
| 40 | | if (typeof(obj) !== 'object') obj = $(obj)[0]; |
| 41 | | if (typeof(opt) !== 'object') opt = { }; |
| | 64 | $.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) { |
| | 65 | if (typeof(options[e]) !== 'function') options[e] = function () {}; |
| | 66 | }); |
| | 67 | } |
| | 68 | //}}} |
| | 69 | function startDragMode(mode, pos) //{{{ |
| | 70 | { |
| | 71 | docOffset = getPos($img); |
| | 72 | Tracker.setCursor(mode === 'move' ? mode : mode + '-resize'); |
| 81 | | boxWidth: 0, |
| 82 | | boxHeight: 0, |
| | 176 | btndown = true; |
| | 177 | startDragMode(ord, mouseAbs(e)); |
| | 178 | e.stopPropagation(); |
| | 179 | e.preventDefault(); |
| | 180 | return false; |
| | 181 | }; |
| | 182 | } |
| | 183 | //}}} |
| | 184 | function presize($obj, w, h) //{{{ |
| | 185 | { |
| | 186 | var nw = $obj.width(), |
| | 187 | nh = $obj.height(); |
| | 188 | if ((nw > w) && w > 0) { |
| | 189 | nw = w; |
| | 190 | nh = (w / $obj.width()) * $obj.height(); |
| | 191 | } |
| | 192 | if ((nh > h) && h > 0) { |
| | 193 | nh = h; |
| | 194 | nw = (h / $obj.height()) * $obj.width(); |
| | 195 | } |
| | 196 | xscale = $obj.width() / nw; |
| | 197 | yscale = $obj.height() / nh; |
| | 198 | $obj.width(nw).height(nh); |
| | 199 | } |
| | 200 | //}}} |
| | 201 | function unscale(c) //{{{ |
| | 202 | { |
| | 203 | return { |
| | 204 | x: c.x * xscale, |
| | 205 | y: c.y * yscale, |
| | 206 | x2: c.x2 * xscale, |
| | 207 | y2: c.y2 * yscale, |
| | 208 | w: c.w * xscale, |
| | 209 | h: c.h * yscale |
| | 210 | }; |
| | 211 | } |
| | 212 | //}}} |
| | 213 | function doneSelect(pos) //{{{ |
| | 214 | { |
| | 215 | var c = Coords.getFixed(); |
| | 216 | if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) { |
| | 217 | Selection.enableHandles(); |
| | 218 | Selection.done(); |
| | 219 | } else { |
| | 220 | Selection.release(); |
| | 221 | } |
| | 222 | Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); |
| | 223 | } |
| | 224 | //}}} |
| | 225 | function newSelection(e) //{{{ |
| | 226 | { |
| | 227 | if (options.disabled) { |
| | 228 | return false; |
| | 229 | } |
| | 230 | if (!options.allowSelect) { |
| | 231 | return false; |
| | 232 | } |
| | 233 | btndown = true; |
| | 234 | docOffset = getPos($img); |
| | 235 | Selection.disableHandles(); |
| | 236 | Tracker.setCursor('crosshair'); |
| | 237 | var pos = mouseAbs(e); |
| | 238 | Coords.setPressed(pos); |
| | 239 | Selection.update(); |
| | 240 | Tracker.activateHandlers(selectDrag, doneSelect); |
| | 241 | KeyManager.watchKeys(); |
| 88 | | allowSelect: true, |
| 89 | | allowMove: true, |
| 90 | | allowResize: true, |
| | 267 | // }}} |
| | 268 | // Initialization {{{ |
| | 269 | // Sanitize some options {{{ |
| | 270 | if ($.browser.msie && ($.browser.version.split('.')[0] === '6')) { |
| | 271 | ie6mode = true; |
| | 272 | } |
| | 273 | if (typeof(obj) !== 'object') { |
| | 274 | obj = $(obj)[0]; |
| | 275 | } |
| | 276 | if (typeof(opt) !== 'object') { |
| | 277 | opt = {}; |
| | 278 | } |
| | 279 | // }}} |
| | 280 | setOptions(opt); |
| | 281 | // Initialize some jQuery objects {{{ |
| | 282 | // The values are SET on the image(s) for the interface |
| | 283 | // If the original image has any of these set, they will be reset |
| | 284 | // However, if you destroy() the Jcrop instance the original image's |
| | 285 | // character in the DOM will be as you left it. |
| | 286 | var img_css = { |
| | 287 | border: 'none', |
| | 288 | visibility: 'visible', |
| | 289 | margin: 0, |
| | 290 | padding: 0, |
| | 291 | position: 'absolute', |
| | 292 | top: 0, |
| | 293 | left: 0 |
| | 294 | }; |
| 96 | | // Callbacks / Event Handlers |
| 97 | | onChange: function() { }, |
| 98 | | onSelect: function() { } |
| | 299 | if (obj.tagName == 'IMG') { |
| | 300 | // Fix size of crop image. |
| | 301 | // Necessary when crop image is within a hidden element when page is loaded. |
| | 302 | if ($origimg[0].width != 0 && $origimg[0].height != 0) { |
| | 303 | // Obtain dimensions from contained img element. |
| | 304 | $origimg.width($origimg[0].width); |
| | 305 | $origimg.height($origimg[0].height); |
| | 306 | } else { |
| | 307 | // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0). |
| | 308 | var tempImage = new Image(); |
| | 309 | tempImage.src = $origimg[0].src; |
| | 310 | $origimg.width(tempImage.width); |
| | 311 | $origimg.height(tempImage.height); |
| | 312 | } |
| 131 | | var $img2 = $('<img />')/*{{{*/ |
| 132 | | .attr('src',$img.attr('src')) |
| 133 | | .css('position','absolute') |
| 134 | | .width(boundx).height(boundy) |
| 135 | | ;/*}}}*/ |
| 136 | | var $img_holder = $('<div />')/*{{{*/ |
| 137 | | .width(pct(100)).height(pct(100)) |
| 138 | | .css({ |
| 139 | | zIndex: 310, |
| 140 | | position: 'absolute', |
| 141 | | overflow: 'hidden' |
| 142 | | }) |
| 143 | | .append($img2) |
| 144 | | ;/*}}}*/ |
| 145 | | var $hdl_holder = $('<div />')/*{{{*/ |
| 146 | | .width(pct(100)).height(pct(100)) |
| 147 | | .css('zIndex',320); |
| 148 | | /*}}}*/ |
| 149 | | var $sel = $('<div />')/*{{{*/ |
| 150 | | .css({ |
| 151 | | position: 'absolute', |
| 152 | | zIndex: 300 |
| 153 | | }) |
| 154 | | .insertBefore($img) |
| 155 | | .append($img_holder,$hdl_holder) |
| 156 | | ;/*}}}*/ |
| | 343 | $img_holder = $('<div />') |
| | 344 | .width('100%').height('100%').css({ |
| | 345 | zIndex: 310, |
| | 346 | position: 'absolute', |
| | 347 | overflow: 'hidden' |
| | 348 | }), |
| 158 | | var bound = options.boundary; |
| 159 | | var $trk = newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)) |
| 160 | | .css({ position: 'absolute', top: px(-bound), left: px(-bound), zIndex: 290 }) |
| 161 | | .mousedown(newSelection); |
| 162 | | |
| 163 | | /* }}} */ |
| 164 | | // Set more variables {{{ |
| | 350 | $hdl_holder = $('<div />') |
| | 351 | .width('100%').height('100%').css('zIndex', 320), |
| 166 | | var xlimit, ylimit, xmin, ymin; |
| 167 | | var xscale, yscale, enabled = true; |
| 168 | | var docOffset = getPos($img), |
| 169 | | // Internal states |
| 170 | | btndown, lastcurs, dimmed, animating, |
| 171 | | shift_down; |
| | 353 | $sel = $('<div />') |
| | 354 | .css({ |
| | 355 | position: 'absolute', |
| | 356 | zIndex: 600 |
| | 357 | }).dblclick(function(){ |
| | 358 | var c = Coords.getFixed(); |
| | 359 | options.onDblClick.call(api,c); |
| | 360 | }).insertBefore($img).append($img_holder, $hdl_holder); |
| 214 | | x1 += ox; |
| 215 | | x2 += ox; |
| 216 | | y1 += oy; |
| 217 | | y2 += oy; |
| 218 | | }; |
| 219 | | /*}}}*/ |
| 220 | | function getCorner(ord)/*{{{*/ |
| 221 | | { |
| 222 | | var c = getFixed(); |
| 223 | | switch(ord) |
| 224 | | { |
| 225 | | case 'ne': return [ c.x2, c.y ]; |
| 226 | | case 'nw': return [ c.x, c.y ]; |
| 227 | | case 'se': return [ c.x2, c.y2 ]; |
| 228 | | case 'sw': return [ c.x, c.y2 ]; |
| 229 | | } |
| 230 | | }; |
| 231 | | /*}}}*/ |
| 232 | | function getFixed()/*{{{*/ |
| 233 | | { |
| 234 | | if (!options.aspectRatio) return getRect(); |
| 235 | | // This function could use some optimization I think... |
| 236 | | var aspect = options.aspectRatio, |
| 237 | | min_x = options.minSize[0]/xscale, |
| 238 | | min_y = options.minSize[1]/yscale, |
| 239 | | max_x = options.maxSize[0]/xscale, |
| 240 | | max_y = options.maxSize[1]/yscale, |
| 241 | | rw = x2 - x1, |
| 242 | | rh = y2 - y1, |
| 243 | | rwa = Math.abs(rw), |
| 244 | | rha = Math.abs(rh), |
| 245 | | real_ratio = rwa / rha, |
| 246 | | xx, yy |
| 247 | | ; |
| 248 | | if (max_x == 0) { max_x = boundx * 10 } |
| 249 | | if (max_y == 0) { max_y = boundy * 10 } |
| 250 | | if (real_ratio < aspect) |
| 251 | | { |
| 252 | | yy = y2; |
| 253 | | w = rha * aspect; |
| 254 | | xx = rw < 0 ? x1 - w : w + x1; |
| | 385 | /* }}} */ |
| | 386 | // Set more variables {{{ |
| | 387 | var bgcolor = options.bgColor, |
| | 388 | bgopacity = options.bgOpacity, |
| | 389 | xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true, |
| | 390 | btndown, animating, shift_down; |
| 256 | | if (xx < 0) |
| 257 | | { |
| 258 | | xx = 0; |
| 259 | | h = Math.abs((xx - x1) / aspect); |
| 260 | | yy = rh < 0 ? y1 - h: h + y1; |
| 261 | | } |
| 262 | | else if (xx > boundx) |
| 263 | | { |
| 264 | | xx = boundx; |
| 265 | | h = Math.abs((xx - x1) / aspect); |
| 266 | | yy = rh < 0 ? y1 - h : h + y1; |
| 267 | | } |
| 268 | | } |
| 269 | | else |
| 270 | | { |
| 271 | | xx = x2; |
| 272 | | h = rwa / aspect; |
| 273 | | yy = rh < 0 ? y1 - h : y1 + h; |
| 274 | | if (yy < 0) |
| 275 | | { |
| 276 | | yy = 0; |
| 277 | | w = Math.abs((yy - y1) * aspect); |
| 278 | | xx = rw < 0 ? x1 - w : w + x1; |
| 279 | | } |
| 280 | | else if (yy > boundy) |
| 281 | | { |
| 282 | | yy = boundy; |
| 283 | | w = Math.abs(yy - y1) * aspect; |
| 284 | | xx = rw < 0 ? x1 - w : w + x1; |
| 285 | | } |
| 286 | | } |
| | 392 | docOffset = getPos($img); |
| | 393 | // }}} |
| | 394 | // }}} |
| | 395 | // Internal Modules {{{ |
| | 396 | // Touch Module {{{ |
| | 397 | var Touch = (function () { |
| | 398 | // Touch support detection function adapted (under MIT License) |
| | 399 | // from code by Jeffrey Sambells - http://github.com/iamamused/ |
| | 400 | function hasTouchSupport() { |
| | 401 | var support = {}, |
| | 402 | events = ['touchstart', 'touchmove', 'touchend'], |
| | 403 | el = document.createElement('div'), i; |
| 288 | | // Magic %-) |
| 289 | | if(xx > x1) { // right side |
| 290 | | if(xx - x1 < min_x) { |
| 291 | | xx = x1 + min_x; |
| 292 | | } else if (xx - x1 > max_x) { |
| 293 | | xx = x1 + max_x; |
| 294 | | } |
| 295 | | if(yy > y1) { |
| 296 | | yy = y1 + (xx - x1)/aspect; |
| 297 | | } else { |
| 298 | | yy = y1 - (xx - x1)/aspect; |
| 299 | | } |
| 300 | | } else if (xx < x1) { // left side |
| 301 | | if(x1 - xx < min_x) { |
| 302 | | xx = x1 - min_x |
| 303 | | } else if (x1 - xx > max_x) { |
| 304 | | xx = x1 - max_x; |
| 305 | | } |
| 306 | | if(yy > y1) { |
| 307 | | yy = y1 + (x1 - xx)/aspect; |
| 308 | | } else { |
| 309 | | yy = y1 - (x1 - xx)/aspect; |
| 310 | | } |
| 311 | | } |
| | 405 | try { |
| | 406 | for(i=0; i<events.length; i++) { |
| | 407 | var eventName = events[i]; |
| | 408 | eventName = 'on' + eventName; |
| | 409 | var isSupported = (eventName in el); |
| | 410 | if (!isSupported) { |
| | 411 | el.setAttribute(eventName, 'return;'); |
| | 412 | isSupported = typeof el[eventName] == 'function'; |
| | 413 | } |
| | 414 | support[events[i]] = isSupported; |
| | 415 | } |
| | 416 | return support.touchstart && support.touchend && support.touchmove; |
| | 417 | } |
| | 418 | catch(err) { |
| | 419 | return false; |
| | 420 | } |
| | 421 | } |
| 313 | | if(xx < 0) { |
| 314 | | x1 -= xx; |
| 315 | | xx = 0; |
| 316 | | } else if (xx > boundx) { |
| 317 | | x1 -= xx - boundx; |
| 318 | | xx = boundx; |
| 319 | | } |
| | 423 | function detectSupport() { |
| | 424 | if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport; |
| | 425 | else return hasTouchSupport(); |
| | 426 | } |
| | 427 | return { |
| | 428 | createDragger: function (ord) { |
| | 429 | return function (e) { |
| | 430 | e.pageX = e.originalEvent.changedTouches[0].pageX; |
| | 431 | e.pageY = e.originalEvent.changedTouches[0].pageY; |
| | 432 | if (options.disabled) { |
| | 433 | return false; |
| | 434 | } |
| | 435 | if ((ord === 'move') && !options.allowMove) { |
| | 436 | return false; |
| | 437 | } |
| | 438 | btndown = true; |
| | 439 | startDragMode(ord, mouseAbs(e)); |
| | 440 | e.stopPropagation(); |
| | 441 | e.preventDefault(); |
| | 442 | return false; |
| | 443 | }; |
| | 444 | }, |
| | 445 | newSelection: function (e) { |
| | 446 | e.pageX = e.originalEvent.changedTouches[0].pageX; |
| | 447 | e.pageY = e.originalEvent.changedTouches[0].pageY; |
| | 448 | return newSelection(e); |
| | 449 | }, |
| | 450 | isSupported: hasTouchSupport, |
| | 451 | support: detectSupport() |
| | 452 | }; |
| | 453 | }()); |
| | 454 | // }}} |
| | 455 | // Coords Module {{{ |
| | 456 | var Coords = (function () { |
| | 457 | var x1 = 0, |
| | 458 | y1 = 0, |
| | 459 | x2 = 0, |
| | 460 | y2 = 0, |
| | 461 | ox, oy; |
| 340 | | return [ p[0], p[1] ]; |
| 341 | | }; |
| 342 | | /*}}}*/ |
| 343 | | function flipCoords(x1,y1,x2,y2)/*{{{*/ |
| 344 | | { |
| 345 | | var xa = x1, xb = x2, ya = y1, yb = y2; |
| 346 | | if (x2 < x1) |
| 347 | | { |
| 348 | | xa = x2; |
| 349 | | xb = x1; |
| 350 | | } |
| 351 | | if (y2 < y1) |
| 352 | | { |
| 353 | | ya = y2; |
| 354 | | yb = y1; |
| 355 | | } |
| 356 | | return [ Math.round(xa), Math.round(ya), Math.round(xb), Math.round(yb) ]; |
| 357 | | }; |
| 358 | | /*}}}*/ |
| 359 | | function getRect()/*{{{*/ |
| 360 | | { |
| 361 | | var xsize = x2 - x1; |
| 362 | | var ysize = y2 - y1; |
| | 503 | x1 += ox; |
| | 504 | x2 += ox; |
| | 505 | y1 += oy; |
| | 506 | y2 += oy; |
| | 507 | } |
| | 508 | //}}} |
| | 509 | function getCorner(ord) //{{{ |
| | 510 | { |
| | 511 | var c = getFixed(); |
| | 512 | switch (ord) { |
| | 513 | case 'ne': |
| | 514 | return [c.x2, c.y]; |
| | 515 | case 'nw': |
| | 516 | return [c.x, c.y]; |
| | 517 | case 'se': |
| | 518 | return [c.x2, c.y2]; |
| | 519 | case 'sw': |
| | 520 | return [c.x, c.y2]; |
| | 521 | } |
| | 522 | } |
| | 523 | //}}} |
| | 524 | function getFixed() //{{{ |
| | 525 | { |
| | 526 | if (!options.aspectRatio) { |
| | 527 | return getRect(); |
| | 528 | } |
| | 529 | // This function could use some optimization I think... |
| | 530 | var aspect = options.aspectRatio, |
| | 531 | min_x = options.minSize[0] / xscale, |
| | 532 | |
| | 533 | |
| | 534 | //min_y = options.minSize[1]/yscale, |
| | 535 | max_x = options.maxSize[0] / xscale, |
| | 536 | max_y = options.maxSize[1] / yscale, |
| | 537 | rw = x2 - x1, |
| | 538 | rh = y2 - y1, |
| | 539 | rwa = Math.abs(rw), |
| | 540 | rha = Math.abs(rh), |
| | 541 | real_ratio = rwa / rha, |
| | 542 | xx, yy, w, h; |
| 369 | | if (ymin && (Math.abs(ysize) < ymin)) |
| 370 | | y2 = (ysize > 0) ? (y1 + ymin) : (y1 - ymin); |
| 371 | | if (xmin && (Math.abs(xsize) < xmin)) |
| 372 | | x2 = (xsize > 0) ? (x1 + xmin) : (x1 - xmin); |
| | 555 | if (xx < 0) { |
| | 556 | xx = 0; |
| | 557 | h = Math.abs((xx - x1) / aspect); |
| | 558 | yy = rh < 0 ? y1 - h : h + y1; |
| | 559 | } else if (xx > boundx) { |
| | 560 | xx = boundx; |
| | 561 | h = Math.abs((xx - x1) / aspect); |
| | 562 | yy = rh < 0 ? y1 - h : h + y1; |
| | 563 | } |
| | 564 | } else { |
| | 565 | xx = x2; |
| | 566 | h = rwa / aspect; |
| | 567 | yy = rh < 0 ? y1 - h : y1 + h; |
| | 568 | if (yy < 0) { |
| | 569 | yy = 0; |
| | 570 | w = Math.abs((yy - y1) * aspect); |
| | 571 | xx = rw < 0 ? x1 - w : w + x1; |
| | 572 | } else if (yy > boundy) { |
| | 573 | yy = boundy; |
| | 574 | w = Math.abs(yy - y1) * aspect; |
| | 575 | xx = rw < 0 ? x1 - w : w + x1; |
| | 576 | } |
| | 577 | } |
| 374 | | if (x1 < 0) { x2 -= x1; x1 -= x1; } |
| 375 | | if (y1 < 0) { y2 -= y1; y1 -= y1; } |
| 376 | | if (x2 < 0) { x1 -= x2; x2 -= x2; } |
| 377 | | if (y2 < 0) { y1 -= y2; y2 -= y2; } |
| 378 | | if (x2 > boundx) { var delta = x2 - boundx; x1 -= delta; x2 -= delta; } |
| 379 | | if (y2 > boundy) { var delta = y2 - boundy; y1 -= delta; y2 -= delta; } |
| 380 | | if (x1 > boundx) { var delta = x1 - boundy; y2 -= delta; y1 -= delta; } |
| 381 | | if (y1 > boundy) { var delta = y1 - boundy; y2 -= delta; y1 -= delta; } |
| | 579 | // Magic %-) |
| | 580 | if (xx > x1) { // right side |
| | 581 | if (xx - x1 < min_x) { |
| | 582 | xx = x1 + min_x; |
| | 583 | } else if (xx - x1 > max_x) { |
| | 584 | xx = x1 + max_x; |
| | 585 | } |
| | 586 | if (yy > y1) { |
| | 587 | yy = y1 + (xx - x1) / aspect; |
| | 588 | } else { |
| | 589 | yy = y1 - (xx - x1) / aspect; |
| | 590 | } |
| | 591 | } else if (xx < x1) { // left side |
| | 592 | if (x1 - xx < min_x) { |
| | 593 | xx = x1 - min_x; |
| | 594 | } else if (x1 - xx > max_x) { |
| | 595 | xx = x1 - max_x; |
| | 596 | } |
| | 597 | if (yy > y1) { |
| | 598 | yy = y1 + (x1 - xx) / aspect; |
| | 599 | } else { |
| | 600 | yy = y1 - (x1 - xx) / aspect; |
| | 601 | } |
| | 602 | } |
| 415 | | // Insert border divs for outline |
| 416 | | if (options.drawBorders) { |
| 417 | | borders = { |
| 418 | | top: insertBorder('hline') |
| 419 | | .css('top',$.browser.msie?px(-1):px(0)), |
| 420 | | bottom: insertBorder('hline'), |
| 421 | | left: insertBorder('vline'), |
| 422 | | right: insertBorder('vline') |
| 423 | | }; |
| 424 | | } |
| | 639 | return [p[0], p[1]]; |
| | 640 | } |
| | 641 | //}}} |
| | 642 | function flipCoords(x1, y1, x2, y2) //{{{ |
| | 643 | { |
| | 644 | var xa = x1, |
| | 645 | xb = x2, |
| | 646 | ya = y1, |
| | 647 | yb = y2; |
| | 648 | if (x2 < x1) { |
| | 649 | xa = x2; |
| | 650 | xb = x1; |
| | 651 | } |
| | 652 | if (y2 < y1) { |
| | 653 | ya = y2; |
| | 654 | yb = y1; |
| | 655 | } |
| | 656 | return [xa, ya, xb, yb]; |
| | 657 | } |
| | 658 | //}}} |
| | 659 | function getRect() //{{{ |
| | 660 | { |
| | 661 | var xsize = x2 - x1, |
| | 662 | ysize = y2 - y1, |
| | 663 | delta; |
| 426 | | // Insert handles on edges |
| 427 | | if (options.dragEdges) { |
| 428 | | handle.t = insertDragbar('n'); |
| 429 | | handle.b = insertDragbar('s'); |
| 430 | | handle.r = insertDragbar('e'); |
| 431 | | handle.l = insertDragbar('w'); |
| 432 | | } |
| | 665 | if (xlimit && (Math.abs(xsize) > xlimit)) { |
| | 666 | x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit); |
| | 667 | } |
| | 668 | if (ylimit && (Math.abs(ysize) > ylimit)) { |
| | 669 | y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit); |
| | 670 | } |
| 442 | | /*}}}*/ |
| 443 | | // Private Methods |
| 444 | | function insertBorder(type)/*{{{*/ |
| 445 | | { |
| 446 | | var jq = $('<div />') |
| 447 | | .css({position: 'absolute', opacity: options.borderOpacity }) |
| 448 | | .addClass(cssClass(type)); |
| 449 | | $img_holder.append(jq); |
| 450 | | return jq; |
| 451 | | }; |
| 452 | | /*}}}*/ |
| 453 | | function dragDiv(ord,zi)/*{{{*/ |
| 454 | | { |
| 455 | | var jq = $('<div />') |
| 456 | | .mousedown(createDragger(ord)) |
| 457 | | .css({ |
| 458 | | cursor: ord+'-resize', |
| 459 | | position: 'absolute', |
| 460 | | zIndex: zi |
| 461 | | }) |
| 462 | | ; |
| 463 | | $hdl_holder.append(jq); |
| 464 | | return jq; |
| 465 | | }; |
| 466 | | /*}}}*/ |
| 467 | | function insertHandle(ord)/*{{{*/ |
| 468 | | { |
| 469 | | return dragDiv(ord,hdep++) |
| 470 | | .css({ top: px(-hhs+1), left: px(-hhs+1), opacity: options.handleOpacity }) |
| 471 | | .addClass(cssClass('handle')); |
| 472 | | }; |
| 473 | | /*}}}*/ |
| 474 | | function insertDragbar(ord)/*{{{*/ |
| 475 | | { |
| 476 | | var s = options.handleSize, |
| 477 | | o = hhs, |
| 478 | | h = s, w = s, |
| 479 | | t = o, l = o; |
| | 716 | return makeObj(flipCoords(x1, y1, x2, y2)); |
| | 717 | } |
| | 718 | //}}} |
| | 719 | function makeObj(a) //{{{ |
| | 720 | { |
| | 721 | return { |
| | 722 | x: a[0], |
| | 723 | y: a[1], |
| | 724 | x2: a[2], |
| | 725 | y2: a[3], |
| | 726 | w: a[2] - a[0], |
| | 727 | h: a[3] - a[1] |
| | 728 | }; |
| | 729 | } |
| | 730 | //}}} |
| 487 | | return dragDiv(ord,hdep++).width(w).height(h) |
| 488 | | .css({ top: px(-t+1), left: px(-l+1)}); |
| 489 | | }; |
| 490 | | /*}}}*/ |
| 491 | | function createHandles(li)/*{{{*/ |
| 492 | | { |
| 493 | | for(i in li) handle[li[i]] = insertHandle(li[i]); |
| 494 | | }; |
| 495 | | /*}}}*/ |
| 496 | | function moveHandles(c)/*{{{*/ |
| 497 | | { |
| 498 | | var midvert = Math.round((c.h / 2) - hhs), |
| 499 | | midhoriz = Math.round((c.w / 2) - hhs), |
| 500 | | north = west = -hhs+1, |
| 501 | | east = c.w - hhs, |
| 502 | | south = c.h - hhs, |
| 503 | | x, y; |
| | 743 | //}}} |
| | 744 | // Shade Module {{{ |
| | 745 | var Shade = (function() { |
| | 746 | var enabled = false, |
| | 747 | holder = $('<div />').css({ |
| | 748 | position: 'absolute', |
| | 749 | zIndex: 240, |
| | 750 | opacity: 0 |
| | 751 | }), |
| | 752 | shades = { |
| | 753 | top: createShade(), |
| | 754 | left: createShade().height(boundy), |
| | 755 | right: createShade().height(boundy), |
| | 756 | bottom: createShade() |
| | 757 | }; |
| 505 | | 'e' in handle && |
| 506 | | handle.e.css({ top: px(midvert), left: px(east) }) && |
| 507 | | handle.w.css({ top: px(midvert) }) && |
| 508 | | handle.s.css({ top: px(south), left: px(midhoriz) }) && |
| 509 | | handle.n.css({ left: px(midhoriz) }); |
| | 759 | function resizeShades(w,h) { |
| | 760 | shades.left.css({ height: px(h) }); |
| | 761 | shades.right.css({ height: px(h) }); |
| | 762 | } |
| | 763 | function updateAuto() |
| | 764 | { |
| | 765 | return updateShade(Coords.getFixed()); |
| | 766 | } |
| | 767 | function updateShade(c) |
| | 768 | { |
| | 769 | shades.top.css({ |
| | 770 | left: px(c.x), |
| | 771 | width: px(c.w), |
| | 772 | height: px(c.y) |
| | 773 | }); |
| | 774 | shades.bottom.css({ |
| | 775 | top: px(c.y2), |
| | 776 | left: px(c.x), |
| | 777 | width: px(c.w), |
| | 778 | height: px(boundy-c.y2) |
| | 779 | }); |
| | 780 | shades.right.css({ |
| | 781 | left: px(c.x2), |
| | 782 | width: px(boundx-c.x2) |
| | 783 | }); |
| | 784 | shades.left.css({ |
| | 785 | width: px(c.x) |
| | 786 | }); |
| | 787 | } |
| | 788 | function createShade() { |
| | 789 | return $('<div />').css({ |
| | 790 | position: 'absolute', |
| | 791 | backgroundColor: options.shadeColor||options.bgColor |
| | 792 | }).appendTo(holder); |
| | 793 | } |
| | 794 | function enableShade() { |
| | 795 | if (!enabled) { |
| | 796 | enabled = true; |
| | 797 | holder.insertBefore($img); |
| | 798 | updateAuto(); |
| | 799 | Selection.setBgOpacity(1,0,1); |
| | 800 | $img2.hide(); |
| 511 | | 'ne' in handle && |
| 512 | | handle.ne.css({ left: px(east) }) && |
| 513 | | handle.se.css({ top: px(south), left: px(east) }) && |
| 514 | | handle.sw.css({ top: px(south) }); |
| | 802 | setBgColor(options.shadeColor||options.bgColor,1); |
| | 803 | if (Selection.isAwake()) |
| | 804 | { |
| | 805 | setOpacity(options.bgOpacity,1); |
| | 806 | } |
| | 807 | else setOpacity(1,1); |
| | 808 | } |
| | 809 | } |
| | 810 | function setBgColor(color,now) { |
| | 811 | colorChangeMacro(getShades(),color,now); |
| | 812 | } |
| | 813 | function disableShade() { |
| | 814 | if (enabled) { |
| | 815 | holder.remove(); |
| | 816 | $img2.show(); |
| | 817 | enabled = false; |
| | 818 | if (Selection.isAwake()) { |
| | 819 | Selection.setBgOpacity(options.bgOpacity,1,1); |
| | 820 | } else { |
| | 821 | Selection.setBgOpacity(1,1,1); |
| | 822 | Selection.disableHandles(); |
| | 823 | } |
| | 824 | colorChangeMacro($div,0,1); |
| | 825 | } |
| | 826 | } |
| | 827 | function setOpacity(opacity,now) { |
| | 828 | if (enabled) { |
| | 829 | if (options.bgFade && !now) { |
| | 830 | holder.animate({ |
| | 831 | opacity: 1-opacity |
| | 832 | },{ |
| | 833 | queue: false, |
| | 834 | duration: options.fadeTime |
| | 835 | }); |
| | 836 | } |
| | 837 | else holder.css({opacity:1-opacity}); |
| | 838 | } |
| | 839 | } |
| | 840 | function refreshAll() { |
| | 841 | options.shade ? enableShade() : disableShade(); |
| | 842 | if (Selection.isAwake()) setOpacity(options.bgOpacity); |
| | 843 | } |
| | 844 | function getShades() { |
| | 845 | return holder.children(); |
| | 846 | } |
| 516 | | 'b' in handle && |
| 517 | | handle.b.css({ top: px(south) }) && |
| 518 | | handle.r.css({ left: px(east) }); |
| 519 | | }; |
| 520 | | /*}}}*/ |
| 521 | | function moveto(x,y)/*{{{*/ |
| 522 | | { |
| 523 | | $img2.css({ top: px(-y), left: px(-x) }); |
| 524 | | $sel.css({ top: px(y), left: px(x) }); |
| 525 | | }; |
| 526 | | /*}}}*/ |
| 527 | | function resize(w,h)/*{{{*/ |
| 528 | | { |
| 529 | | $sel.width(w).height(h); |
| 530 | | }; |
| 531 | | /*}}}*/ |
| 532 | | function refresh()/*{{{*/ |
| 533 | | { |
| 534 | | var c = Coords.getFixed(); |
| | 848 | return { |
| | 849 | update: updateAuto, |
| | 850 | updateRaw: updateShade, |
| | 851 | getShades: getShades, |
| | 852 | setBgColor: setBgColor, |
| | 853 | enable: enableShade, |
| | 854 | disable: disableShade, |
| | 855 | resize: resizeShades, |
| | 856 | refresh: refreshAll, |
| | 857 | opacity: setOpacity |
| | 858 | }; |
| | 859 | }()); |
| | 860 | // }}} |
| | 861 | // Selection Module {{{ |
| | 862 | var Selection = (function () { |
| | 863 | var awake, |
| | 864 | hdep = 370, |
| | 865 | borders = {}, |
| | 866 | handle = {}, |
| | 867 | dragbar = {}, |
| | 868 | seehandles = false; |
| 536 | | Coords.setPressed([c.x,c.y]); |
| 537 | | Coords.setCurrent([c.x2,c.y2]); |
| | 870 | // Private Methods |
| | 871 | function insertBorder(type) //{{{ |
| | 872 | { |
| | 873 | var jq = $('<div />').css({ |
| | 874 | position: 'absolute', |
| | 875 | opacity: options.borderOpacity |
| | 876 | }).addClass(cssClass(type)); |
| | 877 | $img_holder.append(jq); |
| | 878 | return jq; |
| | 879 | } |
| | 880 | //}}} |
| | 881 | function dragDiv(ord, zi) //{{{ |
| | 882 | { |
| | 883 | var jq = $('<div />').mousedown(createDragger(ord)).css({ |
| | 884 | cursor: ord + '-resize', |
| | 885 | position: 'absolute', |
| | 886 | zIndex: zi |
| | 887 | }).addClass('ord-'+ord); |
| 543 | | // Internal Methods |
| 544 | | function updateVisible()/*{{{*/ |
| 545 | | { if (awake) return update(); }; |
| 546 | | /*}}}*/ |
| 547 | | function update()/*{{{*/ |
| 548 | | { |
| 549 | | var c = Coords.getFixed(); |
| | 893 | $hdl_holder.append(jq); |
| | 894 | return jq; |
| | 895 | } |
| | 896 | //}}} |
| | 897 | function insertHandle(ord) //{{{ |
| | 898 | { |
| | 899 | var hs = options.handleSize; |
| | 900 | return dragDiv(ord, hdep++).css({ |
| | 901 | opacity: options.handleOpacity |
| | 902 | }).width(hs).height(hs).addClass(cssClass('handle')); |
| | 903 | } |
| | 904 | //}}} |
| | 905 | function insertDragbar(ord) //{{{ |
| | 906 | { |
| | 907 | return dragDiv(ord, hdep++).addClass('jcrop-dragbar'); |
| | 908 | } |
| | 909 | //}}} |
| | 910 | function createDragbars(li) //{{{ |
| | 911 | { |
| | 912 | var i; |
| | 913 | for (i = 0; i < li.length; i++) { |
| | 914 | dragbar[li[i]] = insertDragbar(li[i]); |
| | 915 | } |
| | 916 | } |
| | 917 | //}}} |
| | 918 | function createBorders(li) //{{{ |
| | 919 | { |
| | 920 | var cl,i; |
| | 921 | for (i = 0; i < li.length; i++) { |
| | 922 | switch(li[i]){ |
| | 923 | case'n': cl='hline'; break; |
| | 924 | case's': cl='hline bottom'; break; |
| | 925 | case'e': cl='vline right'; break; |
| | 926 | case'w': cl='vline'; break; |
| | 927 | } |
| | 928 | borders[li[i]] = insertBorder(cl); |
| | 929 | } |
| | 930 | } |
| | 931 | //}}} |
| | 932 | function createHandles(li) //{{{ |
| | 933 | { |
| | 934 | var i; |
| | 935 | for (i = 0; i < li.length; i++) { |
| | 936 | handle[li[i]] = insertHandle(li[i]); |
| | 937 | } |
| | 938 | } |
| | 939 | //}}} |
| | 940 | function moveto(x, y) //{{{ |
| | 941 | { |
| | 942 | if (!options.shade) { |
| | 943 | $img2.css({ |
| | 944 | top: px(-y), |
| | 945 | left: px(-x) |
| | 946 | }); |
| | 947 | } |
| | 948 | $sel.css({ |
| | 949 | top: px(y), |
| | 950 | left: px(x) |
| | 951 | }); |
| | 952 | } |
| | 953 | //}}} |
| | 954 | function resize(w, h) //{{{ |
| | 955 | { |
| | 956 | $sel.width(w).height(h); |
| | 957 | } |
| | 958 | //}}} |
| | 959 | function refresh() //{{{ |
| | 960 | { |
| | 961 | var c = Coords.getFixed(); |
| 561 | | options.onChange(unscale(c)); |
| 562 | | }; |
| 563 | | /*}}}*/ |
| 564 | | function show()/*{{{*/ |
| 565 | | { |
| 566 | | $sel.show(); |
| 567 | | $img.css('opacity',options.bgOpacity); |
| 568 | | awake = true; |
| 569 | | }; |
| 570 | | /*}}}*/ |
| 571 | | function release()/*{{{*/ |
| 572 | | { |
| 573 | | disableHandles(); |
| 574 | | $sel.hide(); |
| 575 | | $img.css('opacity',1); |
| 576 | | awake = false; |
| 577 | | }; |
| 578 | | /*}}}*/ |
| 579 | | function showHandles()//{{{ |
| 580 | | { |
| 581 | | if (seehandles) |
| 582 | | { |
| 583 | | moveHandles(Coords.getFixed()); |
| 584 | | $hdl_holder.show(); |
| 585 | | } |
| 586 | | }; |
| 587 | | //}}} |
| 588 | | function enableHandles()/*{{{*/ |
| 589 | | { |
| 590 | | seehandles = true; |
| 591 | | if (options.allowResize) |
| 592 | | { |
| 593 | | moveHandles(Coords.getFixed()); |
| 594 | | $hdl_holder.show(); |
| 595 | | return true; |
| 596 | | } |
| 597 | | }; |
| 598 | | /*}}}*/ |
| 599 | | function disableHandles()/*{{{*/ |
| 600 | | { |
| 601 | | seehandles = false; |
| 602 | | $hdl_holder.hide(); |
| 603 | | }; |
| 604 | | /*}}}*/ |
| 605 | | function animMode(v)/*{{{*/ |
| 606 | | { |
| 607 | | (animating = v) ? disableHandles(): enableHandles(); |
| 608 | | }; |
| 609 | | /*}}}*/ |
| 610 | | function done()/*{{{*/ |
| 611 | | { |
| 612 | | animMode(false); |
| 613 | | refresh(); |
| 614 | | }; |
| 615 | | /*}}}*/ |
| | 982 | resize(c.w, c.h); |
| | 983 | moveto(c.x, c.y); |
| | 984 | if (options.shade) Shade.updateRaw(c); |
| 620 | | $img_holder.append($track); |
| 621 | | disableHandles(); |
| | 988 | if (select) { |
| | 989 | options.onSelect.call(api, unscale(c)); |
| | 990 | } else { |
| | 991 | options.onChange.call(api, unscale(c)); |
| | 992 | } |
| | 993 | } |
| | 994 | //}}} |
| | 995 | function setBgOpacity(opacity,force,now) //{{{ |
| | 996 | { |
| | 997 | if (!awake && !force) return; |
| | 998 | if (options.bgFade && !now) { |
| | 999 | $img.animate({ |
| | 1000 | opacity: opacity |
| | 1001 | },{ |
| | 1002 | queue: false, |
| | 1003 | duration: options.fadeTime |
| | 1004 | }); |
| | 1005 | } else { |
| | 1006 | $img.css('opacity', opacity); |
| | 1007 | } |
| | 1008 | } |
| | 1009 | //}}} |
| | 1010 | function show() //{{{ |
| | 1011 | { |
| | 1012 | $sel.show(); |
| 623 | | return { |
| 624 | | updateVisible: updateVisible, |
| 625 | | update: update, |
| 626 | | release: release, |
| 627 | | refresh: refresh, |
| 628 | | setCursor: function (cursor) { $track.css('cursor',cursor); }, |
| 629 | | enableHandles: enableHandles, |
| 630 | | enableOnly: function() { seehandles = true; }, |
| 631 | | showHandles: showHandles, |
| 632 | | disableHandles: disableHandles, |
| 633 | | animMode: animMode, |
| 634 | | done: done |
| 635 | | }; |
| 636 | | }(); |
| 637 | | /*}}}*/ |
| 638 | | var Tracker = function()/*{{{*/ |
| 639 | | { |
| 640 | | var onMove = function() { }, |
| 641 | | onDone = function() { }, |
| 642 | | trackDoc = options.trackDocument; |
| | 1014 | if (options.shade) Shade.opacity(bgopacity); |
| | 1015 | else setBgOpacity(bgopacity,true); |
| 736 | | function watchKeys()/*{{{*/ |
| 737 | | { |
| 738 | | if (options.keySupport) |
| 739 | | { |
| 740 | | $keymgr.show(); |
| 741 | | $keymgr.focus(); |
| 742 | | } |
| 743 | | }; |
| 744 | | /*}}}*/ |
| 745 | | function onBlur(e)/*{{{*/ |
| 746 | | { |
| 747 | | $keymgr.hide(); |
| 748 | | }; |
| 749 | | /*}}}*/ |
| 750 | | function doNudge(e,x,y)/*{{{*/ |
| 751 | | { |
| 752 | | if (options.allowMove) { |
| 753 | | Coords.moveOffset([x,y]); |
| 754 | | Selection.updateVisible(); |
| 755 | | }; |
| 756 | | e.preventDefault(); |
| 757 | | e.stopPropagation(); |
| 758 | | }; |
| 759 | | /*}}}*/ |
| 760 | | function parseKey(e)/*{{{*/ |
| 761 | | { |
| 762 | | if (e.ctrlKey) return true; |
| 763 | | shift_down = e.shiftKey ? true : false; |
| 764 | | var nudge = shift_down ? 10 : 1; |
| 765 | | switch(e.keyCode) |
| 766 | | { |
| 767 | | case 37: doNudge(e,-nudge,0); break; |
| 768 | | case 39: doNudge(e,nudge,0); break; |
| 769 | | case 38: doNudge(e,0,-nudge); break; |
| 770 | | case 40: doNudge(e,0,nudge); break; |
| | 1094 | if (Touch.support) { |
| | 1095 | $track.bind('touchstart.jcrop', Touch.createDragger('move')); |
| | 1096 | } |
| 774 | | case 9: return true; |
| 775 | | } |
| | 1101 | return { |
| | 1102 | updateVisible: updateVisible, |
| | 1103 | update: update, |
| | 1104 | release: release, |
| | 1105 | refresh: refresh, |
| | 1106 | isAwake: function () { |
| | 1107 | return awake; |
| | 1108 | }, |
| | 1109 | setCursor: function (cursor) { |
| | 1110 | $track.css('cursor', cursor); |
| | 1111 | }, |
| | 1112 | enableHandles: enableHandles, |
| | 1113 | enableOnly: function () { |
| | 1114 | seehandles = true; |
| | 1115 | }, |
| | 1116 | showHandles: showHandles, |
| | 1117 | disableHandles: disableHandles, |
| | 1118 | animMode: animMode, |
| | 1119 | setBgOpacity: setBgOpacity, |
| | 1120 | done: done |
| | 1121 | }; |
| | 1122 | }()); |
| | 1123 | |
| | 1124 | //}}} |
| | 1125 | // Tracker Module {{{ |
| | 1126 | var Tracker = (function () { |
| | 1127 | var onMove = function () {}, |
| | 1128 | onDone = function () {}, |
| | 1129 | trackDoc = options.trackDocument; |
| 777 | | return nothing(e); |
| 778 | | }; |
| 779 | | /*}}}*/ |
| 780 | | |
| 781 | | if (options.keySupport) $keywrap.insertBefore($img); |
| 782 | | return { |
| 783 | | watchKeys: watchKeys |
| 784 | | }; |
| 785 | | }(); |
| 786 | | /*}}}*/ |
| | 1131 | function toFront() //{{{ |
| | 1132 | { |
| | 1133 | $trk.css({ |
| | 1134 | zIndex: 450 |
| | 1135 | }); |
| | 1136 | if (Touch.support) { |
| | 1137 | $(document) |
| | 1138 | .bind('touchmove.jcrop', trackTouchMove) |
| | 1139 | .bind('touchend.jcrop', trackTouchEnd); |
| | 1140 | } |
| | 1141 | if (trackDoc) { |
| | 1142 | $(document) |
| | 1143 | .bind('mousemove.jcrop',trackMove) |
| | 1144 | .bind('mouseup.jcrop',trackUp); |
| | 1145 | } |
| | 1146 | } |
| | 1147 | //}}} |
| | 1148 | function toBack() //{{{ |
| | 1149 | { |
| | 1150 | $trk.css({ |
| | 1151 | zIndex: 290 |
| | 1152 | }); |
| | 1153 | $(document).unbind('.jcrop'); |
| | 1154 | } |
| | 1155 | //}}} |
| | 1156 | function trackMove(e) //{{{ |
| | 1157 | { |
| | 1158 | onMove(mouseAbs(e)); |
| | 1159 | return false; |
| | 1160 | } |
| | 1161 | //}}} |
| | 1162 | function trackUp(e) //{{{ |
| | 1163 | { |
| | 1164 | e.preventDefault(); |
| | 1165 | e.stopPropagation(); |
| 791 | | function px(n) { return '' + parseInt(n) + 'px'; }; |
| 792 | | function pct(n) { return '' + parseInt(n) + '%'; }; |
| 793 | | function cssClass(cl) { return options.baseClass + '-' + cl; }; |
| 794 | | function getPos(obj)/*{{{*/ |
| 795 | | { |
| 796 | | // Updated in v0.9.4 to use built-in dimensions plugin |
| 797 | | var pos = $(obj).offset(); |
| 798 | | return [ pos.left, pos.top ]; |
| 799 | | }; |
| 800 | | /*}}}*/ |
| 801 | | function mouseAbs(e)/*{{{*/ |
| 802 | | { |
| 803 | | return [ (e.pageX - docOffset[0]), (e.pageY - docOffset[1]) ]; |
| 804 | | }; |
| 805 | | /*}}}*/ |
| 806 | | function myCursor(type)/*{{{*/ |
| 807 | | { |
| 808 | | if (type != lastcurs) |
| 809 | | { |
| 810 | | Tracker.setCursor(type); |
| 811 | | //Handles.xsetCursor(type); |
| 812 | | lastcurs = type; |
| 813 | | } |
| 814 | | }; |
| 815 | | /*}}}*/ |
| 816 | | function startDragMode(mode,pos)/*{{{*/ |
| 817 | | { |
| 818 | | docOffset = getPos($img); |
| 819 | | Tracker.setCursor(mode=='move'?mode:mode+'-resize'); |
| | 1170 | onDone(mouseAbs(e)); |
| 828 | | Coords.setPressed(Coords.getCorner(opp)); |
| 829 | | Coords.setCurrent(opc); |
| | 1181 | return false; |
| | 1182 | } |
| | 1183 | //}}} |
| | 1184 | function activateHandlers(move, done) //{{{ |
| | 1185 | { |
| | 1186 | btndown = true; |
| | 1187 | onMove = move; |
| | 1188 | onDone = done; |
| | 1189 | toFront(); |
| | 1190 | return false; |
| | 1191 | } |
| | 1192 | //}}} |
| | 1193 | function trackTouchMove(e) //{{{ |
| | 1194 | { |
| | 1195 | e.pageX = e.originalEvent.changedTouches[0].pageX; |
| | 1196 | e.pageY = e.originalEvent.changedTouches[0].pageY; |
| | 1197 | return trackMove(e); |
| | 1198 | } |
| | 1199 | //}}} |
| | 1200 | function trackTouchEnd(e) //{{{ |
| | 1201 | { |
| | 1202 | e.pageX = e.originalEvent.changedTouches[0].pageX; |
| | 1203 | e.pageY = e.originalEvent.changedTouches[0].pageY; |
| | 1204 | return trackUp(e); |
| | 1205 | } |
| | 1206 | //}}} |
| | 1207 | function setCursor(t) //{{{ |
| | 1208 | { |
| | 1209 | $trk.css('cursor', t); |
| | 1210 | } |
| | 1211 | //}}} |
| 831 | | Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect); |
| 832 | | }; |
| 833 | | /*}}}*/ |
| 834 | | function dragmodeHandler(mode,f)/*{{{*/ |
| 835 | | { |
| 836 | | return function(pos) { |
| 837 | | if (!options.aspectRatio) switch(mode) |
| 838 | | { |
| 839 | | case 'e': pos[1] = f.y2; break; |
| 840 | | case 'w': pos[1] = f.y2; break; |
| 841 | | case 'n': pos[0] = f.x2; break; |
| 842 | | case 's': pos[0] = f.x2; break; |
| 843 | | } |
| 844 | | else switch(mode) |
| 845 | | { |
| 846 | | case 'e': pos[1] = f.y+1; break; |
| 847 | | case 'w': pos[1] = f.y+1; break; |
| 848 | | case 'n': pos[0] = f.x+1; break; |
| 849 | | case 's': pos[0] = f.x+1; break; |
| 850 | | } |
| 851 | | Coords.setCurrent(pos); |
| 852 | | Selection.update(); |
| 853 | | }; |
| 854 | | }; |
| 855 | | /*}}}*/ |
| 856 | | function createMover(pos)/*{{{*/ |
| 857 | | { |
| 858 | | var lloc = pos; |
| 859 | | KeyManager.watchKeys(); |
| | 1213 | if (!trackDoc) { |
| | 1214 | $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp); |
| | 1215 | } |
| 861 | | return function(pos) |
| 862 | | { |
| 863 | | Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]); |
| 864 | | lloc = pos; |
| 865 | | |
| 866 | | Selection.update(); |
| 867 | | }; |
| 868 | | }; |
| 869 | | /*}}}*/ |
| 870 | | function oppLockCorner(ord)/*{{{*/ |
| 871 | | { |
| 872 | | switch(ord) |
| 873 | | { |
| 874 | | case 'n': return 'sw'; |
| 875 | | case 's': return 'nw'; |
| 876 | | case 'e': return 'nw'; |
| 877 | | case 'w': return 'ne'; |
| 878 | | case 'ne': return 'sw'; |
| 879 | | case 'nw': return 'se'; |
| 880 | | case 'se': return 'nw'; |
| 881 | | case 'sw': return 'ne'; |
| 882 | | }; |
| 883 | | }; |
| 884 | | /*}}}*/ |
| 885 | | function createDragger(ord)/*{{{*/ |
| 886 | | { |
| 887 | | return function(e) { |
| 888 | | if (options.disabled) return false; |
| 889 | | if ((ord == 'move') && !options.allowMove) return false; |
| 890 | | btndown = true; |
| 891 | | startDragMode(ord,mouseAbs(e)); |
| 892 | | e.stopPropagation(); |
| 893 | | e.preventDefault(); |
| 894 | | return false; |
| 895 | | }; |
| 896 | | }; |
| 897 | | /*}}}*/ |
| 898 | | function presize($obj,w,h)/*{{{*/ |
| 899 | | { |
| 900 | | var nw = $obj.width(), nh = $obj.height(); |
| 901 | | if ((nw > w) && w > 0) |
| 902 | | { |
| 903 | | nw = w; |
| 904 | | nh = (w/$obj.width()) * $obj.height(); |
| 905 | | } |
| 906 | | if ((nh > h) && h > 0) |
| 907 | | { |
| 908 | | nh = h; |
| 909 | | nw = (h/$obj.height()) * $obj.width(); |
| 910 | | } |
| 911 | | xscale = $obj.width() / nw; |
| 912 | | yscale = $obj.height() / nh; |
| 913 | | $obj.width(nw).height(nh); |
| 914 | | }; |
| 915 | | /*}}}*/ |
| 916 | | function unscale(c)/*{{{*/ |
| 917 | | { |
| 918 | | return { |
| 919 | | x: parseInt(c.x * xscale), y: parseInt(c.y * yscale), |
| 920 | | x2: parseInt(c.x2 * xscale), y2: parseInt(c.y2 * yscale), |
| 921 | | w: parseInt(c.w * xscale), h: parseInt(c.h * yscale) |
| 922 | | }; |
| 923 | | }; |
| 924 | | /*}}}*/ |
| 925 | | function doneSelect(pos)/*{{{*/ |
| 926 | | { |
| 927 | | var c = Coords.getFixed(); |
| 928 | | if (c.w > options.minSelect[0] && c.h > options.minSelect[1]) |
| 929 | | { |
| 930 | | Selection.enableHandles(); |
| 931 | | Selection.done(); |
| 932 | | } |
| 933 | | else |
| 934 | | { |
| 935 | | Selection.release(); |
| 936 | | } |
| 937 | | Tracker.setCursor( options.allowSelect?'crosshair':'default' ); |
| 938 | | }; |
| 939 | | /*}}}*/ |
| 940 | | function newSelection(e)/*{{{*/ |
| 941 | | { |
| 942 | | if (options.disabled) return false; |
| 943 | | if (!options.allowSelect) return false; |
| 944 | | btndown = true; |
| 945 | | docOffset = getPos($img); |
| 946 | | Selection.disableHandles(); |
| 947 | | myCursor('crosshair'); |
| 948 | | var pos = mouseAbs(e); |
| 949 | | Coords.setPressed(pos); |
| 950 | | Tracker.activateHandlers(selectDrag,doneSelect); |
| 951 | | KeyManager.watchKeys(); |
| 952 | | Selection.update(); |
| | 1217 | $img.before($trk); |
| | 1218 | return { |
| | 1219 | activateHandlers: activateHandlers, |
| | 1220 | setCursor: setCursor |
| | 1221 | }; |
| | 1222 | }()); |
| | 1223 | //}}} |
| | 1224 | // KeyManager Module {{{ |
| | 1225 | var KeyManager = (function () { |
| | 1226 | var $keymgr = $('<input type="radio" />').css({ |
| | 1227 | position: 'fixed', |
| | 1228 | left: '-120px', |
| | 1229 | width: '12px' |
| | 1230 | }), |
| | 1231 | $keywrap = $('<div />').css({ |
| | 1232 | position: 'absolute', |
| | 1233 | overflow: 'hidden' |
| | 1234 | }).append($keymgr); |
| 954 | | e.stopPropagation(); |
| 955 | | e.preventDefault(); |
| 956 | | return false; |
| 957 | | }; |
| 958 | | /*}}}*/ |
| 959 | | function selectDrag(pos)/*{{{*/ |
| 960 | | { |
| 961 | | Coords.setCurrent(pos); |
| 962 | | Selection.update(); |
| 963 | | }; |
| 964 | | /*}}}*/ |
| 965 | | function newTracker() |
| 966 | | { |
| 967 | | var trk = $('<div></div>').addClass(cssClass('tracker')); |
| 968 | | $.browser.msie && trk.css({ opacity: 0, backgroundColor: 'white' }); |
| 969 | | return trk; |
| 970 | | }; |
| | 1236 | function watchKeys() //{{{ |
| | 1237 | { |
| | 1238 | if (options.keySupport) { |
| | 1239 | $keymgr.show(); |
| | 1240 | $keymgr.focus(); |
| | 1241 | } |
| | 1242 | } |
| | 1243 | //}}} |
| | 1244 | function onBlur(e) //{{{ |
| | 1245 | { |
| | 1246 | $keymgr.hide(); |
| | 1247 | } |
| | 1248 | //}}} |
| | 1249 | function doNudge(e, x, y) //{{{ |
| | 1250 | { |
| | 1251 | if (options.allowMove) { |
| | 1252 | Coords.moveOffset([x, y]); |
| | 1253 | Selection.updateVisible(true); |
| | 1254 | } |
| | 1255 | e.preventDefault(); |
| | 1256 | e.stopPropagation(); |
| | 1257 | } |
| | 1258 | //}}} |
| | 1259 | function parseKey(e) //{{{ |
| | 1260 | { |
| | 1261 | if (e.ctrlKey || e.metaKey) { |
| | 1262 | return true; |
| | 1263 | } |
| | 1264 | shift_down = e.shiftKey ? true : false; |
| | 1265 | var nudge = shift_down ? 10 : 1; |
| 984 | | var animto = Coords.flipCoords(x1,y1,x2,y2); |
| 985 | | var c = Coords.getFixed(); |
| 986 | | var animat = initcr = [ c.x, c.y, c.x2, c.y2 ]; |
| 987 | | var interv = options.animationDelay; |
| | 1291 | if (options.keySupport) { |
| | 1292 | $keymgr.keydown(parseKey).blur(onBlur); |
| | 1293 | if (ie6mode || !options.fixedSupport) { |
| | 1294 | $keymgr.css({ |
| | 1295 | position: 'absolute', |
| | 1296 | left: '-20px' |
| | 1297 | }); |
| | 1298 | $keywrap.append($keymgr).insertBefore($img); |
| | 1299 | } else { |
| | 1300 | $keymgr.insertBefore($img); |
| | 1301 | } |
| | 1302 | } |
| 1008 | | animat[0] = x + ((pcent / 100) * ix1); |
| 1009 | | animat[1] = y + ((pcent / 100) * iy1); |
| 1010 | | animat[2] = x2 + ((pcent / 100) * ix2); |
| 1011 | | animat[3] = y2 + ((pcent / 100) * iy2); |
| | 1328 | var animto = Coords.flipCoords(x1, y1, x2, y2), |
| | 1329 | c = Coords.getFixed(), |
| | 1330 | initcr = [c.x, c.y, c.x2, c.y2], |
| | 1331 | animat = initcr, |
| | 1332 | interv = options.animationDelay, |
| | 1333 | ix1 = animto[0] - initcr[0], |
| | 1334 | iy1 = animto[1] - initcr[1], |
| | 1335 | ix2 = animto[2] - initcr[2], |
| | 1336 | iy2 = animto[3] - initcr[3], |
| | 1337 | pcent = 0, |
| | 1338 | velocity = options.swingSpeed; |
| 1025 | | animateStart(); |
| 1026 | | }; |
| 1027 | | /*}}}*/ |
| 1028 | | function setSelect(rect)//{{{ |
| 1029 | | { |
| 1030 | | setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]); |
| 1031 | | }; |
| 1032 | | //}}} |
| 1033 | | function setSelectRaw(l) /*{{{*/ |
| 1034 | | { |
| 1035 | | Coords.setPressed([l[0],l[1]]); |
| 1036 | | Coords.setCurrent([l[2],l[3]]); |
| 1037 | | Selection.update(); |
| 1038 | | }; |
| 1039 | | /*}}}*/ |
| 1040 | | function setOptions(opt)/*{{{*/ |
| 1041 | | { |
| 1042 | | if (typeof(opt) != 'object') opt = { }; |
| 1043 | | options = $.extend(options,opt); |
| | 1360 | if (pcent >= 99.8) { |
| | 1361 | pcent = 100; |
| | 1362 | } |
| | 1363 | if (pcent < 100) { |
| | 1364 | setSelectRaw(animat); |
| | 1365 | queueAnimator(); |
| | 1366 | } else { |
| | 1367 | Selection.done(); |
| | 1368 | if (typeof(callback) === 'function') { |
| | 1369 | callback.call(api); |
| | 1370 | } |
| | 1371 | } |
| | 1372 | }; |
| | 1373 | }()); |
| | 1374 | queueAnimator(); |
| | 1375 | } |
| | 1376 | //}}} |
| | 1377 | function setSelect(rect) //{{{ |
| | 1378 | { |
| | 1379 | setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]); |
| | 1380 | options.onSelect.call(api, unscale(Coords.getFixed())); |
| | 1381 | Selection.enableHandles(); |
| | 1382 | } |
| | 1383 | //}}} |
| | 1384 | function setSelectRaw(l) //{{{ |
| | 1385 | { |
| | 1386 | Coords.setPressed([l[0], l[1]]); |
| | 1387 | Coords.setCurrent([l[2], l[3]]); |
| | 1388 | Selection.update(); |
| | 1389 | } |
| | 1390 | //}}} |
| | 1391 | function tellSelect() //{{{ |
| | 1392 | { |
| | 1393 | return unscale(Coords.getFixed()); |
| | 1394 | } |
| | 1395 | //}}} |
| | 1396 | function tellScaled() //{{{ |
| | 1397 | { |
| | 1398 | return Coords.getFixed(); |
| | 1399 | } |
| | 1400 | //}}} |
| | 1401 | function setOptionsNew(opt) //{{{ |
| | 1402 | { |
| | 1403 | setOptions(opt); |
| | 1404 | interfaceUpdate(); |
| | 1405 | } |
| | 1406 | //}}} |
| | 1407 | function disableCrop() //{{{ |
| | 1408 | { |
| | 1409 | options.disabled = true; |
| | 1410 | Selection.disableHandles(); |
| | 1411 | Selection.setCursor('default'); |
| | 1412 | Tracker.setCursor('default'); |
| | 1413 | } |
| | 1414 | //}}} |
| | 1415 | function enableCrop() //{{{ |
| | 1416 | { |
| | 1417 | options.disabled = false; |
| | 1418 | interfaceUpdate(); |
| | 1419 | } |
| | 1420 | //}}} |
| | 1421 | function cancelCrop() //{{{ |
| | 1422 | { |
| | 1423 | Selection.done(); |
| | 1424 | Tracker.activateHandlers(null, null); |
| | 1425 | } |
| | 1426 | //}}} |
| | 1427 | function destroy() //{{{ |
| | 1428 | { |
| | 1429 | $div.remove(); |
| | 1430 | $origimg.show(); |
| | 1431 | $(obj).removeData('Jcrop'); |
| | 1432 | } |
| | 1433 | //}}} |
| | 1434 | function setImage(src, callback) //{{{ |
| | 1435 | { |
| | 1436 | Selection.release(); |
| | 1437 | disableCrop(); |
| | 1438 | var img = new Image(); |
| | 1439 | img.onload = function () { |
| | 1440 | var iw = img.width; |
| | 1441 | var ih = img.height; |
| | 1442 | var bw = options.boxWidth; |
| | 1443 | var bh = options.boxHeight; |
| | 1444 | $img.width(iw).height(ih); |
| | 1445 | $img.attr('src', src); |
| | 1446 | $img2.attr('src', src); |
| | 1447 | presize($img, bw, bh); |
| | 1448 | boundx = $img.width(); |
| | 1449 | boundy = $img.height(); |
| | 1450 | $img2.width(boundx).height(boundy); |
| | 1451 | $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2)); |
| | 1452 | $div.width(boundx).height(boundy); |
| | 1453 | Shade.resize(boundx,boundy); |
| | 1454 | enableCrop(); |
| 1045 | | if (typeof(options.onChange)!=='function') |
| 1046 | | options.onChange = function() { }; |
| | 1456 | if (typeof(callback) === 'function') { |
| | 1457 | callback.call(api); |
| | 1458 | } |
| | 1459 | }; |
| | 1460 | img.src = src; |
| | 1461 | } |
| | 1462 | //}}} |
| | 1463 | function colorChangeMacro($obj,color,now) { |
| | 1464 | var mycolor = color || options.bgColor; |
| | 1465 | if (options.bgFade && supportsColorFade() && options.fadeTime && !now) { |
| | 1466 | $obj.animate({ |
| | 1467 | backgroundColor: mycolor |
| | 1468 | }, { |
| | 1469 | queue: false, |
| | 1470 | duration: options.fadeTime |
| | 1471 | }); |
| | 1472 | } else { |
| | 1473 | $obj.css('backgroundColor', mycolor); |
| | 1474 | } |
| | 1475 | } |
| | 1476 | function interfaceUpdate(alt) //{{{ |
| | 1477 | // This method tweaks the interface based on options object. |
| | 1478 | // Called when options are changed and at end of initialization. |
| | 1479 | { |
| | 1480 | if (options.allowResize) { |
| | 1481 | if (alt) { |
| | 1482 | Selection.enableOnly(); |
| | 1483 | } else { |
| | 1484 | Selection.enableHandles(); |
| | 1485 | } |
| | 1486 | } else { |
| | 1487 | Selection.disableHandles(); |
| | 1488 | } |
| 1051 | | }; |
| 1052 | | /*}}}*/ |
| 1053 | | function tellSelect()/*{{{*/ |
| 1054 | | { |
| 1055 | | return unscale(Coords.getFixed()); |
| 1056 | | }; |
| 1057 | | /*}}}*/ |
| 1058 | | function tellScaled()/*{{{*/ |
| 1059 | | { |
| 1060 | | return Coords.getFixed(); |
| 1061 | | }; |
| 1062 | | /*}}}*/ |
| 1063 | | function setOptionsNew(opt)/*{{{*/ |
| 1064 | | { |
| 1065 | | setOptions(opt); |
| 1066 | | interfaceUpdate(); |
| 1067 | | }; |
| 1068 | | /*}}}*/ |
| 1069 | | function disableCrop()//{{{ |
| 1070 | | { |
| 1071 | | options.disabled = true; |
| 1072 | | Selection.disableHandles(); |
| 1073 | | Selection.setCursor('default'); |
| 1074 | | Tracker.setCursor('default'); |
| 1075 | | }; |
| 1076 | | //}}} |
| 1077 | | function enableCrop()//{{{ |
| 1078 | | { |
| 1079 | | options.disabled = false; |
| 1080 | | interfaceUpdate(); |
| 1081 | | }; |
| 1082 | | //}}} |
| 1083 | | function cancelCrop()//{{{ |
| 1084 | | { |
| 1085 | | Selection.done(); |
| 1086 | | Tracker.activateHandlers(null,null); |
| 1087 | | }; |
| 1088 | | //}}} |
| 1089 | | function destroy()//{{{ |
| 1090 | | { |
| 1091 | | $div.remove(); |
| 1092 | | $origimg.show(); |
| 1093 | | }; |
| 1094 | | //}}} |
| | 1493 | if (options.hasOwnProperty('trueSize')) { |
| | 1494 | xscale = options.trueSize[0] / boundx; |
| | 1495 | yscale = options.trueSize[1] / boundy; |
| | 1496 | } |
| 1161 | | $origimg.data('Jcrop',api); |
| 1162 | | return api; |
| 1163 | | }; |
| | 1582 | $origimg.data('Jcrop', api); |
| | 1583 | return api; |
| | 1584 | }; |
| | 1585 | $.fn.Jcrop = function (options, callback) //{{{ |
| | 1586 | { |
| | 1587 | var api; |
| | 1588 | // Iterate over each object, attach Jcrop |
| | 1589 | this.each(function () { |
| | 1590 | // If we've already attached to this object |
| | 1591 | if ($(this).data('Jcrop')) { |
| | 1592 | // The API can be requested this way (undocumented) |
| | 1593 | if (options === 'api') return $(this).data('Jcrop'); |
| | 1594 | // Otherwise, we just reset the options... |
| | 1595 | else $(this).data('Jcrop').setOptions(options); |
| | 1596 | } |
| | 1597 | // If we haven't been attached, preload and attach |
| | 1598 | else { |
| | 1599 | if (this.tagName == 'IMG') |
| | 1600 | $.Jcrop.Loader(this,function(){ |
| | 1601 | $(this).css({display:'block',visibility:'hidden'}); |
| | 1602 | api = $.Jcrop(this, options); |
| | 1603 | if ($.isFunction(callback)) callback.call(api); |
| | 1604 | }); |
| | 1605 | else { |
| | 1606 | $(this).css({display:'block',visibility:'hidden'}); |
| | 1607 | api = $.Jcrop(this, options); |
| | 1608 | if ($.isFunction(callback)) callback.call(api); |
| | 1609 | } |
| | 1610 | } |
| | 1611 | }); |
| 1177 | | // Iterate over each object, attach Jcrop |
| 1178 | | this.each(function() |
| 1179 | | { |
| 1180 | | // If we've already attached to this object |
| 1181 | | if ($(this).data('Jcrop')) |
| 1182 | | { |
| 1183 | | // The API can be requested this way (undocumented) |
| 1184 | | if (options == 'api') return $(this).data('Jcrop'); |
| 1185 | | // Otherwise, we just reset the options... |
| 1186 | | else $(this).data('Jcrop').setOptions(options); |
| 1187 | | } |
| 1188 | | // If we haven't been attached, preload and attach |
| 1189 | | else attachWhenDone(this); |
| 1190 | | }); |
| | 1619 | $.Jcrop.Loader = function(imgobj,success,error){ |
| | 1620 | var $img = $(imgobj), img = $img[0]; |
| 1197 | | })(jQuery); |
| | 1630 | $img |
| | 1631 | .bind('load.jcloader',completeCheck) |
| | 1632 | .bind('error.jcloader',function(e){ |
| | 1633 | $img.unbind('.jcloader'); |
| | 1634 | if ($.isFunction(error)) error.call(img); |
| | 1635 | }); |
| | 1636 | |
| | 1637 | if (img.complete && $.isFunction(success)){ |
| | 1638 | $img.unbind('.jcloader'); |
| | 1639 | success.call(img); |
| | 1640 | } |
| | 1641 | }; |
| | 1642 | |
| | 1643 | //}}} |
| | 1644 | // Global Defaults {{{ |
| | 1645 | $.Jcrop.defaults = { |
| | 1646 | |
| | 1647 | // Basic Settings |
| | 1648 | allowSelect: true, |
| | 1649 | allowMove: true, |
| | 1650 | allowResize: true, |
| | 1651 | |
| | 1652 | trackDocument: true, |
| | 1653 | |
| | 1654 | // Styling Options |
| | 1655 | baseClass: 'jcrop', |
| | 1656 | addClass: null, |
| | 1657 | bgColor: 'black', |
| | 1658 | bgOpacity: 0.6, |
| | 1659 | bgFade: false, |
| | 1660 | borderOpacity: 0.4, |
| | 1661 | handleOpacity: 0.5, |
| | 1662 | handleSize: 7, |
| | 1663 | |
| | 1664 | aspectRatio: 0, |
| | 1665 | keySupport: true, |
| | 1666 | createHandles: ['n','s','e','w','nw','ne','se','sw'], |
| | 1667 | createDragbars: ['n','s','e','w'], |
| | 1668 | createBorders: ['n','s','e','w'], |
| | 1669 | drawBorders: true, |
| | 1670 | dragEdges: true, |
| | 1671 | fixedSupport: true, |
| | 1672 | touchSupport: null, |
| | 1673 | |
| | 1674 | shade: null, |
| | 1675 | |
| | 1676 | boxWidth: 0, |
| | 1677 | boxHeight: 0, |
| | 1678 | boundary: 2, |
| | 1679 | fadeTime: 400, |
| | 1680 | animationDelay: 20, |
| | 1681 | swingSpeed: 3, |
| | 1682 | |
| | 1683 | minSelect: [0, 0], |
| | 1684 | maxSize: [0, 0], |
| | 1685 | minSize: [0, 0], |
| | 1686 | |
| | 1687 | // Callbacks / Event Handlers |
| | 1688 | onChange: function () {}, |
| | 1689 | onSelect: function () {}, |
| | 1690 | onDblClick: function () {}, |
| | 1691 | onRelease: function () {} |
| | 1692 | }; |
| | 1693 | |
| | 1694 | // }}} |
| | 1695 | }(jQuery)); |