cropper-rails 2.2.1.1 → 2.3.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 18d109addd9bd9f6dfcb09582646d5584694bfba
4
- data.tar.gz: 66b623b517132f47a24cbc479dc3c08314cff729
3
+ metadata.gz: e1ff6df294ba7bba894a943e74ce62cfd9c7f8bb
4
+ data.tar.gz: 3e8f319611b3fc50f2d93f632975907ae3f21670
5
5
  SHA512:
6
- metadata.gz: 01f2bc23e589e3ab86f98df95bae68fca597968d3b9506099bb665f59c95dc7b308b20e52b549c44826aee57f6b5ee7ba3a1c13bb4578c3f5d9b027d3b332c85
7
- data.tar.gz: a9eeb6fc980918288e1b0a9bd3e5a873213f88de6c2fc9f95fb815ad525b252cb0f5f661918d5b57293d19a4f79eb2f9f0382339a736ea7919328b74ca5d123f
6
+ metadata.gz: 3d233dc2dbcd7c7f85f5e76e2f9a45d52d5f62028885eeaebead68397a6ffa678e346f31c2fd61aca89322f430305b5974e52cb8f4de9dedba69be7f662d0c03
7
+ data.tar.gz: 718da9b48066fe2e862b19049ee36174dd61498e0ede12b882bca93b062797cafe91af9c7a5e7814b949dceae7df004daad0ebc52ce019355f68c542378a141d
@@ -1,5 +1,5 @@
1
1
  module Cropper
2
2
  module Rails
3
- VERSION = "2.2.1.1"
3
+ VERSION = "2.3.2.1"
4
4
  end
5
5
  end
@@ -1,11 +1,11 @@
1
1
  /*!
2
- * Cropper v2.2.1
2
+ * Cropper v2.3.2
3
3
  * https://github.com/fengyuanchen/cropper
4
4
  *
5
- * Copyright (c) 2014-2015 Fengyuan Chen and contributors
5
+ * Copyright (c) 2014-2016 Fengyuan Chen and contributors
6
6
  * Released under the MIT license
7
7
  *
8
- * Date: 2015-12-12T07:24:25.791Z
8
+ * Date: 2016-06-08T12:14:46.286Z
9
9
  */
10
10
 
11
11
  (function (factory) {
@@ -27,6 +27,7 @@
27
27
  var $window = $(window);
28
28
  var $document = $(document);
29
29
  var location = window.location;
30
+ var navigator = window.navigator;
30
31
  var ArrayBuffer = window.ArrayBuffer;
31
32
  var Uint8Array = window.Uint8Array;
32
33
  var DataView = window.DataView;
@@ -89,6 +90,7 @@
89
90
 
90
91
  // Supports
91
92
  var SUPPORT_CANVAS = $.isFunction($('<canvas>')[0].getContext);
93
+ var IS_SAFARI_OR_UIWEBVIEW = navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent);
92
94
 
93
95
  // Maths
94
96
  var num = Number;
@@ -101,11 +103,7 @@
101
103
  var round = Math.round;
102
104
  var floor = Math.floor;
103
105
 
104
- // Prototype
105
- var prototype = {
106
- version: '2.2.1'
107
- };
108
-
106
+ // Utilities
109
107
  var fromCharCode = String.fromCharCode;
110
108
 
111
109
  function isNumber(n) {
@@ -159,8 +157,8 @@
159
157
  function getImageSize(image, callback) {
160
158
  var newImage;
161
159
 
162
- // Modern browsers
163
- if (image.naturalWidth) {
160
+ // Modern browsers (ignore Safari, #120 & #509)
161
+ if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) {
164
162
  return callback(image.naturalWidth, image.naturalHeight);
165
163
  }
166
164
 
@@ -180,14 +178,15 @@
180
178
  var scaleX = options.scaleX;
181
179
  var scaleY = options.scaleY;
182
180
 
183
- if (isNumber(rotate)) {
184
- transforms.push('rotate(' + rotate + 'deg)');
185
- }
186
-
181
+ // Scale should come first before rotate (#633)
187
182
  if (isNumber(scaleX) && isNumber(scaleY)) {
188
183
  transforms.push('scale(' + scaleX + ',' + scaleY + ')');
189
184
  }
190
185
 
186
+ if (isNumber(rotate)) {
187
+ transforms.push('rotate(' + rotate + 'deg)');
188
+ }
189
+
191
190
  return transforms.length ? transforms.join(' ') : 'none';
192
191
  }
193
192
 
@@ -219,61 +218,61 @@
219
218
  function getSourceCanvas(image, data) {
220
219
  var canvas = $('<canvas>')[0];
221
220
  var context = canvas.getContext('2d');
222
- var x = 0;
223
- var y = 0;
224
- var width = data.naturalWidth;
225
- var height = data.naturalHeight;
221
+ var dstX = 0;
222
+ var dstY = 0;
223
+ var dstWidth = data.naturalWidth;
224
+ var dstHeight = data.naturalHeight;
226
225
  var rotate = data.rotate;
227
226
  var scaleX = data.scaleX;
228
227
  var scaleY = data.scaleY;
229
228
  var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1);
230
229
  var rotatable = isNumber(rotate) && rotate !== 0;
231
230
  var advanced = rotatable || scalable;
232
- var canvasWidth = width;
233
- var canvasHeight = height;
231
+ var canvasWidth = dstWidth * abs(scaleX || 1);
232
+ var canvasHeight = dstHeight * abs(scaleY || 1);
234
233
  var translateX;
235
234
  var translateY;
236
235
  var rotated;
237
236
 
238
237
  if (scalable) {
239
- translateX = width / 2;
240
- translateY = height / 2;
238
+ translateX = canvasWidth / 2;
239
+ translateY = canvasHeight / 2;
241
240
  }
242
241
 
243
242
  if (rotatable) {
244
243
  rotated = getRotatedSizes({
245
- width: width,
246
- height: height,
244
+ width: canvasWidth,
245
+ height: canvasHeight,
247
246
  degree: rotate
248
247
  });
249
248
 
250
249
  canvasWidth = rotated.width;
251
250
  canvasHeight = rotated.height;
252
- translateX = rotated.width / 2;
253
- translateY = rotated.height / 2;
251
+ translateX = canvasWidth / 2;
252
+ translateY = canvasHeight / 2;
254
253
  }
255
254
 
256
255
  canvas.width = canvasWidth;
257
256
  canvas.height = canvasHeight;
258
257
 
259
258
  if (advanced) {
260
- x = -width / 2;
261
- y = -height / 2;
259
+ dstX = -dstWidth / 2;
260
+ dstY = -dstHeight / 2;
262
261
 
263
262
  context.save();
264
263
  context.translate(translateX, translateY);
265
264
  }
266
265
 
267
- if (rotatable) {
268
- context.rotate(rotate * Math.PI / 180);
269
- }
270
-
271
- // Should call `scale` after rotated
266
+ // Scale should come first before rotate (#633, #709)
272
267
  if (scalable) {
273
268
  context.scale(scaleX, scaleY);
274
269
  }
275
270
 
276
- context.drawImage(image, floor(x), floor(y), floor(width), floor(height));
271
+ if (rotatable) {
272
+ context.rotate(rotate * Math.PI / 180);
273
+ }
274
+
275
+ context.drawImage(image, floor(dstX), floor(dstY), floor(dstWidth), floor(dstHeight));
277
276
 
278
277
  if (advanced) {
279
278
  context.restore();
@@ -282,6 +281,27 @@
282
281
  return canvas;
283
282
  }
284
283
 
284
+ function getTouchesCenter(touches) {
285
+ var length = touches.length;
286
+ var pageX = 0;
287
+ var pageY = 0;
288
+
289
+ if (length) {
290
+ $.each(touches, function (i, touch) {
291
+ pageX += touch.pageX;
292
+ pageY += touch.pageY;
293
+ });
294
+
295
+ pageX /= length;
296
+ pageY /= length;
297
+ }
298
+
299
+ return {
300
+ pageX: pageX,
301
+ pageY: pageY
302
+ };
303
+ }
304
+
285
305
  function getStringFromCharCode(dataView, start, length) {
286
306
  var str = '';
287
307
  var i;
@@ -355,8 +375,11 @@
355
375
  // Get the original orientation value
356
376
  orientation = dataView.getUint16(offset, littleEndian);
357
377
 
358
- // Override the orientation with the default value: 1
359
- dataView.setUint16(offset, 1, littleEndian);
378
+ // Override the orientation with its default value for Safari (#120)
379
+ if (IS_SAFARI_OR_UIWEBVIEW) {
380
+ dataView.setUint16(offset, 1, littleEndian);
381
+ }
382
+
360
383
  break;
361
384
  }
362
385
  }
@@ -405,6 +428,7 @@
405
428
  this.isDisabled = false;
406
429
  this.isReplaced = false;
407
430
  this.isLimited = false;
431
+ this.wheeling = false;
408
432
  this.isImg = false;
409
433
  this.originalUrl = '';
410
434
  this.canvas = null;
@@ -412,7 +436,9 @@
412
436
  this.init();
413
437
  }
414
438
 
415
- $.extend(prototype, {
439
+ Cropper.prototype = {
440
+ constructor: Cropper,
441
+
416
442
  init: function () {
417
443
  var $this = this.$element;
418
444
  var url;
@@ -489,6 +515,10 @@
489
515
  read(this.response);
490
516
  };
491
517
 
518
+ if (options.checkCrossOrigin && isCrossOriginURL(url) && $this.prop('crossOrigin')) {
519
+ url = addTimestamp(url);
520
+ }
521
+
492
522
  xhr.open('get', url);
493
523
  xhr.responseType = 'arraybuffer';
494
524
  xhr.send();
@@ -569,9 +599,12 @@
569
599
  if (options.checkCrossOrigin && isCrossOriginURL(url)) {
570
600
  crossOrigin = $this.prop('crossOrigin');
571
601
 
572
- // Bust cache (#148), only when there was not a "crossOrigin" property
573
- if (!crossOrigin) {
602
+ if (crossOrigin) {
603
+ crossOriginUrl = url;
604
+ } else {
574
605
  crossOrigin = 'anonymous';
606
+
607
+ // Bust cache (#148) when there is not a "crossOrigin" property
575
608
  crossOriginUrl = addTimestamp(url);
576
609
  }
577
610
  }
@@ -619,10 +652,8 @@
619
652
  stop: function () {
620
653
  this.$clone.remove();
621
654
  this.$clone = null;
622
- }
623
- });
655
+ },
624
656
 
625
- $.extend(prototype, {
626
657
  build: function () {
627
658
  var options = this.options;
628
659
  var $this = this.$element;
@@ -706,6 +737,7 @@
706
737
  // Trigger the built event asynchronously to keep `data('cropper')` is defined
707
738
  setTimeout($.proxy(function () {
708
739
  this.trigger(EVENT_BUILT);
740
+ this.trigger(EVENT_CROP, this.getData());
709
741
  this.isCompleted = true;
710
742
  }, this), 0);
711
743
  },
@@ -740,10 +772,8 @@
740
772
 
741
773
  this.$cropper.remove();
742
774
  this.$cropper = null;
743
- }
744
- });
775
+ },
745
776
 
746
- $.extend(prototype, {
747
777
  render: function () {
748
778
  this.initContainer();
749
779
  this.initCanvas();
@@ -1202,23 +1232,17 @@
1202
1232
 
1203
1233
  if (this.isCompleted) {
1204
1234
  this.trigger(EVENT_CROP, this.getData());
1205
- } else if (!this.isBuilt) {
1206
-
1207
- // Only trigger one crop event before complete
1208
- this.$element.one(EVENT_BUILT, $.proxy(function () {
1209
- this.trigger(EVENT_CROP, this.getData());
1210
- }, this));
1211
1235
  }
1212
- }
1213
- });
1236
+ },
1214
1237
 
1215
- $.extend(prototype, {
1216
1238
  initPreview: function () {
1217
1239
  var crossOrigin = getCrossOrigin(this.crossOrigin);
1218
1240
  var url = crossOrigin ? this.crossOriginUrl : this.url;
1241
+ var $clone2;
1219
1242
 
1220
1243
  this.$preview = $(this.options.preview);
1221
- this.$viewBox.html('<img' + crossOrigin + ' src="' + url + '">');
1244
+ this.$clone2 = $clone2 = $('<img' + crossOrigin + ' src="' + url + '">');
1245
+ this.$viewBox.html($clone2);
1222
1246
  this.$preview.each(function () {
1223
1247
  var $this = $(this);
1224
1248
 
@@ -1271,7 +1295,7 @@
1271
1295
  return;
1272
1296
  }
1273
1297
 
1274
- this.$viewBox.find('img').css({
1298
+ this.$clone2.css({
1275
1299
  width: width,
1276
1300
  height: height,
1277
1301
  marginLeft: -left,
@@ -1310,10 +1334,8 @@
1310
1334
  transform: getTransform(image)
1311
1335
  });
1312
1336
  });
1313
- }
1314
- });
1337
+ },
1315
1338
 
1316
- $.extend(prototype, {
1317
1339
  bind: function () {
1318
1340
  var options = this.options;
1319
1341
  var $this = this.$element;
@@ -1400,10 +1422,8 @@
1400
1422
  if (options.responsive) {
1401
1423
  $window.off(EVENT_RESIZE, this._resize);
1402
1424
  }
1403
- }
1404
- });
1425
+ },
1405
1426
 
1406
- $.extend(prototype, {
1407
1427
  resize: function () {
1408
1428
  var restore = this.options.restore;
1409
1429
  var $container = this.$container;
@@ -1452,8 +1472,7 @@
1452
1472
  },
1453
1473
 
1454
1474
  wheel: function (event) {
1455
- var originalEvent = event.originalEvent;
1456
- var e = originalEvent || event;
1475
+ var e = event.originalEvent || event;
1457
1476
  var ratio = num(this.options.wheelZoomRatio) || 0.1;
1458
1477
  var delta = 1;
1459
1478
 
@@ -1463,6 +1482,17 @@
1463
1482
 
1464
1483
  event.preventDefault();
1465
1484
 
1485
+ // Limit wheel speed to prevent zoom too fast
1486
+ if (this.wheeling) {
1487
+ return;
1488
+ }
1489
+
1490
+ this.wheeling = true;
1491
+
1492
+ setTimeout($.proxy(function () {
1493
+ this.wheeling = false;
1494
+ }, this), 50);
1495
+
1466
1496
  if (e.deltaY) {
1467
1497
  delta = e.deltaY > 0 ? 1 : -1;
1468
1498
  } else if (e.wheelDelta) {
@@ -1471,7 +1501,7 @@
1471
1501
  delta = e.detail > 0 ? 1 : -1;
1472
1502
  }
1473
1503
 
1474
- this.zoom(-delta * ratio, originalEvent);
1504
+ this.zoom(-delta * ratio, event);
1475
1505
  },
1476
1506
 
1477
1507
  cropStart: function (event) {
@@ -1571,7 +1601,7 @@
1571
1601
  this.endX = e.pageX || originalEvent && originalEvent.pageX;
1572
1602
  this.endY = e.pageY || originalEvent && originalEvent.pageY;
1573
1603
 
1574
- this.change(e.shiftKey, action === ACTION_ZOOM ? originalEvent : null);
1604
+ this.change(e.shiftKey, action === ACTION_ZOOM ? event : null);
1575
1605
  }
1576
1606
  },
1577
1607
 
@@ -1598,11 +1628,9 @@
1598
1628
  action: action
1599
1629
  });
1600
1630
  }
1601
- }
1602
- });
1631
+ },
1603
1632
 
1604
- $.extend(prototype, {
1605
- change: function (shiftKey, originalEvent) {
1633
+ change: function (shiftKey, event) {
1606
1634
  var options = this.options;
1607
1635
  var aspectRatio = options.aspectRatio;
1608
1636
  var action = this.action;
@@ -1628,11 +1656,11 @@
1628
1656
  aspectRatio = width && height ? width / height : 1;
1629
1657
  }
1630
1658
 
1631
- if (this.limited) {
1659
+ if (this.isLimited) {
1632
1660
  minLeft = cropBox.minLeft;
1633
1661
  minTop = cropBox.minTop;
1634
- maxWidth = minLeft + min(container.width, canvas.width);
1635
- maxHeight = minTop + min(container.height, canvas.height);
1662
+ maxWidth = minLeft + min(container.width, canvas.left + canvas.width);
1663
+ maxHeight = minTop + min(container.height, canvas.top + canvas.height);
1636
1664
  }
1637
1665
 
1638
1666
  range = {
@@ -1945,7 +1973,7 @@
1945
1973
  abs(this.startY - this.startY2),
1946
1974
  abs(this.endX - this.endX2),
1947
1975
  abs(this.endY - this.endY2)
1948
- ), originalEvent);
1976
+ ), event);
1949
1977
  this.startX2 = this.endX2;
1950
1978
  this.startY2 = this.endY2;
1951
1979
  renderable = false;
@@ -1980,7 +2008,7 @@
1980
2008
  this.$cropBox.removeClass(CLASS_HIDDEN);
1981
2009
  this.isCropped = true;
1982
2010
 
1983
- if (this.limited) {
2011
+ if (this.isLimited) {
1984
2012
  this.limitCropBox(true, true);
1985
2013
  }
1986
2014
  }
@@ -2003,10 +2031,7 @@
2003
2031
  // Override
2004
2032
  this.startX = this.endX;
2005
2033
  this.startY = this.endY;
2006
- }
2007
- });
2008
-
2009
- $.extend(prototype, {
2034
+ },
2010
2035
 
2011
2036
  // Show the crop box manually
2012
2037
  crop: function () {
@@ -2074,17 +2099,30 @@
2074
2099
  * Replace the image's src and rebuild the cropper
2075
2100
  *
2076
2101
  * @param {String} url
2102
+ * @param {Boolean} onlyColorChanged (optional)
2077
2103
  */
2078
- replace: function (url) {
2104
+ replace: function (url, onlyColorChanged) {
2079
2105
  if (!this.isDisabled && url) {
2080
2106
  if (this.isImg) {
2081
- this.isReplaced = true;
2082
2107
  this.$element.attr('src', url);
2083
2108
  }
2084
2109
 
2085
- // Clear previous data
2086
- this.options.data = null;
2087
- this.load(url);
2110
+ if (onlyColorChanged) {
2111
+ this.url = url;
2112
+ this.$clone.attr('src', url);
2113
+
2114
+ if (this.isBuilt) {
2115
+ this.$preview.find('img').add(this.$clone2).attr('src', url);
2116
+ }
2117
+ } else {
2118
+ if (this.isImg) {
2119
+ this.isReplaced = true;
2120
+ }
2121
+
2122
+ // Clear previous data
2123
+ this.options.data = null;
2124
+ this.load(url);
2125
+ }
2088
2126
  }
2089
2127
  },
2090
2128
 
@@ -2180,9 +2218,9 @@
2180
2218
  * Zoom the canvas with a relative ratio
2181
2219
  *
2182
2220
  * @param {Number} ratio
2183
- * @param {Event} _originalEvent (private)
2221
+ * @param {jQuery Event} _event (private)
2184
2222
  */
2185
- zoom: function (ratio, _originalEvent) {
2223
+ zoom: function (ratio, _event) {
2186
2224
  var canvas = this.canvas;
2187
2225
 
2188
2226
  ratio = num(ratio);
@@ -2193,24 +2231,27 @@
2193
2231
  ratio = 1 + ratio;
2194
2232
  }
2195
2233
 
2196
- this.zoomTo(canvas.width * ratio / canvas.naturalWidth, _originalEvent);
2234
+ this.zoomTo(canvas.width * ratio / canvas.naturalWidth, _event);
2197
2235
  },
2198
2236
 
2199
2237
  /**
2200
2238
  * Zoom the canvas to an absolute ratio
2201
2239
  *
2202
2240
  * @param {Number} ratio
2203
- * @param {Event} _originalEvent (private)
2241
+ * @param {jQuery Event} _event (private)
2204
2242
  */
2205
- zoomTo: function (ratio, _originalEvent) {
2243
+ zoomTo: function (ratio, _event) {
2206
2244
  var options = this.options;
2207
2245
  var canvas = this.canvas;
2208
2246
  var width = canvas.width;
2209
2247
  var height = canvas.height;
2210
2248
  var naturalWidth = canvas.naturalWidth;
2211
2249
  var naturalHeight = canvas.naturalHeight;
2250
+ var originalEvent;
2212
2251
  var newWidth;
2213
2252
  var newHeight;
2253
+ var offset;
2254
+ var center;
2214
2255
 
2215
2256
  ratio = num(ratio);
2216
2257
 
@@ -2218,16 +2259,39 @@
2218
2259
  newWidth = naturalWidth * ratio;
2219
2260
  newHeight = naturalHeight * ratio;
2220
2261
 
2262
+ if (_event) {
2263
+ originalEvent = _event.originalEvent;
2264
+ }
2265
+
2221
2266
  if (this.trigger(EVENT_ZOOM, {
2222
- originalEvent: _originalEvent,
2267
+ originalEvent: originalEvent,
2223
2268
  oldRatio: width / naturalWidth,
2224
2269
  ratio: newWidth / naturalWidth
2225
2270
  }).isDefaultPrevented()) {
2226
2271
  return;
2227
2272
  }
2228
2273
 
2229
- canvas.left -= (newWidth - width) / 2;
2230
- canvas.top -= (newHeight - height) / 2;
2274
+ if (originalEvent) {
2275
+ offset = this.$cropper.offset();
2276
+ center = originalEvent.touches ? getTouchesCenter(originalEvent.touches) : {
2277
+ pageX: _event.pageX || originalEvent.pageX || 0,
2278
+ pageY: _event.pageY || originalEvent.pageY || 0
2279
+ };
2280
+
2281
+ // Zoom from the triggering point of the event
2282
+ canvas.left -= (newWidth - width) * (
2283
+ ((center.pageX - offset.left) - canvas.left) / width
2284
+ );
2285
+ canvas.top -= (newHeight - height) * (
2286
+ ((center.pageY - offset.top) - canvas.top) / height
2287
+ );
2288
+ } else {
2289
+
2290
+ // Zoom from the center of the canvas
2291
+ canvas.left -= (newWidth - width) / 2;
2292
+ canvas.top -= (newHeight - height) / 2;
2293
+ }
2294
+
2231
2295
  canvas.width = newWidth;
2232
2296
  canvas.height = newHeight;
2233
2297
  this.renderCanvas(true);
@@ -2556,12 +2620,12 @@
2556
2620
  cropBox.top = data.top;
2557
2621
  }
2558
2622
 
2559
- if (isNumber(data.width) && data.width !== cropBox.width) {
2623
+ if (isNumber(data.width)) {
2560
2624
  isWidthChanged = true;
2561
2625
  cropBox.width = data.width;
2562
2626
  }
2563
2627
 
2564
- if (isNumber(data.height) && data.height !== cropBox.height) {
2628
+ if (isNumber(data.height)) {
2565
2629
  isHeightChanged = true;
2566
2630
  cropBox.height = data.height;
2567
2631
  }
@@ -2597,10 +2661,14 @@
2597
2661
  var context;
2598
2662
  var data;
2599
2663
 
2600
- if (!this.isBuilt || !this.isCropped || !SUPPORT_CANVAS) {
2664
+ if (!this.isBuilt || !SUPPORT_CANVAS) {
2601
2665
  return;
2602
2666
  }
2603
2667
 
2668
+ if (!this.isCropped) {
2669
+ return getSourceCanvas(this.$clone[0], this.image);
2670
+ }
2671
+
2604
2672
  if (!$.isPlainObject(options)) {
2605
2673
  options = {};
2606
2674
  }
@@ -2623,9 +2691,9 @@
2623
2691
  }
2624
2692
  }
2625
2693
 
2626
-
2627
- canvasWidth = round(scaledWidth || originalWidth);
2628
- canvasHeight = round(scaledHeight || originalHeight);
2694
+ // The canvas element will use `Math.floor` on a float number, so floor first
2695
+ canvasWidth = floor(scaledWidth || originalWidth);
2696
+ canvasHeight = floor(scaledHeight || originalHeight);
2629
2697
 
2630
2698
  canvas = $('<canvas>')[0];
2631
2699
  canvas.width = canvasWidth;
@@ -2642,11 +2710,12 @@
2642
2710
  var source = getSourceCanvas(this.$clone[0], this.image);
2643
2711
  var sourceWidth = source.width;
2644
2712
  var sourceHeight = source.height;
2645
- var args = [source];
2713
+ var canvas = this.canvas;
2714
+ var params = [source];
2646
2715
 
2647
2716
  // Source canvas
2648
- var srcX = data.x;
2649
- var srcY = data.y;
2717
+ var srcX = data.x + canvas.naturalWidth * (abs(data.scaleX || 1) - 1) / 2;
2718
+ var srcY = data.y + canvas.naturalHeight * (abs(data.scaleY || 1) - 1) / 2;
2650
2719
  var srcWidth;
2651
2720
  var srcHeight;
2652
2721
 
@@ -2679,7 +2748,7 @@
2679
2748
  }
2680
2749
 
2681
2750
  // All the numerical parameters should be integer for `drawImage` (#476)
2682
- args.push(floor(srcX), floor(srcY), floor(srcWidth), floor(srcHeight));
2751
+ params.push(floor(srcX), floor(srcY), floor(srcWidth), floor(srcHeight));
2683
2752
 
2684
2753
  // Scale destination sizes
2685
2754
  if (scaledRatio) {
@@ -2691,10 +2760,10 @@
2691
2760
 
2692
2761
  // Avoid "IndexSizeError" in IE and Firefox
2693
2762
  if (dstWidth > 0 && dstHeight > 0) {
2694
- args.push(floor(dstX), floor(dstY), floor(dstWidth), floor(dstHeight));
2763
+ params.push(floor(dstX), floor(dstY), floor(dstWidth), floor(dstHeight));
2695
2764
  }
2696
2765
 
2697
- return args;
2766
+ return params;
2698
2767
  }).call(this));
2699
2768
 
2700
2769
  return canvas;
@@ -2753,9 +2822,7 @@
2753
2822
  }
2754
2823
  }
2755
2824
  }
2756
- });
2757
-
2758
- $.extend(Cropper.prototype, prototype);
2825
+ };
2759
2826
 
2760
2827
  Cropper.DEFAULTS = {
2761
2828
 
@@ -2891,24 +2958,26 @@
2891
2958
  Cropper.other = $.fn.cropper;
2892
2959
 
2893
2960
  // Register as jQuery plugin
2894
- $.fn.cropper = function (options) {
2961
+ $.fn.cropper = function (option) {
2895
2962
  var args = toArray(arguments, 1);
2896
2963
  var result;
2897
2964
 
2898
2965
  this.each(function () {
2899
2966
  var $this = $(this);
2900
2967
  var data = $this.data(NAMESPACE);
2968
+ var options;
2901
2969
  var fn;
2902
2970
 
2903
2971
  if (!data) {
2904
- if (/destroy/.test(options)) {
2972
+ if (/destroy/.test(option)) {
2905
2973
  return;
2906
2974
  }
2907
2975
 
2976
+ options = $.extend({}, $this.data(), $.isPlainObject(option) && option);
2908
2977
  $this.data(NAMESPACE, (data = new Cropper(this, options)));
2909
2978
  }
2910
2979
 
2911
- if (typeof options === 'string' && $.isFunction(fn = data[options])) {
2980
+ if (typeof option === 'string' && $.isFunction(fn = data[option])) {
2912
2981
  result = fn.apply(data, args);
2913
2982
  }
2914
2983
  });
@@ -1,36 +1,41 @@
1
1
  /*!
2
- * Cropper v2.2.1
2
+ * Cropper v2.3.2
3
3
  * https://github.com/fengyuanchen/cropper
4
4
  *
5
- * Copyright (c) 2014-2015 Fengyuan Chen and contributors
5
+ * Copyright (c) 2014-2016 Fengyuan Chen and contributors
6
6
  * Released under the MIT license
7
7
  *
8
- * Date: 2015-12-12T07:24:22.254Z
8
+ * Date: 2016-06-08T12:14:46.286Z
9
9
  */
10
10
  .cropper-container {
11
- position: relative;
12
11
  font-size: 0;
13
12
  line-height: 0;
14
- direction: ltr !important;
15
- -ms-touch-action: none;
16
- touch-action: none;
13
+
14
+ position: relative;
15
+
17
16
  -webkit-user-select: none;
18
17
  -moz-user-select: none;
19
18
  -ms-user-select: none;
20
19
  user-select: none;
20
+
21
+ direction: ltr !important;
22
+ -ms-touch-action: none;
23
+ touch-action: none;
21
24
  -webkit-tap-highlight-color: transparent;
22
25
  -webkit-touch-callout: none;
23
26
  }
24
27
 
25
28
  .cropper-container img {
26
29
  display: block;
27
- image-orientation: 0deg !important;
30
+
31
+ width: 100%;
28
32
  min-width: 0 !important;
29
- min-height: 0 !important;
30
33
  max-width: none !important;
31
- max-height: none !important;
32
- width: 100%;
33
34
  height: 100%;
35
+ min-height: 0 !important;
36
+ max-height: none !important;
37
+
38
+ image-orientation: 0deg !important;
34
39
  }
35
40
 
36
41
  .cropper-wrap-box,
@@ -50,73 +55,93 @@
50
55
  }
51
56
 
52
57
  .cropper-drag-box {
53
- background-color: #fff;
54
58
  opacity: 0;
59
+ background-color: #fff;
60
+
55
61
  filter: alpha(opacity=0);
56
62
  }
57
63
 
58
64
  .cropper-modal {
65
+ opacity: .5;
59
66
  background-color: #000;
60
- opacity: 0.5;
67
+
61
68
  filter: alpha(opacity=50);
62
69
  }
63
70
 
64
71
  .cropper-view-box {
65
72
  display: block;
66
73
  overflow: hidden;
67
- outline: 1px solid #39f;
68
- outline-color: rgba(51, 153, 255, 0.75);
74
+
69
75
  width: 100%;
70
76
  height: 100%;
77
+
78
+ outline: 1px solid #39f;
79
+ outline-color: rgba(51, 153, 255, .75);
71
80
  }
72
81
 
73
82
  .cropper-dashed {
74
83
  position: absolute;
84
+
75
85
  display: block;
86
+
87
+ opacity: .5;
76
88
  border: 0 dashed #eee;
77
- opacity: 0.5;
89
+
78
90
  filter: alpha(opacity=50);
79
91
  }
80
92
 
81
93
  .cropper-dashed.dashed-h {
82
94
  top: 33.33333%;
83
95
  left: 0;
84
- border-top-width: 1px;
85
- border-bottom-width: 1px;
96
+
86
97
  width: 100%;
87
98
  height: 33.33333%;
99
+
100
+ border-top-width: 1px;
101
+ border-bottom-width: 1px;
88
102
  }
89
103
 
90
104
  .cropper-dashed.dashed-v {
91
105
  top: 0;
92
106
  left: 33.33333%;
93
- border-right-width: 1px;
94
- border-left-width: 1px;
107
+
95
108
  width: 33.33333%;
96
109
  height: 100%;
110
+
111
+ border-right-width: 1px;
112
+ border-left-width: 1px;
97
113
  }
98
114
 
99
115
  .cropper-center {
100
116
  position: absolute;
101
117
  top: 50%;
102
118
  left: 50%;
119
+
103
120
  display: block;
121
+
104
122
  width: 0;
105
123
  height: 0;
106
- opacity: 0.75;
124
+
125
+ opacity: .75;
126
+
107
127
  filter: alpha(opacity=75);
108
128
  }
109
129
 
110
- .cropper-center:before, .cropper-center:after {
130
+ .cropper-center:before,
131
+ .cropper-center:after {
111
132
  position: absolute;
133
+
112
134
  display: block;
135
+
136
+ content: ' ';
137
+
113
138
  background-color: #eee;
114
- content: " ";
115
139
  }
116
140
 
117
141
  .cropper-center:before {
118
142
  top: 0;
119
143
  left: -3px;
144
+
120
145
  width: 7px;
121
146
  height: 1px;
122
147
  }
@@ -124,6 +149,7 @@
124
149
  .cropper-center:after {
125
150
  top: -3px;
126
151
  left: 0;
152
+
127
153
  width: 1px;
128
154
  height: 7px;
129
155
  }
@@ -132,16 +158,21 @@
132
158
  .cropper-line,
133
159
  .cropper-point {
134
160
  position: absolute;
161
+
135
162
  display: block;
163
+
136
164
  width: 100%;
137
165
  height: 100%;
138
- opacity: 0.1;
166
+
167
+ opacity: .1;
168
+
139
169
  filter: alpha(opacity=10);
140
170
  }
141
171
 
142
172
  .cropper-face {
143
173
  top: 0;
144
174
  left: 0;
175
+
145
176
  background-color: #fff;
146
177
  }
147
178
 
@@ -152,92 +183,117 @@
152
183
  .cropper-line.line-e {
153
184
  top: 0;
154
185
  right: -3px;
186
+
155
187
  width: 5px;
188
+
156
189
  cursor: e-resize;
157
190
  }
158
191
 
159
192
  .cropper-line.line-n {
160
193
  top: -3px;
161
194
  left: 0;
195
+
162
196
  height: 5px;
197
+
163
198
  cursor: n-resize;
164
199
  }
165
200
 
166
201
  .cropper-line.line-w {
167
202
  top: 0;
168
203
  left: -3px;
204
+
169
205
  width: 5px;
206
+
170
207
  cursor: w-resize;
171
208
  }
172
209
 
173
210
  .cropper-line.line-s {
174
211
  bottom: -3px;
175
212
  left: 0;
213
+
176
214
  height: 5px;
215
+
177
216
  cursor: s-resize;
178
217
  }
179
218
 
180
219
  .cropper-point {
181
- background-color: #39f;
182
220
  width: 5px;
183
221
  height: 5px;
184
- opacity: 0.75;
222
+
223
+ opacity: .75;
224
+ background-color: #39f;
225
+
185
226
  filter: alpha(opacity=75);
186
227
  }
187
228
 
188
229
  .cropper-point.point-e {
189
230
  top: 50%;
190
231
  right: -3px;
232
+
191
233
  margin-top: -3px;
234
+
192
235
  cursor: e-resize;
193
236
  }
194
237
 
195
238
  .cropper-point.point-n {
196
239
  top: -3px;
197
240
  left: 50%;
241
+
198
242
  margin-left: -3px;
243
+
199
244
  cursor: n-resize;
200
245
  }
201
246
 
202
247
  .cropper-point.point-w {
203
248
  top: 50%;
204
249
  left: -3px;
250
+
205
251
  margin-top: -3px;
252
+
206
253
  cursor: w-resize;
207
254
  }
208
255
 
209
256
  .cropper-point.point-s {
210
257
  bottom: -3px;
211
258
  left: 50%;
259
+
212
260
  margin-left: -3px;
261
+
213
262
  cursor: s-resize;
214
263
  }
215
264
 
216
265
  .cropper-point.point-ne {
217
266
  top: -3px;
218
267
  right: -3px;
268
+
219
269
  cursor: ne-resize;
220
270
  }
221
271
 
222
272
  .cropper-point.point-nw {
223
273
  top: -3px;
224
274
  left: -3px;
275
+
225
276
  cursor: nw-resize;
226
277
  }
227
278
 
228
279
  .cropper-point.point-sw {
229
280
  bottom: -3px;
230
281
  left: -3px;
282
+
231
283
  cursor: sw-resize;
232
284
  }
233
285
 
234
286
  .cropper-point.point-se {
235
287
  right: -3px;
236
288
  bottom: -3px;
237
- cursor: se-resize;
289
+
238
290
  width: 20px;
239
291
  height: 20px;
292
+
293
+ cursor: se-resize;
294
+
240
295
  opacity: 1;
296
+
241
297
  filter: alpha(opacity=100);
242
298
  }
243
299
 
@@ -245,12 +301,17 @@
245
301
  position: absolute;
246
302
  right: -50%;
247
303
  bottom: -50%;
304
+
248
305
  display: block;
249
- content: " ";
250
- background-color: #39f;
306
+
251
307
  width: 200%;
252
308
  height: 200%;
309
+
310
+ content: ' ';
311
+
253
312
  opacity: 0;
313
+ background-color: #39f;
314
+
254
315
  filter: alpha(opacity=0);
255
316
  }
256
317
 
@@ -272,23 +333,28 @@
272
333
  .cropper-point.point-se {
273
334
  width: 5px;
274
335
  height: 5px;
275
- opacity: 0.75;
336
+
337
+ opacity: .75;
338
+
276
339
  filter: alpha(opacity=75);
277
340
  }
278
341
  }
279
342
 
280
343
  .cropper-invisible {
281
344
  opacity: 0;
345
+
282
346
  filter: alpha(opacity=0);
283
347
  }
284
348
 
285
349
  .cropper-bg {
286
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC");
350
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
287
351
  }
288
352
 
289
353
  .cropper-hide {
290
354
  position: absolute;
355
+
291
356
  display: block;
357
+
292
358
  width: 0;
293
359
  height: 0;
294
360
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cropper-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1.1
4
+ version: 2.3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cristian Bica
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-12-15 00:00:00.000000000 Z
11
+ date: 2016-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -97,3 +97,4 @@ signing_key:
97
97
  specification_version: 4
98
98
  summary: Fengyuanchen's Cropper with Rails assets pipeline.
99
99
  test_files: []
100
+ has_rdoc: