jcrop-rails 1.0.2 → 1.0.3

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,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2FkZDhhMWI5ZGE5NzA2Y2MzYjg4YWRiOWM1NDA1OGY3NDhhZWEwMQ==
5
+ data.tar.gz: !binary |-
6
+ ZThhNTEzM2NjNGMzMmJkZTJhOTc3MGVlN2NlNzI2N2JjMTkwODA5Nw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ Yzc5ZTk0YzFlNWE5MTNmYWZmYTAzZGQ5MTE2M2U4OTgwZWRiYTIyZGNjMWI2
10
+ NWFlMGRjNGExMzA0ZjQ5ODkxZDY5YWE2MWE0NjJkM2M5YzBhZDA5NTNjZGEx
11
+ ZGJhMDgxOTYwYThkMDdjOTZmZTc1NGZhNTAwNTUwOGQ1ZDAyMDM=
12
+ data.tar.gz: !binary |-
13
+ NzBlOGU0NWUyZjFiNDEyMmI5ZWYxZjFjYzFhNDI2ODEyNTY0YjZkNTNjZjVh
14
+ ODdkZDY0ZTlmZWUzZTg3NGY3Y2JjMmUyOWE2NTA4ODEzOGE5YjkyMzU4ZDQ3
15
+ MjlkMGZhZGY4NDZhNjgwMGFkNWY1NmE4MDk3YWQwMDg1MjcyY2E=
data/Gemfile CHANGED
@@ -1,9 +1,3 @@
1
1
  source :gemcutter
2
2
 
3
- # Specify your gem's dependencies in jquery-rails.gemspec
4
- gemspec
5
- # Rails is already being pulled in through gemspec
6
- # gem "rails", :git => "git://github.com/rails/rails.git"
7
- gem "rack", :git => "git://github.com/rack/rack.git"
8
- gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git"
9
- gem "i18n", "0.6.0beta1"
3
+ gemspec
@@ -1,120 +1,94 @@
1
- GIT
2
- remote: git://github.com/rack/rack.git
3
- revision: a9beb476b27914794743d0677b327d5bafb5e8a3
4
- specs:
5
- rack (1.2.1)
6
-
7
- GIT
8
- remote: git://github.com/rails/rails.git
9
- revision: 2fbbd08616c25dc2931eca914349dd2161766f69
10
- specs:
11
- actionmailer (3.1.0.beta)
12
- actionpack (= 3.1.0.beta)
13
- mail (~> 2.3.0)
14
- actionpack (3.1.0.beta)
15
- activemodel (= 3.1.0.beta)
16
- activesupport (= 3.1.0.beta)
17
- builder (~> 3.0.0)
18
- erubis (~> 2.7.0)
19
- i18n (~> 0.6.0beta1)
20
- rack (~> 1.2.1)
21
- rack-cache (~> 1.0.0)
22
- rack-mount (~> 0.7.2)
23
- rack-test (~> 0.5.7)
24
- sprockets (~> 2.0.0.beta.2)
25
- tzinfo (~> 0.3.23)
26
- activemodel (3.1.0.beta)
27
- activesupport (= 3.1.0.beta)
28
- bcrypt-ruby (~> 2.1.4)
29
- builder (~> 3.0.0)
30
- i18n (~> 0.6.0beta1)
31
- activerecord (3.1.0.beta)
32
- activemodel (= 3.1.0.beta)
33
- activesupport (= 3.1.0.beta)
34
- arel (~> 2.1.0)
35
- tzinfo (~> 0.3.23)
36
- activeresource (3.1.0.beta)
37
- activemodel (= 3.1.0.beta)
38
- activesupport (= 3.1.0.beta)
39
- activesupport (3.1.0.beta)
40
- multi_json (~> 1.0.0)
41
- rails (3.1.0.beta)
42
- actionmailer (= 3.1.0.beta)
43
- actionpack (= 3.1.0.beta)
44
- activerecord (= 3.1.0.beta)
45
- activeresource (= 3.1.0.beta)
46
- activesupport (= 3.1.0.beta)
47
- bundler (~> 1.0)
48
- railties (= 3.1.0.beta)
49
- railties (3.1.0.beta)
50
- actionpack (= 3.1.0.beta)
51
- activesupport (= 3.1.0.beta)
52
- rack-ssl (~> 1.3.2)
53
- rake (>= 0.8.7)
54
- thor (~> 0.14.4)
55
-
56
- GIT
57
- remote: git://github.com/sstephenson/sprockets.git
58
- revision: c4800417792744c11eb1fb888bbe9a3a82859952
59
- specs:
60
- sprockets (2.0.0.beta.2)
61
- hike (~> 1.0)
62
- rack (~> 1.0)
63
- tilt (~> 1.0)
64
-
65
1
  PATH
66
2
  remote: .
67
3
  specs:
68
- jquery-rails (0.3)
69
- rails (~> 3.1)
70
- thor (~> 0.14.4)
4
+ jcrop-rails (1.0.2)
5
+ railties (~> 3.0)
6
+ thor (~> 0.14)
71
7
 
72
8
  GEM
73
9
  remote: http://rubygems.org/
74
10
  specs:
75
- addressable (2.2.4)
76
- arel (2.1.0)
77
- bcrypt-ruby (2.1.4)
11
+ actionmailer (3.2.2)
12
+ actionpack (= 3.2.2)
13
+ mail (~> 2.4.0)
14
+ actionpack (3.2.2)
15
+ activemodel (= 3.2.2)
16
+ activesupport (= 3.2.2)
17
+ builder (~> 3.0.0)
18
+ erubis (~> 2.7.0)
19
+ journey (~> 1.0.1)
20
+ rack (~> 1.4.0)
21
+ rack-cache (~> 1.1)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.1.2)
24
+ activemodel (3.2.2)
25
+ activesupport (= 3.2.2)
26
+ builder (~> 3.0.0)
27
+ activerecord (3.2.2)
28
+ activemodel (= 3.2.2)
29
+ activesupport (= 3.2.2)
30
+ arel (~> 3.0.2)
31
+ tzinfo (~> 0.3.29)
32
+ activeresource (3.2.2)
33
+ activemodel (= 3.2.2)
34
+ activesupport (= 3.2.2)
35
+ activesupport (3.2.2)
36
+ i18n (~> 0.6)
37
+ multi_json (~> 1.0)
38
+ arel (3.0.2)
78
39
  builder (3.0.0)
79
- crack (0.1.8)
80
40
  erubis (2.7.0)
81
- hike (1.0.0)
82
- i18n (0.6.0beta1)
83
- mail (2.3.0)
41
+ hike (1.2.1)
42
+ i18n (0.6.0)
43
+ journey (1.0.3)
44
+ json (1.6.5)
45
+ mail (2.4.4)
84
46
  i18n (>= 0.4.0)
85
47
  mime-types (~> 1.16)
86
48
  treetop (~> 1.4.8)
87
- mime-types (1.16)
88
- multi_json (1.0.0)
89
- polyglot (0.3.1)
90
- rack-cache (1.0.1)
49
+ mime-types (1.17.2)
50
+ multi_json (1.1.0)
51
+ polyglot (0.3.3)
52
+ rack (1.4.1)
53
+ rack-cache (1.2)
91
54
  rack (>= 0.4)
92
- rack-mount (0.7.2)
93
- rack (>= 1.0.0)
94
55
  rack-ssl (1.3.2)
95
56
  rack
96
- rack-test (0.5.7)
57
+ rack-test (0.6.1)
97
58
  rack (>= 1.0)
98
- rake (0.8.7)
99
- rspec (1.3.1)
59
+ rails (3.2.2)
60
+ actionmailer (= 3.2.2)
61
+ actionpack (= 3.2.2)
62
+ activerecord (= 3.2.2)
63
+ activeresource (= 3.2.2)
64
+ activesupport (= 3.2.2)
65
+ bundler (~> 1.0)
66
+ railties (= 3.2.2)
67
+ railties (3.2.2)
68
+ actionpack (= 3.2.2)
69
+ activesupport (= 3.2.2)
70
+ rack-ssl (~> 1.3.2)
71
+ rake (>= 0.8.7)
72
+ rdoc (~> 3.4)
73
+ thor (~> 0.14.6)
74
+ rake (0.9.2.2)
75
+ rdoc (3.12)
76
+ json (~> 1.4)
77
+ sprockets (2.1.2)
78
+ hike (~> 1.2)
79
+ rack (~> 1.0)
80
+ tilt (~> 1.1, != 1.3.0)
100
81
  thor (0.14.6)
101
- tilt (1.3)
102
- treetop (1.4.9)
82
+ tilt (1.3.3)
83
+ treetop (1.4.10)
84
+ polyglot
103
85
  polyglot (>= 0.3.1)
104
- tzinfo (0.3.27)
105
- webmock (1.6.2)
106
- addressable (>= 2.2.2)
107
- crack (>= 0.1.7)
86
+ tzinfo (0.3.32)
108
87
 
109
88
  PLATFORMS
110
89
  ruby
111
90
 
112
91
  DEPENDENCIES
113
- bundler (~> 1.0.0)
114
- i18n (= 0.6.0beta1)
115
- jquery-rails!
116
- rack!
117
- rails!
118
- rspec (~> 1.3)
119
- sprockets!
120
- webmock (~> 1.6.2)
92
+ bundler (~> 1.0)
93
+ jcrop-rails!
94
+ rails (~> 3.0)
data/LICENSE CHANGED
@@ -1,11 +1,13 @@
1
1
  JCrop jQuery plugin:
2
2
 
3
- Copyright (c) 2011 Tapmodo Interactive LLC,
4
- http://github.com/tapmodo/Jcrop
5
-
3
+ Copyright (c) 2011 Tapmodo Interactive LLC,
4
+ http://github.com/tapmodo/Jcrop
5
+
6
6
  jcrop-rails gem:
7
7
 
8
- Copyright (c) 2011 Nick Ragaz
8
+ Copyright (c) 2011 Nick Ragaz
9
+
10
+ Both:
9
11
 
10
12
  Permission is hereby granted, free of charge, to any person obtaining
11
13
  a copy of this software and associated documentation files (the
@@ -8,14 +8,14 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["Nick Ragaz"]
9
9
  s.email = ["nick.ragaz@gmail.com"]
10
10
  s.homepage = "http://rubygems.org/gems/jcrop-rails"
11
- s.summary = "Use the Jcrop jQuery plugin with Rails 3.1"
12
- s.description = "This gem provides the Jcrop jQuery plugin for your Rails 3.1 application."
11
+ s.summary = "Use the Jcrop jQuery plugin with Rails 3.1+"
12
+ s.description = "This gem provides the Jcrop jQuery plugin for your Rails 3.1+ application."
13
13
 
14
14
  s.required_rubygems_version = ">= 1.3.6"
15
15
 
16
16
  s.add_dependency "railties", "~> 3.0"
17
17
  s.add_dependency "thor", "~> 0.14"
18
- s.add_development_dependency "bundler", "~> 1.0.0"
18
+ s.add_development_dependency "bundler", "~> 1.0"
19
19
  s.add_development_dependency "rails", "~> 3.0"
20
20
 
21
21
  s.files = `git ls-files`.split("\n")
@@ -1,6 +1,6 @@
1
1
  module Jcrop
2
2
  module Rails
3
- VERSION = "1.0.2"
4
- JCROP_VERSION = "0.9.9"
3
+ VERSION = "1.0.3"
4
+ JCROP_VERSION = "0.9.12"
5
5
  end
6
6
  end
File without changes
@@ -1,8 +1,9 @@
1
1
  /**
2
- * jquery.Jcrop.js v0.9.9
3
- * jQuery Image Cropping Plugin
4
- * @author Kelly Hallman <khallman@gmail.com>
5
- * Copyright (c) 2008-2011 Kelly Hallman - released under MIT License {{{
2
+ * jquery.Jcrop.js v0.9.12
3
+ * jQuery Image Cropping Plugin - released under MIT License
4
+ * Author: Kelly Hallman <khallman@gmail.com>
5
+ * http://github.com/tapmodo/Jcrop
6
+ * Copyright (c) 2008-2013 Tapmodo Interactive LLC {{{
6
7
  *
7
8
  * Permission is hereby granted, free of charge, to any person
8
9
  * obtaining a copy of this software and associated documentation
@@ -32,14 +33,14 @@
32
33
 
33
34
  $.Jcrop = function (obj, opt) {
34
35
  var options = $.extend({}, $.Jcrop.defaults),
35
- docOffset, lastcurs, ie6mode = false;
36
+ docOffset,
37
+ _ua = navigator.userAgent.toLowerCase(),
38
+ is_msie = /msie/.test(_ua),
39
+ ie6mode = /msie [1-6]\./.test(_ua);
36
40
 
37
41
  // Internal Methods {{{
38
42
  function px(n) {
39
- return parseInt(n, 10) + 'px';
40
- }
41
- function pct(n) {
42
- return parseInt(n, 10) + '%';
43
+ return Math.round(n) + 'px';
43
44
  }
44
45
  function cssClass(cl) {
45
46
  return options.baseClass + '-' + cl;
@@ -49,7 +50,6 @@
49
50
  }
50
51
  function getPos(obj) //{{{
51
52
  {
52
- // Updated in v0.9.4 to use built-in dimensions plugin
53
53
  var pos = $(obj).offset();
54
54
  return [pos.left, pos.top];
55
55
  }
@@ -61,37 +61,21 @@
61
61
  //}}}
62
62
  function setOptions(opt) //{{{
63
63
  {
64
- if (typeof(opt) !== 'object') {
65
- opt = {};
66
- }
64
+ if (typeof(opt) !== 'object') opt = {};
67
65
  options = $.extend(options, opt);
68
66
 
69
- if (typeof(options.onChange) !== 'function') {
70
- options.onChange = function () {};
71
- }
72
- if (typeof(options.onSelect) !== 'function') {
73
- options.onSelect = function () {};
74
- }
75
- if (typeof(options.onRelease) !== 'function') {
76
- options.onRelease = function () {};
77
- }
78
- }
79
- //}}}
80
- function myCursor(type) //{{{
81
- {
82
- if (type !== lastcurs) {
83
- Tracker.setCursor(type);
84
- lastcurs = type;
85
- }
67
+ $.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) {
68
+ if (typeof(options[e]) !== 'function') options[e] = function () {};
69
+ });
86
70
  }
87
71
  //}}}
88
- function startDragMode(mode, pos) //{{{
72
+ function startDragMode(mode, pos, touch) //{{{
89
73
  {
90
74
  docOffset = getPos($img);
91
75
  Tracker.setCursor(mode === 'move' ? mode : mode + '-resize');
92
76
 
93
77
  if (mode === 'move') {
94
- return Tracker.activateHandlers(createMover(pos), doneSelect);
78
+ return Tracker.activateHandlers(createMover(pos), doneSelect, touch);
95
79
  }
96
80
 
97
81
  var fc = Coords.getFixed();
@@ -101,7 +85,7 @@
101
85
  Coords.setPressed(Coords.getCorner(opp));
102
86
  Coords.setCurrent(opc);
103
87
 
104
- Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect);
88
+ Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch);
105
89
  }
106
90
  //}}}
107
91
  function dragmodeHandler(mode, f) //{{{
@@ -187,6 +171,11 @@
187
171
  if ((ord === 'move') && !options.allowMove) {
188
172
  return false;
189
173
  }
174
+
175
+ // Fix position of crop area when dragged the very first time.
176
+ // Necessary when crop image is in a hidden element when page is loaded.
177
+ docOffset = getPos($img);
178
+
190
179
  btndown = true;
191
180
  startDragMode(ord, mouseAbs(e));
192
181
  e.stopPropagation();
@@ -215,12 +204,12 @@
215
204
  function unscale(c) //{{{
216
205
  {
217
206
  return {
218
- x: parseInt(c.x * xscale, 10),
219
- y: parseInt(c.y * yscale, 10),
220
- x2: parseInt(c.x2 * xscale, 10),
221
- y2: parseInt(c.y2 * yscale, 10),
222
- w: parseInt(c.w * xscale, 10),
223
- h: parseInt(c.h * yscale, 10)
207
+ x: c.x * xscale,
208
+ y: c.y * yscale,
209
+ x2: c.x2 * xscale,
210
+ y2: c.y2 * yscale,
211
+ w: c.w * xscale,
212
+ h: c.h * yscale
224
213
  };
225
214
  }
226
215
  //}}}
@@ -247,11 +236,11 @@
247
236
  btndown = true;
248
237
  docOffset = getPos($img);
249
238
  Selection.disableHandles();
250
- myCursor('crosshair');
239
+ Tracker.setCursor('crosshair');
251
240
  var pos = mouseAbs(e);
252
241
  Coords.setPressed(pos);
253
242
  Selection.update();
254
- Tracker.activateHandlers(selectDrag, doneSelect);
243
+ Tracker.activateHandlers(selectDrag, doneSelect, e.type.substring(0,5)==='touch');
255
244
  KeyManager.watchKeys();
256
245
 
257
246
  e.stopPropagation();
@@ -268,7 +257,7 @@
268
257
  function newTracker() //{{{
269
258
  {
270
259
  var trk = $('<div></div>').addClass(cssClass('tracker'));
271
- if ($.browser.msie) {
260
+ if (is_msie) {
272
261
  trk.css({
273
262
  opacity: 0,
274
263
  backgroundColor: 'white'
@@ -281,9 +270,6 @@
281
270
  // }}}
282
271
  // Initialization {{{
283
272
  // Sanitize some options {{{
284
- if ($.browser.msie && ($.browser.version.split('.')[0] === '6')) {
285
- ie6mode = true;
286
- }
287
273
  if (typeof(obj) !== 'object') {
288
274
  obj = $(obj)[0];
289
275
  }
@@ -299,52 +285,88 @@
299
285
  // character in the DOM will be as you left it.
300
286
  var img_css = {
301
287
  border: 'none',
288
+ visibility: 'visible',
302
289
  margin: 0,
303
290
  padding: 0,
304
- position: 'absolute'
291
+ position: 'absolute',
292
+ top: 0,
293
+ left: 0
305
294
  };
306
295
 
307
- var $origimg = $(obj);
308
- var $img = $origimg.clone().removeAttr('id').css(img_css);
296
+ var $origimg = $(obj),
297
+ img_mode = true;
298
+
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
+ }
313
+
314
+ var $img = $origimg.clone().removeAttr('id').css(img_css).show();
315
+
316
+ $img.width($origimg.width());
317
+ $img.height($origimg.height());
318
+ $origimg.after($img).hide();
309
319
 
310
- $img.width($origimg.width());
311
- $img.height($origimg.height());
312
- $origimg.after($img).hide();
320
+ } else {
321
+ $img = $origimg.css(img_css).show();
322
+ img_mode = false;
323
+ if (options.shade === null) { options.shade = true; }
324
+ }
313
325
 
314
326
  presize($img, options.boxWidth, options.boxHeight);
315
327
 
316
328
  var boundx = $img.width(),
317
329
  boundy = $img.height(),
318
-
319
-
330
+
331
+
320
332
  $div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({
321
333
  position: 'relative',
322
334
  backgroundColor: options.bgColor
323
335
  }).insertAfter($origimg).append($img);
324
336
 
325
- delete(options.bgColor);
326
337
  if (options.addClass) {
327
338
  $div.addClass(options.addClass);
328
339
  }
329
340
 
330
- var $img2 = $('<img />')
331
- .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy),
341
+ var $img2 = $('<div />'),
332
342
 
333
- $img_holder = $('<div />')
334
- .width(pct(100)).height(pct(100)).css({
343
+ $img_holder = $('<div />')
344
+ .width('100%').height('100%').css({
335
345
  zIndex: 310,
336
346
  position: 'absolute',
337
347
  overflow: 'hidden'
338
- }).append($img2),
348
+ }),
339
349
 
340
- $hdl_holder = $('<div />')
341
- .width(pct(100)).height(pct(100)).css('zIndex', 320),
350
+ $hdl_holder = $('<div />')
351
+ .width('100%').height('100%').css('zIndex', 320),
342
352
 
343
- $sel = $('<div />')
353
+ $sel = $('<div />')
344
354
  .css({
345
355
  position: 'absolute',
346
- zIndex: 300
347
- }).insertBefore($img).append($img_holder, $hdl_holder);
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);
361
+
362
+ if (img_mode) {
363
+
364
+ $img2 = $('<img />')
365
+ .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy),
366
+
367
+ $img_holder.append($img2);
368
+
369
+ }
348
370
 
349
371
  if (ie6mode) {
350
372
  $sel.css({
@@ -362,7 +384,8 @@
362
384
 
363
385
  /* }}} */
364
386
  // Set more variables {{{
365
- var bgopacity = options.bgOpacity,
387
+ var bgcolor = options.bgColor,
388
+ bgopacity = options.bgOpacity,
366
389
  xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true,
367
390
  btndown, animating, shift_down;
368
391
 
@@ -370,13 +393,12 @@
370
393
  // }}}
371
394
  // }}}
372
395
  // Internal Modules {{{
373
- // Touch Module {{{
396
+ // Touch Module {{{
374
397
  var Touch = (function () {
375
398
  // Touch support detection function adapted (under MIT License)
376
399
  // from code by Jeffrey Sambells - http://github.com/iamamused/
377
400
  function hasTouchSupport() {
378
- var support = {},
379
- events = ['touchstart', 'touchmove', 'touchend'],
401
+ var support = {}, events = ['touchstart', 'touchmove', 'touchend'],
380
402
  el = document.createElement('div'), i;
381
403
 
382
404
  try {
@@ -404,25 +426,27 @@
404
426
  return {
405
427
  createDragger: function (ord) {
406
428
  return function (e) {
407
- e.pageX = e.originalEvent.changedTouches[0].pageX;
408
- e.pageY = e.originalEvent.changedTouches[0].pageY;
409
429
  if (options.disabled) {
410
430
  return false;
411
431
  }
412
432
  if ((ord === 'move') && !options.allowMove) {
413
433
  return false;
414
434
  }
435
+ docOffset = getPos($img);
415
436
  btndown = true;
416
- startDragMode(ord, mouseAbs(e));
437
+ startDragMode(ord, mouseAbs(Touch.cfilter(e)), true);
417
438
  e.stopPropagation();
418
439
  e.preventDefault();
419
440
  return false;
420
441
  };
421
442
  },
422
443
  newSelection: function (e) {
444
+ return newSelection(Touch.cfilter(e));
445
+ },
446
+ cfilter: function (e){
423
447
  e.pageX = e.originalEvent.changedTouches[0].pageX;
424
448
  e.pageY = e.originalEvent.changedTouches[0].pageY;
425
- return newSelection(e);
449
+ return e;
426
450
  },
427
451
  isSupported: hasTouchSupport,
428
452
  support: detectSupport()
@@ -506,8 +530,8 @@
506
530
  // This function could use some optimization I think...
507
531
  var aspect = options.aspectRatio,
508
532
  min_x = options.minSize[0] / xscale,
509
-
510
-
533
+
534
+
511
535
  //min_y = options.minSize[1]/yscale,
512
536
  max_x = options.maxSize[0] / xscale,
513
537
  max_y = options.maxSize[1] / yscale,
@@ -516,7 +540,7 @@
516
540
  rwa = Math.abs(rw),
517
541
  rha = Math.abs(rh),
518
542
  real_ratio = rwa / rha,
519
- xx, yy;
543
+ xx, yy, w, h;
520
544
 
521
545
  if (max_x === 0) {
522
546
  max_x = boundx * 10;
@@ -599,21 +623,13 @@
599
623
  //}}}
600
624
  function rebound(p) //{{{
601
625
  {
602
- if (p[0] < 0) {
603
- p[0] = 0;
604
- }
605
- if (p[1] < 0) {
606
- p[1] = 0;
607
- }
626
+ if (p[0] < 0) p[0] = 0;
627
+ if (p[1] < 0) p[1] = 0;
608
628
 
609
- if (p[0] > boundx) {
610
- p[0] = boundx;
611
- }
612
- if (p[1] > boundy) {
613
- p[1] = boundy;
614
- }
629
+ if (p[0] > boundx) p[0] = boundx;
630
+ if (p[1] > boundy) p[1] = boundy;
615
631
 
616
- return [p[0], p[1]];
632
+ return [Math.round(p[0]), Math.round(p[1])];
617
633
  }
618
634
  //}}}
619
635
  function flipCoords(x1, y1, x2, y2) //{{{
@@ -630,7 +646,7 @@
630
646
  ya = y2;
631
647
  yb = y1;
632
648
  }
633
- return [Math.round(xa), Math.round(ya), Math.round(xb), Math.round(yb)];
649
+ return [xa, ya, xb, yb];
634
650
  }
635
651
  //}}}
636
652
  function getRect() //{{{
@@ -718,13 +734,131 @@
718
734
  }());
719
735
 
720
736
  //}}}
737
+ // Shade Module {{{
738
+ var Shade = (function() {
739
+ var enabled = false,
740
+ holder = $('<div />').css({
741
+ position: 'absolute',
742
+ zIndex: 240,
743
+ opacity: 0
744
+ }),
745
+ shades = {
746
+ top: createShade(),
747
+ left: createShade().height(boundy),
748
+ right: createShade().height(boundy),
749
+ bottom: createShade()
750
+ };
751
+
752
+ function resizeShades(w,h) {
753
+ shades.left.css({ height: px(h) });
754
+ shades.right.css({ height: px(h) });
755
+ }
756
+ function updateAuto()
757
+ {
758
+ return updateShade(Coords.getFixed());
759
+ }
760
+ function updateShade(c)
761
+ {
762
+ shades.top.css({
763
+ left: px(c.x),
764
+ width: px(c.w),
765
+ height: px(c.y)
766
+ });
767
+ shades.bottom.css({
768
+ top: px(c.y2),
769
+ left: px(c.x),
770
+ width: px(c.w),
771
+ height: px(boundy-c.y2)
772
+ });
773
+ shades.right.css({
774
+ left: px(c.x2),
775
+ width: px(boundx-c.x2)
776
+ });
777
+ shades.left.css({
778
+ width: px(c.x)
779
+ });
780
+ }
781
+ function createShade() {
782
+ return $('<div />').css({
783
+ position: 'absolute',
784
+ backgroundColor: options.shadeColor||options.bgColor
785
+ }).appendTo(holder);
786
+ }
787
+ function enableShade() {
788
+ if (!enabled) {
789
+ enabled = true;
790
+ holder.insertBefore($img);
791
+ updateAuto();
792
+ Selection.setBgOpacity(1,0,1);
793
+ $img2.hide();
794
+
795
+ setBgColor(options.shadeColor||options.bgColor,1);
796
+ if (Selection.isAwake())
797
+ {
798
+ setOpacity(options.bgOpacity,1);
799
+ }
800
+ else setOpacity(1,1);
801
+ }
802
+ }
803
+ function setBgColor(color,now) {
804
+ colorChangeMacro(getShades(),color,now);
805
+ }
806
+ function disableShade() {
807
+ if (enabled) {
808
+ holder.remove();
809
+ $img2.show();
810
+ enabled = false;
811
+ if (Selection.isAwake()) {
812
+ Selection.setBgOpacity(options.bgOpacity,1,1);
813
+ } else {
814
+ Selection.setBgOpacity(1,1,1);
815
+ Selection.disableHandles();
816
+ }
817
+ colorChangeMacro($div,0,1);
818
+ }
819
+ }
820
+ function setOpacity(opacity,now) {
821
+ if (enabled) {
822
+ if (options.bgFade && !now) {
823
+ holder.animate({
824
+ opacity: 1-opacity
825
+ },{
826
+ queue: false,
827
+ duration: options.fadeTime
828
+ });
829
+ }
830
+ else holder.css({opacity:1-opacity});
831
+ }
832
+ }
833
+ function refreshAll() {
834
+ options.shade ? enableShade() : disableShade();
835
+ if (Selection.isAwake()) setOpacity(options.bgOpacity);
836
+ }
837
+ function getShades() {
838
+ return holder.children();
839
+ }
840
+
841
+ return {
842
+ update: updateAuto,
843
+ updateRaw: updateShade,
844
+ getShades: getShades,
845
+ setBgColor: setBgColor,
846
+ enable: enableShade,
847
+ disable: disableShade,
848
+ resize: resizeShades,
849
+ refresh: refreshAll,
850
+ opacity: setOpacity
851
+ };
852
+ }());
853
+ // }}}
721
854
  // Selection Module {{{
722
855
  var Selection = (function () {
723
- var awake, hdep = 370;
724
- var borders = {};
725
- var handle = {};
726
- var seehandles = false;
727
- var hhs = options.handleOffset;
856
+ var awake,
857
+ hdep = 370,
858
+ borders = {},
859
+ handle = {},
860
+ dragbar = {},
861
+ seehandles = false;
728
862
 
729
863
  // Private Methods
730
864
  function insertBorder(type) //{{{
@@ -743,10 +877,10 @@
743
877
  cursor: ord + '-resize',
744
878
  position: 'absolute',
745
879
  zIndex: zi
746
- });
880
+ }).addClass('ord-'+ord);
747
881
 
748
882
  if (Touch.support) {
749
- jq.bind('touchstart', Touch.createDragger(ord));
883
+ jq.bind('touchstart.jcrop', Touch.createDragger(ord));
750
884
  }
751
885
 
752
886
  $hdl_holder.append(jq);
@@ -755,100 +889,60 @@
755
889
  //}}}
756
890
  function insertHandle(ord) //{{{
757
891
  {
758
- return dragDiv(ord, hdep++).css({
759
- top: px(-hhs + 1),
760
- left: px(-hhs + 1),
761
- opacity: options.handleOpacity
762
- }).addClass(cssClass('handle'));
892
+ var hs = options.handleSize,
893
+
894
+ div = dragDiv(ord, hdep++).css({
895
+ opacity: options.handleOpacity
896
+ }).addClass(cssClass('handle'));
897
+
898
+ if (hs) { div.width(hs).height(hs); }
899
+
900
+ return div;
763
901
  }
764
902
  //}}}
765
903
  function insertDragbar(ord) //{{{
766
904
  {
767
- var s = options.handleSize,
768
- h = s,
769
- w = s,
770
- t = hhs,
771
- l = hhs;
772
-
773
- switch (ord) {
774
- case 'n':
775
- case 's':
776
- w = pct(100);
777
- break;
778
- case 'e':
779
- case 'w':
780
- h = pct(100);
781
- break;
782
- }
783
-
784
- return dragDiv(ord, hdep++).width(w).height(h).css({
785
- top: px(-t + 1),
786
- left: px(-l + 1)
787
- });
905
+ return dragDiv(ord, hdep++).addClass('jcrop-dragbar');
788
906
  }
789
907
  //}}}
790
- function createHandles(li) //{{{
908
+ function createDragbars(li) //{{{
791
909
  {
792
910
  var i;
793
911
  for (i = 0; i < li.length; i++) {
794
- handle[li[i]] = insertHandle(li[i]);
912
+ dragbar[li[i]] = insertDragbar(li[i]);
795
913
  }
796
914
  }
797
915
  //}}}
798
- function moveHandles(c) //{{{
916
+ function createBorders(li) //{{{
799
917
  {
800
- var midvert = Math.round((c.h / 2) - hhs),
801
- midhoriz = Math.round((c.w / 2) - hhs),
802
- north = -hhs + 1,
803
- west = -hhs + 1,
804
- east = c.w - hhs,
805
- south = c.h - hhs,
806
- x, y;
807
-
808
- if (handle.e) {
809
- handle.e.css({
810
- top: px(midvert),
811
- left: px(east)
812
- });
813
- handle.w.css({
814
- top: px(midvert)
815
- });
816
- handle.s.css({
817
- top: px(south),
818
- left: px(midhoriz)
819
- });
820
- handle.n.css({
821
- left: px(midhoriz)
822
- });
823
- }
824
- if (handle.ne) {
825
- handle.ne.css({
826
- left: px(east)
827
- });
828
- handle.se.css({
829
- top: px(south),
830
- left: px(east)
831
- });
832
- handle.sw.css({
833
- top: px(south)
834
- });
918
+ var cl,i;
919
+ for (i = 0; i < li.length; i++) {
920
+ switch(li[i]){
921
+ case'n': cl='hline'; break;
922
+ case's': cl='hline bottom'; break;
923
+ case'e': cl='vline right'; break;
924
+ case'w': cl='vline'; break;
925
+ }
926
+ borders[li[i]] = insertBorder(cl);
835
927
  }
836
- if (handle.b) {
837
- handle.b.css({
838
- top: px(south)
839
- });
840
- handle.r.css({
841
- left: px(east)
842
- });
928
+ }
929
+ //}}}
930
+ function createHandles(li) //{{{
931
+ {
932
+ var i;
933
+ for (i = 0; i < li.length; i++) {
934
+ handle[li[i]] = insertHandle(li[i]);
843
935
  }
844
936
  }
845
937
  //}}}
846
938
  function moveto(x, y) //{{{
847
939
  {
848
- $img2.css({
849
- top: px(-y),
850
- left: px(-x)
851
- });
940
+ if (!options.shade) {
941
+ $img2.css({
942
+ top: px(-y),
943
+ left: px(-x)
944
+ });
945
+ }
852
946
  $sel.css({
853
947
  top: px(y),
854
948
  left: px(x)
@@ -857,7 +951,7 @@
857
951
  //}}}
858
952
  function resize(w, h) //{{{
859
953
  {
860
- $sel.width(w).height(h);
954
+ $sel.width(Math.round(w)).height(Math.round(h));
861
955
  }
862
956
  //}}}
863
957
  function refresh() //{{{
@@ -872,45 +966,51 @@
872
966
  //}}}
873
967
 
874
968
  // Internal Methods
875
- function updateVisible() //{{{
969
+ function updateVisible(select) //{{{
876
970
  {
877
971
  if (awake) {
878
- return update();
972
+ return update(select);
879
973
  }
880
974
  }
881
975
  //}}}
882
- function update() //{{{
976
+ function update(select) //{{{
883
977
  {
884
978
  var c = Coords.getFixed();
885
979
 
886
980
  resize(c.w, c.h);
887
981
  moveto(c.x, c.y);
982
+ if (options.shade) Shade.updateRaw(c);
888
983
 
889
- /*
890
- options.drawBorders &&
891
- borders.right.css({ left: px(c.w-1) }) &&
892
- borders.bottom.css({ top: px(c.h-1) });
893
- */
984
+ awake || show();
894
985
 
895
- if (seehandles) {
896
- moveHandles(c);
986
+ if (select) {
987
+ options.onSelect.call(api, unscale(c));
988
+ } else {
989
+ options.onChange.call(api, unscale(c));
897
990
  }
898
- if (!awake) {
899
- show();
991
+ }
992
+ //}}}
993
+ function setBgOpacity(opacity,force,now) //{{{
994
+ {
995
+ if (!awake && !force) return;
996
+ if (options.bgFade && !now) {
997
+ $img.animate({
998
+ opacity: opacity
999
+ },{
1000
+ queue: false,
1001
+ duration: options.fadeTime
1002
+ });
1003
+ } else {
1004
+ $img.css('opacity', opacity);
900
1005
  }
901
-
902
- options.onChange.call(api, unscale(c));
903
1006
  }
904
1007
  //}}}
905
1008
  function show() //{{{
906
1009
  {
907
1010
  $sel.show();
908
1011
 
909
- if (options.bgFade) {
910
- $img.fadeTo(options.fadeTime, bgopacity);
911
- } else {
912
- $img.css('opacity', bgopacity);
913
- }
1012
+ if (options.shade) Shade.opacity(bgopacity);
1013
+ else setBgOpacity(bgopacity,true);
914
1014
 
915
1015
  awake = true;
916
1016
  }
@@ -920,11 +1020,8 @@
920
1020
  disableHandles();
921
1021
  $sel.hide();
922
1022
 
923
- if (options.bgFade) {
924
- $img.fadeTo(options.fadeTime, 1);
925
- } else {
926
- $img.css('opacity', 1);
927
- }
1023
+ if (options.shade) Shade.opacity(1);
1024
+ else setBgOpacity(1);
928
1025
 
929
1026
  awake = false;
930
1027
  options.onRelease.call(api);
@@ -933,7 +1030,6 @@
933
1030
  function showHandles() //{{{
934
1031
  {
935
1032
  if (seehandles) {
936
- moveHandles(Coords.getFixed());
937
1033
  $hdl_holder.show();
938
1034
  }
939
1035
  }
@@ -942,7 +1038,6 @@
942
1038
  {
943
1039
  seehandles = true;
944
1040
  if (options.allowResize) {
945
- moveHandles(Coords.getFixed());
946
1041
  $hdl_holder.show();
947
1042
  return true;
948
1043
  }
@@ -952,54 +1047,44 @@
952
1047
  {
953
1048
  seehandles = false;
954
1049
  $hdl_holder.hide();
955
- }
1050
+ }
956
1051
  //}}}
957
1052
  function animMode(v) //{{{
958
1053
  {
959
- if (animating === v) {
1054
+ if (v) {
1055
+ animating = true;
960
1056
  disableHandles();
961
1057
  } else {
1058
+ animating = false;
962
1059
  enableHandles();
963
1060
  }
964
- }
1061
+ }
965
1062
  //}}}
966
1063
  function done() //{{{
967
1064
  {
968
1065
  animMode(false);
969
1066
  refresh();
970
- }
1067
+ }
971
1068
  //}}}
972
- /* Insert draggable elements {{{*/
973
-
1069
+ // Insert draggable elements {{{
974
1070
  // Insert border divs for outline
975
- if (options.drawBorders) {
976
- borders = {
977
- top: insertBorder('hline'),
978
- bottom: insertBorder('hline bottom'),
979
- left: insertBorder('vline'),
980
- right: insertBorder('vline right')
981
- };
982
- }
983
1071
 
984
- // Insert handles on edges
985
- if (options.dragEdges) {
986
- handle.t = insertDragbar('n');
987
- handle.b = insertDragbar('s');
988
- handle.r = insertDragbar('e');
989
- handle.l = insertDragbar('w');
990
- }
1072
+ if (options.dragEdges && $.isArray(options.createDragbars))
1073
+ createDragbars(options.createDragbars);
991
1074
 
992
- // Insert side and corner handles
993
- if (options.sideHandles) {
994
- createHandles(['n', 's', 'e', 'w']);
995
- }
996
- if (options.cornerHandles) {
997
- createHandles(['sw', 'nw', 'ne', 'se']);
998
- }
1075
+ if ($.isArray(options.createHandles))
1076
+ createHandles(options.createHandles);
1077
+
1078
+ if (options.drawBorders && $.isArray(options.createBorders))
1079
+ createBorders(options.createBorders);
999
1080
 
1000
-
1001
1081
  //}}}
1002
1082
 
1083
+ // This is a hack for iOS5 to support drag/move touch functionality
1084
+ $(document).bind('touchstart.jcrop-ios',function(e) {
1085
+ if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation();
1086
+ });
1087
+
1003
1088
  var $track = newTracker().mousedown(createDragger('move')).css({
1004
1089
  cursor: 'move',
1005
1090
  position: 'absolute',
@@ -1031,10 +1116,11 @@
1031
1116
  showHandles: showHandles,
1032
1117
  disableHandles: disableHandles,
1033
1118
  animMode: animMode,
1119
+ setBgOpacity: setBgOpacity,
1034
1120
  done: done
1035
1121
  };
1036
1122
  }());
1037
-
1123
+
1038
1124
  //}}}
1039
1125
  // Tracker Module {{{
1040
1126
  var Tracker = (function () {
@@ -1042,35 +1128,36 @@
1042
1128
  onDone = function () {},
1043
1129
  trackDoc = options.trackDocument;
1044
1130
 
1045
- function toFront() //{{{
1131
+ function toFront(touch) //{{{
1046
1132
  {
1047
1133
  $trk.css({
1048
1134
  zIndex: 450
1049
1135
  });
1050
- if (trackDoc) {
1136
+
1137
+ if (touch)
1051
1138
  $(document)
1052
- .bind('mousemove',trackMove)
1053
- .bind('mouseup',trackUp);
1054
- }
1055
- }
1139
+ .bind('touchmove.jcrop', trackTouchMove)
1140
+ .bind('touchend.jcrop', trackTouchEnd);
1141
+
1142
+ else if (trackDoc)
1143
+ $(document)
1144
+ .bind('mousemove.jcrop',trackMove)
1145
+ .bind('mouseup.jcrop',trackUp);
1146
+ }
1056
1147
  //}}}
1057
1148
  function toBack() //{{{
1058
1149
  {
1059
1150
  $trk.css({
1060
1151
  zIndex: 290
1061
1152
  });
1062
- if (trackDoc) {
1063
- $(document)
1064
- .unbind('mousemove', trackMove)
1065
- .unbind('mouseup', trackUp);
1066
- }
1067
- }
1153
+ $(document).unbind('.jcrop');
1154
+ }
1068
1155
  //}}}
1069
1156
  function trackMove(e) //{{{
1070
1157
  {
1071
1158
  onMove(mouseAbs(e));
1072
1159
  return false;
1073
- }
1160
+ }
1074
1161
  //}}}
1075
1162
  function trackUp(e) //{{{
1076
1163
  {
@@ -1094,27 +1181,24 @@
1094
1181
  return false;
1095
1182
  }
1096
1183
  //}}}
1097
- function activateHandlers(move, done) //{{{
1184
+ function activateHandlers(move, done, touch) //{{{
1098
1185
  {
1099
1186
  btndown = true;
1100
1187
  onMove = move;
1101
1188
  onDone = done;
1102
- toFront();
1189
+ toFront(touch);
1103
1190
  return false;
1104
1191
  }
1105
1192
  //}}}
1106
1193
  function trackTouchMove(e) //{{{
1107
1194
  {
1108
- e.pageX = e.originalEvent.changedTouches[0].pageX;
1109
- e.pageY = e.originalEvent.changedTouches[0].pageY;
1110
- return trackMove(e);
1195
+ onMove(mouseAbs(Touch.cfilter(e)));
1196
+ return false;
1111
1197
  }
1112
1198
  //}}}
1113
1199
  function trackTouchEnd(e) //{{{
1114
1200
  {
1115
- e.pageX = e.originalEvent.changedTouches[0].pageX;
1116
- e.pageY = e.originalEvent.changedTouches[0].pageY;
1117
- return trackUp(e);
1201
+ return trackUp(Touch.cfilter(e));
1118
1202
  }
1119
1203
  //}}}
1120
1204
  function setCursor(t) //{{{
@@ -1123,12 +1207,6 @@
1123
1207
  }
1124
1208
  //}}}
1125
1209
 
1126
- if (Touch.support) {
1127
- $(document)
1128
- .bind('touchmove', trackTouchMove)
1129
- .bind('touchend', trackTouchEnd);
1130
- }
1131
-
1132
1210
  if (!trackDoc) {
1133
1211
  $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);
1134
1212
  }
@@ -1146,8 +1224,9 @@
1146
1224
  position: 'fixed',
1147
1225
  left: '-120px',
1148
1226
  width: '12px'
1149
- }),
1150
- $keywrap = $('<div />').css({
1227
+ }).addClass('jcrop-keymgr'),
1228
+
1229
+ $keywrap = $('<div />').css({
1151
1230
  position: 'absolute',
1152
1231
  overflow: 'hidden'
1153
1232
  }).append($keymgr);
@@ -1169,7 +1248,7 @@
1169
1248
  {
1170
1249
  if (options.allowMove) {
1171
1250
  Coords.moveOffset([x, y]);
1172
- Selection.updateVisible();
1251
+ Selection.updateVisible(true);
1173
1252
  }
1174
1253
  e.preventDefault();
1175
1254
  e.stopPropagation();
@@ -1177,7 +1256,7 @@
1177
1256
  //}}}
1178
1257
  function parseKey(e) //{{{
1179
1258
  {
1180
- if (e.ctrlKey) {
1259
+ if (e.ctrlKey || e.metaKey) {
1181
1260
  return true;
1182
1261
  }
1183
1262
  shift_down = e.shiftKey ? true : false;
@@ -1197,7 +1276,7 @@
1197
1276
  doNudge(e, 0, nudge);
1198
1277
  break;
1199
1278
  case 27:
1200
- Selection.release();
1279
+ if (options.allowSelect) Selection.release();
1201
1280
  break;
1202
1281
  case 9:
1203
1282
  return true;
@@ -1235,10 +1314,10 @@
1235
1314
  //}}}
1236
1315
  function animateTo(a, callback) //{{{
1237
1316
  {
1238
- var x1 = parseInt(a[0], 10) / xscale,
1239
- y1 = parseInt(a[1], 10) / yscale,
1240
- x2 = parseInt(a[2], 10) / xscale,
1241
- y2 = parseInt(a[3], 10) / yscale;
1317
+ var x1 = a[0] / xscale,
1318
+ y1 = a[1] / yscale,
1319
+ x2 = a[2] / xscale,
1320
+ y2 = a[3] / yscale;
1242
1321
 
1243
1322
  if (animating) {
1244
1323
  return;
@@ -1256,8 +1335,8 @@
1256
1335
  pcent = 0,
1257
1336
  velocity = options.swingSpeed;
1258
1337
 
1259
- x = animat[0];
1260
- y = animat[1];
1338
+ x1 = animat[0];
1339
+ y1 = animat[1];
1261
1340
  x2 = animat[2];
1262
1341
  y2 = animat[3];
1263
1342
 
@@ -1271,10 +1350,10 @@
1271
1350
  return function () {
1272
1351
  pcent += (100 - pcent) / velocity;
1273
1352
 
1274
- animat[0] = x + ((pcent / 100) * ix1);
1275
- animat[1] = y + ((pcent / 100) * iy1);
1276
- animat[2] = x2 + ((pcent / 100) * ix2);
1277
- animat[3] = y2 + ((pcent / 100) * iy2);
1353
+ animat[0] = Math.round(x1 + ((pcent / 100) * ix1));
1354
+ animat[1] = Math.round(y1 + ((pcent / 100) * iy1));
1355
+ animat[2] = Math.round(x2 + ((pcent / 100) * ix2));
1356
+ animat[3] = Math.round(y2 + ((pcent / 100) * iy2));
1278
1357
 
1279
1358
  if (pcent >= 99.8) {
1280
1359
  pcent = 100;
@@ -1284,6 +1363,7 @@
1284
1363
  queueAnimator();
1285
1364
  } else {
1286
1365
  Selection.done();
1366
+ Selection.animMode(false);
1287
1367
  if (typeof(callback) === 'function') {
1288
1368
  callback.call(api);
1289
1369
  }
@@ -1295,8 +1375,9 @@
1295
1375
  //}}}
1296
1376
  function setSelect(rect) //{{{
1297
1377
  {
1298
- setSelectRaw([
1299
- parseInt(rect[0], 10) / xscale, parseInt(rect[1], 10) / yscale, parseInt(rect[2], 10) / xscale, parseInt(rect[3], 10) / yscale]);
1378
+ setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]);
1379
+ options.onSelect.call(api, unscale(Coords.getFixed()));
1380
+ Selection.enableHandles();
1300
1381
  }
1301
1382
  //}}}
1302
1383
  function setSelectRaw(l) //{{{
@@ -1346,6 +1427,7 @@
1346
1427
  {
1347
1428
  $div.remove();
1348
1429
  $origimg.show();
1430
+ $origimg.css('visibility','visible');
1349
1431
  $(obj).removeData('Jcrop');
1350
1432
  }
1351
1433
  //}}}
@@ -1368,6 +1450,7 @@
1368
1450
  $img2.width(boundx).height(boundy);
1369
1451
  $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2));
1370
1452
  $div.width(boundx).height(boundy);
1453
+ Shade.resize(boundx,boundy);
1371
1454
  enableCrop();
1372
1455
 
1373
1456
  if (typeof(callback) === 'function') {
@@ -1377,6 +1460,19 @@
1377
1460
  img.src = src;
1378
1461
  }
1379
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
+ }
1380
1476
  function interfaceUpdate(alt) //{{{
1381
1477
  // This method tweaks the interface based on options object.
1382
1478
  // Called when options are changed and at end of initialization.
@@ -1394,6 +1490,10 @@
1394
1490
  Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');
1395
1491
  Selection.setCursor(options.allowMove ? 'move' : 'default');
1396
1492
 
1493
+ if (options.hasOwnProperty('trueSize')) {
1494
+ xscale = options.trueSize[0] / boundx;
1495
+ yscale = options.trueSize[1] / boundy;
1496
+ }
1397
1497
 
1398
1498
  if (options.hasOwnProperty('setSelect')) {
1399
1499
  setSelect(options.setSelect);
@@ -1401,36 +1501,22 @@
1401
1501
  delete(options.setSelect);
1402
1502
  }
1403
1503
 
1404
- if (options.hasOwnProperty('trueSize')) {
1405
- xscale = options.trueSize[0] / boundx;
1406
- yscale = options.trueSize[1] / boundy;
1407
- }
1408
- if (options.hasOwnProperty('bgColor')) {
1409
-
1410
- if (supportsColorFade() && options.fadeTime) {
1411
- $div.animate({
1412
- backgroundColor: options.bgColor
1413
- }, {
1414
- queue: false,
1415
- duration: options.fadeTime
1416
- });
1417
- } else {
1418
- $div.css('backgroundColor', options.bgColor);
1419
- }
1504
+ Shade.refresh();
1420
1505
 
1421
- delete(options.bgColor);
1506
+ if (options.bgColor != bgcolor) {
1507
+ colorChangeMacro(
1508
+ options.shade? Shade.getShades(): $div,
1509
+ options.shade?
1510
+ (options.shadeColor || options.bgColor):
1511
+ options.bgColor
1512
+ );
1513
+ bgcolor = options.bgColor;
1422
1514
  }
1423
- if (options.hasOwnProperty('bgOpacity')) {
1424
- bgopacity = options.bgOpacity;
1425
1515
 
1426
- if (Selection.isAwake()) {
1427
- if (options.fadeTime) {
1428
- $img.fadeTo(options.fadeTime, bgopacity);
1429
- } else {
1430
- $div.css('opacity', options.opacity);
1431
- }
1432
- }
1433
- delete(options.bgOpacity);
1516
+ if (bgopacity != options.bgOpacity) {
1517
+ bgopacity = options.bgOpacity;
1518
+ if (options.shade) Shade.refresh();
1519
+ else Selection.setBgOpacity(bgopacity);
1434
1520
  }
1435
1521
 
1436
1522
  xlimit = options.maxSize[0] || 0;
@@ -1448,9 +1534,7 @@
1448
1534
  //}}}
1449
1535
  //}}}
1450
1536
 
1451
- if (Touch.support) {
1452
- $trk.bind('touchstart', Touch.newSelection);
1453
- }
1537
+ if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection);
1454
1538
 
1455
1539
  $hdl_holder.hide();
1456
1540
  interfaceUpdate(true);
@@ -1481,6 +1565,10 @@
1481
1565
  getScaleFactor: function () {
1482
1566
  return [xscale, yscale];
1483
1567
  },
1568
+ getOptions: function() {
1569
+ // careful: internal values are returned
1570
+ return options;
1571
+ },
1484
1572
 
1485
1573
  ui: {
1486
1574
  holder: $div,
@@ -1488,66 +1576,69 @@
1488
1576
  }
1489
1577
  };
1490
1578
 
1491
- if ($.browser.msie) {
1492
- $div.bind('selectstart', function () {
1493
- return false;
1494
- });
1495
- }
1579
+ if (is_msie) $div.bind('selectstart', function () { return false; });
1496
1580
 
1497
1581
  $origimg.data('Jcrop', api);
1498
1582
  return api;
1499
1583
  };
1500
1584
  $.fn.Jcrop = function (options, callback) //{{{
1501
1585
  {
1502
-
1503
- function attachWhenDone(from) //{{{
1504
- {
1505
- var opt = (typeof(options) === 'object') ? options : {};
1506
- var loadsrc = opt.useImg || from.src;
1507
- var img = new Image();
1508
- img.onload = function () {
1509
- function attachJcrop() {
1510
- var api = $.Jcrop(from, opt);
1511
- if (typeof(callback) === 'function') {
1512
- callback.call(api);
1513
- }
1514
- }
1515
-
1516
- function attachAttempt() {
1517
- if (!img.width || !img.height) {
1518
- window.setTimeout(attachAttempt, 50);
1519
- } else {
1520
- attachJcrop();
1521
- }
1522
- }
1523
- window.setTimeout(attachAttempt, 50);
1524
- };
1525
- img.src = loadsrc;
1526
- }
1527
- //}}}
1528
-
1586
+ var api;
1529
1587
  // Iterate over each object, attach Jcrop
1530
1588
  this.each(function () {
1531
1589
  // If we've already attached to this object
1532
1590
  if ($(this).data('Jcrop')) {
1533
1591
  // The API can be requested this way (undocumented)
1534
- if (options === 'api') {
1535
- return $(this).data('Jcrop');
1536
- }
1592
+ if (options === 'api') return $(this).data('Jcrop');
1537
1593
  // Otherwise, we just reset the options...
1538
- else {
1539
- $(this).data('Jcrop').setOptions(options);
1540
- }
1594
+ else $(this).data('Jcrop').setOptions(options);
1541
1595
  }
1542
1596
  // If we haven't been attached, preload and attach
1543
1597
  else {
1544
- attachWhenDone(this);
1598
+ if (this.tagName == 'IMG')
1599
+ $.Jcrop.Loader(this,function(){
1600
+ $(this).css({display:'block',visibility:'hidden'});
1601
+ api = $.Jcrop(this, options);
1602
+ if ($.isFunction(callback)) callback.call(api);
1603
+ });
1604
+ else {
1605
+ $(this).css({display:'block',visibility:'hidden'});
1606
+ api = $.Jcrop(this, options);
1607
+ if ($.isFunction(callback)) callback.call(api);
1608
+ }
1545
1609
  }
1546
1610
  });
1547
1611
 
1548
1612
  // Return "this" so the object is chainable (jQuery-style)
1549
1613
  return this;
1550
1614
  };
1615
+ //}}}
1616
+ // $.Jcrop.Loader - basic image loader {{{
1617
+
1618
+ $.Jcrop.Loader = function(imgobj,success,error){
1619
+ var $img = $(imgobj), img = $img[0];
1620
+
1621
+ function completeCheck(){
1622
+ if (img.complete) {
1623
+ $img.unbind('.jcloader');
1624
+ if ($.isFunction(success)) success.call(img);
1625
+ }
1626
+ else window.setTimeout(completeCheck,50);
1627
+ }
1628
+
1629
+ $img
1630
+ .bind('load.jcloader',completeCheck)
1631
+ .bind('error.jcloader',function(e){
1632
+ $img.unbind('.jcloader');
1633
+ if ($.isFunction(error)) error.call(img);
1634
+ });
1635
+
1636
+ if (img.complete && $.isFunction(success)){
1637
+ $img.unbind('.jcloader');
1638
+ success.call(img);
1639
+ }
1640
+ };
1641
+
1551
1642
  //}}}
1552
1643
  // Global Defaults {{{
1553
1644
  $.Jcrop.defaults = {
@@ -1567,18 +1658,20 @@
1567
1658
  bgFade: false,
1568
1659
  borderOpacity: 0.4,
1569
1660
  handleOpacity: 0.5,
1570
- handleSize: 9,
1571
- handleOffset: 5,
1661
+ handleSize: null,
1572
1662
 
1573
1663
  aspectRatio: 0,
1574
1664
  keySupport: true,
1575
- cornerHandles: true,
1576
- sideHandles: true,
1665
+ createHandles: ['n','s','e','w','nw','ne','se','sw'],
1666
+ createDragbars: ['n','s','e','w'],
1667
+ createBorders: ['n','s','e','w'],
1577
1668
  drawBorders: true,
1578
1669
  dragEdges: true,
1579
1670
  fixedSupport: true,
1580
1671
  touchSupport: null,
1581
1672
 
1673
+ shade: null,
1674
+
1582
1675
  boxWidth: 0,
1583
1676
  boxHeight: 0,
1584
1677
  boundary: 2,
@@ -1593,6 +1686,7 @@
1593
1686
  // Callbacks / Event Handlers
1594
1687
  onChange: function () {},
1595
1688
  onSelect: function () {},
1689
+ onDblClick: function () {},
1596
1690
  onRelease: function () {}
1597
1691
  };
1598
1692