rails_cropit 0.1.0 → 0.1.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.
@@ -0,0 +1,1188 @@
1
+ /*! cropit - v0.4.4 <https://github.com/scottcheng/cropit> */
2
+ (function webpackUniversalModuleDefinition(root, factory) {
3
+ if(typeof exports === 'object' && typeof module === 'object')
4
+ module.exports = factory(require("jquery"));
5
+ else if(typeof define === 'function' && define.amd)
6
+ define(["jquery"], factory);
7
+ else if(typeof exports === 'object')
8
+ exports["cropit"] = factory(require("jquery"));
9
+ else
10
+ root["cropit"] = factory(root["jQuery"]);
11
+ })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
12
+ return /******/ (function(modules) { // webpackBootstrap
13
+ /******/ // The module cache
14
+ /******/ var installedModules = {};
15
+
16
+ /******/ // The require function
17
+ /******/ function __webpack_require__(moduleId) {
18
+
19
+ /******/ // Check if module is in cache
20
+ /******/ if(installedModules[moduleId])
21
+ /******/ return installedModules[moduleId].exports;
22
+
23
+ /******/ // Create a new module (and put it into the cache)
24
+ /******/ var module = installedModules[moduleId] = {
25
+ /******/ exports: {},
26
+ /******/ id: moduleId,
27
+ /******/ loaded: false
28
+ /******/ };
29
+
30
+ /******/ // Execute the module function
31
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
32
+
33
+ /******/ // Flag the module as loaded
34
+ /******/ module.loaded = true;
35
+
36
+ /******/ // Return the exports of the module
37
+ /******/ return module.exports;
38
+ /******/ }
39
+
40
+
41
+ /******/ // expose the modules object (__webpack_modules__)
42
+ /******/ __webpack_require__.m = modules;
43
+
44
+ /******/ // expose the module cache
45
+ /******/ __webpack_require__.c = installedModules;
46
+
47
+ /******/ // __webpack_public_path__
48
+ /******/ __webpack_require__.p = "";
49
+
50
+ /******/ // Load entry module and return exports
51
+ /******/ return __webpack_require__(0);
52
+ /******/ })
53
+ /************************************************************************/
54
+ /******/ ([
55
+ /* 0 */
56
+ /***/ function(module, exports, __webpack_require__) {
57
+
58
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
59
+
60
+ var _jquery = __webpack_require__(1);
61
+
62
+ var _jquery2 = _interopRequireDefault(_jquery);
63
+
64
+ var _cropit = __webpack_require__(2);
65
+
66
+ var _cropit2 = _interopRequireDefault(_cropit);
67
+
68
+ var _constants = __webpack_require__(4);
69
+
70
+ var _utils = __webpack_require__(6);
71
+
72
+ var applyOnEach = function applyOnEach($el, callback) {
73
+ return $el.each(function () {
74
+ var cropit = _jquery2['default'].data(this, _constants.PLUGIN_KEY);
75
+
76
+ if (!cropit) {
77
+ return;
78
+ }
79
+ callback(cropit);
80
+ });
81
+ };
82
+
83
+ var callOnFirst = function callOnFirst($el, method, options) {
84
+ var cropit = $el.first().data(_constants.PLUGIN_KEY);
85
+
86
+ if (!cropit || !_jquery2['default'].isFunction(cropit[method])) {
87
+ return null;
88
+ }
89
+ return cropit[method](options);
90
+ };
91
+
92
+ var methods = {
93
+ init: function init(options) {
94
+ return this.each(function () {
95
+ // Only instantiate once per element
96
+ if (_jquery2['default'].data(this, _constants.PLUGIN_KEY)) {
97
+ return;
98
+ }
99
+
100
+ var cropit = new _cropit2['default'](_jquery2['default'], this, options);
101
+ _jquery2['default'].data(this, _constants.PLUGIN_KEY, cropit);
102
+ });
103
+ },
104
+
105
+ destroy: function destroy() {
106
+ return this.each(function () {
107
+ _jquery2['default'].removeData(this, _constants.PLUGIN_KEY);
108
+ });
109
+ },
110
+
111
+ isZoomable: function isZoomable() {
112
+ return callOnFirst(this, 'isZoomable');
113
+ },
114
+
115
+ 'export': function _export(options) {
116
+ return callOnFirst(this, 'getCroppedImageData', options);
117
+ },
118
+
119
+ imageState: function imageState() {
120
+ return callOnFirst(this, 'getImageState');
121
+ },
122
+
123
+ imageSize: function imageSize() {
124
+ return callOnFirst(this, 'getImageSize');
125
+ },
126
+
127
+ prop: function prop(name, value) {
128
+ if ((0, _utils.exists)(value)) {
129
+ return applyOnEach(this, function (cropit) {
130
+ cropit['set' + (0, _utils.capitalize)(name)](value);
131
+ });
132
+ } else {
133
+ return callOnFirst(this, 'get' + (0, _utils.capitalize)(name));
134
+ }
135
+ },
136
+
137
+ disable: function disable() {
138
+ return applyOnEach(this, function (cropit) {
139
+ cropit.disable();
140
+ });
141
+ },
142
+
143
+ reenable: function reenable() {
144
+ return applyOnEach(this, function (cropit) {
145
+ cropit.reenable();
146
+ });
147
+ }
148
+ };
149
+
150
+ _jquery2['default'].fn.cropit = function (method) {
151
+ if (methods[method]) {
152
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
153
+ } else if (['imageSrc', 'offset', 'previewSize', 'zoom', 'initialZoom', 'exportZoom', 'minZoom', 'maxZoom'].indexOf(method) >= 0) {
154
+ return methods.prop.apply(this, arguments);
155
+ } else {
156
+ return methods.init.apply(this, arguments);
157
+ }
158
+ };
159
+
160
+ /***/ },
161
+ /* 1 */
162
+ /***/ function(module, exports) {
163
+
164
+ module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
165
+
166
+ /***/ },
167
+ /* 2 */
168
+ /***/ function(module, exports, __webpack_require__) {
169
+
170
+ Object.defineProperty(exports, '__esModule', {
171
+ value: true
172
+ });
173
+
174
+ var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
175
+
176
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
177
+
178
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
179
+
180
+ var _jquery = __webpack_require__(1);
181
+
182
+ var _jquery2 = _interopRequireDefault(_jquery);
183
+
184
+ var _Zoomer = __webpack_require__(3);
185
+
186
+ var _Zoomer2 = _interopRequireDefault(_Zoomer);
187
+
188
+ var _constants = __webpack_require__(4);
189
+
190
+ var _options = __webpack_require__(5);
191
+
192
+ var _utils = __webpack_require__(6);
193
+
194
+ var Cropit = (function () {
195
+ function Cropit(jQuery, element, options) {
196
+ _classCallCheck(this, Cropit);
197
+
198
+ this.$el = (0, _jquery2['default'])(element);
199
+
200
+ var defaults = (0, _options.loadDefaults)(this.$el);
201
+ this.options = _jquery2['default'].extend({}, defaults, options);
202
+
203
+ this.init();
204
+ }
205
+
206
+ _createClass(Cropit, [{
207
+ key: 'init',
208
+ value: function init() {
209
+ var _this = this;
210
+
211
+ this.image = new Image();
212
+ this.preImage = new Image();
213
+ this.image.onload = this.onImageLoaded.bind(this);
214
+ this.preImage.onload = this.onPreImageLoaded.bind(this);
215
+ this.image.onerror = this.preImage.onerror = function () {
216
+ _this.onImageError.call(_this, _constants.ERRORS.IMAGE_FAILED_TO_LOAD);
217
+ };
218
+
219
+ this.$fileInput = this.options.$fileInput.attr({ accept: 'image/*' });
220
+ this.$preview = this.options.$preview.css({ backgroundRepeat: 'no-repeat' });
221
+ this.$zoomSlider = this.options.$zoomSlider.attr({ min: 0, max: 1, step: 0.01 });
222
+
223
+ this.previewSize = {
224
+ w: this.options.width || this.$preview.width(),
225
+ h: this.options.height || this.$preview.height()
226
+ };
227
+ if (this.options.width) {
228
+ this.$preview.width(this.previewSize.w);
229
+ }
230
+ if (this.options.height) {
231
+ this.$preview.height(this.previewSize.h);
232
+ }
233
+
234
+ if (this.options.imageBackground) {
235
+ if (_jquery2['default'].isArray(this.options.imageBackgroundBorderWidth)) {
236
+ this.imageBgBorderWidthArray = this.options.imageBackgroundBorderWidth;
237
+ } else {
238
+ this.imageBgBorderWidthArray = [];
239
+ [0, 1, 2, 3].forEach(function (i) {
240
+ _this.imageBgBorderWidthArray[i] = _this.options.imageBackgroundBorderWidth;
241
+ });
242
+ }
243
+
244
+ var $previewContainer = this.options.$previewContainer;
245
+ this.$imageBg = (0, _jquery2['default'])('<img />').addClass(_constants.CLASS_NAMES.IMAGE_BACKGROUND).attr('alt', '').css('position', 'absolute');
246
+ this.$imageBgContainer = (0, _jquery2['default'])('<div />').addClass(_constants.CLASS_NAMES.IMAGE_BACKGROUND_CONTAINER).css({
247
+ position: 'absolute',
248
+ zIndex: 0,
249
+ left: -this.imageBgBorderWidthArray[3] + window.parseInt(this.$preview.css('border-left-width') || 0),
250
+ top: -this.imageBgBorderWidthArray[0] + window.parseInt(this.$preview.css('border-top-width') || 0),
251
+ width: this.previewSize.w + this.imageBgBorderWidthArray[1] + this.imageBgBorderWidthArray[3],
252
+ height: this.previewSize.h + this.imageBgBorderWidthArray[0] + this.imageBgBorderWidthArray[2]
253
+ }).append(this.$imageBg);
254
+ if (this.imageBgBorderWidthArray[0] > 0) {
255
+ this.$imageBgContainer.css('overflow', 'hidden');
256
+ }
257
+ $previewContainer.css('position', 'relative').prepend(this.$imageBgContainer);
258
+ this.$preview.css('position', 'relative');
259
+
260
+ this.$preview.hover(function () {
261
+ _this.$imageBg.addClass(_constants.CLASS_NAMES.PREVIEW_HOVERED);
262
+ }, function () {
263
+ _this.$imageBg.removeClass(_constants.CLASS_NAMES.PREVIEW_HOVERED);
264
+ });
265
+ }
266
+
267
+ this.setInitialZoom(this.options.initialZoom);
268
+
269
+ this.imageLoaded = false;
270
+
271
+ this.moveContinue = false;
272
+
273
+ this.zoomer = new _Zoomer2['default']();
274
+
275
+ if (this.options.allowDragNDrop) {
276
+ _jquery2['default'].event.props.push('dataTransfer');
277
+ }
278
+
279
+ this.bindListeners();
280
+
281
+ if (this.options.imageState && this.options.imageState.src) {
282
+ this.loadImage(this.options.imageState.src);
283
+ }
284
+ }
285
+ }, {
286
+ key: 'bindListeners',
287
+ value: function bindListeners() {
288
+ this.$fileInput.on('change.cropit', this.onFileChange.bind(this));
289
+ this.$preview.on(_constants.EVENTS.PREVIEW, this.onPreviewEvent.bind(this));
290
+ this.$zoomSlider.on(_constants.EVENTS.ZOOM_INPUT, this.onZoomSliderChange.bind(this));
291
+
292
+ if (this.options.allowDragNDrop) {
293
+ this.$preview.on('dragover.cropit dragleave.cropit', this.onDragOver.bind(this));
294
+ this.$preview.on('drop.cropit', this.onDrop.bind(this));
295
+ }
296
+ }
297
+ }, {
298
+ key: 'unbindListeners',
299
+ value: function unbindListeners() {
300
+ this.$fileInput.off('change.cropit');
301
+ this.$preview.off(_constants.EVENTS.PREVIEW);
302
+ this.$preview.off('dragover.cropit dragleave.cropit drop.cropit');
303
+ this.$zoomSlider.off(_constants.EVENTS.ZOOM_INPUT);
304
+ }
305
+ }, {
306
+ key: 'onFileChange',
307
+ value: function onFileChange(e) {
308
+ this.options.onFileChange(e);
309
+
310
+ if (this.$fileInput.get(0).files) {
311
+ this.loadFileReader(this.$fileInput.get(0).files[0]);
312
+ }
313
+ }
314
+ }, {
315
+ key: 'loadFileReader',
316
+ value: function loadFileReader(file) {
317
+ var fileReader = new FileReader();
318
+ if (file && file.type.match('image')) {
319
+ fileReader.readAsDataURL(file);
320
+ fileReader.onload = this.onFileReaderLoaded.bind(this);
321
+ fileReader.onerror = this.onFileReaderError.bind(this);
322
+ } else if (file) {
323
+ this.onFileReaderError();
324
+ }
325
+ }
326
+ }, {
327
+ key: 'onFileReaderLoaded',
328
+ value: function onFileReaderLoaded(e) {
329
+ this.loadImage(e.target.result);
330
+ }
331
+ }, {
332
+ key: 'onFileReaderError',
333
+ value: function onFileReaderError() {
334
+ this.options.onFileReaderError();
335
+ }
336
+ }, {
337
+ key: 'onDragOver',
338
+ value: function onDragOver(e) {
339
+ e.preventDefault();
340
+ e.dataTransfer.dropEffect = 'copy';
341
+ this.$preview.toggleClass(_constants.CLASS_NAMES.DRAG_HOVERED, e.type === 'dragover');
342
+ }
343
+ }, {
344
+ key: 'onDrop',
345
+ value: function onDrop(e) {
346
+ var _this2 = this;
347
+
348
+ e.preventDefault();
349
+ e.stopPropagation();
350
+
351
+ var files = Array.prototype.slice.call(e.dataTransfer.files, 0);
352
+ files.some(function (file) {
353
+ if (!file.type.match('image')) {
354
+ return false;
355
+ }
356
+
357
+ _this2.loadFileReader(file);
358
+ return true;
359
+ });
360
+
361
+ this.$preview.removeClass(_constants.CLASS_NAMES.DRAG_HOVERED);
362
+ }
363
+ }, {
364
+ key: 'loadImage',
365
+ value: function loadImage(imageSrc) {
366
+ if (!imageSrc) {
367
+ return;
368
+ }
369
+
370
+ this.options.onImageLoading();
371
+ this.setImageLoadingClass();
372
+
373
+ this.preImage.src = imageSrc;
374
+ }
375
+ }, {
376
+ key: 'setImageSrc',
377
+ value: function setImageSrc(imageSrc) {
378
+ this.loadImage(imageSrc);
379
+ }
380
+ }, {
381
+ key: 'onPreImageLoaded',
382
+ value: function onPreImageLoaded() {
383
+ if (this.options.smallImage === 'reject' && (this.preImage.width * this.options.maxZoom < this.previewSize.w * this.options.exportZoom || this.preImage.height * this.options.maxZoom < this.previewSize.h * this.options.exportZoom)) {
384
+ this.onImageError(_constants.ERRORS.SMALL_IMAGE);
385
+ if (this.image.src) {
386
+ this.setImageLoadedClass();
387
+ }
388
+ return;
389
+ }
390
+
391
+ if (this.options.allowCrossOrigin) {
392
+ this.image.crossOrigin = this.preImage.src.indexOf('data:') === 0 ? null : 'Anonymous';
393
+ }
394
+
395
+ this.image.src = this.imageSrc = this.preImage.src;
396
+ }
397
+ }, {
398
+ key: 'onImageLoaded',
399
+ value: function onImageLoaded() {
400
+ this.imageSize = {
401
+ w: this.image.width,
402
+ h: this.image.height
403
+ };
404
+
405
+ this.setupZoomer(this.options.imageState && this.options.imageState.zoom || this.initialZoom);
406
+ if (this.options.imageState && this.options.imageState.offset) {
407
+ this.setOffset(this.options.imageState.offset);
408
+ } else {
409
+ this.centerImage();
410
+ }
411
+
412
+ this.options.imageState = {};
413
+
414
+ this.$preview.css('background-image', 'url(' + this.imageSrc + ')');
415
+ if (this.options.imageBackground) {
416
+ this.$imageBg.attr('src', this.imageSrc);
417
+ }
418
+
419
+ this.setImageLoadedClass();
420
+
421
+ this.imageLoaded = true;
422
+
423
+ this.options.onImageLoaded();
424
+ }
425
+ }, {
426
+ key: 'onImageError',
427
+ value: function onImageError() {
428
+ this.options.onImageError.apply(this, arguments);
429
+ this.removeImageLoadingClass();
430
+ }
431
+ }, {
432
+ key: 'setImageLoadingClass',
433
+ value: function setImageLoadingClass() {
434
+ this.$preview.removeClass(_constants.CLASS_NAMES.IMAGE_LOADED).addClass(_constants.CLASS_NAMES.IMAGE_LOADING);
435
+ }
436
+ }, {
437
+ key: 'setImageLoadedClass',
438
+ value: function setImageLoadedClass() {
439
+ this.$preview.removeClass(_constants.CLASS_NAMES.IMAGE_LOADING).addClass(_constants.CLASS_NAMES.IMAGE_LOADED);
440
+ }
441
+ }, {
442
+ key: 'removeImageLoadingClass',
443
+ value: function removeImageLoadingClass() {
444
+ this.$preview.removeClass(_constants.CLASS_NAMES.IMAGE_LOADING);
445
+ }
446
+ }, {
447
+ key: 'getEventPosition',
448
+ value: function getEventPosition(e) {
449
+ if (e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]) {
450
+ e = e.originalEvent.touches[0];
451
+ }
452
+ if (e.clientX && e.clientY) {
453
+ return { x: e.clientX, y: e.clientY };
454
+ }
455
+ }
456
+ }, {
457
+ key: 'onPreviewEvent',
458
+ value: function onPreviewEvent(e) {
459
+ if (!this.imageLoaded) {
460
+ return;
461
+ }
462
+
463
+ this.moveContinue = false;
464
+ this.$preview.off(_constants.EVENTS.PREVIEW_MOVE);
465
+
466
+ if (e.type === 'mousedown' || e.type === 'touchstart') {
467
+ this.origin = this.getEventPosition(e);
468
+ this.moveContinue = true;
469
+ this.$preview.on(_constants.EVENTS.PREVIEW_MOVE, this.onMove.bind(this));
470
+ } else {
471
+ (0, _jquery2['default'])(document.body).focus();
472
+ }
473
+
474
+ e.stopPropagation();
475
+ return false;
476
+ }
477
+ }, {
478
+ key: 'onMove',
479
+ value: function onMove(e) {
480
+ var eventPosition = this.getEventPosition(e);
481
+
482
+ if (this.moveContinue && eventPosition) {
483
+ this.setOffset({
484
+ x: this.offset.x + eventPosition.x - this.origin.x,
485
+ y: this.offset.y + eventPosition.y - this.origin.y
486
+ });
487
+ }
488
+
489
+ this.origin = eventPosition;
490
+
491
+ e.stopPropagation();
492
+ return false;
493
+ }
494
+ }, {
495
+ key: 'setOffset',
496
+ value: function setOffset(position) {
497
+ if (!position || !(0, _utils.exists)(position.x) || !(0, _utils.exists)(position.y)) {
498
+ return;
499
+ }
500
+
501
+ this.offset = this.fixOffset(position);
502
+ this.$preview.css('background-position', '' + this.offset.x + 'px ' + this.offset.y + 'px');
503
+ if (this.options.imageBackground) {
504
+ this.$imageBg.css({
505
+ left: this.offset.x + this.imageBgBorderWidthArray[3],
506
+ top: this.offset.y + this.imageBgBorderWidthArray[0]
507
+ });
508
+ }
509
+
510
+ this.options.onOffsetChange(position);
511
+ }
512
+ }, {
513
+ key: 'fixOffset',
514
+ value: function fixOffset(offset) {
515
+ if (!this.imageLoaded) {
516
+ return offset;
517
+ }
518
+
519
+ var ret = { x: offset.x, y: offset.y };
520
+
521
+ if (!this.options.freeMove) {
522
+ if (this.imageSize.w * this.zoom >= this.previewSize.w) {
523
+ ret.x = Math.min(0, Math.max(ret.x, this.previewSize.w - this.imageSize.w * this.zoom));
524
+ } else {
525
+ ret.x = Math.max(0, Math.min(ret.x, this.previewSize.w - this.imageSize.w * this.zoom));
526
+ }
527
+
528
+ if (this.imageSize.h * this.zoom >= this.previewSize.h) {
529
+ ret.y = Math.min(0, Math.max(ret.y, this.previewSize.h - this.imageSize.h * this.zoom));
530
+ } else {
531
+ ret.y = Math.max(0, Math.min(ret.y, this.previewSize.h - this.imageSize.h * this.zoom));
532
+ }
533
+ }
534
+
535
+ ret.x = (0, _utils.round)(ret.x);
536
+ ret.y = (0, _utils.round)(ret.y);
537
+
538
+ return ret;
539
+ }
540
+ }, {
541
+ key: 'centerImage',
542
+ value: function centerImage() {
543
+ if (!this.imageSize || !this.zoom) {
544
+ return;
545
+ }
546
+
547
+ this.setOffset({
548
+ x: (this.previewSize.w - this.imageSize.w * this.zoom) / 2,
549
+ y: (this.previewSize.h - this.imageSize.h * this.zoom) / 2
550
+ });
551
+ }
552
+ }, {
553
+ key: 'onZoomSliderChange',
554
+ value: function onZoomSliderChange() {
555
+ if (!this.imageLoaded) {
556
+ return;
557
+ }
558
+
559
+ this.zoomSliderPos = Number(this.$zoomSlider.val());
560
+ var newZoom = this.zoomer.getZoom(this.zoomSliderPos);
561
+ if (newZoom === this.zoom) {
562
+ return;
563
+ }
564
+ this.setZoom(newZoom);
565
+ }
566
+ }, {
567
+ key: 'enableZoomSlider',
568
+ value: function enableZoomSlider() {
569
+ this.$zoomSlider.removeAttr('disabled');
570
+ this.options.onZoomEnabled();
571
+ }
572
+ }, {
573
+ key: 'disableZoomSlider',
574
+ value: function disableZoomSlider() {
575
+ this.$zoomSlider.attr('disabled', true);
576
+ this.options.onZoomDisabled();
577
+ }
578
+ }, {
579
+ key: 'setupZoomer',
580
+ value: function setupZoomer(zoom) {
581
+ this.zoomer.setup({
582
+ imageSize: this.imageSize,
583
+ previewSize: this.previewSize,
584
+ exportZoom: this.options.exportZoom,
585
+ maxZoom: this.options.maxZoom,
586
+ minZoom: this.options.minZoom,
587
+ smallImage: this.options.smallImage
588
+ });
589
+ this.setZoom((0, _utils.exists)(zoom) ? zoom : this.zoom);
590
+
591
+ if (this.isZoomable()) {
592
+ this.enableZoomSlider();
593
+ } else {
594
+ this.disableZoomSlider();
595
+ }
596
+ }
597
+ }, {
598
+ key: 'setZoom',
599
+ value: function setZoom(newZoom) {
600
+ newZoom = this.fixZoom(newZoom);
601
+
602
+ var updatedWidth = (0, _utils.round)(this.imageSize.w * newZoom);
603
+ var updatedHeight = (0, _utils.round)(this.imageSize.h * newZoom);
604
+
605
+ if (this.imageLoaded) {
606
+ var oldZoom = this.zoom;
607
+
608
+ var newX = this.previewSize.w / 2 - (this.previewSize.w / 2 - this.offset.x) * newZoom / oldZoom;
609
+ var newY = this.previewSize.h / 2 - (this.previewSize.h / 2 - this.offset.y) * newZoom / oldZoom;
610
+
611
+ this.zoom = newZoom;
612
+ this.setOffset({ x: newX, y: newY });
613
+ } else {
614
+ this.zoom = newZoom;
615
+ }
616
+
617
+ this.zoomSliderPos = this.zoomer.getSliderPos(this.zoom);
618
+ this.$zoomSlider.val(this.zoomSliderPos);
619
+
620
+ this.$preview.css('background-size', '' + updatedWidth + 'px ' + updatedHeight + 'px');
621
+ if (this.options.imageBackground) {
622
+ this.$imageBg.css({
623
+ width: updatedWidth,
624
+ height: updatedHeight
625
+ });
626
+ }
627
+
628
+ this.options.onZoomChange(newZoom);
629
+ }
630
+ }, {
631
+ key: 'fixZoom',
632
+ value: function fixZoom(zoom) {
633
+ return this.zoomer.fixZoom(zoom);
634
+ }
635
+ }, {
636
+ key: 'isZoomable',
637
+ value: function isZoomable() {
638
+ return this.zoomer.isZoomable();
639
+ }
640
+ }, {
641
+ key: 'getCroppedImageData',
642
+ value: function getCroppedImageData(exportOptions) {
643
+ if (!this.imageSrc) {
644
+ return;
645
+ }
646
+
647
+ var exportDefaults = {
648
+ type: 'image/png',
649
+ quality: 0.75,
650
+ originalSize: false,
651
+ fillBg: '#fff'
652
+ };
653
+ exportOptions = _jquery2['default'].extend({}, exportDefaults, exportOptions);
654
+
655
+ var exportZoom = exportOptions.originalSize ? 1 / this.zoom : this.options.exportZoom;
656
+
657
+ var zoomedSize = {
658
+ w: this.zoom * exportZoom * this.imageSize.w,
659
+ h: this.zoom * exportZoom * this.imageSize.h
660
+ };
661
+
662
+ var canvas = (0, _jquery2['default'])('<canvas />').attr({
663
+ width: this.previewSize.w * exportZoom,
664
+ height: this.previewSize.h * exportZoom
665
+ }).get(0);
666
+ var canvasContext = canvas.getContext('2d');
667
+
668
+ if (exportOptions.type === 'image/jpeg') {
669
+ canvasContext.fillStyle = exportOptions.fillBg;
670
+ canvasContext.fillRect(0, 0, canvas.width, canvas.height);
671
+ }
672
+
673
+ var preresizedImage = this.preresizeImage(this.image, zoomedSize.w, zoomedSize.h);
674
+ canvasContext.drawImage(preresizedImage, this.offset.x * exportZoom, this.offset.y * exportZoom, zoomedSize.w, zoomedSize.h);
675
+
676
+ return canvas.toDataURL(exportOptions.type, exportOptions.quality);
677
+ }
678
+ }, {
679
+ key: 'preresizeImage',
680
+ value: function preresizeImage(src, targetWidth, targetHeight) {
681
+ var tmp = new Image();
682
+ tmp.src = src.src;
683
+
684
+ var canvas = document.createElement('canvas');
685
+ var context = canvas.getContext('2d');
686
+ var canvasWidth = tmp.width;
687
+ var canvasHeight = tmp.height;
688
+
689
+ while (true) {
690
+ canvasWidth /= 2;
691
+ canvasHeight /= 2;
692
+
693
+ if (canvasWidth < targetWidth || canvasHeight < targetHeight) {
694
+ break;
695
+ }
696
+
697
+ canvas.width = canvasWidth;
698
+ canvas.height = canvasHeight;
699
+
700
+ context.drawImage(tmp, 0, 0, canvasWidth, canvasHeight);
701
+ tmp.src = canvas.toDataURL();
702
+ }
703
+
704
+ return tmp;
705
+ }
706
+ }, {
707
+ key: 'getImageState',
708
+ value: function getImageState() {
709
+ return {
710
+ src: this.imageSrc,
711
+ offset: this.offset,
712
+ zoom: this.zoom
713
+ };
714
+ }
715
+ }, {
716
+ key: 'getImageSrc',
717
+ value: function getImageSrc() {
718
+ return this.imageSrc;
719
+ }
720
+ }, {
721
+ key: 'getOffset',
722
+ value: function getOffset() {
723
+ return this.offset;
724
+ }
725
+ }, {
726
+ key: 'getZoom',
727
+ value: function getZoom() {
728
+ return this.zoom;
729
+ }
730
+ }, {
731
+ key: 'getImageSize',
732
+ value: function getImageSize() {
733
+ if (!this.imageSize) {
734
+ return null;
735
+ }
736
+
737
+ return {
738
+ width: this.imageSize.w,
739
+ height: this.imageSize.h
740
+ };
741
+ }
742
+ }, {
743
+ key: 'getInitialZoom',
744
+ value: function getInitialZoom() {
745
+ return this.options.initialZoom;
746
+ }
747
+ }, {
748
+ key: 'setInitialZoom',
749
+ value: function setInitialZoom(initialZoomOption) {
750
+ this.options.initialZoom = initialZoomOption;
751
+ if (initialZoomOption === 'min') {
752
+ this.initialZoom = 0; // Will be fixed when image loads
753
+ } else if (initialZoomOption === 'image') {
754
+ this.initialZoom = 1;
755
+ } else {
756
+ this.initialZoom = 0;
757
+ }
758
+ }
759
+ }, {
760
+ key: 'getExportZoom',
761
+ value: function getExportZoom() {
762
+ return this.options.exportZoom;
763
+ }
764
+ }, {
765
+ key: 'setExportZoom',
766
+ value: function setExportZoom(exportZoom) {
767
+ this.options.exportZoom = exportZoom;
768
+ this.setupZoomer();
769
+ }
770
+ }, {
771
+ key: 'getMinZoom',
772
+ value: function getMinZoom() {
773
+ return this.options.minZoom;
774
+ }
775
+ }, {
776
+ key: 'setMinZoom',
777
+ value: function setMinZoom(minZoom) {
778
+ this.options.minZoom = minZoom;
779
+ this.setupZoomer();
780
+ }
781
+ }, {
782
+ key: 'getMaxZoom',
783
+ value: function getMaxZoom() {
784
+ return this.options.maxZoom;
785
+ }
786
+ }, {
787
+ key: 'setMaxZoom',
788
+ value: function setMaxZoom(maxZoom) {
789
+ this.options.maxZoom = maxZoom;
790
+ this.setupZoomer();
791
+ }
792
+ }, {
793
+ key: 'getPreviewSize',
794
+ value: function getPreviewSize() {
795
+ return {
796
+ width: this.previewSize.w,
797
+ height: this.previewSize.h
798
+ };
799
+ }
800
+ }, {
801
+ key: 'setPreviewSize',
802
+ value: function setPreviewSize(size) {
803
+ if (!size || size.width <= 0 || size.height <= 0) {
804
+ return;
805
+ }
806
+
807
+ this.previewSize = {
808
+ w: size.width,
809
+ h: size.height
810
+ };
811
+ this.$preview.css({
812
+ width: this.previewSize.w,
813
+ height: this.previewSize.h
814
+ });
815
+
816
+ if (this.options.imageBackground) {
817
+ this.$imageBgContainer.css({
818
+ width: this.previewSize.w + this.imageBgBorderWidthArray[1] + this.imageBgBorderWidthArray[3],
819
+ height: this.previewSize.h + this.imageBgBorderWidthArray[0] + this.imageBgBorderWidthArray[2]
820
+ });
821
+ }
822
+
823
+ if (this.imageLoaded) {
824
+ this.setupZoomer();
825
+ }
826
+ }
827
+ }, {
828
+ key: 'disable',
829
+ value: function disable() {
830
+ this.unbindListeners();
831
+ this.disableZoomSlider();
832
+ this.$el.addClass(_constants.CLASS_NAMES.DISABLED);
833
+ }
834
+ }, {
835
+ key: 'reenable',
836
+ value: function reenable() {
837
+ this.bindListeners();
838
+ this.enableZoomSlider();
839
+ this.$el.removeClass(_constants.CLASS_NAMES.DISABLED);
840
+ }
841
+ }, {
842
+ key: '$',
843
+ value: function $(selector) {
844
+ if (!this.$el) {
845
+ return null;
846
+ }
847
+ return this.$el.find(selector);
848
+ }
849
+ }]);
850
+
851
+ return Cropit;
852
+ })();
853
+
854
+ exports['default'] = Cropit;
855
+ module.exports = exports['default'];
856
+
857
+ /***/ },
858
+ /* 3 */
859
+ /***/ function(module, exports) {
860
+
861
+ Object.defineProperty(exports, '__esModule', {
862
+ value: true
863
+ });
864
+
865
+ var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
866
+
867
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
868
+
869
+ var Zoomer = (function () {
870
+ function Zoomer() {
871
+ _classCallCheck(this, Zoomer);
872
+
873
+ this.minZoom = this.maxZoom = 1;
874
+ }
875
+
876
+ _createClass(Zoomer, [{
877
+ key: 'setup',
878
+ value: function setup(_ref) {
879
+ var imageSize = _ref.imageSize;
880
+ var previewSize = _ref.previewSize;
881
+ var exportZoom = _ref.exportZoom;
882
+ var maxZoom = _ref.maxZoom;
883
+ var minZoom = _ref.minZoom;
884
+ var smallImage = _ref.smallImage;
885
+
886
+ var widthRatio = previewSize.w / imageSize.w;
887
+ var heightRatio = previewSize.h / imageSize.h;
888
+
889
+ if (minZoom === 'fit') {
890
+ this.minZoom = Math.min(widthRatio, heightRatio);
891
+ } else {
892
+ this.minZoom = Math.max(widthRatio, heightRatio);
893
+ }
894
+
895
+ if (smallImage === 'allow') {
896
+ this.minZoom = Math.min(this.minZoom, 1);
897
+ }
898
+
899
+ this.maxZoom = Math.max(this.minZoom, maxZoom / exportZoom);
900
+ }
901
+ }, {
902
+ key: 'getZoom',
903
+ value: function getZoom(sliderPos) {
904
+ if (!this.minZoom || !this.maxZoom) {
905
+ return null;
906
+ }
907
+
908
+ return sliderPos * (this.maxZoom - this.minZoom) + this.minZoom;
909
+ }
910
+ }, {
911
+ key: 'getSliderPos',
912
+ value: function getSliderPos(zoom) {
913
+ if (!this.minZoom || !this.maxZoom) {
914
+ return null;
915
+ }
916
+
917
+ if (this.minZoom === this.maxZoom) {
918
+ return 0;
919
+ } else {
920
+ return (zoom - this.minZoom) / (this.maxZoom - this.minZoom);
921
+ }
922
+ }
923
+ }, {
924
+ key: 'isZoomable',
925
+ value: function isZoomable() {
926
+ if (!this.minZoom || !this.maxZoom) {
927
+ return null;
928
+ }
929
+
930
+ return this.minZoom !== this.maxZoom;
931
+ }
932
+ }, {
933
+ key: 'fixZoom',
934
+ value: function fixZoom(zoom) {
935
+ return Math.max(this.minZoom, Math.min(this.maxZoom, zoom));
936
+ }
937
+ }]);
938
+
939
+ return Zoomer;
940
+ })();
941
+
942
+ exports['default'] = Zoomer;
943
+ module.exports = exports['default'];
944
+
945
+ /***/ },
946
+ /* 4 */
947
+ /***/ function(module, exports) {
948
+
949
+ Object.defineProperty(exports, '__esModule', {
950
+ value: true
951
+ });
952
+ var PLUGIN_KEY = 'cropit';
953
+
954
+ exports.PLUGIN_KEY = PLUGIN_KEY;
955
+ var CLASS_NAMES = {
956
+ PREVIEW: 'cropit-image-preview',
957
+ PREVIEW_CONTAINER: 'cropit-image-preview-container',
958
+ FILE_INPUT: 'cropit-image-input',
959
+ ZOOM_SLIDER: 'cropit-image-zoom-input',
960
+ IMAGE_BACKGROUND: 'cropit-image-background',
961
+ IMAGE_BACKGROUND_CONTAINER: 'cropit-image-background-container',
962
+ PREVIEW_HOVERED: 'cropit-preview-hovered',
963
+ DRAG_HOVERED: 'cropit-drag-hovered',
964
+ IMAGE_LOADING: 'cropit-image-loading',
965
+ IMAGE_LOADED: 'cropit-image-loaded',
966
+ DISABLED: 'cropit-disabled'
967
+ };
968
+
969
+ exports.CLASS_NAMES = CLASS_NAMES;
970
+ var ERRORS = {
971
+ IMAGE_FAILED_TO_LOAD: { code: 0, message: 'Image failed to load.' },
972
+ SMALL_IMAGE: { code: 1, message: 'Image is too small.' }
973
+ };
974
+
975
+ exports.ERRORS = ERRORS;
976
+ var eventName = function eventName(events) {
977
+ return events.map(function (e) {
978
+ return '' + e + '.cropit';
979
+ }).join(' ');
980
+ };
981
+ var EVENTS = {
982
+ PREVIEW: eventName(['mousedown', 'mouseup', 'mouseleave', 'touchstart', 'touchend', 'touchcancel', 'touchleave']),
983
+ PREVIEW_MOVE: eventName(['mousemove', 'touchmove']),
984
+ ZOOM_INPUT: eventName(['mousemove', 'touchmove', 'change'])
985
+ };
986
+ exports.EVENTS = EVENTS;
987
+
988
+ /***/ },
989
+ /* 5 */
990
+ /***/ function(module, exports, __webpack_require__) {
991
+
992
+ Object.defineProperty(exports, '__esModule', {
993
+ value: true
994
+ });
995
+
996
+ var _constants = __webpack_require__(4);
997
+
998
+ var options = {
999
+ elements: [{
1000
+ name: '$preview',
1001
+ description: 'The HTML element that displays image preview.',
1002
+ defaultSelector: '.' + _constants.CLASS_NAMES.PREVIEW
1003
+ }, {
1004
+ name: '$fileInput',
1005
+ description: 'File input element.',
1006
+ defaultSelector: 'input.' + _constants.CLASS_NAMES.FILE_INPUT
1007
+ }, {
1008
+ name: '$zoomSlider',
1009
+ description: 'Range input element that controls image zoom.',
1010
+ defaultSelector: 'input.' + _constants.CLASS_NAMES.ZOOM_SLIDER
1011
+ }, {
1012
+ name: '$previewContainer',
1013
+ description: 'Preview container. Only needed when `imageBackground` is true.',
1014
+ defaultSelector: '.' + _constants.CLASS_NAMES.PREVIEW_CONTAINER
1015
+ }].map(function (o) {
1016
+ o.type = 'jQuery element';
1017
+ o['default'] = '$imageCropper.find(\'' + o.defaultSelector + '\')';
1018
+ return o;
1019
+ }),
1020
+
1021
+ values: [{
1022
+ name: 'width',
1023
+ type: 'number',
1024
+ description: 'Width of image preview in pixels. If set, it will override the CSS property.',
1025
+ 'default': null
1026
+ }, {
1027
+ name: 'height',
1028
+ type: 'number',
1029
+ description: 'Height of image preview in pixels. If set, it will override the CSS property.',
1030
+ 'default': null
1031
+ }, {
1032
+ name: 'imageBackground',
1033
+ type: 'boolean',
1034
+ description: 'Whether or not to display the background image beyond the preview area.',
1035
+ 'default': false
1036
+ }, {
1037
+ name: 'imageBackgroundBorderWidth',
1038
+ type: 'array or number',
1039
+ description: 'Width of background image border in pixels.\n The four array elements specify the width of background image width on the top, right, bottom, left side respectively.\n The background image beyond the width will be hidden.\n If specified as a number, border with uniform width on all sides will be applied.',
1040
+ 'default': [0, 0, 0, 0]
1041
+ }, {
1042
+ name: 'exportZoom',
1043
+ type: 'number',
1044
+ description: 'The ratio between the desired image size to export and the preview size.\n For example, if the preview size is `300px * 200px`, and `exportZoom = 2`, then\n the exported image size will be `600px * 400px`.\n This also affects the maximum zoom level, since the exported image cannot be zoomed to larger than its original size.',
1045
+ 'default': 1
1046
+ }, {
1047
+ name: 'allowDragNDrop',
1048
+ type: 'boolean',
1049
+ description: 'When set to true, you can load an image by dragging it from local file browser onto the preview area.',
1050
+ 'default': true
1051
+ }, {
1052
+ name: 'minZoom',
1053
+ type: 'string',
1054
+ description: 'This options decides the minimal zoom level of the image.\n If set to `\'fill\'`, the image has to fill the preview area, i.e. both width and height must not go smaller than the preview area.\n If set to `\'fit\'`, the image can shrink further to fit the preview area, i.e. at least one of its edges must not go smaller than the preview area.',
1055
+ 'default': 'fill'
1056
+ }, {
1057
+ name: 'maxZoom',
1058
+ type: 'number',
1059
+ description: 'Determines how big the image can be zoomed. E.g. if set to 1.5, the image can be zoomed to 150% of its original size.',
1060
+ 'default': 1
1061
+ }, {
1062
+ name: 'initialZoom',
1063
+ type: 'string',
1064
+ description: 'Determines the zoom when an image is loaded.\n When set to `\'min\'`, image is zoomed to the smallest when loaded.\n When set to `\'image\'`, image is zoomed to 100% when loaded.',
1065
+ 'default': 'min'
1066
+ }, {
1067
+ name: 'freeMove',
1068
+ type: 'boolean',
1069
+ description: 'When set to true, you can freely move the image instead of being bound to the container borders',
1070
+ 'default': false
1071
+ }, {
1072
+ name: 'smallImage',
1073
+ type: 'string',
1074
+ description: 'When set to `\'reject\'`, `onImageError` would be called when cropit loads an image that is smaller than the container.\n When set to `\'allow\'`, images smaller than the container can be zoomed down to its original size, overiding `minZoom` option.\n When set to `\'stretch\'`, the minimum zoom of small images would follow `minZoom` option.',
1075
+ 'default': 'reject'
1076
+ }, {
1077
+ name: 'allowCrossOrigin',
1078
+ type: 'boolean',
1079
+ description: 'Set to true if you need to crop image served from other domains.',
1080
+ 'default': false
1081
+ }],
1082
+
1083
+ callbacks: [{
1084
+ name: 'onFileChange',
1085
+ description: 'Called when user selects a file in the select file input.',
1086
+ params: [{
1087
+ name: 'event',
1088
+ type: 'object',
1089
+ description: 'File change event object'
1090
+ }]
1091
+ }, {
1092
+ name: 'onFileReaderError',
1093
+ description: 'Called when `FileReader` encounters an error while loading the image file.'
1094
+ }, {
1095
+ name: 'onImageLoading',
1096
+ description: 'Called when image starts to be loaded.'
1097
+ }, {
1098
+ name: 'onImageLoaded',
1099
+ description: 'Called when image is loaded.'
1100
+ }, {
1101
+ name: 'onImageError',
1102
+ description: 'Called when image cannot be loaded.',
1103
+ params: [{
1104
+ name: 'error',
1105
+ type: 'object',
1106
+ description: 'Error object.'
1107
+ }, {
1108
+ name: 'error.code',
1109
+ type: 'number',
1110
+ description: 'Error code. `0` means generic image loading failure. `1` means image is too small.'
1111
+ }, {
1112
+ name: 'error.message',
1113
+ type: 'string',
1114
+ description: 'A message explaining the error.'
1115
+ }]
1116
+ }, {
1117
+ name: 'onZoomEnabled',
1118
+ description: 'Called when image the zoom slider is enabled.'
1119
+ }, {
1120
+ name: 'onZoomDisabled',
1121
+ description: 'Called when image the zoom slider is disabled.'
1122
+ }, {
1123
+ name: 'onZoomChange',
1124
+ description: 'Called when zoom changes.',
1125
+ params: [{
1126
+ name: 'zoom',
1127
+ type: 'number',
1128
+ description: 'New zoom.'
1129
+ }]
1130
+ }, {
1131
+ name: 'onOffsetChange',
1132
+ description: 'Called when image offset changes.',
1133
+ params: [{
1134
+ name: 'offset',
1135
+ type: 'object',
1136
+ description: 'New offset, with `x` and `y` values.'
1137
+ }]
1138
+ }].map(function (o) {
1139
+ o.type = 'function';return o;
1140
+ })
1141
+ };
1142
+
1143
+ var loadDefaults = function loadDefaults($el) {
1144
+ var defaults = {};
1145
+ if ($el) {
1146
+ options.elements.forEach(function (o) {
1147
+ defaults[o.name] = $el.find(o.defaultSelector);
1148
+ });
1149
+ }
1150
+ options.values.forEach(function (o) {
1151
+ defaults[o.name] = o['default'];
1152
+ });
1153
+ options.callbacks.forEach(function (o) {
1154
+ defaults[o.name] = function () {};
1155
+ });
1156
+
1157
+ return defaults;
1158
+ };
1159
+
1160
+ exports.loadDefaults = loadDefaults;
1161
+ exports['default'] = options;
1162
+
1163
+ /***/ },
1164
+ /* 6 */
1165
+ /***/ function(module, exports) {
1166
+
1167
+ Object.defineProperty(exports, '__esModule', {
1168
+ value: true
1169
+ });
1170
+ var exists = function exists(v) {
1171
+ return typeof v !== 'undefined';
1172
+ };
1173
+
1174
+ exports.exists = exists;
1175
+ var round = function round(x) {
1176
+ return +(Math.round(x * 100) + 'e-2');
1177
+ };
1178
+
1179
+ exports.round = round;
1180
+ var capitalize = function capitalize(s) {
1181
+ return s.charAt(0).toUpperCase() + s.slice(1);
1182
+ };
1183
+ exports.capitalize = capitalize;
1184
+
1185
+ /***/ }
1186
+ /******/ ])
1187
+ });
1188
+ ;