imgareaselect-rails 1.0.1 → 1.0.2
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.
- data/lib/imgareaselect/rails/version.rb +2 -2
- data/vendor/MIT-LICENSE.txt +1 -1
- data/vendor/assets/javascripts/jquery.imgareaselect.js +566 -85
- metadata +10 -10
data/vendor/MIT-LICENSE.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2008-
|
|
1
|
+
Copyright (c) 2008-2013 Michal Wojciechowski, http://odyniec.net/
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
4
|
a copy of this software and associated documentation files (the
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* imgAreaSelect jQuery plugin
|
|
3
|
-
* version 0.9.
|
|
3
|
+
* version 0.9.10
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c) 2008-
|
|
5
|
+
* Copyright (c) 2008-2013 Michal Wojciechowski (odyniec.net)
|
|
6
6
|
*
|
|
7
7
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
|
8
8
|
* and GPL (GPL-LICENSE.txt) licenses.
|
|
@@ -13,91 +13,207 @@
|
|
|
13
13
|
|
|
14
14
|
(function($) {
|
|
15
15
|
|
|
16
|
+
/*
|
|
17
|
+
* Math functions will be used extensively, so it's convenient to make a few
|
|
18
|
+
* shortcuts
|
|
19
|
+
*/
|
|
16
20
|
var abs = Math.abs,
|
|
17
21
|
max = Math.max,
|
|
18
22
|
min = Math.min,
|
|
19
23
|
round = Math.round;
|
|
20
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Create a new HTML div element
|
|
27
|
+
*
|
|
28
|
+
* @return A jQuery object representing the new element
|
|
29
|
+
*/
|
|
21
30
|
function div() {
|
|
22
31
|
return $('<div/>');
|
|
23
32
|
}
|
|
24
33
|
|
|
34
|
+
/**
|
|
35
|
+
* imgAreaSelect initialization
|
|
36
|
+
*
|
|
37
|
+
* @param img
|
|
38
|
+
* A HTML image element to attach the plugin to
|
|
39
|
+
* @param options
|
|
40
|
+
* An options object
|
|
41
|
+
*/
|
|
25
42
|
$.imgAreaSelect = function (img, options) {
|
|
26
|
-
var
|
|
27
|
-
|
|
43
|
+
var
|
|
44
|
+
/* jQuery object representing the image */
|
|
28
45
|
$img = $(img),
|
|
29
|
-
|
|
46
|
+
|
|
47
|
+
/* Has the image finished loading? */
|
|
30
48
|
imgLoaded,
|
|
31
|
-
|
|
49
|
+
|
|
50
|
+
/* Plugin elements */
|
|
51
|
+
|
|
52
|
+
/* Container box */
|
|
32
53
|
$box = div(),
|
|
54
|
+
/* Selection area */
|
|
33
55
|
$area = div(),
|
|
56
|
+
/* Border (four divs) */
|
|
34
57
|
$border = div().add(div()).add(div()).add(div()),
|
|
58
|
+
/* Outer area (four divs) */
|
|
35
59
|
$outer = div().add(div()).add(div()).add(div()),
|
|
60
|
+
/* Handles (empty by default, initialized in setOptions()) */
|
|
36
61
|
$handles = $([]),
|
|
37
|
-
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* Additional element to work around a cursor problem in Opera
|
|
65
|
+
* (explained later)
|
|
66
|
+
*/
|
|
38
67
|
$areaOpera,
|
|
39
|
-
|
|
68
|
+
|
|
69
|
+
/* Image position (relative to viewport) */
|
|
40
70
|
left, top,
|
|
41
|
-
|
|
71
|
+
|
|
72
|
+
/* Image offset (as returned by .offset()) */
|
|
42
73
|
imgOfs = { left: 0, top: 0 },
|
|
43
|
-
|
|
74
|
+
|
|
75
|
+
/* Image dimensions (as returned by .width() and .height()) */
|
|
44
76
|
imgWidth, imgHeight,
|
|
45
|
-
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
* jQuery object representing the parent element that the plugin
|
|
80
|
+
* elements are appended to
|
|
81
|
+
*/
|
|
46
82
|
$parent,
|
|
47
|
-
|
|
83
|
+
|
|
84
|
+
/* Parent element offset (as returned by .offset()) */
|
|
48
85
|
parOfs = { left: 0, top: 0 },
|
|
49
|
-
|
|
86
|
+
|
|
87
|
+
/* Base z-index for plugin elements */
|
|
50
88
|
zIndex = 0,
|
|
51
|
-
|
|
89
|
+
|
|
90
|
+
/* Plugin elements position */
|
|
52
91
|
position = 'absolute',
|
|
53
|
-
|
|
92
|
+
|
|
93
|
+
/* X/Y coordinates of the starting point for move/resize operations */
|
|
54
94
|
startX, startY,
|
|
55
|
-
|
|
95
|
+
|
|
96
|
+
/* Horizontal and vertical scaling factors */
|
|
56
97
|
scaleX, scaleY,
|
|
57
|
-
|
|
98
|
+
|
|
99
|
+
/* Current resize mode ("nw", "se", etc.) */
|
|
58
100
|
resize,
|
|
59
|
-
|
|
101
|
+
|
|
102
|
+
/* Selection area constraints */
|
|
60
103
|
minWidth, minHeight, maxWidth, maxHeight,
|
|
61
|
-
|
|
104
|
+
|
|
105
|
+
/* Aspect ratio to maintain (floating point number) */
|
|
62
106
|
aspectRatio,
|
|
63
|
-
|
|
107
|
+
|
|
108
|
+
/* Are the plugin elements currently displayed? */
|
|
64
109
|
shown,
|
|
65
|
-
|
|
110
|
+
|
|
111
|
+
/* Current selection (relative to parent element) */
|
|
66
112
|
x1, y1, x2, y2,
|
|
67
|
-
|
|
113
|
+
|
|
114
|
+
/* Current selection (relative to scaled image) */
|
|
68
115
|
selection = { x1: 0, y1: 0, x2: 0, y2: 0, width: 0, height: 0 },
|
|
69
|
-
|
|
116
|
+
|
|
117
|
+
/* Document element */
|
|
70
118
|
docElem = document.documentElement,
|
|
71
119
|
|
|
120
|
+
/* User agent */
|
|
121
|
+
ua = navigator.userAgent,
|
|
122
|
+
|
|
123
|
+
/* Various helper variables used throughout the code */
|
|
72
124
|
$p, d, i, o, w, h, adjusted;
|
|
73
125
|
|
|
126
|
+
/*
|
|
127
|
+
* Translate selection coordinates (relative to scaled image) to viewport
|
|
128
|
+
* coordinates (relative to parent element)
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Translate selection X to viewport X
|
|
133
|
+
*
|
|
134
|
+
* @param x
|
|
135
|
+
* Selection X
|
|
136
|
+
* @return Viewport X
|
|
137
|
+
*/
|
|
74
138
|
function viewX(x) {
|
|
75
139
|
return x + imgOfs.left - parOfs.left;
|
|
76
140
|
}
|
|
77
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Translate selection Y to viewport Y
|
|
144
|
+
*
|
|
145
|
+
* @param y
|
|
146
|
+
* Selection Y
|
|
147
|
+
* @return Viewport Y
|
|
148
|
+
*/
|
|
78
149
|
function viewY(y) {
|
|
79
150
|
return y + imgOfs.top - parOfs.top;
|
|
80
151
|
}
|
|
81
152
|
|
|
153
|
+
/*
|
|
154
|
+
* Translate viewport coordinates to selection coordinates
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Translate viewport X to selection X
|
|
159
|
+
*
|
|
160
|
+
* @param x
|
|
161
|
+
* Viewport X
|
|
162
|
+
* @return Selection X
|
|
163
|
+
*/
|
|
82
164
|
function selX(x) {
|
|
83
165
|
return x - imgOfs.left + parOfs.left;
|
|
84
166
|
}
|
|
85
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Translate viewport Y to selection Y
|
|
170
|
+
*
|
|
171
|
+
* @param y
|
|
172
|
+
* Viewport Y
|
|
173
|
+
* @return Selection Y
|
|
174
|
+
*/
|
|
86
175
|
function selY(y) {
|
|
87
176
|
return y - imgOfs.top + parOfs.top;
|
|
88
177
|
}
|
|
89
|
-
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
* Translate event coordinates (relative to document) to viewport
|
|
181
|
+
* coordinates
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get event X and translate it to viewport X
|
|
186
|
+
*
|
|
187
|
+
* @param event
|
|
188
|
+
* The event object
|
|
189
|
+
* @return Viewport X
|
|
190
|
+
*/
|
|
90
191
|
function evX(event) {
|
|
91
192
|
return event.pageX - parOfs.left;
|
|
92
193
|
}
|
|
93
194
|
|
|
195
|
+
/**
|
|
196
|
+
* Get event Y and translate it to viewport Y
|
|
197
|
+
*
|
|
198
|
+
* @param event
|
|
199
|
+
* The event object
|
|
200
|
+
* @return Viewport Y
|
|
201
|
+
*/
|
|
94
202
|
function evY(event) {
|
|
95
203
|
return event.pageY - parOfs.top;
|
|
96
204
|
}
|
|
97
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Get the current selection
|
|
208
|
+
*
|
|
209
|
+
* @param noScale
|
|
210
|
+
* If set to <code>true</code>, scaling is not applied to the
|
|
211
|
+
* returned selection
|
|
212
|
+
* @return Selection object
|
|
213
|
+
*/
|
|
98
214
|
function getSelection(noScale) {
|
|
99
215
|
var sx = noScale || scaleX, sy = noScale || scaleY;
|
|
100
|
-
|
|
216
|
+
|
|
101
217
|
return { x1: round(selection.x1 * sx),
|
|
102
218
|
y1: round(selection.y1 * sy),
|
|
103
219
|
x2: round(selection.x2 * sx),
|
|
@@ -105,38 +221,71 @@ $.imgAreaSelect = function (img, options) {
|
|
|
105
221
|
width: round(selection.x2 * sx) - round(selection.x1 * sx),
|
|
106
222
|
height: round(selection.y2 * sy) - round(selection.y1 * sy) };
|
|
107
223
|
}
|
|
108
|
-
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Set the current selection
|
|
227
|
+
*
|
|
228
|
+
* @param x1
|
|
229
|
+
* X coordinate of the upper left corner of the selection area
|
|
230
|
+
* @param y1
|
|
231
|
+
* Y coordinate of the upper left corner of the selection area
|
|
232
|
+
* @param x2
|
|
233
|
+
* X coordinate of the lower right corner of the selection area
|
|
234
|
+
* @param y2
|
|
235
|
+
* Y coordinate of the lower right corner of the selection area
|
|
236
|
+
* @param noScale
|
|
237
|
+
* If set to <code>true</code>, scaling is not applied to the
|
|
238
|
+
* new selection
|
|
239
|
+
*/
|
|
109
240
|
function setSelection(x1, y1, x2, y2, noScale) {
|
|
110
241
|
var sx = noScale || scaleX, sy = noScale || scaleY;
|
|
111
|
-
|
|
242
|
+
|
|
112
243
|
selection = {
|
|
113
244
|
x1: round(x1 / sx || 0),
|
|
114
245
|
y1: round(y1 / sy || 0),
|
|
115
246
|
x2: round(x2 / sx || 0),
|
|
116
247
|
y2: round(y2 / sy || 0)
|
|
117
248
|
};
|
|
118
|
-
|
|
249
|
+
|
|
119
250
|
selection.width = selection.x2 - selection.x1;
|
|
120
251
|
selection.height = selection.y2 - selection.y1;
|
|
121
252
|
}
|
|
122
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Recalculate image and parent offsets
|
|
256
|
+
*/
|
|
123
257
|
function adjust() {
|
|
258
|
+
/*
|
|
259
|
+
* Do not adjust if image has not yet loaded or if width is not a
|
|
260
|
+
* positive number. The latter might happen when imgAreaSelect is put
|
|
261
|
+
* on a parent element which is then hidden.
|
|
262
|
+
*/
|
|
124
263
|
if (!imgLoaded || !$img.width())
|
|
125
264
|
return;
|
|
126
|
-
|
|
265
|
+
|
|
266
|
+
/*
|
|
267
|
+
* Get image offset. The .offset() method returns float values, so they
|
|
268
|
+
* need to be rounded.
|
|
269
|
+
*/
|
|
127
270
|
imgOfs = { left: round($img.offset().left), top: round($img.offset().top) };
|
|
128
|
-
|
|
271
|
+
|
|
272
|
+
/* Get image dimensions */
|
|
129
273
|
imgWidth = $img.innerWidth();
|
|
130
274
|
imgHeight = $img.innerHeight();
|
|
131
|
-
|
|
275
|
+
|
|
132
276
|
imgOfs.top += ($img.outerHeight() - imgHeight) >> 1;
|
|
133
277
|
imgOfs.left += ($img.outerWidth() - imgWidth) >> 1;
|
|
134
278
|
|
|
279
|
+
/* Set minimum and maximum selection area dimensions */
|
|
135
280
|
minWidth = round(options.minWidth / scaleX) || 0;
|
|
136
281
|
minHeight = round(options.minHeight / scaleY) || 0;
|
|
137
282
|
maxWidth = round(min(options.maxWidth / scaleX || 1<<24, imgWidth));
|
|
138
283
|
maxHeight = round(min(options.maxHeight / scaleY || 1<<24, imgHeight));
|
|
139
|
-
|
|
284
|
+
|
|
285
|
+
/*
|
|
286
|
+
* Workaround for jQuery 1.3.2 incorrect offset calculation, originally
|
|
287
|
+
* observed in Safari 3. Firefox 2 is also affected.
|
|
288
|
+
*/
|
|
140
289
|
if ($().jquery == '1.3.2' && position == 'fixed' &&
|
|
141
290
|
!docElem['getBoundingClientRect'])
|
|
142
291
|
{
|
|
@@ -144,32 +293,55 @@ $.imgAreaSelect = function (img, options) {
|
|
|
144
293
|
imgOfs.left += max(document.body.scrollLeft, docElem.scrollLeft);
|
|
145
294
|
}
|
|
146
295
|
|
|
296
|
+
/* Determine parent element offset */
|
|
147
297
|
parOfs = /absolute|relative/.test($parent.css('position')) ?
|
|
148
298
|
{ left: round($parent.offset().left) - $parent.scrollLeft(),
|
|
149
299
|
top: round($parent.offset().top) - $parent.scrollTop() } :
|
|
150
300
|
position == 'fixed' ?
|
|
151
301
|
{ left: $(document).scrollLeft(), top: $(document).scrollTop() } :
|
|
152
302
|
{ left: 0, top: 0 };
|
|
153
|
-
|
|
303
|
+
|
|
154
304
|
left = viewX(0);
|
|
155
305
|
top = viewY(0);
|
|
156
|
-
|
|
306
|
+
|
|
307
|
+
/*
|
|
308
|
+
* Check if selection area is within image boundaries, adjust if
|
|
309
|
+
* necessary
|
|
310
|
+
*/
|
|
157
311
|
if (selection.x2 > imgWidth || selection.y2 > imgHeight)
|
|
158
312
|
doResize();
|
|
159
313
|
}
|
|
160
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Update plugin elements
|
|
317
|
+
*
|
|
318
|
+
* @param resetKeyPress
|
|
319
|
+
* If set to <code>false</code>, this instance's keypress
|
|
320
|
+
* event handler is not activated
|
|
321
|
+
*/
|
|
161
322
|
function update(resetKeyPress) {
|
|
323
|
+
/* If plugin elements are hidden, do nothing */
|
|
162
324
|
if (!shown) return;
|
|
163
325
|
|
|
326
|
+
/*
|
|
327
|
+
* Set the position and size of the container box and the selection area
|
|
328
|
+
* inside it
|
|
329
|
+
*/
|
|
164
330
|
$box.css({ left: viewX(selection.x1), top: viewY(selection.y1) })
|
|
165
331
|
.add($area).width(w = selection.width).height(h = selection.height);
|
|
166
332
|
|
|
333
|
+
/*
|
|
334
|
+
* Reset the position of selection area, borders, and handles (IE6/IE7
|
|
335
|
+
* position them incorrectly if we don't do this)
|
|
336
|
+
*/
|
|
167
337
|
$area.add($border).add($handles).css({ left: 0, top: 0 });
|
|
168
338
|
|
|
339
|
+
/* Set border dimensions */
|
|
169
340
|
$border
|
|
170
341
|
.width(max(w - $border.outerWidth() + $border.innerWidth(), 0))
|
|
171
342
|
.height(max(h - $border.outerHeight() + $border.innerHeight(), 0));
|
|
172
343
|
|
|
344
|
+
/* Arrange the outer area elements */
|
|
173
345
|
$($outer[0]).css({ left: left, top: top,
|
|
174
346
|
width: selection.x1, height: imgHeight });
|
|
175
347
|
$($outer[1]).css({ left: left + selection.x1, top: top,
|
|
@@ -178,10 +350,11 @@ $.imgAreaSelect = function (img, options) {
|
|
|
178
350
|
width: imgWidth - selection.x2, height: imgHeight });
|
|
179
351
|
$($outer[3]).css({ left: left + selection.x1, top: top + selection.y2,
|
|
180
352
|
width: w, height: imgHeight - selection.y2 });
|
|
181
|
-
|
|
353
|
+
|
|
182
354
|
w -= $handles.outerWidth();
|
|
183
355
|
h -= $handles.outerHeight();
|
|
184
|
-
|
|
356
|
+
|
|
357
|
+
/* Arrange handles */
|
|
185
358
|
switch ($handles.length) {
|
|
186
359
|
case 8:
|
|
187
360
|
$($handles[4]).css({ left: w >> 1 });
|
|
@@ -194,37 +367,78 @@ $.imgAreaSelect = function (img, options) {
|
|
|
194
367
|
}
|
|
195
368
|
|
|
196
369
|
if (resetKeyPress !== false) {
|
|
370
|
+
/*
|
|
371
|
+
* Need to reset the document keypress event handler -- unbind the
|
|
372
|
+
* current handler
|
|
373
|
+
*/
|
|
197
374
|
if ($.imgAreaSelect.onKeyPress != docKeyPress)
|
|
198
375
|
$(document).unbind($.imgAreaSelect.keyPress,
|
|
199
376
|
$.imgAreaSelect.onKeyPress);
|
|
200
377
|
|
|
201
378
|
if (options.keys)
|
|
379
|
+
/*
|
|
380
|
+
* Set the document keypress event handler to this instance's
|
|
381
|
+
* docKeyPress() function
|
|
382
|
+
*/
|
|
202
383
|
$(document)[$.imgAreaSelect.keyPress](
|
|
203
384
|
$.imgAreaSelect.onKeyPress = docKeyPress);
|
|
204
385
|
}
|
|
205
386
|
|
|
206
|
-
|
|
387
|
+
/*
|
|
388
|
+
* Internet Explorer displays 1px-wide dashed borders incorrectly by
|
|
389
|
+
* filling the spaces between dashes with white. Toggling the margin
|
|
390
|
+
* property between 0 and "auto" fixes this in IE6 and IE7 (IE8 is still
|
|
391
|
+
* broken). This workaround is not perfect, as it requires setTimeout()
|
|
392
|
+
* and thus causes the border to flicker a bit, but I haven't found a
|
|
393
|
+
* better solution.
|
|
394
|
+
*
|
|
395
|
+
* Note: This only happens with CSS borders, set with the borderWidth,
|
|
396
|
+
* borderOpacity, borderColor1, and borderColor2 options (which are now
|
|
397
|
+
* deprecated). Borders created with GIF background images are fine.
|
|
398
|
+
*/
|
|
399
|
+
if (msie && $border.outerWidth() - $border.innerWidth() == 2) {
|
|
207
400
|
$border.css('margin', 0);
|
|
208
401
|
setTimeout(function () { $border.css('margin', 'auto'); }, 0);
|
|
209
402
|
}
|
|
210
403
|
}
|
|
211
|
-
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Do the complete update sequence: recalculate offsets, update the
|
|
407
|
+
* elements, and set the correct values of x1, y1, x2, and y2.
|
|
408
|
+
*
|
|
409
|
+
* @param resetKeyPress
|
|
410
|
+
* If set to <code>false</code>, this instance's keypress
|
|
411
|
+
* event handler is not activated
|
|
412
|
+
*/
|
|
212
413
|
function doUpdate(resetKeyPress) {
|
|
213
414
|
adjust();
|
|
214
415
|
update(resetKeyPress);
|
|
215
416
|
x1 = viewX(selection.x1); y1 = viewY(selection.y1);
|
|
216
417
|
x2 = viewX(selection.x2); y2 = viewY(selection.y2);
|
|
217
418
|
}
|
|
218
|
-
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Hide or fade out an element (or multiple elements)
|
|
422
|
+
*
|
|
423
|
+
* @param $elem
|
|
424
|
+
* A jQuery object containing the element(s) to hide/fade out
|
|
425
|
+
* @param fn
|
|
426
|
+
* Callback function to be called when fadeOut() completes
|
|
427
|
+
*/
|
|
219
428
|
function hide($elem, fn) {
|
|
220
|
-
options.fadeSpeed ? $elem.fadeOut(options.fadeSpeed, fn) : $elem.hide();
|
|
221
|
-
|
|
429
|
+
options.fadeSpeed ? $elem.fadeOut(options.fadeSpeed, fn) : $elem.hide();
|
|
222
430
|
}
|
|
223
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Selection area mousemove event handler
|
|
434
|
+
*
|
|
435
|
+
* @param event
|
|
436
|
+
* The event object
|
|
437
|
+
*/
|
|
224
438
|
function areaMouseMove(event) {
|
|
225
439
|
var x = selX(evX(event)) - selection.x1,
|
|
226
440
|
y = selY(evY(event)) - selection.y1;
|
|
227
|
-
|
|
441
|
+
|
|
228
442
|
if (!adjusted) {
|
|
229
443
|
adjust();
|
|
230
444
|
adjusted = true;
|
|
@@ -232,9 +446,14 @@ $.imgAreaSelect = function (img, options) {
|
|
|
232
446
|
$box.one('mouseout', function () { adjusted = false; });
|
|
233
447
|
}
|
|
234
448
|
|
|
449
|
+
/* Clear the resize mode */
|
|
235
450
|
resize = '';
|
|
236
451
|
|
|
237
452
|
if (options.resizable) {
|
|
453
|
+
/*
|
|
454
|
+
* Check if the mouse pointer is over the resize margin area and set
|
|
455
|
+
* the resize mode accordingly
|
|
456
|
+
*/
|
|
238
457
|
if (y <= options.resizeMargin)
|
|
239
458
|
resize = 'n';
|
|
240
459
|
else if (y >= selection.height - options.resizeMargin)
|
|
@@ -251,28 +470,47 @@ $.imgAreaSelect = function (img, options) {
|
|
|
251
470
|
$areaOpera.toggle();
|
|
252
471
|
}
|
|
253
472
|
|
|
473
|
+
/**
|
|
474
|
+
* Document mouseup event handler
|
|
475
|
+
*
|
|
476
|
+
* @param event
|
|
477
|
+
* The event object
|
|
478
|
+
*/
|
|
254
479
|
function docMouseUp(event) {
|
|
480
|
+
/* Set back the default cursor */
|
|
255
481
|
$('body').css('cursor', '');
|
|
482
|
+
/*
|
|
483
|
+
* If autoHide is enabled, or if the selection has zero width/height,
|
|
484
|
+
* hide the selection and the outer area
|
|
485
|
+
*/
|
|
256
486
|
if (options.autoHide || selection.width * selection.height == 0)
|
|
257
487
|
hide($box.add($outer), function () { $(this).hide(); });
|
|
258
488
|
|
|
259
489
|
$(document).unbind('mousemove', selectingMouseMove);
|
|
260
490
|
$box.mousemove(areaMouseMove);
|
|
261
|
-
|
|
491
|
+
|
|
262
492
|
options.onSelectEnd(img, getSelection());
|
|
263
493
|
}
|
|
264
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Selection area mousedown event handler
|
|
497
|
+
*
|
|
498
|
+
* @param event
|
|
499
|
+
* The event object
|
|
500
|
+
* @return false
|
|
501
|
+
*/
|
|
265
502
|
function areaMouseDown(event) {
|
|
266
503
|
if (event.which != 1) return false;
|
|
267
504
|
|
|
268
505
|
adjust();
|
|
269
506
|
|
|
270
507
|
if (resize) {
|
|
508
|
+
/* Resize mode is in effect */
|
|
271
509
|
$('body').css('cursor', resize + '-resize');
|
|
272
510
|
|
|
273
511
|
x1 = viewX(selection[/w/.test(resize) ? 'x2' : 'x1']);
|
|
274
512
|
y1 = viewY(selection[/n/.test(resize) ? 'y2' : 'y1']);
|
|
275
|
-
|
|
513
|
+
|
|
276
514
|
$(document).mousemove(selectingMouseMove)
|
|
277
515
|
.one('mouseup', docMouseUp);
|
|
278
516
|
$box.unbind('mousemove', areaMouseMove);
|
|
@@ -297,12 +535,18 @@ $.imgAreaSelect = function (img, options) {
|
|
|
297
535
|
return false;
|
|
298
536
|
}
|
|
299
537
|
|
|
538
|
+
/**
|
|
539
|
+
* Adjust the x2/y2 coordinates to maintain aspect ratio (if defined)
|
|
540
|
+
*
|
|
541
|
+
* @param xFirst
|
|
542
|
+
* If set to <code>true</code>, calculate x2 first. Otherwise,
|
|
543
|
+
* calculate y2 first.
|
|
544
|
+
*/
|
|
300
545
|
function fixAspectRatio(xFirst) {
|
|
301
546
|
if (aspectRatio)
|
|
302
547
|
if (xFirst) {
|
|
303
548
|
x2 = max(left, min(left + imgWidth,
|
|
304
|
-
x1 + abs(y2 - y1) * aspectRatio * (x2 > x1 || -1)));
|
|
305
|
-
|
|
549
|
+
x1 + abs(y2 - y1) * aspectRatio * (x2 > x1 || -1)));
|
|
306
550
|
y2 = round(max(top, min(top + imgHeight,
|
|
307
551
|
y1 + abs(x2 - x1) / aspectRatio * (y2 > y1 || -1))));
|
|
308
552
|
x2 = round(x2);
|
|
@@ -316,11 +560,21 @@ $.imgAreaSelect = function (img, options) {
|
|
|
316
560
|
}
|
|
317
561
|
}
|
|
318
562
|
|
|
563
|
+
/**
|
|
564
|
+
* Resize the selection area respecting the minimum/maximum dimensions and
|
|
565
|
+
* aspect ratio
|
|
566
|
+
*/
|
|
319
567
|
function doResize() {
|
|
568
|
+
/*
|
|
569
|
+
* Make sure the top left corner of the selection area stays within
|
|
570
|
+
* image boundaries (it might not if the image source was dynamically
|
|
571
|
+
* changed).
|
|
572
|
+
*/
|
|
320
573
|
x1 = min(x1, left + imgWidth);
|
|
321
574
|
y1 = min(y1, top + imgHeight);
|
|
322
|
-
|
|
575
|
+
|
|
323
576
|
if (abs(x2 - x1) < minWidth) {
|
|
577
|
+
/* Selection width is smaller than minWidth */
|
|
324
578
|
x2 = x1 - minWidth * (x2 < x1 || -1);
|
|
325
579
|
|
|
326
580
|
if (x2 < left)
|
|
@@ -330,6 +584,7 @@ $.imgAreaSelect = function (img, options) {
|
|
|
330
584
|
}
|
|
331
585
|
|
|
332
586
|
if (abs(y2 - y1) < minHeight) {
|
|
587
|
+
/* Selection height is smaller than minHeight */
|
|
333
588
|
y2 = y1 - minHeight * (y2 < y1 || -1);
|
|
334
589
|
|
|
335
590
|
if (y2 < top)
|
|
@@ -340,15 +595,17 @@ $.imgAreaSelect = function (img, options) {
|
|
|
340
595
|
|
|
341
596
|
x2 = max(left, min(x2, left + imgWidth));
|
|
342
597
|
y2 = max(top, min(y2, top + imgHeight));
|
|
343
|
-
|
|
598
|
+
|
|
344
599
|
fixAspectRatio(abs(x2 - x1) < abs(y2 - y1) * aspectRatio);
|
|
345
600
|
|
|
346
601
|
if (abs(x2 - x1) > maxWidth) {
|
|
602
|
+
/* Selection width is greater than maxWidth */
|
|
347
603
|
x2 = x1 - maxWidth * (x2 < x1 || -1);
|
|
348
604
|
fixAspectRatio();
|
|
349
605
|
}
|
|
350
606
|
|
|
351
607
|
if (abs(y2 - y1) > maxHeight) {
|
|
608
|
+
/* Selection height is greater than maxHeight */
|
|
352
609
|
y2 = y1 - maxHeight * (y2 < y1 || -1);
|
|
353
610
|
fixAspectRatio(true);
|
|
354
611
|
}
|
|
@@ -362,16 +619,30 @@ $.imgAreaSelect = function (img, options) {
|
|
|
362
619
|
options.onSelectChange(img, getSelection());
|
|
363
620
|
}
|
|
364
621
|
|
|
622
|
+
/**
|
|
623
|
+
* Mousemove event handler triggered when the user is selecting an area
|
|
624
|
+
*
|
|
625
|
+
* @param event
|
|
626
|
+
* The event object
|
|
627
|
+
* @return false
|
|
628
|
+
*/
|
|
365
629
|
function selectingMouseMove(event) {
|
|
366
630
|
x2 = /w|e|^$/.test(resize) || aspectRatio ? evX(event) : viewX(selection.x2);
|
|
367
631
|
y2 = /n|s|^$/.test(resize) || aspectRatio ? evY(event) : viewY(selection.y2);
|
|
368
632
|
|
|
369
633
|
doResize();
|
|
370
634
|
|
|
371
|
-
return false;
|
|
372
|
-
|
|
635
|
+
return false;
|
|
373
636
|
}
|
|
374
637
|
|
|
638
|
+
/**
|
|
639
|
+
* Move the selection area
|
|
640
|
+
*
|
|
641
|
+
* @param newX1
|
|
642
|
+
* New viewport X1
|
|
643
|
+
* @param newY1
|
|
644
|
+
* New viewport Y1
|
|
645
|
+
*/
|
|
375
646
|
function doMove(newX1, newY1) {
|
|
376
647
|
x2 = (x1 = newX1) + selection.width;
|
|
377
648
|
y2 = (y1 = newY1) + selection.height;
|
|
@@ -384,29 +655,38 @@ $.imgAreaSelect = function (img, options) {
|
|
|
384
655
|
options.onSelectChange(img, getSelection());
|
|
385
656
|
}
|
|
386
657
|
|
|
658
|
+
/**
|
|
659
|
+
* Mousemove event handler triggered when the selection area is being moved
|
|
660
|
+
*
|
|
661
|
+
* @param event
|
|
662
|
+
* The event object
|
|
663
|
+
* @return false
|
|
664
|
+
*/
|
|
387
665
|
function movingMouseMove(event) {
|
|
388
666
|
x1 = max(left, min(startX + evX(event), left + imgWidth - selection.width));
|
|
389
667
|
y1 = max(top, min(startY + evY(event), top + imgHeight - selection.height));
|
|
390
668
|
|
|
391
669
|
doMove(x1, y1);
|
|
392
670
|
|
|
393
|
-
event.preventDefault();
|
|
394
|
-
|
|
671
|
+
event.preventDefault();
|
|
395
672
|
return false;
|
|
396
673
|
}
|
|
397
674
|
|
|
675
|
+
/**
|
|
676
|
+
* Start selection
|
|
677
|
+
*/
|
|
398
678
|
function startSelection() {
|
|
399
679
|
$(document).unbind('mousemove', startSelection);
|
|
400
680
|
adjust();
|
|
401
681
|
|
|
402
682
|
x2 = x1;
|
|
403
|
-
y2 = y1;
|
|
404
|
-
|
|
683
|
+
y2 = y1;
|
|
405
684
|
doResize();
|
|
406
685
|
|
|
407
686
|
resize = '';
|
|
408
687
|
|
|
409
688
|
if (!$outer.is(':visible'))
|
|
689
|
+
/* Show the plugin elements */
|
|
410
690
|
$box.add($outer).hide().fadeIn(options.fadeSpeed||0);
|
|
411
691
|
|
|
412
692
|
shown = true;
|
|
@@ -418,38 +698,59 @@ $.imgAreaSelect = function (img, options) {
|
|
|
418
698
|
options.onSelectStart(img, getSelection());
|
|
419
699
|
}
|
|
420
700
|
|
|
701
|
+
/**
|
|
702
|
+
* Cancel selection
|
|
703
|
+
*/
|
|
421
704
|
function cancelSelection() {
|
|
422
705
|
$(document).unbind('mousemove', startSelection)
|
|
423
706
|
.unbind('mouseup', cancelSelection);
|
|
424
707
|
hide($box.add($outer));
|
|
425
|
-
|
|
708
|
+
|
|
426
709
|
setSelection(selX(x1), selY(y1), selX(x1), selY(y1));
|
|
427
|
-
|
|
710
|
+
|
|
711
|
+
/* If this is an API call, callback functions should not be triggered */
|
|
428
712
|
if (!(this instanceof $.imgAreaSelect)) {
|
|
429
713
|
options.onSelectChange(img, getSelection());
|
|
430
714
|
options.onSelectEnd(img, getSelection());
|
|
431
715
|
}
|
|
432
716
|
}
|
|
433
717
|
|
|
718
|
+
/**
|
|
719
|
+
* Image mousedown event handler
|
|
720
|
+
*
|
|
721
|
+
* @param event
|
|
722
|
+
* The event object
|
|
723
|
+
* @return false
|
|
724
|
+
*/
|
|
434
725
|
function imgMouseDown(event) {
|
|
726
|
+
/* Ignore the event if animation is in progress */
|
|
435
727
|
if (event.which != 1 || $outer.is(':animated')) return false;
|
|
436
728
|
|
|
437
729
|
adjust();
|
|
438
730
|
startX = x1 = evX(event);
|
|
439
731
|
startY = y1 = evY(event);
|
|
440
732
|
|
|
733
|
+
/* Selection will start when the mouse is moved */
|
|
441
734
|
$(document).mousemove(startSelection).mouseup(cancelSelection);
|
|
442
735
|
|
|
443
736
|
return false;
|
|
444
737
|
}
|
|
445
|
-
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Window resize event handler
|
|
741
|
+
*/
|
|
446
742
|
function windowResize() {
|
|
447
743
|
doUpdate(false);
|
|
448
744
|
}
|
|
449
745
|
|
|
746
|
+
/**
|
|
747
|
+
* Image load event handler. This is the final part of the initialization
|
|
748
|
+
* process.
|
|
749
|
+
*/
|
|
450
750
|
function imgLoad() {
|
|
451
751
|
imgLoaded = true;
|
|
452
752
|
|
|
753
|
+
/* Set options */
|
|
453
754
|
setOptions(options = $.extend({
|
|
454
755
|
classPrefix: 'imgareaselect',
|
|
455
756
|
movable: true,
|
|
@@ -463,7 +764,7 @@ $.imgAreaSelect = function (img, options) {
|
|
|
463
764
|
}, options));
|
|
464
765
|
|
|
465
766
|
$box.add($outer).css({ visibility: '' });
|
|
466
|
-
|
|
767
|
+
|
|
467
768
|
if (options.show) {
|
|
468
769
|
shown = true;
|
|
469
770
|
adjust();
|
|
@@ -471,12 +772,24 @@ $.imgAreaSelect = function (img, options) {
|
|
|
471
772
|
$box.add($outer).hide().fadeIn(options.fadeSpeed||0);
|
|
472
773
|
}
|
|
473
774
|
|
|
775
|
+
/*
|
|
776
|
+
* Call the onInit callback. The setTimeout() call is used to ensure
|
|
777
|
+
* that the plugin has been fully initialized and the object instance is
|
|
778
|
+
* available (so that it can be obtained in the callback).
|
|
779
|
+
*/
|
|
474
780
|
setTimeout(function () { options.onInit(img, getSelection()); }, 0);
|
|
475
781
|
}
|
|
476
782
|
|
|
783
|
+
/**
|
|
784
|
+
* Document keypress event handler
|
|
785
|
+
*
|
|
786
|
+
* @param event
|
|
787
|
+
* The event object
|
|
788
|
+
* @return false
|
|
789
|
+
*/
|
|
477
790
|
var docKeyPress = function(event) {
|
|
478
791
|
var k = options.keys, d, t, key = event.keyCode;
|
|
479
|
-
|
|
792
|
+
|
|
480
793
|
d = !isNaN(k.alt) && (event.altKey || event.originalEvent.altKey) ? k.alt :
|
|
481
794
|
!isNaN(k.ctrl) && event.ctrlKey ? k.ctrl :
|
|
482
795
|
!isNaN(k.shift) && event.shiftKey ? k.shift :
|
|
@@ -486,18 +799,24 @@ $.imgAreaSelect = function (img, options) {
|
|
|
486
799
|
(k.ctrl == 'resize' && event.ctrlKey) ||
|
|
487
800
|
(k.alt == 'resize' && (event.altKey || event.originalEvent.altKey)))
|
|
488
801
|
{
|
|
802
|
+
/* Resize selection */
|
|
803
|
+
|
|
489
804
|
switch (key) {
|
|
490
805
|
case 37:
|
|
806
|
+
/* Left */
|
|
491
807
|
d = -d;
|
|
492
808
|
case 39:
|
|
809
|
+
/* Right */
|
|
493
810
|
t = max(x1, x2);
|
|
494
811
|
x1 = min(x1, x2);
|
|
495
812
|
x2 = max(t + d, x1);
|
|
496
813
|
fixAspectRatio();
|
|
497
814
|
break;
|
|
498
815
|
case 38:
|
|
816
|
+
/* Up */
|
|
499
817
|
d = -d;
|
|
500
818
|
case 40:
|
|
819
|
+
/* Down */
|
|
501
820
|
t = max(y1, y2);
|
|
502
821
|
y1 = min(y1, y2);
|
|
503
822
|
y2 = max(t + d, y1);
|
|
@@ -510,20 +829,26 @@ $.imgAreaSelect = function (img, options) {
|
|
|
510
829
|
doResize();
|
|
511
830
|
}
|
|
512
831
|
else {
|
|
832
|
+
/* Move selection */
|
|
833
|
+
|
|
513
834
|
x1 = min(x1, x2);
|
|
514
835
|
y1 = min(y1, y2);
|
|
515
836
|
|
|
516
837
|
switch (key) {
|
|
517
838
|
case 37:
|
|
839
|
+
/* Left */
|
|
518
840
|
doMove(max(x1 - d, left), y1);
|
|
519
841
|
break;
|
|
520
842
|
case 38:
|
|
843
|
+
/* Up */
|
|
521
844
|
doMove(x1, max(y1 - d, top));
|
|
522
845
|
break;
|
|
523
846
|
case 39:
|
|
847
|
+
/* Right */
|
|
524
848
|
doMove(x1 + min(d, imgWidth - selX(x2)), y1);
|
|
525
849
|
break;
|
|
526
850
|
case 40:
|
|
851
|
+
/* Down */
|
|
527
852
|
doMove(x1, y1 + min(d, imgHeight - selY(y2)));
|
|
528
853
|
break;
|
|
529
854
|
default:
|
|
@@ -534,21 +859,38 @@ $.imgAreaSelect = function (img, options) {
|
|
|
534
859
|
return false;
|
|
535
860
|
};
|
|
536
861
|
|
|
862
|
+
/**
|
|
863
|
+
* Apply style options to plugin element (or multiple elements)
|
|
864
|
+
*
|
|
865
|
+
* @param $elem
|
|
866
|
+
* A jQuery object representing the element(s) to style
|
|
867
|
+
* @param props
|
|
868
|
+
* An object that maps option names to corresponding CSS
|
|
869
|
+
* properties
|
|
870
|
+
*/
|
|
537
871
|
function styleOptions($elem, props) {
|
|
538
872
|
for (var option in props)
|
|
539
873
|
if (options[option] !== undefined)
|
|
540
874
|
$elem.css(props[option], options[option]);
|
|
541
875
|
}
|
|
542
876
|
|
|
877
|
+
/**
|
|
878
|
+
* Set plugin options
|
|
879
|
+
*
|
|
880
|
+
* @param newOptions
|
|
881
|
+
* The new options object
|
|
882
|
+
*/
|
|
543
883
|
function setOptions(newOptions) {
|
|
544
884
|
if (newOptions.parent)
|
|
545
885
|
($parent = $(newOptions.parent)).append($box.add($outer));
|
|
546
|
-
|
|
886
|
+
|
|
887
|
+
/* Merge the new options with the existing ones */
|
|
547
888
|
$.extend(options, newOptions);
|
|
548
889
|
|
|
549
890
|
adjust();
|
|
550
891
|
|
|
551
892
|
if (newOptions.handles != null) {
|
|
893
|
+
/* Recreate selection area handles */
|
|
552
894
|
$handles.remove();
|
|
553
895
|
$handles = $([]);
|
|
554
896
|
|
|
@@ -556,27 +898,43 @@ $.imgAreaSelect = function (img, options) {
|
|
|
556
898
|
|
|
557
899
|
while (i--)
|
|
558
900
|
$handles = $handles.add(div());
|
|
559
|
-
|
|
901
|
+
|
|
902
|
+
/* Add a class to handles and set the CSS properties */
|
|
560
903
|
$handles.addClass(options.classPrefix + '-handle').css({
|
|
561
904
|
position: 'absolute',
|
|
905
|
+
/*
|
|
906
|
+
* The font-size property needs to be set to zero, otherwise
|
|
907
|
+
* Internet Explorer makes the handles too large
|
|
908
|
+
*/
|
|
562
909
|
fontSize: 0,
|
|
563
910
|
zIndex: zIndex + 1 || 1
|
|
564
911
|
});
|
|
565
|
-
|
|
912
|
+
|
|
913
|
+
/*
|
|
914
|
+
* If handle width/height has not been set with CSS rules, set the
|
|
915
|
+
* default 5px
|
|
916
|
+
*/
|
|
566
917
|
if (!parseInt($handles.css('width')) >= 0)
|
|
567
918
|
$handles.width(5).height(5);
|
|
568
|
-
|
|
919
|
+
|
|
920
|
+
/*
|
|
921
|
+
* If the borderWidth option is in use, add a solid border to
|
|
922
|
+
* handles
|
|
923
|
+
*/
|
|
569
924
|
if (o = options.borderWidth)
|
|
570
925
|
$handles.css({ borderWidth: o, borderStyle: 'solid' });
|
|
571
926
|
|
|
927
|
+
/* Apply other style options */
|
|
572
928
|
styleOptions($handles, { borderColor1: 'border-color',
|
|
573
929
|
borderColor2: 'background-color',
|
|
574
930
|
borderOpacity: 'opacity' });
|
|
575
931
|
}
|
|
576
932
|
|
|
933
|
+
/* Calculate scale factors */
|
|
577
934
|
scaleX = options.imageWidth / imgWidth || 1;
|
|
578
935
|
scaleY = options.imageHeight / imgHeight || 1;
|
|
579
936
|
|
|
937
|
+
/* Set selection */
|
|
580
938
|
if (newOptions.x1 != null) {
|
|
581
939
|
setSelection(newOptions.x1, newOptions.y1, newOptions.x2,
|
|
582
940
|
newOptions.y2);
|
|
@@ -584,14 +942,17 @@ $.imgAreaSelect = function (img, options) {
|
|
|
584
942
|
}
|
|
585
943
|
|
|
586
944
|
if (newOptions.keys)
|
|
945
|
+
/* Enable keyboard support */
|
|
587
946
|
options.keys = $.extend({ shift: 1, ctrl: 'resize' },
|
|
588
947
|
newOptions.keys);
|
|
589
948
|
|
|
949
|
+
/* Add classes to plugin elements */
|
|
590
950
|
$outer.addClass(options.classPrefix + '-outer');
|
|
591
951
|
$area.addClass(options.classPrefix + '-selection');
|
|
592
952
|
for (i = 0; i++ < 4;)
|
|
593
953
|
$($border[i-1]).addClass(options.classPrefix + '-border' + i);
|
|
594
954
|
|
|
955
|
+
/* Apply style options */
|
|
595
956
|
styleOptions($area, { selectionColor: 'background-color',
|
|
596
957
|
selectionOpacity: 'opacity' });
|
|
597
958
|
styleOptions($border, { borderOpacity: 'opacity',
|
|
@@ -603,15 +964,16 @@ $.imgAreaSelect = function (img, options) {
|
|
|
603
964
|
if (o = options.borderColor2)
|
|
604
965
|
$($border[1]).css({ borderStyle: 'dashed', borderColor: o });
|
|
605
966
|
|
|
606
|
-
|
|
967
|
+
/* Append all the selection area elements to the container box */
|
|
968
|
+
$box.append($area.add($border).add($areaOpera)).append($handles);
|
|
607
969
|
|
|
608
|
-
if (
|
|
970
|
+
if (msie) {
|
|
609
971
|
if (o = ($outer.css('filter')||'').match(/opacity=(\d+)/))
|
|
610
972
|
$outer.css('opacity', o[1]/100);
|
|
611
973
|
if (o = ($border.css('filter')||'').match(/opacity=(\d+)/))
|
|
612
974
|
$border.css('opacity', o[1]/100);
|
|
613
975
|
}
|
|
614
|
-
|
|
976
|
+
|
|
615
977
|
if (newOptions.hide)
|
|
616
978
|
hide($box.add($outer));
|
|
617
979
|
else if (newOptions.show && imgLoaded) {
|
|
@@ -620,102 +982,221 @@ $.imgAreaSelect = function (img, options) {
|
|
|
620
982
|
doUpdate();
|
|
621
983
|
}
|
|
622
984
|
|
|
985
|
+
/* Calculate the aspect ratio factor */
|
|
623
986
|
aspectRatio = (d = (options.aspectRatio || '').split(/:/))[0] / d[1];
|
|
624
987
|
|
|
625
988
|
$img.add($outer).unbind('mousedown', imgMouseDown);
|
|
626
|
-
|
|
989
|
+
|
|
627
990
|
if (options.disable || options.enable === false) {
|
|
991
|
+
/* Disable the plugin */
|
|
628
992
|
$box.unbind('mousemove', areaMouseMove).unbind('mousedown', areaMouseDown);
|
|
629
993
|
$(window).unbind('resize', windowResize);
|
|
630
994
|
}
|
|
631
995
|
else {
|
|
632
996
|
if (options.enable || options.disable === false) {
|
|
997
|
+
/* Enable the plugin */
|
|
633
998
|
if (options.resizable || options.movable)
|
|
634
999
|
$box.mousemove(areaMouseMove).mousedown(areaMouseDown);
|
|
635
|
-
|
|
1000
|
+
|
|
636
1001
|
$(window).resize(windowResize);
|
|
637
1002
|
}
|
|
638
1003
|
|
|
639
1004
|
if (!options.persistent)
|
|
640
1005
|
$img.add($outer).mousedown(imgMouseDown);
|
|
641
1006
|
}
|
|
642
|
-
|
|
1007
|
+
|
|
643
1008
|
options.enable = options.disable = undefined;
|
|
644
1009
|
}
|
|
645
|
-
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Remove plugin completely
|
|
1013
|
+
*/
|
|
646
1014
|
this.remove = function () {
|
|
1015
|
+
/*
|
|
1016
|
+
* Call setOptions with { disable: true } to unbind the event handlers
|
|
1017
|
+
*/
|
|
647
1018
|
setOptions({ disable: true });
|
|
648
1019
|
$box.add($outer).remove();
|
|
649
1020
|
};
|
|
650
|
-
|
|
1021
|
+
|
|
1022
|
+
/*
|
|
1023
|
+
* Public API
|
|
1024
|
+
*/
|
|
1025
|
+
|
|
1026
|
+
/**
|
|
1027
|
+
* Get current options
|
|
1028
|
+
*
|
|
1029
|
+
* @return An object containing the set of options currently in use
|
|
1030
|
+
*/
|
|
651
1031
|
this.getOptions = function () { return options; };
|
|
652
|
-
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* Set plugin options
|
|
1035
|
+
*
|
|
1036
|
+
* @param newOptions
|
|
1037
|
+
* The new options object
|
|
1038
|
+
*/
|
|
653
1039
|
this.setOptions = setOptions;
|
|
654
|
-
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Get the current selection
|
|
1043
|
+
*
|
|
1044
|
+
* @param noScale
|
|
1045
|
+
* If set to <code>true</code>, scaling is not applied to the
|
|
1046
|
+
* returned selection
|
|
1047
|
+
* @return Selection object
|
|
1048
|
+
*/
|
|
655
1049
|
this.getSelection = getSelection;
|
|
656
|
-
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Set the current selection
|
|
1053
|
+
*
|
|
1054
|
+
* @param x1
|
|
1055
|
+
* X coordinate of the upper left corner of the selection area
|
|
1056
|
+
* @param y1
|
|
1057
|
+
* Y coordinate of the upper left corner of the selection area
|
|
1058
|
+
* @param x2
|
|
1059
|
+
* X coordinate of the lower right corner of the selection area
|
|
1060
|
+
* @param y2
|
|
1061
|
+
* Y coordinate of the lower right corner of the selection area
|
|
1062
|
+
* @param noScale
|
|
1063
|
+
* If set to <code>true</code>, scaling is not applied to the
|
|
1064
|
+
* new selection
|
|
1065
|
+
*/
|
|
657
1066
|
this.setSelection = setSelection;
|
|
658
|
-
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Cancel selection
|
|
1070
|
+
*/
|
|
659
1071
|
this.cancelSelection = cancelSelection;
|
|
660
|
-
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* Update plugin elements
|
|
1075
|
+
*
|
|
1076
|
+
* @param resetKeyPress
|
|
1077
|
+
* If set to <code>false</code>, this instance's keypress
|
|
1078
|
+
* event handler is not activated
|
|
1079
|
+
*/
|
|
661
1080
|
this.update = doUpdate;
|
|
662
1081
|
|
|
1082
|
+
/* Do the dreaded browser detection */
|
|
1083
|
+
var msie = (/msie ([\w.]+)/i.exec(ua)||[])[1],
|
|
1084
|
+
opera = /opera/i.test(ua),
|
|
1085
|
+
safari = /webkit/i.test(ua) && !/chrome/i.test(ua);
|
|
1086
|
+
|
|
1087
|
+
/*
|
|
1088
|
+
* Traverse the image's parent elements (up to <body>) and find the
|
|
1089
|
+
* highest z-index
|
|
1090
|
+
*/
|
|
663
1091
|
$p = $img;
|
|
664
1092
|
|
|
665
1093
|
while ($p.length) {
|
|
666
1094
|
zIndex = max(zIndex,
|
|
667
1095
|
!isNaN($p.css('z-index')) ? $p.css('z-index') : zIndex);
|
|
1096
|
+
/* Also check if any of the ancestor elements has fixed position */
|
|
668
1097
|
if ($p.css('position') == 'fixed')
|
|
669
1098
|
position = 'fixed';
|
|
670
1099
|
|
|
671
1100
|
$p = $p.parent(':not(body)');
|
|
672
1101
|
}
|
|
673
|
-
|
|
1102
|
+
|
|
1103
|
+
/*
|
|
1104
|
+
* If z-index is given as an option, it overrides the one found by the
|
|
1105
|
+
* above loop
|
|
1106
|
+
*/
|
|
674
1107
|
zIndex = options.zIndex || zIndex;
|
|
675
1108
|
|
|
676
|
-
if (
|
|
1109
|
+
if (msie)
|
|
677
1110
|
$img.attr('unselectable', 'on');
|
|
678
1111
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
1112
|
+
/*
|
|
1113
|
+
* In MSIE and WebKit, we need to use the keydown event instead of keypress
|
|
1114
|
+
*/
|
|
1115
|
+
$.imgAreaSelect.keyPress = msie || safari ? 'keydown' : 'keypress';
|
|
1116
|
+
|
|
1117
|
+
/*
|
|
1118
|
+
* There is a bug affecting the CSS cursor property in Opera (observed in
|
|
1119
|
+
* versions up to 10.00) that prevents the cursor from being updated unless
|
|
1120
|
+
* the mouse leaves and enters the element again. To trigger the mouseover
|
|
1121
|
+
* event, we're adding an additional div to $box and we're going to toggle
|
|
1122
|
+
* it when mouse moves inside the selection area.
|
|
1123
|
+
*/
|
|
1124
|
+
if (opera)
|
|
683
1125
|
$areaOpera = div().css({ width: '100%', height: '100%',
|
|
684
1126
|
position: 'absolute', zIndex: zIndex + 2 || 2 });
|
|
685
1127
|
|
|
1128
|
+
/*
|
|
1129
|
+
* We initially set visibility to "hidden" as a workaround for a weird
|
|
1130
|
+
* behaviour observed in Google Chrome 1.0.154.53 (on Windows XP). Normally
|
|
1131
|
+
* we would just set display to "none", but, for some reason, if we do so
|
|
1132
|
+
* then Chrome refuses to later display the element with .show() or
|
|
1133
|
+
* .fadeIn().
|
|
1134
|
+
*/
|
|
686
1135
|
$box.add($outer).css({ visibility: 'hidden', position: position,
|
|
687
1136
|
overflow: 'hidden', zIndex: zIndex || '0' });
|
|
688
1137
|
$box.css({ zIndex: zIndex + 2 || 2 });
|
|
689
1138
|
$area.add($border).css({ position: 'absolute', fontSize: 0 });
|
|
690
|
-
|
|
1139
|
+
|
|
1140
|
+
/*
|
|
1141
|
+
* If the image has been fully loaded, or if it is not really an image (eg.
|
|
1142
|
+
* a div), call imgLoad() immediately; otherwise, bind it to be called once
|
|
1143
|
+
* on image load event.
|
|
1144
|
+
*/
|
|
691
1145
|
img.complete || img.readyState == 'complete' || !$img.is('img') ?
|
|
692
1146
|
imgLoad() : $img.one('load', imgLoad);
|
|
693
1147
|
|
|
694
|
-
|
|
1148
|
+
/*
|
|
1149
|
+
* MSIE 9.0 doesn't always fire the image load event -- resetting the src
|
|
1150
|
+
* attribute seems to trigger it. The check is for version 7 and above to
|
|
1151
|
+
* accommodate for MSIE 9 running in compatibility mode.
|
|
1152
|
+
*/
|
|
1153
|
+
if (!imgLoaded && msie && msie >= 7)
|
|
695
1154
|
img.src = img.src;
|
|
696
1155
|
};
|
|
697
1156
|
|
|
1157
|
+
/**
|
|
1158
|
+
* Invoke imgAreaSelect on a jQuery object containing the image(s)
|
|
1159
|
+
*
|
|
1160
|
+
* @param options
|
|
1161
|
+
* Options object
|
|
1162
|
+
* @return The jQuery object or a reference to imgAreaSelect instance (if the
|
|
1163
|
+
* <code>instance</code> option was specified)
|
|
1164
|
+
*/
|
|
698
1165
|
$.fn.imgAreaSelect = function (options) {
|
|
699
1166
|
options = options || {};
|
|
700
1167
|
|
|
701
1168
|
this.each(function () {
|
|
1169
|
+
/* Is there already an imgAreaSelect instance bound to this element? */
|
|
702
1170
|
if ($(this).data('imgAreaSelect')) {
|
|
1171
|
+
/* Yes there is -- is it supposed to be removed? */
|
|
703
1172
|
if (options.remove) {
|
|
1173
|
+
/* Remove the plugin */
|
|
704
1174
|
$(this).data('imgAreaSelect').remove();
|
|
705
1175
|
$(this).removeData('imgAreaSelect');
|
|
706
1176
|
}
|
|
707
1177
|
else
|
|
1178
|
+
/* Reset options */
|
|
708
1179
|
$(this).data('imgAreaSelect').setOptions(options);
|
|
709
1180
|
}
|
|
710
1181
|
else if (!options.remove) {
|
|
1182
|
+
/* No exising instance -- create a new one */
|
|
1183
|
+
|
|
1184
|
+
/*
|
|
1185
|
+
* If neither the "enable" nor the "disable" option is present, add
|
|
1186
|
+
* "enable" as the default
|
|
1187
|
+
*/
|
|
711
1188
|
if (options.enable === undefined && options.disable === undefined)
|
|
712
1189
|
options.enable = true;
|
|
713
1190
|
|
|
714
1191
|
$(this).data('imgAreaSelect', new $.imgAreaSelect(this, options));
|
|
715
1192
|
}
|
|
716
1193
|
});
|
|
717
|
-
|
|
1194
|
+
|
|
718
1195
|
if (options.instance)
|
|
1196
|
+
/*
|
|
1197
|
+
* Return the imgAreaSelect instance bound to the first element in the
|
|
1198
|
+
* set
|
|
1199
|
+
*/
|
|
719
1200
|
return $(this).data('imgAreaSelect');
|
|
720
1201
|
|
|
721
1202
|
return this;
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: imgareaselect-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 19
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 1
|
|
8
8
|
- 0
|
|
9
|
-
-
|
|
10
|
-
version: 1.0.
|
|
9
|
+
- 2
|
|
10
|
+
version: 1.0.2
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Aaron Lasseigne
|
|
@@ -15,10 +15,10 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date:
|
|
18
|
+
date: 2013-02-04 00:00:00 Z
|
|
19
19
|
dependencies:
|
|
20
20
|
- !ruby/object:Gem::Dependency
|
|
21
|
-
|
|
21
|
+
prerelease: false
|
|
22
22
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
|
23
23
|
none: false
|
|
24
24
|
requirements:
|
|
@@ -29,10 +29,10 @@ dependencies:
|
|
|
29
29
|
- 3
|
|
30
30
|
- 1
|
|
31
31
|
version: "3.1"
|
|
32
|
-
type: :runtime
|
|
33
32
|
requirement: *id001
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
name: rails
|
|
34
|
+
type: :runtime
|
|
35
|
+
description: Places imgAreaSelect 0.9.10 in the Rails asset pipeline.
|
|
36
36
|
email:
|
|
37
37
|
- aaron@orgsync.com
|
|
38
38
|
executables: []
|
|
@@ -91,9 +91,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
91
91
|
requirements: []
|
|
92
92
|
|
|
93
93
|
rubyforge_project:
|
|
94
|
-
rubygems_version: 1.8.
|
|
94
|
+
rubygems_version: 1.8.15
|
|
95
95
|
signing_key:
|
|
96
96
|
specification_version: 3
|
|
97
|
-
summary: Places imgAreaSelect 0.9.
|
|
97
|
+
summary: Places imgAreaSelect 0.9.10 in the Rails asset pipeline.
|
|
98
98
|
test_files: []
|
|
99
99
|
|