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)); |