voltron-crop 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +21 -0
- data/README.md +102 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/cropit.js +1234 -0
- data/app/assets/javascripts/simple-slider.js +363 -0
- data/app/assets/javascripts/voltron-crop.js +233 -0
- data/app/assets/stylesheets/voltron-crop.scss +98 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/generators/voltron/crop/install/assets_generator.rb +25 -0
- data/lib/generators/voltron/crop/install_generator.rb +39 -0
- data/lib/voltron/config/crop.rb +18 -0
- data/lib/voltron/crop.rb +16 -0
- data/lib/voltron/crop/action_view/field.rb +28 -0
- data/lib/voltron/crop/active_record/base.rb +52 -0
- data/lib/voltron/crop/engine.rb +17 -0
- data/lib/voltron/crop/version.rb +5 -0
- data/voltron-crop.gemspec +33 -0
- metadata +221 -0
@@ -0,0 +1,363 @@
|
|
1
|
+
/*
|
2
|
+
jQuery Simple Slider
|
3
|
+
|
4
|
+
Copyright (c) 2012 James Smith (http://loopj.com)
|
5
|
+
|
6
|
+
Licensed under the MIT license (http://mit-license.org/)
|
7
|
+
*/
|
8
|
+
|
9
|
+
var __slice = [].slice,
|
10
|
+
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
11
|
+
|
12
|
+
(function($, window) {
|
13
|
+
var SimpleSlider;
|
14
|
+
SimpleSlider = (function() {
|
15
|
+
|
16
|
+
function SimpleSlider(input, options) {
|
17
|
+
var ratio,
|
18
|
+
_this = this;
|
19
|
+
this.input = input;
|
20
|
+
this.defaultOptions = {
|
21
|
+
animate: true,
|
22
|
+
snapMid: false,
|
23
|
+
classPrefix: null,
|
24
|
+
classSuffix: null,
|
25
|
+
theme: null,
|
26
|
+
highlight: false
|
27
|
+
};
|
28
|
+
this.settings = $.extend({}, this.defaultOptions, options);
|
29
|
+
if (this.settings.theme) {
|
30
|
+
this.settings.classSuffix = "-" + this.settings.theme;
|
31
|
+
}
|
32
|
+
this.input.hide();
|
33
|
+
this.slider = $("<div>").addClass("slider" + (this.settings.classSuffix || "")).css({
|
34
|
+
position: "relative",
|
35
|
+
userSelect: "none",
|
36
|
+
boxSizing: "border-box"
|
37
|
+
}).insertBefore(this.input);
|
38
|
+
if (this.input.attr("id")) {
|
39
|
+
this.slider.attr("id", this.input.attr("id") + "-slider");
|
40
|
+
}
|
41
|
+
this.track = this.createDivElement("track").css({
|
42
|
+
width: "100%"
|
43
|
+
});
|
44
|
+
if (this.settings.highlight) {
|
45
|
+
this.highlightTrack = this.createDivElement("highlight-track").css({
|
46
|
+
width: "0"
|
47
|
+
});
|
48
|
+
}
|
49
|
+
this.dragger = this.createDivElement("dragger");
|
50
|
+
this.slider.css({
|
51
|
+
minHeight: this.dragger.outerHeight(),
|
52
|
+
marginLeft: this.dragger.outerWidth() / 2,
|
53
|
+
marginRight: this.dragger.outerWidth() / 2
|
54
|
+
});
|
55
|
+
this.track.css({
|
56
|
+
marginTop: this.track.outerHeight() / -2
|
57
|
+
});
|
58
|
+
if (this.settings.highlight) {
|
59
|
+
this.highlightTrack.css({
|
60
|
+
marginTop: this.track.outerHeight() / -2
|
61
|
+
});
|
62
|
+
}
|
63
|
+
this.dragger.css({
|
64
|
+
marginTop: this.dragger.outerHeight() / -2,
|
65
|
+
marginLeft: this.dragger.outerWidth() / -2
|
66
|
+
});
|
67
|
+
this.track.mousedown(function(e) {
|
68
|
+
return _this.trackEvent(e);
|
69
|
+
});
|
70
|
+
if (this.settings.highlight) {
|
71
|
+
this.highlightTrack.mousedown(function(e) {
|
72
|
+
return _this.trackEvent(e);
|
73
|
+
});
|
74
|
+
}
|
75
|
+
this.dragger.mousedown(function(e) {
|
76
|
+
if (e.which !== 1) {
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
_this.dragging = true;
|
80
|
+
_this.dragger.addClass("dragging");
|
81
|
+
_this.domDrag(e.pageX, e.pageY);
|
82
|
+
return false;
|
83
|
+
});
|
84
|
+
$("body").mousemove(function(e) {
|
85
|
+
if (_this.dragging) {
|
86
|
+
_this.domDrag(e.pageX, e.pageY);
|
87
|
+
return $("body").css({
|
88
|
+
cursor: "pointer"
|
89
|
+
});
|
90
|
+
}
|
91
|
+
}).mouseup(function(e) {
|
92
|
+
if (_this.dragging) {
|
93
|
+
_this.dragging = false;
|
94
|
+
_this.dragger.removeClass("dragging");
|
95
|
+
return $("body").css({
|
96
|
+
cursor: "auto"
|
97
|
+
});
|
98
|
+
}
|
99
|
+
});
|
100
|
+
this.pagePos = 0;
|
101
|
+
if (this.input.val() === "") {
|
102
|
+
this.value = this.getRange().min;
|
103
|
+
this.input.val(this.value);
|
104
|
+
} else {
|
105
|
+
this.value = this.nearestValidValue(this.input.val());
|
106
|
+
}
|
107
|
+
this.setSliderPositionFromValue(this.value);
|
108
|
+
ratio = this.valueToRatio(this.value);
|
109
|
+
this.input.trigger("slider:ready", {
|
110
|
+
value: this.value,
|
111
|
+
ratio: ratio,
|
112
|
+
position: ratio * this.slider.outerWidth(),
|
113
|
+
el: this.slider
|
114
|
+
});
|
115
|
+
}
|
116
|
+
|
117
|
+
SimpleSlider.prototype.createDivElement = function(classname) {
|
118
|
+
var item;
|
119
|
+
item = $("<div>").addClass(classname).css({
|
120
|
+
position: "absolute",
|
121
|
+
top: "50%",
|
122
|
+
userSelect: "none",
|
123
|
+
cursor: "pointer"
|
124
|
+
}).appendTo(this.slider);
|
125
|
+
return item;
|
126
|
+
};
|
127
|
+
|
128
|
+
SimpleSlider.prototype.setRatio = function(ratio) {
|
129
|
+
var value;
|
130
|
+
ratio = Math.min(1, ratio);
|
131
|
+
ratio = Math.max(0, ratio);
|
132
|
+
value = this.ratioToValue(ratio);
|
133
|
+
this.setSliderPositionFromValue(value);
|
134
|
+
return this.valueChanged(value, ratio, "setRatio");
|
135
|
+
};
|
136
|
+
|
137
|
+
SimpleSlider.prototype.setValue = function(value) {
|
138
|
+
var ratio;
|
139
|
+
value = this.nearestValidValue(value);
|
140
|
+
ratio = this.valueToRatio(value);
|
141
|
+
this.setSliderPositionFromValue(value);
|
142
|
+
return this.valueChanged(value, ratio, "setValue");
|
143
|
+
};
|
144
|
+
|
145
|
+
SimpleSlider.prototype.trackEvent = function(e) {
|
146
|
+
if (e.which !== 1) {
|
147
|
+
return;
|
148
|
+
}
|
149
|
+
this.domDrag(e.pageX, e.pageY, true);
|
150
|
+
this.dragging = true;
|
151
|
+
return false;
|
152
|
+
};
|
153
|
+
|
154
|
+
SimpleSlider.prototype.domDrag = function(pageX, pageY, animate) {
|
155
|
+
var pagePos, ratio, value;
|
156
|
+
if (animate == null) {
|
157
|
+
animate = false;
|
158
|
+
}
|
159
|
+
pagePos = pageX - this.slider.offset().left;
|
160
|
+
pagePos = Math.min(this.slider.outerWidth(), pagePos);
|
161
|
+
pagePos = Math.max(0, pagePos);
|
162
|
+
if (this.pagePos !== pagePos) {
|
163
|
+
this.pagePos = pagePos;
|
164
|
+
ratio = pagePos / this.slider.outerWidth();
|
165
|
+
value = this.ratioToValue(ratio);
|
166
|
+
this.valueChanged(value, ratio, "domDrag");
|
167
|
+
if (this.settings.snap) {
|
168
|
+
return this.setSliderPositionFromValue(value, animate);
|
169
|
+
} else {
|
170
|
+
return this.setSliderPosition(pagePos, animate);
|
171
|
+
}
|
172
|
+
}
|
173
|
+
};
|
174
|
+
|
175
|
+
SimpleSlider.prototype.setSliderPosition = function(position, animate) {
|
176
|
+
if (animate == null) {
|
177
|
+
animate = false;
|
178
|
+
}
|
179
|
+
if (animate && this.settings.animate) {
|
180
|
+
this.dragger.animate({
|
181
|
+
left: position
|
182
|
+
}, 200);
|
183
|
+
if (this.settings.highlight) {
|
184
|
+
return this.highlightTrack.animate({
|
185
|
+
width: position
|
186
|
+
}, 200);
|
187
|
+
}
|
188
|
+
} else {
|
189
|
+
this.dragger.css({
|
190
|
+
left: position
|
191
|
+
});
|
192
|
+
if (this.settings.highlight) {
|
193
|
+
return this.highlightTrack.css({
|
194
|
+
width: position
|
195
|
+
});
|
196
|
+
}
|
197
|
+
}
|
198
|
+
};
|
199
|
+
|
200
|
+
SimpleSlider.prototype.setSliderPositionFromValue = function(value, animate) {
|
201
|
+
var ratio;
|
202
|
+
if (animate == null) {
|
203
|
+
animate = false;
|
204
|
+
}
|
205
|
+
ratio = this.valueToRatio(value);
|
206
|
+
return this.setSliderPosition(ratio * this.slider.outerWidth(), animate);
|
207
|
+
};
|
208
|
+
|
209
|
+
SimpleSlider.prototype.getRange = function() {
|
210
|
+
if (this.settings.allowedValues) {
|
211
|
+
return {
|
212
|
+
min: Math.min.apply(Math, this.settings.allowedValues),
|
213
|
+
max: Math.max.apply(Math, this.settings.allowedValues)
|
214
|
+
};
|
215
|
+
} else if (this.settings.range) {
|
216
|
+
return {
|
217
|
+
min: parseFloat(this.settings.range[0]),
|
218
|
+
max: parseFloat(this.settings.range[1])
|
219
|
+
};
|
220
|
+
} else {
|
221
|
+
return {
|
222
|
+
min: 0,
|
223
|
+
max: 1
|
224
|
+
};
|
225
|
+
}
|
226
|
+
};
|
227
|
+
|
228
|
+
SimpleSlider.prototype.nearestValidValue = function(rawValue) {
|
229
|
+
var closest, maxSteps, range, steps;
|
230
|
+
range = this.getRange();
|
231
|
+
rawValue = Math.min(range.max, rawValue);
|
232
|
+
rawValue = Math.max(range.min, rawValue);
|
233
|
+
if (this.settings.allowedValues) {
|
234
|
+
closest = null;
|
235
|
+
$.each(this.settings.allowedValues, function() {
|
236
|
+
if (closest === null || Math.abs(this - rawValue) < Math.abs(closest - rawValue)) {
|
237
|
+
return closest = this;
|
238
|
+
}
|
239
|
+
});
|
240
|
+
return closest;
|
241
|
+
} else if (this.settings.step) {
|
242
|
+
maxSteps = (range.max - range.min) / this.settings.step;
|
243
|
+
steps = Math.floor((rawValue - range.min) / this.settings.step);
|
244
|
+
if ((rawValue - range.min) % this.settings.step > this.settings.step / 2 && steps < maxSteps) {
|
245
|
+
steps += 1;
|
246
|
+
}
|
247
|
+
return steps * this.settings.step + range.min;
|
248
|
+
} else {
|
249
|
+
return rawValue;
|
250
|
+
}
|
251
|
+
};
|
252
|
+
|
253
|
+
SimpleSlider.prototype.valueToRatio = function(value) {
|
254
|
+
var allowedVal, closest, closestIdx, idx, range, _i, _len, _ref;
|
255
|
+
if (this.settings.equalSteps) {
|
256
|
+
_ref = this.settings.allowedValues;
|
257
|
+
for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
|
258
|
+
allowedVal = _ref[idx];
|
259
|
+
if (!(typeof closest !== "undefined" && closest !== null) || Math.abs(allowedVal - value) < Math.abs(closest - value)) {
|
260
|
+
closest = allowedVal;
|
261
|
+
closestIdx = idx;
|
262
|
+
}
|
263
|
+
}
|
264
|
+
if (this.settings.snapMid) {
|
265
|
+
return (closestIdx + 0.5) / this.settings.allowedValues.length;
|
266
|
+
} else {
|
267
|
+
return closestIdx / (this.settings.allowedValues.length - 1);
|
268
|
+
}
|
269
|
+
} else {
|
270
|
+
range = this.getRange();
|
271
|
+
return (value - range.min) / (range.max - range.min);
|
272
|
+
}
|
273
|
+
};
|
274
|
+
|
275
|
+
SimpleSlider.prototype.ratioToValue = function(ratio) {
|
276
|
+
var idx, range, rawValue, step, steps;
|
277
|
+
if (this.settings.equalSteps) {
|
278
|
+
steps = this.settings.allowedValues.length;
|
279
|
+
step = Math.round(ratio * steps - 0.5);
|
280
|
+
idx = Math.min(step, this.settings.allowedValues.length - 1);
|
281
|
+
return this.settings.allowedValues[idx];
|
282
|
+
} else {
|
283
|
+
range = this.getRange();
|
284
|
+
rawValue = ratio * (range.max - range.min) + range.min;
|
285
|
+
return this.nearestValidValue(rawValue);
|
286
|
+
}
|
287
|
+
};
|
288
|
+
|
289
|
+
SimpleSlider.prototype.valueChanged = function(value, ratio, trigger) {
|
290
|
+
var eventData;
|
291
|
+
if (value.toString() === this.value.toString()) {
|
292
|
+
return;
|
293
|
+
}
|
294
|
+
this.value = value;
|
295
|
+
eventData = {
|
296
|
+
value: value,
|
297
|
+
ratio: ratio,
|
298
|
+
position: ratio * this.slider.outerWidth(),
|
299
|
+
trigger: trigger,
|
300
|
+
el: this.slider
|
301
|
+
};
|
302
|
+
return this.input.val(value).trigger($.Event("change", eventData)).trigger("slider:changed", eventData);
|
303
|
+
};
|
304
|
+
|
305
|
+
return SimpleSlider;
|
306
|
+
|
307
|
+
})();
|
308
|
+
$.extend($.fn, {
|
309
|
+
simpleSlider: function() {
|
310
|
+
var params, publicMethods, settingsOrMethod;
|
311
|
+
settingsOrMethod = arguments[0], params = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
312
|
+
publicMethods = ["setRatio", "setValue"];
|
313
|
+
return $(this).each(function() {
|
314
|
+
var obj, settings;
|
315
|
+
if (settingsOrMethod && __indexOf.call(publicMethods, settingsOrMethod) >= 0) {
|
316
|
+
obj = $(this).data("slider-object");
|
317
|
+
return obj[settingsOrMethod].apply(obj, params);
|
318
|
+
} else {
|
319
|
+
settings = settingsOrMethod;
|
320
|
+
return $(this).data("slider-object", new SimpleSlider($(this), settings));
|
321
|
+
}
|
322
|
+
});
|
323
|
+
}
|
324
|
+
});
|
325
|
+
return $(function() {
|
326
|
+
return $("[data-slider]").each(function() {
|
327
|
+
var $el, allowedValues, settings, x;
|
328
|
+
$el = $(this);
|
329
|
+
settings = {};
|
330
|
+
allowedValues = $el.data("slider-values");
|
331
|
+
if (allowedValues) {
|
332
|
+
settings.allowedValues = (function() {
|
333
|
+
var _i, _len, _ref, _results;
|
334
|
+
_ref = allowedValues.split(",");
|
335
|
+
_results = [];
|
336
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
337
|
+
x = _ref[_i];
|
338
|
+
_results.push(parseFloat(x));
|
339
|
+
}
|
340
|
+
return _results;
|
341
|
+
})();
|
342
|
+
}
|
343
|
+
if ($el.data("slider-range")) {
|
344
|
+
settings.range = $el.data("slider-range").split(",");
|
345
|
+
}
|
346
|
+
if ($el.data("slider-step")) {
|
347
|
+
settings.step = $el.data("slider-step");
|
348
|
+
}
|
349
|
+
settings.snap = $el.data("slider-snap");
|
350
|
+
settings.equalSteps = $el.data("slider-equal-steps");
|
351
|
+
if ($el.data("slider-theme")) {
|
352
|
+
settings.theme = $el.data("slider-theme");
|
353
|
+
}
|
354
|
+
if ($el.attr("data-slider-highlight")) {
|
355
|
+
settings.highlight = $el.data("slider-highlight");
|
356
|
+
}
|
357
|
+
if ($el.data("slider-animate") != null) {
|
358
|
+
settings.animate = $el.data("slider-animate");
|
359
|
+
}
|
360
|
+
return $el.simpleSlider(settings);
|
361
|
+
});
|
362
|
+
});
|
363
|
+
})(this.jQuery || this.Zepto, this);
|
@@ -0,0 +1,233 @@
|
|
1
|
+
//= require voltron
|
2
|
+
//= require cropit
|
3
|
+
//= require simple-slider
|
4
|
+
|
5
|
+
Voltron.addModule('Crop', function(){
|
6
|
+
|
7
|
+
var Crop = function(options, config){
|
8
|
+
|
9
|
+
var _positioned = false;
|
10
|
+
|
11
|
+
var configDefaults = {
|
12
|
+
preview: $('<div />', { class: 'cropit-preview' }),
|
13
|
+
input: $('<input />', { type: 'file', class: 'cropit-input' }),
|
14
|
+
zoom: $('<input />', { type: 'text', class: 'cropit-zoom' }),
|
15
|
+
fileInput: null,
|
16
|
+
container: null,
|
17
|
+
image: null
|
18
|
+
};
|
19
|
+
|
20
|
+
var cropDefaults = {
|
21
|
+
imageBackground: true,
|
22
|
+
imageBackgroundBorderWidth: 100,
|
23
|
+
width: 300,
|
24
|
+
height: 300,
|
25
|
+
onImageLoading: function(){
|
26
|
+
var el = this.$fileInput,
|
27
|
+
crop = el.data('crop');
|
28
|
+
|
29
|
+
// If the crop class exists on the element, store the current zoom value so
|
30
|
+
// we can pick it up later in onImageLoaded callback
|
31
|
+
if(crop){
|
32
|
+
Voltron.dispatch('crop:loading', { crop: crop, element: el.get(0) });
|
33
|
+
el.data('last_zoom', parseFloat(crop.getZoom().val()));
|
34
|
+
}
|
35
|
+
},
|
36
|
+
onImageLoaded: function(){
|
37
|
+
// Reset the zoom value to what it was before,
|
38
|
+
// then trigger a change event on the input so the image is properly resized
|
39
|
+
var el = this.$fileInput,
|
40
|
+
crop = el.data('crop'),
|
41
|
+
zoom = el.data('last_zoom');
|
42
|
+
|
43
|
+
if(crop && zoom){
|
44
|
+
Voltron.dispatch('crop:loaded', { crop: crop, element: el.get(0), data: { zoom: zoom } });
|
45
|
+
crop.getZoom().simpleSlider('setRatio', zoom);
|
46
|
+
crop.getZoom().data('sliderObject').input.val(zoom).trigger('change');
|
47
|
+
crop.setPosition();
|
48
|
+
}
|
49
|
+
}
|
50
|
+
};
|
51
|
+
|
52
|
+
config = $.extend(configDefaults, config);
|
53
|
+
options = $.extend(cropDefaults, options);
|
54
|
+
|
55
|
+
return {
|
56
|
+
initialize: function(){
|
57
|
+
// When the form is submitted, gather the x, y, width, height, zoom inputs
|
58
|
+
this.getFileInput().closest('form').on('submit', $.proxy(this.update, this))
|
59
|
+
// Add the crop html
|
60
|
+
this.getFileInput().before(this.getCropContainer());
|
61
|
+
// Initiate the zoom slider
|
62
|
+
this.getZoom().simpleSlider();
|
63
|
+
|
64
|
+
// If a cached file is present (form was submitted, but page re-rendered, possibly due to failed validation), include the input
|
65
|
+
if(this.getFileInput().data('crop-cache')){
|
66
|
+
this.getCropContainer().prepend($('<input />', { type: 'hidden', name: this.getName('cache'), value: this.getFileInput().data('crop-cache') }));
|
67
|
+
}
|
68
|
+
|
69
|
+
// If a zoom level was passed, set the slider to the specified zoom level
|
70
|
+
if(this.getFileInput().data('crop-zoom')){
|
71
|
+
this.getZoom().data('sliderObject').input.val(this.getFileInput().data('crop-zoom')).trigger('change');
|
72
|
+
}
|
73
|
+
|
74
|
+
// Include self on the file input element's data
|
75
|
+
this.getFileInput().data('crop', this);
|
76
|
+
},
|
77
|
+
|
78
|
+
update: function(){
|
79
|
+
var dimensions = this.getDimensions(),
|
80
|
+
zoom = parseFloat(this.getZoom().val());
|
81
|
+
|
82
|
+
this.getCropContainer().find('.' + this.getFieldName() + '-crop-dimension-x').val(dimensions.x);
|
83
|
+
this.getCropContainer().find('.' + this.getFieldName() + '-crop-dimension-y').val(dimensions.y);
|
84
|
+
this.getCropContainer().find('.' + this.getFieldName() + '-crop-dimension-w').val(dimensions.w);
|
85
|
+
this.getCropContainer().find('.' + this.getFieldName() + '-crop-dimension-h').val(dimensions.h);
|
86
|
+
this.getCropContainer().find('.' + this.getFieldName() + '-crop-zoom').val(zoom);
|
87
|
+
},
|
88
|
+
|
89
|
+
getDimensions: function(){
|
90
|
+
var imageBg = this.getCropObject().$bg,
|
91
|
+
borderWidth = this.getCropObject().bgBorderWidthArray,
|
92
|
+
cropImage = this.getCropContainer().cropit('imageSize'),
|
93
|
+
cropWindow = this.getCropContainer().cropit('previewSize'),
|
94
|
+
zoom = this.getCropContainer().cropit('zoom'),
|
95
|
+
cropPosition = imageBg.position(),
|
96
|
+
cropPercentX = Math.abs(cropPosition.left-borderWidth[3])/(cropImage.width*zoom),
|
97
|
+
cropPercentY = Math.abs(cropPosition.top-borderWidth[0])/(cropImage.height*zoom),
|
98
|
+
cropPercentW = cropWindow.width/(cropImage.width*zoom),
|
99
|
+
cropPercentH = cropWindow.height/(cropImage.height*zoom),
|
100
|
+
positionX = Math.abs(cropPosition.left-borderWidth[3]),
|
101
|
+
positionY = Math.abs(cropPosition.top-borderWidth[0]),
|
102
|
+
cropX = cropImage.width*cropPercentX,
|
103
|
+
cropY = cropImage.height*cropPercentY,
|
104
|
+
cropW = cropImage.width*cropPercentW,
|
105
|
+
cropH = cropImage.height*cropPercentH;
|
106
|
+
|
107
|
+
return { x: cropX, y: cropY, w: cropW, h: cropH };
|
108
|
+
},
|
109
|
+
|
110
|
+
setPosition: function(){
|
111
|
+
// Only set the position of the image once, after the initial image is loaded
|
112
|
+
// For additionl uploads the default positioning should be used
|
113
|
+
if(!_positioned){
|
114
|
+
var cropImage = this.getCropContainer().cropit('imageSize'),
|
115
|
+
x = this.getFileInput().data('crop-x'),
|
116
|
+
y = this.getFileInput().data('crop-y'),
|
117
|
+
zoom = this.getCropContainer().cropit('zoom');
|
118
|
+
|
119
|
+
x = ((cropImage.width*zoom)*x)/cropImage.width;
|
120
|
+
y = ((cropImage.height*zoom)*y)/cropImage.height;
|
121
|
+
|
122
|
+
if(!isNaN(parseFloat(x)) && !isNaN(parseFloat(y))){
|
123
|
+
this.getCropContainer().cropit('offset', { x: -x, y: -y });
|
124
|
+
}
|
125
|
+
_positioned = true;
|
126
|
+
}
|
127
|
+
},
|
128
|
+
|
129
|
+
getName: function(field){
|
130
|
+
return $(config.fileInput).attr('name').replace(/([a-z0-9_]+)\]$/i, '$1_' + field + ']');
|
131
|
+
},
|
132
|
+
|
133
|
+
getFieldName: function(){
|
134
|
+
return $(config.fileInput).attr('name').replace(/.*\[([a-z0-9_]+)\]$/i, '$1');
|
135
|
+
},
|
136
|
+
|
137
|
+
getImage: function(){
|
138
|
+
return this.getCropContainer().cropit('imageSrc');
|
139
|
+
},
|
140
|
+
|
141
|
+
setImage: function(path){
|
142
|
+
this.getCropContainer().cropit('imageSrc', Voltron.getBaseUrl() + path);
|
143
|
+
},
|
144
|
+
|
145
|
+
getZoom: function(){
|
146
|
+
return $(config.zoom);
|
147
|
+
},
|
148
|
+
|
149
|
+
getFileInput: function(){
|
150
|
+
return $(config.fileInput);
|
151
|
+
},
|
152
|
+
|
153
|
+
getPreview: function(){
|
154
|
+
return $(config.preview);
|
155
|
+
},
|
156
|
+
|
157
|
+
getDimensionInput: function(){
|
158
|
+
var content = $('<div />');
|
159
|
+
content.append($('<input />', { type: 'hidden', name: this.getName('x'), class: this.getFieldName() + '-crop-dimension-x' }));
|
160
|
+
content.append($('<input />', { type: 'hidden', name: this.getName('y'), class: this.getFieldName() + '-crop-dimension-y' }));
|
161
|
+
content.append($('<input />', { type: 'hidden', name: this.getName('w'), class: this.getFieldName() + '-crop-dimension-w' }));
|
162
|
+
content.append($('<input />', { type: 'hidden', name: this.getName('h'), class: this.getFieldName() + '-crop-dimension-h' }));
|
163
|
+
content.append($('<input />', { type: 'hidden', name: this.getName('zoom'), class: this.getFieldName() + '-crop-zoom' }));
|
164
|
+
return content.html();
|
165
|
+
},
|
166
|
+
|
167
|
+
getConfig: function(){
|
168
|
+
return $.extend(options, {
|
169
|
+
imageState: { src: config.image },
|
170
|
+
minZoom: 0,
|
171
|
+
maxZoom: 2,
|
172
|
+
freeMove: false,
|
173
|
+
$preview: this.getPreview(),
|
174
|
+
$fileInput: this.getFileInput(),
|
175
|
+
$zoomSlider: this.getZoom()
|
176
|
+
});
|
177
|
+
},
|
178
|
+
|
179
|
+
getCropContainer: function(){
|
180
|
+
if(config.container === null){
|
181
|
+
config.container = $('<div />', { class: 'cropit-container' });
|
182
|
+
config.container.append(this.getDimensionInput());
|
183
|
+
config.container.append(this.getPreview());
|
184
|
+
config.container.append($('<div />', { class: 'zoom-container' }).append(this.getZoom()));
|
185
|
+
|
186
|
+
config.container.cropit(this.getConfig());
|
187
|
+
|
188
|
+
var borderWidth = config.container.data('cropit').bgBorderWidthArray;
|
189
|
+
|
190
|
+
this.getPreview().css({
|
191
|
+
marginTop: borderWidth[0],
|
192
|
+
marginRight: borderWidth[1],
|
193
|
+
marginBottom: borderWidth[2],
|
194
|
+
marginLeft: borderWidth[3]
|
195
|
+
});
|
196
|
+
}
|
197
|
+
return config.container;
|
198
|
+
},
|
199
|
+
|
200
|
+
getCropObject: function(){
|
201
|
+
return this.getCropContainer().data('cropit');
|
202
|
+
}
|
203
|
+
};
|
204
|
+
};
|
205
|
+
|
206
|
+
return {
|
207
|
+
initialize: function(){
|
208
|
+
$('input[data-crop-image]').each(function(){
|
209
|
+
var crop = Voltron('Crop/new', $(this).data('crop-options'), $.extend({ fileInput: this, image: $(this).data('crop-image') }, $(this).data('crop-config')));
|
210
|
+
crop.initialize();
|
211
|
+
});
|
212
|
+
},
|
213
|
+
|
214
|
+
new: function(options, config){
|
215
|
+
return new Crop(options, config);
|
216
|
+
},
|
217
|
+
|
218
|
+
// START: Compatibility with Voltron Upload module
|
219
|
+
// Ensures the crop container is created before the Upload dropzone is instantiated.
|
220
|
+
onBeforeModuleInitializeUpload: function(o){
|
221
|
+
this.initialize();
|
222
|
+
},
|
223
|
+
|
224
|
+
// Updates the crop image when an upload is completed
|
225
|
+
onUploadComplete: function(o){
|
226
|
+
var crop = $(o.element).data('crop');
|
227
|
+
if(o.data.uploads && crop){
|
228
|
+
crop.setImage(o.data.uploads.first().url);
|
229
|
+
}
|
230
|
+
}
|
231
|
+
// END: Compatibility with Voltron Upload module
|
232
|
+
};
|
233
|
+
}, true);
|