papermill 1.3.6 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1197 @@
1
+ /**
2
+ * jquery.Jcrop.js v0.9.8
3
+ * jQuery Image Cropping Plugin
4
+ * @author Kelly Hallman <khallman@gmail.com>
5
+ * Copyright (c) 2008-2009 Kelly Hallman - released under MIT License {{{
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person
8
+ * obtaining a copy of this software and associated documentation
9
+ * files (the "Software"), to deal in the Software without
10
+ * restriction, including without limitation the rights to use,
11
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the
13
+ * Software is furnished to do so, subject to the following
14
+ * conditions:
15
+
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26
+ * OTHER DEALINGS IN THE SOFTWARE.
27
+
28
+ * }}}
29
+ */
30
+
31
+ (function($) {
32
+
33
+ $.Jcrop = function(obj,opt)
34
+ {
35
+ // Initialization {{{
36
+
37
+ // Sanitize some options {{{
38
+ var obj = obj, opt = opt;
39
+
40
+ if (typeof(obj) !== 'object') obj = $(obj)[0];
41
+ if (typeof(opt) !== 'object') opt = { };
42
+
43
+ // Some on-the-fly fixes for MSIE...sigh
44
+ if (!('trackDocument' in opt))
45
+ {
46
+ opt.trackDocument = $.browser.msie ? false : true;
47
+ if ($.browser.msie && $.browser.version.split('.')[0] == '8')
48
+ opt.trackDocument = true;
49
+ }
50
+
51
+ if (!('keySupport' in opt))
52
+ opt.keySupport = $.browser.msie ? false : true;
53
+
54
+ // }}}
55
+ // Extend the default options {{{
56
+ var defaults = {
57
+
58
+ // Basic Settings
59
+ trackDocument: false,
60
+ baseClass: 'jcrop',
61
+ addClass: null,
62
+
63
+ // Styling Options
64
+ bgColor: 'black',
65
+ bgOpacity: .6,
66
+ borderOpacity: .4,
67
+ handleOpacity: .5,
68
+
69
+ handlePad: 5,
70
+ handleSize: 9,
71
+ handleOffset: 5,
72
+ edgeMargin: 14,
73
+
74
+ aspectRatio: 0,
75
+ keySupport: true,
76
+ cornerHandles: true,
77
+ sideHandles: true,
78
+ drawBorders: true,
79
+ dragEdges: true,
80
+
81
+ boxWidth: 0,
82
+ boxHeight: 0,
83
+
84
+ boundary: 8,
85
+ animationDelay: 20,
86
+ swingSpeed: 3,
87
+
88
+ allowSelect: true,
89
+ allowMove: true,
90
+ allowResize: true,
91
+
92
+ minSelect: [ 0, 0 ],
93
+ maxSize: [ 0, 0 ],
94
+ minSize: [ 0, 0 ],
95
+
96
+ // Callbacks / Event Handlers
97
+ onChange: function() { },
98
+ onSelect: function() { }
99
+
100
+ };
101
+ var options = defaults;
102
+ setOptions(opt);
103
+
104
+ // }}}
105
+ // Initialize some jQuery objects {{{
106
+
107
+ var $origimg = $(obj);
108
+ var $img = $origimg.clone().removeAttr('id').css({ position: 'absolute' });
109
+
110
+ $img.width($origimg.width());
111
+ $img.height($origimg.height());
112
+ $origimg.after($img).hide();
113
+
114
+ presize($img,options.boxWidth,options.boxHeight);
115
+
116
+ var boundx = $img.width(),
117
+ boundy = $img.height(),
118
+
119
+ $div = $('<div />')
120
+ .width(boundx).height(boundy)
121
+ .addClass(cssClass('holder'))
122
+ .css({
123
+ position: 'relative',
124
+ backgroundColor: options.bgColor
125
+ }).insertAfter($origimg).append($img);
126
+ ;
127
+
128
+ if (options.addClass) $div.addClass(options.addClass);
129
+ //$img.wrap($div);
130
+
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
+ ;/*}}}*/
157
+
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 {{{
165
+
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;
172
+
173
+ // }}}
174
+
175
+
176
+ // }}}
177
+ // Internal Modules {{{
178
+
179
+ var Coords = function()/*{{{*/
180
+ {
181
+ var x1 = 0, y1 = 0, x2 = 0, y2 = 0, ox, oy;
182
+
183
+ function setPressed(pos)/*{{{*/
184
+ {
185
+ var pos = rebound(pos);
186
+ x2 = x1 = pos[0];
187
+ y2 = y1 = pos[1];
188
+ };
189
+ /*}}}*/
190
+ function setCurrent(pos)/*{{{*/
191
+ {
192
+ var pos = rebound(pos);
193
+ ox = pos[0] - x2;
194
+ oy = pos[1] - y2;
195
+ x2 = pos[0];
196
+ y2 = pos[1];
197
+ };
198
+ /*}}}*/
199
+ function getOffset()/*{{{*/
200
+ {
201
+ return [ ox, oy ];
202
+ };
203
+ /*}}}*/
204
+ function moveOffset(offset)/*{{{*/
205
+ {
206
+ var ox = offset[0], oy = offset[1];
207
+
208
+ if (0 > x1 + ox) ox -= ox + x1;
209
+ if (0 > y1 + oy) oy -= oy + y1;
210
+
211
+ if (boundy < y2 + oy) oy += boundy - (y2 + oy);
212
+ if (boundx < x2 + ox) ox += boundx - (x2 + ox);
213
+
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;
255
+
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
+ }
287
+
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
+ }
312
+
313
+ if(xx < 0) {
314
+ x1 -= xx;
315
+ xx = 0;
316
+ } else if (xx > boundx) {
317
+ x1 -= xx - boundx;
318
+ xx = boundx;
319
+ }
320
+
321
+ if(yy < 0) {
322
+ y1 -= yy;
323
+ yy = 0;
324
+ } else if (yy > boundy) {
325
+ y1 -= yy - boundy;
326
+ yy = boundy;
327
+ }
328
+
329
+ return last = makeObj(flipCoords(x1,y1,xx,yy));
330
+ };
331
+ /*}}}*/
332
+ function rebound(p)/*{{{*/
333
+ {
334
+ if (p[0] < 0) p[0] = 0;
335
+ if (p[1] < 0) p[1] = 0;
336
+
337
+ if (p[0] > boundx) p[0] = boundx;
338
+ if (p[1] > boundy) p[1] = boundy;
339
+
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;
363
+
364
+ if (xlimit && (Math.abs(xsize) > xlimit))
365
+ x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit);
366
+ if (ylimit && (Math.abs(ysize) > ylimit))
367
+ y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit);
368
+
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);
373
+
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; }
382
+
383
+ return makeObj(flipCoords(x1,y1,x2,y2));
384
+ };
385
+ /*}}}*/
386
+ function makeObj(a)/*{{{*/
387
+ {
388
+ return { x: a[0], y: a[1], x2: a[2], y2: a[3],
389
+ w: a[2] - a[0], h: a[3] - a[1] };
390
+ };
391
+ /*}}}*/
392
+
393
+ return {
394
+ flipCoords: flipCoords,
395
+ setPressed: setPressed,
396
+ setCurrent: setCurrent,
397
+ getOffset: getOffset,
398
+ moveOffset: moveOffset,
399
+ getCorner: getCorner,
400
+ getFixed: getFixed
401
+ };
402
+ }();
403
+
404
+ /*}}}*/
405
+ var Selection = function()/*{{{*/
406
+ {
407
+ var start, end, dragmode, awake, hdep = 370;
408
+ var borders = { };
409
+ var handle = { };
410
+ var seehandles = false;
411
+ var hhs = options.handleOffset;
412
+
413
+ /* Insert draggable elements {{{*/
414
+
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
+ }
425
+
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
+ }
433
+
434
+ // Insert side handles
435
+ options.sideHandles &&
436
+ createHandles(['n','s','e','w']);
437
+
438
+ // Insert corner handles
439
+ options.cornerHandles &&
440
+ createHandles(['sw','nw','ne','se']);
441
+
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;
480
+
481
+ switch(ord)
482
+ {
483
+ case 'n': case 's': w = pct(100); break;
484
+ case 'e': case 'w': h = pct(100); break;
485
+ }
486
+
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;
504
+
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) });
510
+
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) });
515
+
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();
535
+
536
+ Coords.setPressed([c.x,c.y]);
537
+ Coords.setCurrent([c.x2,c.y2]);
538
+
539
+ updateVisible();
540
+ };
541
+ /*}}}*/
542
+
543
+ // Internal Methods
544
+ function updateVisible()/*{{{*/
545
+ { if (awake) return update(); };
546
+ /*}}}*/
547
+ function update()/*{{{*/
548
+ {
549
+ var c = Coords.getFixed();
550
+
551
+ resize(c.w,c.h);
552
+ moveto(c.x,c.y);
553
+
554
+ options.drawBorders &&
555
+ borders['right'].css({ left: px(c.w-1) }) &&
556
+ borders['bottom'].css({ top: px(c.h-1) });
557
+
558
+ seehandles && moveHandles(c);
559
+ awake || show();
560
+
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
+ /*}}}*/
616
+
617
+ var $track = newTracker().mousedown(createDragger('move'))
618
+ .css({ cursor: 'move', position: 'absolute', zIndex: 360 })
619
+
620
+ $img_holder.append($track);
621
+ disableHandles();
622
+
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;
643
+
644
+ if (!trackDoc)
645
+ {
646
+ $trk
647
+ .mousemove(trackMove)
648
+ .mouseup(trackUp)
649
+ .mouseout(trackUp)
650
+ ;
651
+ }
652
+
653
+ function toFront()/*{{{*/
654
+ {
655
+ $trk.css({zIndex:450});
656
+ if (trackDoc)
657
+ {
658
+ $(document)
659
+ .mousemove(trackMove)
660
+ .mouseup(trackUp)
661
+ ;
662
+ }
663
+ }
664
+ /*}}}*/
665
+ function toBack()/*{{{*/
666
+ {
667
+ $trk.css({zIndex:290});
668
+ if (trackDoc)
669
+ {
670
+ $(document)
671
+ .unbind('mousemove',trackMove)
672
+ .unbind('mouseup',trackUp)
673
+ ;
674
+ }
675
+ }
676
+ /*}}}*/
677
+ function trackMove(e)/*{{{*/
678
+ {
679
+ onMove(mouseAbs(e));
680
+ };
681
+ /*}}}*/
682
+ function trackUp(e)/*{{{*/
683
+ {
684
+ e.preventDefault();
685
+ e.stopPropagation();
686
+
687
+ if (btndown)
688
+ {
689
+ btndown = false;
690
+
691
+ onDone(mouseAbs(e));
692
+ options.onSelect(unscale(Coords.getFixed()));
693
+ toBack();
694
+ onMove = function() { };
695
+ onDone = function() { };
696
+ }
697
+
698
+ return false;
699
+ };
700
+ /*}}}*/
701
+
702
+ function activateHandlers(move,done)/* {{{ */
703
+ {
704
+ btndown = true;
705
+ onMove = move;
706
+ onDone = done;
707
+ toFront();
708
+ return false;
709
+ };
710
+ /* }}} */
711
+
712
+ function setCursor(t) { $trk.css('cursor',t); };
713
+
714
+ $img.before($trk);
715
+ return {
716
+ activateHandlers: activateHandlers,
717
+ setCursor: setCursor
718
+ };
719
+ }();
720
+ /*}}}*/
721
+ var KeyManager = function()/*{{{*/
722
+ {
723
+ var $keymgr = $('<input type="radio" />')
724
+ .css({ position: 'absolute', left: '-30px' })
725
+ .keypress(parseKey)
726
+ .blur(onBlur),
727
+
728
+ $keywrap = $('<div />')
729
+ .css({
730
+ position: 'absolute',
731
+ overflow: 'hidden'
732
+ })
733
+ .append($keymgr)
734
+ ;
735
+
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;
771
+
772
+ case 27: Selection.release(); break;
773
+
774
+ case 9: return true;
775
+ }
776
+
777
+ return nothing(e);
778
+ };
779
+ /*}}}*/
780
+
781
+ if (options.keySupport) $keywrap.insertBefore($img);
782
+ return {
783
+ watchKeys: watchKeys
784
+ };
785
+ }();
786
+ /*}}}*/
787
+
788
+ // }}}
789
+ // Internal Methods {{{
790
+
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');
820
+
821
+ if (mode == 'move')
822
+ return Tracker.activateHandlers(createMover(pos), doneSelect);
823
+
824
+ var fc = Coords.getFixed();
825
+ var opp = oppLockCorner(mode);
826
+ var opc = Coords.getCorner(oppLockCorner(opp));
827
+
828
+ Coords.setPressed(Coords.getCorner(opp));
829
+ Coords.setCurrent(opc);
830
+
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();
860
+
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();
953
+
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
+ };
971
+
972
+ // }}}
973
+ // API methods {{{
974
+
975
+ function animateTo(a)/*{{{*/
976
+ {
977
+ var x1 = a[0] / xscale,
978
+ y1 = a[1] / yscale,
979
+ x2 = a[2] / xscale,
980
+ y2 = a[3] / yscale;
981
+
982
+ if (animating) return;
983
+
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;
988
+
989
+ var x = animat[0];
990
+ var y = animat[1];
991
+ var x2 = animat[2];
992
+ var y2 = animat[3];
993
+ var ix1 = animto[0] - initcr[0];
994
+ var iy1 = animto[1] - initcr[1];
995
+ var ix2 = animto[2] - initcr[2];
996
+ var iy2 = animto[3] - initcr[3];
997
+ var pcent = 0;
998
+ var velocity = options.swingSpeed;
999
+
1000
+ Selection.animMode(true);
1001
+
1002
+ var animator = function()
1003
+ {
1004
+ return function()
1005
+ {
1006
+ pcent += (100 - pcent) / velocity;
1007
+
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);
1012
+
1013
+ if (pcent < 100) animateStart();
1014
+ else Selection.done();
1015
+
1016
+ if (pcent >= 99.8) pcent = 100;
1017
+
1018
+ setSelectRaw(animat);
1019
+ };
1020
+ }();
1021
+
1022
+ function animateStart()
1023
+ { window.setTimeout(animator,interv); };
1024
+
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);
1044
+
1045
+ if (typeof(options.onChange)!=='function')
1046
+ options.onChange = function() { };
1047
+
1048
+ if (typeof(options.onSelect)!=='function')
1049
+ options.onSelect = function() { };
1050
+
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
+ //}}}
1095
+
1096
+ function interfaceUpdate(alt)//{{{
1097
+ // This method tweaks the interface based on options object.
1098
+ // Called when options are changed and at end of initialization.
1099
+ {
1100
+ options.allowResize ?
1101
+ alt?Selection.enableOnly():Selection.enableHandles():
1102
+ Selection.disableHandles();
1103
+
1104
+ Tracker.setCursor( options.allowSelect? 'crosshair': 'default' );
1105
+ Selection.setCursor( options.allowMove? 'move': 'default' );
1106
+
1107
+ $div.css('backgroundColor',options.bgColor);
1108
+
1109
+ if ('setSelect' in options) {
1110
+ setSelect(opt.setSelect);
1111
+ Selection.done();
1112
+ delete(options.setSelect);
1113
+ }
1114
+
1115
+ if ('trueSize' in options) {
1116
+ xscale = options.trueSize[0] / boundx;
1117
+ yscale = options.trueSize[1] / boundy;
1118
+ }
1119
+
1120
+ xlimit = options.maxSize[0] || 0;
1121
+ ylimit = options.maxSize[1] || 0;
1122
+ xmin = options.minSize[0] || 0;
1123
+ ymin = options.minSize[1] || 0;
1124
+
1125
+ if ('outerImage' in options)
1126
+ {
1127
+ $img.attr('src',options.outerImage);
1128
+ delete(options.outerImage);
1129
+ }
1130
+
1131
+ Selection.refresh();
1132
+ };
1133
+ //}}}
1134
+
1135
+ // }}}
1136
+
1137
+ $hdl_holder.hide();
1138
+ interfaceUpdate(true);
1139
+
1140
+ var api = {
1141
+ animateTo: animateTo,
1142
+ setSelect: setSelect,
1143
+ setOptions: setOptionsNew,
1144
+ tellSelect: tellSelect,
1145
+ tellScaled: tellScaled,
1146
+
1147
+ disable: disableCrop,
1148
+ enable: enableCrop,
1149
+ cancel: cancelCrop,
1150
+
1151
+ focus: KeyManager.watchKeys,
1152
+
1153
+ getBounds: function() { return [ boundx * xscale, boundy * yscale ]; },
1154
+ getWidgetSize: function() { return [ boundx, boundy ]; },
1155
+
1156
+ release: Selection.release,
1157
+ destroy: destroy
1158
+
1159
+ };
1160
+
1161
+ $origimg.data('Jcrop',api);
1162
+ return api;
1163
+ };
1164
+
1165
+ $.fn.Jcrop = function(options)/*{{{*/
1166
+ {
1167
+ function attachWhenDone(from)/*{{{*/
1168
+ {
1169
+ var loadsrc = options.useImg || from.src;
1170
+ var img = new Image();
1171
+ img.onload = function() { $.Jcrop(from,options); };
1172
+ img.src = loadsrc;
1173
+ };
1174
+ /*}}}*/
1175
+ if (typeof(options) !== 'object') options = { };
1176
+
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
+ });
1191
+
1192
+ // Return "this" so we're chainable a la jQuery plugin-style!
1193
+ return this;
1194
+ };
1195
+ /*}}}*/
1196
+
1197
+ })(jQuery);