jquery-cropper 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZWE3ZjkxZjhlODNlMmE4ZGQ3OWZmMWY4OThkNDg5MmViYWUxZDhiYQ==
5
+ data.tar.gz: !binary |-
6
+ NWMwMGRkZDM0MTJkNzhjMTJlMDk3MmYzMmMzYmZjOWQxMzdhMDM3Mw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YjM5MTg4N2QzOGY2YThhOWM2ZGQyMWQ1ZGU2ZTk5OTNjM2UxNzNmNTdiZGM1
10
+ MWNjNWEyMThiYzNhODY4MzkyNDkxNjFlYTU4ZmMwMmUxYThmODIwYjg1MTY5
11
+ NDUxMGNkMGQ4ODYzODhjNDdmNDMwNDBhYjRlNTYwNzRlZjFjZWQ=
12
+ data.tar.gz: !binary |-
13
+ MjI3YjhiMzQ1ZjU2YWM3NmZkZDY0M2FhOGYwM2NmMGZhNDAyNDM1MTFjYzk4
14
+ ZjcxNWQyNzU2NzkyNTY3MmVjYjEwNWZiY2U1ZmMxOGU4ZjU1YjUyZmM2Njhj
15
+ ODRkYmVhNDgxZTNhNmFkNTE1ZDQ2YjFjMDJkNzFlOGMzNTBjZjU=
data/.gemspec ADDED
@@ -0,0 +1,11 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'jquery-cropper'
3
+ s.version = '0.0.1'
4
+ s.license = "MIT"
5
+ s.summary = "Wrapper for jquery cropper plugin"
6
+ s.description = "Provides ability to use jquery cropper plugin through assets pipeline"
7
+ s.authors = ["Vitaliy Yanchuk"]
8
+ s.email = 'vitaliy@yanchuk.me'
9
+ s.files = `git ls-files`.split("\n")
10
+ s.homepage = 'https://github.com/fuksito/jquery-cropper'
11
+ end
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Vitaliy Yanchuk
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Jquery::Cropper
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'jquery-cropper'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install jquery-cropper
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/jquery-cropper/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,778 @@
1
+ (function (factory) {
2
+ if (typeof define === "function" && define.amd) {
3
+ // AMD. Register as anonymous module.
4
+ define(["jquery"], factory);
5
+ } else {
6
+ // Browser globals.
7
+ factory(jQuery);
8
+ }
9
+ })(function ($) {
10
+
11
+ "use strict";
12
+
13
+ var $window = $(window),
14
+ Cropper = function (element, options) {
15
+ options = $.isPlainObject(options) ? options : {};
16
+ this.$image = $(element);
17
+ this.defaults = $.extend({}, Cropper.defaults, this.$image.data(), options);
18
+ this.init();
19
+ };
20
+
21
+ Cropper.prototype = {
22
+ construstor: Cropper,
23
+
24
+ init: function () {
25
+ this.setAspectRatio(this.defaults.aspectRatio);
26
+ this.render();
27
+ },
28
+
29
+ render: function (callback) {
30
+ var _this = this,
31
+ $image = this.$image,
32
+ $clone,
33
+ src;
34
+
35
+ if (this.active) {
36
+ return;
37
+ }
38
+
39
+ if (this.$clone) {
40
+ this.$clone.remove(); // Remove the old clone
41
+ }
42
+
43
+ src = $image.attr("src"); // Don't use "prop"
44
+ $clone = $('<img src="' + src + '">');
45
+
46
+ $clone.on("load", function () {
47
+ var image;
48
+
49
+ $clone.off("load");
50
+
51
+ if (this.naturalWidth && this.naturalHeight) {
52
+ image = {
53
+ naturalHeight: this.naturalHeight,
54
+ naturalWidth: this.naturalWidth
55
+ };
56
+ } else {
57
+ Cropper.fn.size($clone, {
58
+ height: "auto",
59
+ width: "auto"
60
+ });
61
+
62
+ image = Cropper.fn.size($clone);
63
+ image = {
64
+ naturalHeight: image.height,
65
+ naturalWidth: image.width
66
+ };
67
+ }
68
+
69
+ Cropper.fn.size($clone, {
70
+ height: "100%",
71
+ width: "100%"
72
+ });
73
+
74
+ image.aspectRatio = image.naturalWidth / image.naturalHeight;
75
+ _this.src = src;
76
+ _this.image = image;
77
+ _this.active = true;
78
+ _this.createCropper();
79
+ });
80
+
81
+ if ($.isFunction(callback)) {
82
+ $image.on("ready.cropper", callback);
83
+ }
84
+
85
+ this.$clone = $clone;
86
+ $image.after($clone);
87
+ },
88
+
89
+ unrender: function () {
90
+ if (this.active) {
91
+ this.active = false;
92
+ this.removeCropper();
93
+ this.src = "";
94
+ this.image = null;
95
+ this.cropper = null;
96
+ this.dragger = null;
97
+ }
98
+
99
+ return this;
100
+ },
101
+
102
+ rerender: function (reset) {
103
+ var _this = this;
104
+
105
+ this.unrender().render(function () {
106
+ if (!reset) {
107
+ _this.setData(_this.data); // Restore
108
+ }
109
+ });
110
+ },
111
+
112
+ resize: function () {
113
+ this.data = this.getData(); // Record the current data
114
+ clearTimeout(this.resizing);
115
+ this.resizing = setTimeout($.proxy(this.rerender, this), 200);
116
+ },
117
+
118
+ createCropper: function () {
119
+ this.$cropper = $(Cropper.template);
120
+ this.$dragger = this.$cropper.find(".cropper-dragger");
121
+ Cropper.fn.toggle(this.$image);
122
+ this.$image.after(this.$cropper);
123
+ this.$cropper.prepend(this.$clone);
124
+
125
+ if (!this.defaults.modal) {
126
+ Cropper.fn.toggle(this.$cropper.find(".cropper-modal"));
127
+ }
128
+
129
+ this.setPreview();
130
+ this.addListener();
131
+ },
132
+
133
+ removeCropper: function () {
134
+ this.removeListener();
135
+ this.$preview = null;
136
+ this.$clone.remove();
137
+ this.$clone = null;
138
+ this.$dragger = null;
139
+ this.$cropper.remove();
140
+ this.$cropper = null;
141
+ Cropper.fn.toggle(this.$image);
142
+ },
143
+
144
+ addListener: function () {
145
+ this.$cropper.bind("mousedown touchstart", $.proxy(this.dragstart, this));
146
+ this.$cropper.bind("mousemove touchmove", $.proxy(this.dragmove, this));
147
+ this.$cropper.bind("mouseup mouseleave touchend touchleave", $.proxy(this.dragend, this));
148
+ $window.on("resize", $.proxy(this.resize, this));
149
+ },
150
+
151
+ removeListener: function () {
152
+ this.$cropper.unbind("mousedown touchstart", this.dragstart);
153
+ this.$cropper.unbind("mousemove touchmove", this.dragmove);
154
+ this.$cropper.unbind("mouseup mouseleave touchend touchleave", this.dragend);
155
+ $window.off("resize", this.resize);
156
+ },
157
+
158
+ setPreview: function () {
159
+ var preview = this.defaults.preview;
160
+
161
+ this.$preview = this.$cropper.find(".cropper-preview");
162
+
163
+ if (typeof preview === "string" && preview.length > 0) {
164
+ this.$preview = this.$preview.add(preview);
165
+ }
166
+
167
+ this.$preview.html('<img src="' + this.src + '">');
168
+ this.setCropper();
169
+ },
170
+
171
+ setCropper: function () {
172
+ var $container = this.$image.parent(),
173
+ container = Cropper.fn.size($container),
174
+ image = this.image,
175
+ cropper;
176
+
177
+ if (((image.naturalWidth * container.height / image.naturalHeight) - container.width) >= 0) {
178
+ cropper = {
179
+ height: container.width / image.aspectRatio,
180
+ width: container.width,
181
+ left: 0
182
+ };
183
+
184
+ cropper.top = (container.height - cropper.height) / 2;
185
+ } else {
186
+ cropper = {
187
+ height: container.height,
188
+ width: container.height * image.aspectRatio,
189
+ top: 0
190
+ };
191
+
192
+ cropper.left = (container.width - cropper.width) / 2;
193
+ }
194
+
195
+ $.each(cropper, function (i, n) {
196
+ cropper[i] = Math.round(n);
197
+ });
198
+
199
+ image.height = cropper.height;
200
+ image.width = cropper.width;
201
+ image.ratio = image.width / image.naturalWidth;
202
+
203
+ Cropper.fn.position($container);
204
+ this.$cropper.css({
205
+ height: cropper.height,
206
+ left: cropper.left,
207
+ top: cropper.top,
208
+ width: cropper.width
209
+ });
210
+
211
+ this.cropper = cropper;
212
+ this.setDragger();
213
+ },
214
+
215
+ setDragger: function () {
216
+ var cropper = this.cropper,
217
+ // If not set, use the original aspect ratio of the image.
218
+ aspectRatio = this.defaults.aspectRatio || this.image.aspectRatio,
219
+ dragger;
220
+
221
+ if (((cropper.height * aspectRatio) - cropper.width) >= 0) {
222
+ dragger = {
223
+ height: cropper.width / aspectRatio,
224
+ width: cropper.width,
225
+ left: 0,
226
+ top: (cropper.height - (cropper.width / aspectRatio)) / 2,
227
+ maxWidth: cropper.width,
228
+ maxHeight: cropper.width / aspectRatio
229
+ };
230
+ } else {
231
+ dragger = {
232
+ height: cropper.height,
233
+ width: cropper.height * aspectRatio,
234
+ left: (cropper.width - (cropper.height * aspectRatio)) / 2,
235
+ top: 0,
236
+ maxHeight: cropper.height,
237
+ maxWidth: cropper.height * aspectRatio
238
+ };
239
+ }
240
+
241
+ dragger.height *= 0.8;
242
+ dragger.width *= 0.8;
243
+
244
+ dragger.left = (cropper.width - dragger.width) / 2;
245
+ dragger.top = (cropper.height - dragger.height) / 2;
246
+
247
+ this.dragger = Cropper.fn.round(dragger);
248
+ this.setData(this.defaults.data);
249
+ this.$image.trigger("ready.cropper").off("ready.cropper");
250
+ },
251
+
252
+ resetDragger: function () {
253
+ var dragger = this.dragger,
254
+ cropper = this.cropper;
255
+
256
+ dragger.width = dragger.width > dragger.maxWidth ? dragger.maxWidth : Math.abs(dragger.width);
257
+ dragger.height = dragger.height > dragger.maxHeight ? dragger.maxHeight : Math.abs(dragger.height);
258
+
259
+ dragger.maxLeft = cropper.width - dragger.width;
260
+ dragger.maxTop = cropper.height - dragger.height;
261
+
262
+ dragger.left = dragger.left < 0 ? 0 : dragger.left > dragger.maxLeft ? dragger.maxLeft : dragger.left;
263
+ dragger.top = dragger.top < 0 ? 0 : dragger.top > dragger.maxTop ? dragger.maxTop : dragger.top;
264
+
265
+ dragger = Cropper.fn.round(dragger);
266
+
267
+ this.$dragger.css({
268
+ height: dragger.height,
269
+ left: dragger.left,
270
+ top: dragger.top,
271
+ width: dragger.width
272
+ });
273
+
274
+ this.dragger = dragger;
275
+ this.preview();
276
+ this.output();
277
+ },
278
+
279
+ dragging: function () {
280
+ var direction = this.direction,
281
+ dragger = this.dragger,
282
+ aspectRatio = this.defaults.aspectRatio,
283
+ range = {
284
+ x: this.endX - this.startX,
285
+ y: this.endY - this.startY
286
+ };
287
+
288
+ if (aspectRatio) {
289
+ range.X = range.y * aspectRatio;
290
+ range.Y = range.x / aspectRatio;
291
+ }
292
+
293
+ switch (direction) {
294
+
295
+ // dragging
296
+ case "e":
297
+ dragger.width += range.x;
298
+
299
+ if (aspectRatio) {
300
+ dragger.height = dragger.width / aspectRatio;
301
+ dragger.top -= range.Y / 2;
302
+ }
303
+
304
+ if (dragger.width < 0) {
305
+ this.direction = "w";
306
+ dragger.width = 0;
307
+ }
308
+
309
+ break;
310
+
311
+ case "n":
312
+ dragger.height -= range.y;
313
+ dragger.top += range.y;
314
+
315
+ if (aspectRatio) {
316
+ dragger.width = dragger.height * aspectRatio;
317
+ dragger.left += range.X / 2;
318
+ }
319
+
320
+ if (dragger.height < 0) {
321
+ this.direction = "s";
322
+ dragger.height = 0;
323
+ }
324
+
325
+ break;
326
+
327
+ case "w":
328
+ dragger.width -= range.x;
329
+ dragger.left += range.x;
330
+
331
+ if (aspectRatio) {
332
+ dragger.height = dragger.width / aspectRatio;
333
+ dragger.top += range.Y / 2;
334
+ }
335
+
336
+ if (dragger.width < 0) {
337
+ this.direction = "e";
338
+ dragger.width = 0;
339
+ }
340
+
341
+ break;
342
+
343
+ case "s":
344
+ dragger.height += range.y;
345
+
346
+ if (aspectRatio) {
347
+ dragger.width = dragger.height * aspectRatio;
348
+ dragger.left -= range.X / 2;
349
+ }
350
+
351
+ if (dragger.height < 0) {
352
+ this.direction = "n";
353
+ dragger.height = 0;
354
+ }
355
+
356
+ break;
357
+
358
+ case "ne":
359
+ dragger.height -= range.y;
360
+ dragger.top += range.y;
361
+
362
+ if (aspectRatio) {
363
+ dragger.width = dragger.height * aspectRatio;
364
+ } else {
365
+ dragger.width += range.x;
366
+ }
367
+
368
+ if (dragger.height < 0) {
369
+ this.direction = "sw";
370
+ dragger.height = 0;
371
+ dragger.width = 0;
372
+ }
373
+
374
+ break;
375
+
376
+ case "nw":
377
+ dragger.height -= range.y;
378
+ dragger.top += range.y;
379
+
380
+ if (aspectRatio) {
381
+ dragger.width = dragger.height * aspectRatio;
382
+ dragger.left += range.X;
383
+ } else {
384
+ dragger.width -= range.x;
385
+ dragger.left += range.x;
386
+ }
387
+
388
+ if (dragger.height < 0) {
389
+ this.direction = "se";
390
+ dragger.height = 0;
391
+ dragger.width = 0;
392
+ }
393
+
394
+ break;
395
+
396
+ case "sw":
397
+ dragger.width -= range.x;
398
+ dragger.left += range.x;
399
+
400
+ if (aspectRatio) {
401
+ dragger.height = dragger.width / aspectRatio;
402
+ } else {
403
+ dragger.height += range.y;
404
+ }
405
+
406
+ if (dragger.width < 0) {
407
+ this.direction = "ne";
408
+ dragger.height = 0;
409
+ dragger.width = 0;
410
+ }
411
+
412
+ break;
413
+
414
+ case "se":
415
+ dragger.width += range.x;
416
+
417
+ if (aspectRatio) {
418
+ dragger.height = dragger.width / aspectRatio;
419
+ } else {
420
+ dragger.height += range.y;
421
+ }
422
+
423
+ if (dragger.width < 0) {
424
+ this.direction = "nw";
425
+ dragger.height = 0;
426
+ dragger.width = 0;
427
+ }
428
+
429
+ break;
430
+
431
+ // moving
432
+ default:
433
+ dragger.left += range.x;
434
+ dragger.top += range.y;
435
+ }
436
+
437
+ this.resetDragger();
438
+ this.startX = this.endX;
439
+ this.startY = this.endY;
440
+ },
441
+
442
+ output: function () {
443
+ this.defaults.done(this.getData());
444
+ },
445
+
446
+ preview: function () {
447
+ var _this = this,
448
+ cropper = _this.cropper,
449
+ dragger = _this.dragger;
450
+
451
+ this.$preview.each(function () {
452
+ var $this = $(this),
453
+ ratio = $this.width() / dragger.width,
454
+ styles = {
455
+ height: cropper.height,
456
+ marginLeft: - dragger.left,
457
+ marginTop: - dragger.top,
458
+ width: cropper.width
459
+ };
460
+
461
+ $this.css({overflow: "hidden"});
462
+ $this.find("img").css(Cropper.fn.round(styles, function (n) {
463
+ return n * ratio;
464
+ }));
465
+ });
466
+ },
467
+
468
+ // Public methods
469
+
470
+ enable: function (callback) {
471
+ this.render(callback);
472
+ },
473
+
474
+ disable: function () {
475
+ this.unrender();
476
+ },
477
+
478
+ setAspectRatio: function (aspectRatio) {
479
+ if (aspectRatio === "auto" || ($.isNumeric(aspectRatio) && aspectRatio > 0)) {
480
+ this.defaults.aspectRatio = aspectRatio === "auto" ? NaN : aspectRatio;
481
+
482
+ if (this.active) {
483
+ this.setDragger();
484
+ }
485
+ }
486
+ },
487
+
488
+ setData: function (data) {
489
+ var cropper = this.cropper,
490
+ dragger = this.dragger,
491
+ aspectRatio = this.defaults.aspectRatio,
492
+ isNumber = function (n) {
493
+ return typeof n === "number";
494
+ };
495
+
496
+ if (!this.active) {
497
+ return;
498
+ }
499
+
500
+ if ($.isPlainObject(data) && !$.isEmptyObject(data)) {
501
+ data = Cropper.fn.transformData(data, this.image.ratio);
502
+
503
+ if (isNumber(data.x1) && data.x1 <= cropper.width) {
504
+ dragger.left = data.x1;
505
+ }
506
+
507
+ if (isNumber(data.y1) && data.y1 <= cropper.height) {
508
+ dragger.top = data.y1;
509
+ }
510
+
511
+ if (aspectRatio){
512
+ if (isNumber(data.width) && data.width <= cropper.width) {
513
+ dragger.width = data.width;
514
+ dragger.height = dragger.width / aspectRatio;
515
+ } else if (isNumber(data.height) && data.height <= cropper.height) {
516
+ dragger.height = data.height;
517
+ dragger.width = dragger.height * aspectRatio;
518
+ } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
519
+ dragger.width = data.x2 - dragger.left;
520
+ dragger.height = dragger.width / aspectRatio;
521
+ } else if (isNumber(data.y2) && data.y2 <= cropper.height) {
522
+ dragger.height = data.y2 - dragger.top;
523
+ dragger.width = dragger.height * aspectRatio;
524
+ }
525
+ } else {
526
+ if (isNumber(data.width) && data.width <= cropper.width) {
527
+ dragger.width = data.width;
528
+ } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
529
+ dragger.width = data.x2 - dragger.left;
530
+ }
531
+
532
+ if (isNumber(data.height) && data.height <= cropper.height) {
533
+ dragger.height = data.height;
534
+ } else if (isNumber(data.y2) && data.height <= cropper.height) {
535
+ dragger.height = data.y2 - dragger.top;
536
+ }
537
+ }
538
+ }
539
+
540
+ this.dragger = dragger;
541
+ this.resetDragger();
542
+ },
543
+
544
+ getData: function () {
545
+ var dragger = this.dragger,
546
+ data = {};
547
+
548
+ if (this.active) {
549
+ data = {
550
+ x1: dragger.left,
551
+ y1: dragger.top,
552
+ width: dragger.width,
553
+ height: dragger.height,
554
+ x2: dragger.left + dragger.width,
555
+ y2: dragger.top + dragger.height
556
+ };
557
+
558
+ data = Cropper.fn.transformData(data, (1 / this.image.ratio));
559
+ }
560
+
561
+ return data;
562
+ },
563
+
564
+ setImgSrc: function (src) {
565
+ if (typeof src === "string" && src.length > 0 && src !== this.src) {
566
+ this.$image.attr("src", src);
567
+ this.rerender(true);
568
+ }
569
+ },
570
+
571
+ getImgInfo: function () {
572
+ return this.image || {};
573
+ },
574
+
575
+ // Public events
576
+
577
+ dragstart: function (event) {
578
+ var touches = Cropper.fn.getOriginalEvent(event).touches,
579
+ e = event,
580
+ touching,
581
+ direction;
582
+
583
+ if (touches && touches.length === 1) {
584
+ e = touches[0];
585
+ this.touchId = e.identifier;
586
+ touching = true;
587
+ }
588
+
589
+ direction = $(e.target).data().direction;
590
+
591
+ if (Cropper.fn.isDirection(direction)) {
592
+ this.startX = e.pageX;
593
+ this.startY = e.pageY;
594
+ this.direction = direction;
595
+ this.$image.trigger("dragstart");
596
+ touching && event.preventDefault();
597
+ }
598
+ },
599
+
600
+ dragmove: function (event) {
601
+ var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
602
+ e = event,
603
+ touching;
604
+
605
+ if (touches && touches.length === 1) {
606
+ e = touches[0];
607
+ touching = true;
608
+
609
+ if (e.identifier !== this.touchId) {
610
+ return;
611
+ }
612
+ }
613
+
614
+ if (this.direction) {
615
+ this.$image.trigger("dragmove");
616
+ touching && event.preventDefault();
617
+ this.endX = e.pageX;
618
+ this.endY = e.pageY;
619
+ this.dragging();
620
+ }
621
+ },
622
+
623
+ dragend: function (event) {
624
+ var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
625
+ e = event,
626
+ touching;
627
+
628
+ if (touches && touches.length === 1) {
629
+ e = touches[0];
630
+ touching = true;
631
+
632
+ if (e.identifier !== this.touchId) {
633
+ return;
634
+ }
635
+ }
636
+
637
+ if (this.direction) {
638
+ this.direction = "";
639
+ this.$image.trigger("dragend");
640
+ touching && event.preventDefault();
641
+ }
642
+ }
643
+ };
644
+
645
+ // Common methods
646
+ Cropper.fn = {
647
+ toggle: function ($e) {
648
+ $e.toggleClass("cropper-hidden");
649
+ },
650
+
651
+ position: function ($e, option) {
652
+ var position = $e.css("position");
653
+
654
+ if (position === "static") {
655
+ $e.css("position", option || "relative");
656
+ }
657
+ },
658
+
659
+ size: function ($e, options) {
660
+ if ($.isPlainObject(options)) {
661
+ $e.css(options);
662
+ } else {
663
+ return {
664
+ height: $e.height(),
665
+ width: $e.width()
666
+ };
667
+ }
668
+ },
669
+
670
+ round: function (data, fn) {
671
+ var value,
672
+ i;
673
+
674
+ for (i in data) {
675
+ value = data[i];
676
+
677
+ if (data.hasOwnProperty(i) && typeof value === "number") {
678
+ data[i] = Math.round($.isFunction(fn) ? fn(value) : value);
679
+ }
680
+ }
681
+
682
+ return data;
683
+ },
684
+
685
+ transformData: function (data, ratio) {
686
+ var _this = this,
687
+ result = {};
688
+
689
+ $.each(data, function (i, n) {
690
+ if (_this.isDataOption(i) && $.isNumeric(n) && n >= 0) {
691
+ result[i] = Math.round(n * ratio);
692
+ }
693
+ });
694
+
695
+ return result;
696
+ },
697
+
698
+ getOriginalEvent: function (event) {
699
+ if (event && typeof event.originalEvent !== "undefined") {
700
+ event = event.originalEvent;
701
+ }
702
+
703
+ return event;
704
+ },
705
+
706
+ isDataOption: function (s) {
707
+ return /^(x1|y1|x2|y2|width|height)$/i.test(s);
708
+ },
709
+
710
+ isDirection: function (s) {
711
+ return /^(\*|e|n|w|s|ne|nw|sw|se)$/i.test(s);
712
+ }
713
+ };
714
+
715
+ Cropper.template = [
716
+ '<div class="cropper-container">',
717
+ '<div class="cropper-modal"></div>',
718
+ '<div class="cropper-dragger">',
719
+ '<span class="cropper-preview"></span>',
720
+ '<span class="cropper-dashed dashed-h"></span>',
721
+ '<span class="cropper-dashed dashed-v"></span>',
722
+ '<span class="cropper-face" data-direction="*"></span>',
723
+ '<span class="cropper-line line-e" data-direction="e"></span>',
724
+ '<span class="cropper-line line-n" data-direction="n"></span>',
725
+ '<span class="cropper-line line-w" data-direction="w"></span>',
726
+ '<span class="cropper-line line-s" data-direction="s"></span>',
727
+ '<span class="cropper-point point-e" data-direction="e"></span>',
728
+ '<span class="cropper-point point-n" data-direction="n"></span>',
729
+ '<span class="cropper-point point-w" data-direction="w"></span>',
730
+ '<span class="cropper-point point-s" data-direction="s"></span>',
731
+ '<span class="cropper-point point-ne" data-direction="ne"></span>',
732
+ '<span class="cropper-point point-nw" data-direction="nw"></span>',
733
+ '<span class="cropper-point point-sw" data-direction="sw"></span>',
734
+ '<span class="cropper-point point-se" data-direction="se"></span>',
735
+ '</div>',
736
+ '</div>'
737
+ ].join("");
738
+
739
+ Cropper.defaults = {
740
+ aspectRatio: "auto",
741
+ data: {},
742
+ done: function (/* data */) {},
743
+ modal: true,
744
+ preview: ""
745
+ };
746
+
747
+ Cropper.setDefaults = function (options) {
748
+ $.extend(Cropper.defaults, options);
749
+ };
750
+
751
+ // Register as jQuery plugin
752
+ $.fn.cropper = function (options, settings) {
753
+ var result = this;
754
+
755
+ this.each(function () {
756
+ var $this = $(this),
757
+ data = $this.data("cropper");
758
+
759
+ if (!data) {
760
+ data = new Cropper(this, options);
761
+ $this.data("cropper", data);
762
+ }
763
+
764
+ if (typeof options === "string" && $.isFunction(data[options])) {
765
+ result = data[options](settings);
766
+ }
767
+ });
768
+
769
+ return (typeof result !== "undefined" ? result : this);
770
+ };
771
+
772
+ $.fn.cropper.Constructor = Cropper;
773
+ $.fn.cropper.setDefaults = Cropper.setDefaults;
774
+
775
+ $(function () {
776
+ $("img[cropper]").cropper();
777
+ });
778
+ });
@@ -0,0 +1,226 @@
1
+ .cropper-container {
2
+ position: relative;
3
+ overflow: hidden;
4
+ -webkit-user-select: none;
5
+ -moz-user-select: none;
6
+ -ms-user-select: none;
7
+ user-select: none;
8
+ background-color: #fff;
9
+
10
+ -webkit-tap-highlight-color: transparent;
11
+ -webkit-touch-callout: none;
12
+ }
13
+
14
+ .cropper-container img {
15
+ max-width: none !important;
16
+ max-height: none !important;
17
+ }
18
+
19
+ .cropper-container .cropper-modal {
20
+ position: absolute;
21
+ top: 0;
22
+ right: 0;
23
+ bottom: 0;
24
+ left: 0;
25
+ background: #000;
26
+ filter: alpha(opacity=50);
27
+ opacity: .5;
28
+ }
29
+
30
+ .cropper-container .cropper-dragger {
31
+ position: absolute;
32
+ top: 10%;
33
+ left: 10%;
34
+ width: 80%;
35
+ height: 80%;
36
+ }
37
+
38
+ .cropper-container .cropper-preview {
39
+ display: block;
40
+ width: 100%;
41
+ height: 100%;
42
+ -webkit-box-sizing: border-box;
43
+ -moz-box-sizing: border-box;
44
+ box-sizing: border-box;
45
+ overflow: hidden;
46
+ border-color: #69f;
47
+ border-color: rgba(51, 102, 255, .75);
48
+ border-style: solid;
49
+ border-width: 1px;
50
+ }
51
+
52
+ .cropper-container .cropper-dashed {
53
+ position: absolute;
54
+ display: block;
55
+ filter: alpha(opacity=50);
56
+ border: 0 dashed #fff;
57
+ opacity: .5;
58
+ }
59
+
60
+ .cropper-container .dashed-h {
61
+ top: 33.3%;
62
+ left: 0;
63
+ width: 100%;
64
+ height: 33.3%;
65
+ border-top-width: 1px;
66
+ border-bottom-width: 1px;
67
+ }
68
+
69
+ .cropper-container .dashed-v {
70
+ top: 0;
71
+ left: 33.3%;
72
+ width: 33.3%;
73
+ height: 100%;
74
+ border-right-width: 1px;
75
+ border-left-width: 1px;
76
+ }
77
+
78
+ .cropper-container .cropper-face,
79
+ .cropper-container .cropper-line,
80
+ .cropper-container .cropper-point {
81
+ position: absolute;
82
+ display: block;
83
+ width: 100%;
84
+ height: 100%;
85
+ filter: alpha(opacity=10);
86
+ opacity: .1;
87
+ }
88
+
89
+ .cropper-container .cropper-face {
90
+ top: 0;
91
+ left: 0;
92
+ cursor: move;
93
+ background-color: #fff;
94
+ }
95
+
96
+ .cropper-container .cropper-line {
97
+ background-color: #69f;
98
+ }
99
+
100
+ .cropper-container .line-e {
101
+ top: 0;
102
+ right: -2px;
103
+ width: 5px;
104
+ cursor: e-resize;
105
+ }
106
+
107
+ .cropper-container .line-n {
108
+ top: -2px;
109
+ left: 0;
110
+ height: 5px;
111
+ cursor: n-resize;
112
+ }
113
+
114
+ .cropper-container .line-w {
115
+ top: 0;
116
+ left: -2px;
117
+ width: 5px;
118
+ cursor: w-resize;
119
+ }
120
+
121
+ .cropper-container .line-s {
122
+ bottom: -2px;
123
+ left: 0;
124
+ height: 5px;
125
+ cursor: s-resize;
126
+ }
127
+
128
+ .cropper-container .cropper-point {
129
+ width: 5px;
130
+ height: 5px;
131
+ background-color: #69f;
132
+ filter: alpha(opacity=75);
133
+ opacity: .75;
134
+ }
135
+
136
+ .cropper-container .point-e {
137
+ top: 49%;
138
+ right: -2px;
139
+ cursor: e-resize;
140
+ }
141
+
142
+ .cropper-container .point-n {
143
+ top: -2px;
144
+ left: 49%;
145
+ cursor: n-resize;
146
+ }
147
+
148
+ .cropper-container .point-w {
149
+ top: 49%;
150
+ left: -2px;
151
+ cursor: w-resize;
152
+ }
153
+
154
+ .cropper-container .point-s {
155
+ bottom: -2px;
156
+ left: 49%;
157
+ cursor: s-resize;
158
+ }
159
+
160
+ .cropper-container .point-ne {
161
+ top: -2px;
162
+ right: -2px;
163
+ cursor: ne-resize;
164
+ }
165
+
166
+ .cropper-container .point-nw {
167
+ top: -2px;
168
+ left: -2px;
169
+ cursor: nw-resize;
170
+ }
171
+
172
+ .cropper-container .point-sw {
173
+ bottom: -2px;
174
+ left: -2px;
175
+ cursor: sw-resize;
176
+ }
177
+
178
+ .cropper-container .point-se {
179
+ right: -2px;
180
+ bottom: -2px;
181
+ width: 20px;
182
+ height: 20px;
183
+ cursor: se-resize;
184
+ filter: alpha(opacity=100);
185
+ opacity: 1;
186
+ }
187
+
188
+ .cropper-container .point-se:before {
189
+ position: absolute;
190
+ right: -50%;
191
+ bottom: -50%;
192
+ display: block;
193
+ width: 200%;
194
+ height: 200%;
195
+ content: " ";
196
+ background-color: #69f;
197
+ filter: alpha(opacity=0);
198
+ opacity: 0;
199
+ }
200
+
201
+ @media (min-width: 768px) {
202
+ .cropper-container .point-se {
203
+ width: 15px;
204
+ height: 15px;
205
+ }
206
+ }
207
+
208
+ @media (min-width: 992px) {
209
+ .cropper-container .point-se {
210
+ width: 10px;
211
+ height: 10px;
212
+ }
213
+ }
214
+
215
+ @media (min-width: 1200px) {
216
+ .cropper-container .point-se {
217
+ width: 5px;
218
+ height: 5px;
219
+ filter: alpha(opacity=75);
220
+ opacity: .75;
221
+ }
222
+ }
223
+
224
+ .cropper-hidden {
225
+ display: none !important;
226
+ }
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jquery/cropper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jquery-cropper"
8
+ spec.version = Jquery::Cropper::VERSION
9
+ spec.authors = ["Vitaliy Yanchuk"]
10
+ spec.email = ["vitaliy@yanchuk.me"]
11
+ spec.summary = %q{ jquery cropper plugin through assets pipeline }
12
+ spec.description = %q{ Helps using cropper plugin in rails through assets pipeline }
13
+ spec.homepage = "http://github.com/fuksito/jquery-cropper"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.5"
20
+ spec.add_development_dependency "rake"
21
+ end
@@ -0,0 +1,7 @@
1
+ require "jquery/cropper/engine"
2
+ require "jquery/cropper/version"
3
+
4
+ module Jquery
5
+ module Cropper
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ require 'rails'
2
+
3
+ module Jquery
4
+ module Cropper
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Jquery
2
+ module Cropper
3
+ VERSION = "0.3.4"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jquery-cropper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.4
5
+ platform: ruby
6
+ authors:
7
+ - Vitaliy Yanchuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: ! ' Helps using cropper plugin in rails through assets pipeline '
42
+ email:
43
+ - vitaliy@yanchuk.me
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gemspec
49
+ - .gitignore
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - app/assets/javascripts/cropper.js
55
+ - app/assets/stylesheets/cropper.scss
56
+ - jquery-cropper.gemspec
57
+ - lib/jquery/cropper.rb
58
+ - lib/jquery/cropper/engine.rb
59
+ - lib/jquery/cropper/version.rb
60
+ homepage: http://github.com/fuksito/jquery-cropper
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.1.9
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: jquery cropper plugin through assets pipeline
84
+ test_files: []
85
+ has_rdoc: