imgareaselect-rails 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|