1 | /* |
||
2 | * iviewer Widget for jQuery UI |
||
3 | * https://github.com/can3p/iviewer |
||
4 | * |
||
5 | * Copyright (c) 2009 - 2012 Dmitry Petrov |
||
6 | * Dual licensed under the MIT and GPL licenses. |
||
7 | * - http://www.opensource.org/licenses/mit-license.php |
||
8 | * - http://www.gnu.org/copyleft/gpl.html |
||
9 | * |
||
10 | * Author: Dmitry Petrov |
||
11 | * Version: 0.7.7 |
||
12 | */ |
||
13 | |||
14 | ( function( $, undefined ) { |
||
15 | |||
16 | //this code was taken from the https://github.com/furf/jquery-ui-touch-punch |
||
17 | var mouseEvents = { |
||
18 | touchstart: 'mousedown', |
||
19 | touchmove: 'mousemove', |
||
20 | touchend: 'mouseup' |
||
21 | }, |
||
22 | gesturesSupport = 'ongesturestart' in document.createElement('div'); |
||
23 | |||
24 | |||
25 | /** |
||
26 | * Convert a touch event to a mouse-like |
||
27 | */ |
||
28 | function makeMouseEvent (event) { |
||
29 | var touch = event.originalEvent.changedTouches[0]; |
||
30 | |||
31 | return $.extend(event, { |
||
32 | type: mouseEvents[event.type], |
||
33 | which: 1, |
||
34 | pageX: touch.pageX, |
||
35 | pageY: touch.pageY, |
||
36 | screenX: touch.screenX, |
||
37 | screenY: touch.screenY, |
||
38 | clientX: touch.clientX, |
||
39 | clientY: touch.clientY, |
||
40 | isTouchEvent: true |
||
41 | }); |
||
42 | } |
||
43 | |||
44 | var mouseProto = $.ui.mouse.prototype, |
||
45 | _mouseInit = $.ui.mouse.prototype._mouseInit; |
||
46 | |||
47 | mouseProto._mouseInit = function() { |
||
48 | var self = this; |
||
49 | self._touchActive = false; |
||
50 | |||
51 | this.element.bind( 'touchstart.' + this.widgetName, function(event) { |
||
52 | if (gesturesSupport && event.originalEvent.touches.length > 1) { return; } |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
53 | self._touchActive = true; |
||
54 | return self._mouseDown(makeMouseEvent(event)); |
||
55 | }) |
||
56 | |||
57 | var self = this; |
||
0 ignored issues
–
show
Comprehensibility
Naming
Best Practice
introduced
by
The variable
self already seems to be declared on line 48 . Consider using another variable name or omitting the var keyword.
This check looks for variables that are declared in multiple lines. There may be several reasons for this. In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs. If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared. ![]() |
|||
58 | // these delegates are required to keep context |
||
59 | this._mouseMoveDelegate = function(event) { |
||
60 | if (gesturesSupport && event.originalEvent.touches && event.originalEvent.touches.length > 1) { return; } |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
61 | if (self._touchActive) { |
||
0 ignored issues
–
show
There is no return statement if
self._touchActive is false . Are you sure this is correct? If so, consider adding return; explicitly.
This check looks for functions where a Consider this little piece of code function isBig(a) {
if (a > 5000) {
return "yes";
}
}
console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined
The function This behaviour may not be what you had intended. In any case, you can add a
![]() |
|||
62 | return self._mouseMove(makeMouseEvent(event)); |
||
63 | } |
||
64 | }; |
||
65 | this._mouseUpDelegate = function(event) { |
||
66 | if (self._touchActive) { |
||
0 ignored issues
–
show
There is no return statement if
self._touchActive is false . Are you sure this is correct? If so, consider adding return; explicitly.
This check looks for functions where a Consider this little piece of code function isBig(a) {
if (a > 5000) {
return "yes";
}
}
console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined
The function This behaviour may not be what you had intended. In any case, you can add a
![]() |
|||
67 | self._touchActive = false; |
||
68 | return self._mouseUp(makeMouseEvent(event)); |
||
69 | } |
||
70 | }; |
||
71 | |||
72 | $(document) |
||
73 | .bind('touchmove.'+ this.widgetName, this._mouseMoveDelegate) |
||
74 | .bind('touchend.' + this.widgetName, this._mouseUpDelegate); |
||
75 | |||
76 | _mouseInit.apply(this); |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * Simple implementation of jQuery like getters/setters |
||
81 | * var val = something(); |
||
82 | * something(val); |
||
83 | */ |
||
84 | var setter = function(setter, getter) { |
||
85 | return function(val) { |
||
0 ignored issues
–
show
|
|||
86 | if (arguments.length === 0) { |
||
87 | return getter.apply(this); |
||
88 | } else { |
||
0 ignored issues
–
show
|
|||
89 | setter.apply(this, arguments); |
||
0 ignored issues
–
show
|
|||
90 | } |
||
91 | } |
||
92 | }; |
||
93 | |||
94 | /** |
||
95 | * Internet explorer rotates image relative left top corner, so we should |
||
96 | * shift image when it's rotated. |
||
97 | */ |
||
98 | var ieTransforms = { |
||
99 | '0': { |
||
100 | marginLeft: 0, |
||
101 | marginTop: 0, |
||
102 | filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, SizingMethod="auto expand")' |
||
103 | }, |
||
104 | |||
105 | '90': { |
||
106 | marginLeft: -1, |
||
107 | marginTop: 1, |
||
108 | filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=-1, M21=1, M22=0, SizingMethod="auto expand")' |
||
109 | }, |
||
110 | |||
111 | '180': { |
||
112 | marginLeft: 0, |
||
113 | marginTop: 0, |
||
114 | filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=-1, M12=0, M21=0, M22=-1, SizingMethod="auto expand")' |
||
115 | }, |
||
116 | |||
117 | '270': { |
||
118 | marginLeft: -1, |
||
119 | marginTop: 1, |
||
120 | filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=1, M21=-1, M22=0, SizingMethod="auto expand")' |
||
121 | } |
||
122 | }, |
||
123 | // this test is the inversion of the css filters test from the modernizr project |
||
124 | useIeTransforms = function() { |
||
125 | var modElem = document.createElement('modernizr'), |
||
126 | mStyle = modElem.style, |
||
127 | omPrefixes = 'Webkit Moz O ms', |
||
128 | domPrefixes = omPrefixes.toLowerCase().split(' '), |
||
129 | props = ("transform" + ' ' + domPrefixes.join("Transform ") + "Transform").split(' '); |
||
130 | for ( var i in props ) { |
||
0 ignored issues
–
show
A for in loop automatically includes the property of any prototype object, consider checking the key using
hasOwnProperty .
When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically: var someObject;
for (var key in someObject) {
if ( ! someObject.hasOwnProperty(key)) {
continue; // Skip keys from the prototype.
}
doSomethingWith(key);
}
![]() |
|||
131 | var prop = props[i]; |
||
132 | if ( !$.contains(prop, "-") && mStyle[prop] !== undefined ) { |
||
133 | return false; |
||
134 | } |
||
135 | } |
||
136 | return true; |
||
137 | }(); |
||
138 | |||
139 | $.widget( "ui.iviewer", $.ui.mouse, { |
||
140 | widgetEventPrefix: "iviewer", |
||
141 | options : { |
||
142 | /** |
||
143 | * start zoom value for image, not used now |
||
144 | * may be equal to "fit" to fit image into container or scale in % |
||
145 | **/ |
||
146 | zoom: "fit", |
||
147 | /** |
||
148 | * base value to scale image |
||
149 | **/ |
||
150 | zoom_base: 100, |
||
151 | /** |
||
152 | * maximum zoom |
||
153 | **/ |
||
154 | zoom_max: 800, |
||
155 | /** |
||
156 | * minimum zoom |
||
157 | **/ |
||
158 | zoom_min: 25, |
||
159 | /** |
||
160 | * base of rate multiplier. |
||
161 | * zoom is calculated by formula: zoom_base * zoom_delta^rate |
||
162 | **/ |
||
163 | zoom_delta: 1.4, |
||
164 | /** |
||
165 | * whether the zoom should be animated. |
||
166 | */ |
||
167 | zoom_animation: true, |
||
168 | /** |
||
169 | * if true plugin doesn't add its own controls |
||
170 | **/ |
||
171 | ui_disabled: false, |
||
172 | /** |
||
173 | * If false mousewheel will be disabled |
||
174 | */ |
||
175 | mousewheel: true, |
||
176 | /** |
||
177 | * if false, plugin doesn't bind resize event on window and this must |
||
178 | * be handled manually |
||
179 | **/ |
||
180 | update_on_resize: true, |
||
181 | /** |
||
182 | * event is triggered when zoom value is changed |
||
183 | * @param int new zoom value |
||
184 | * @return boolean if false zoom action is aborted |
||
185 | **/ |
||
186 | onZoom: jQuery.noop, |
||
187 | /** |
||
188 | * event is triggered when zoom value is changed after image is set to the new dimensions |
||
189 | * @param int new zoom value |
||
190 | * @return boolean if false zoom action is aborted |
||
191 | **/ |
||
192 | onAfterZoom: jQuery.noop, |
||
193 | /** |
||
194 | * event is fired on drag begin |
||
195 | * @param object coords mouse coordinates on the image |
||
196 | * @return boolean if false is returned, drag action is aborted |
||
197 | **/ |
||
198 | onStartDrag: jQuery.noop, |
||
199 | /** |
||
200 | * event is fired on drag action |
||
201 | * @param object coords mouse coordinates on the image |
||
202 | **/ |
||
203 | onDrag: jQuery.noop, |
||
204 | /** |
||
205 | * event is fired on drag stop |
||
206 | * @param object coords mouse coordinates on the image |
||
207 | **/ |
||
208 | onStopDrag: jQuery.noop, |
||
209 | /** |
||
210 | * event is fired when mouse moves over image |
||
211 | * @param object coords mouse coordinates on the image |
||
212 | **/ |
||
213 | onMouseMove: jQuery.noop, |
||
214 | /** |
||
215 | * mouse click event |
||
216 | * @param object coords mouse coordinates on the image |
||
217 | **/ |
||
218 | onClick: jQuery.noop, |
||
219 | /** |
||
220 | * event is fired when image starts to load |
||
221 | */ |
||
222 | onStartLoad: null, |
||
223 | /** |
||
224 | * event is fired, when image is loaded and initially positioned |
||
225 | */ |
||
226 | onFinishLoad: null, |
||
227 | /** |
||
228 | * event is fired when image load error occurs |
||
229 | */ |
||
230 | onErrorLoad: null |
||
231 | }, |
||
232 | |||
233 | _create: function() { |
||
234 | var me = this; |
||
235 | |||
236 | //drag variables |
||
237 | this.dx = 0; |
||
238 | this.dy = 0; |
||
239 | |||
240 | /* object containing actual information about image |
||
241 | * @img_object.object - jquery img object |
||
242 | * @img_object.orig_{width|height} - original dimensions |
||
243 | * @img_object.display_{width|height} - actual dimensions |
||
244 | */ |
||
245 | this.img_object = {}; |
||
246 | |||
247 | this.zoom_object = {}; //object to show zoom status |
||
248 | |||
249 | this._angle = 0; |
||
250 | |||
251 | this.current_zoom = this.options.zoom; |
||
252 | |||
253 | if(this.options.src === null){ |
||
254 | return; |
||
255 | } |
||
256 | |||
257 | this.container = this.element; |
||
258 | |||
259 | this._updateContainerInfo(); |
||
260 | |||
261 | //init container |
||
262 | this.container.css("overflow","hidden"); |
||
263 | |||
264 | if (this.options.update_on_resize == true) { |
||
0 ignored issues
–
show
|
|||
265 | $(window).resize(function() { |
||
266 | me.update(); |
||
267 | }); |
||
268 | } |
||
269 | |||
270 | this.img_object = new $.ui.iviewer.ImageObject(this.options.zoom_animation); |
||
271 | |||
272 | if (this.options.mousewheel) { |
||
273 | this.container.bind('mousewheel.iviewer', function(ev, delta) |
||
274 | { |
||
275 | //this event is there instead of containing div, because |
||
276 | //at opera it triggers many times on div |
||
277 | var zoom = (delta > 0)?1:-1, |
||
278 | container_offset = me.container.offset(), |
||
279 | mouse_pos = { |
||
280 | //jquery.mousewheel 3.1.0 uses strange MozMousePixelScroll event |
||
281 | //which is not being fixed by jQuery.Event |
||
282 | x: (ev.pageX || ev.originalEvent.pageX) - container_offset.left, |
||
283 | y: (ev.pageY || ev.originalEvent.pageX) - container_offset.top |
||
284 | }; |
||
285 | |||
286 | me.zoom_by(zoom, mouse_pos); |
||
287 | return false; |
||
288 | }); |
||
289 | |||
290 | if (gesturesSupport) { |
||
291 | var gestureThrottle = +new Date(); |
||
292 | var originalScale, originalCenter; |
||
293 | this.img_object.object() |
||
294 | // .bind('gesturestart', function(ev) { |
||
295 | .bind('touchstart', function(ev) { |
||
296 | originalScale = me.current_zoom; |
||
297 | var touches = ev.originalEvent.touches, |
||
298 | container_offset; |
||
299 | if (touches.length == 2) { |
||
300 | container_offset = me.container.offset(); |
||
301 | originalCenter = { |
||
302 | x: (touches[0].pageX + touches[1].pageX) / 2 - container_offset.left, |
||
303 | y: (touches[0].pageY + touches[1].pageY) / 2 - container_offset.top |
||
304 | }; |
||
305 | } else { |
||
306 | originalCenter = null; |
||
307 | } |
||
308 | }).bind('gesturechange', function(ev) { |
||
309 | //do not want to import throttle function from underscore |
||
310 | var d = +new Date(); |
||
311 | if ((d - gestureThrottle) < 50) { return; } |
||
312 | gestureThrottle = d; |
||
313 | var zoom = originalScale * ev.originalEvent.scale; |
||
314 | me.set_zoom(zoom, originalCenter); |
||
315 | ev.preventDefault(); |
||
316 | }).bind('gestureend', function(ev) { |
||
0 ignored issues
–
show
|
|||
317 | originalCenter = null; |
||
318 | }); |
||
319 | } |
||
320 | } |
||
321 | |||
322 | //init object |
||
323 | this.img_object.object() |
||
324 | //bind mouse events |
||
325 | .click(function(e){return me._click(e)}) |
||
326 | .prependTo(this.container); |
||
327 | |||
328 | this.container.bind('mousemove', function(ev) { me._handleMouseMove(ev); }); |
||
329 | |||
330 | this.loadImage(this.options.src); |
||
331 | |||
332 | if(!this.options.ui_disabled) |
||
333 | { |
||
334 | this.createui(); |
||
335 | } |
||
336 | |||
337 | this._mouseInit(); |
||
338 | }, |
||
339 | |||
340 | destroy: function() { |
||
341 | $.Widget.prototype.destroy.call( this ); |
||
342 | this._mouseDestroy(); |
||
343 | this.img_object.object().remove(); |
||
344 | this.container.off('.iviewer'); |
||
345 | this.container.css('overflow', ''); //cleanup styles on destroy |
||
346 | }, |
||
347 | |||
348 | _updateContainerInfo: function() |
||
349 | { |
||
350 | this.options.height = this.container.height(); |
||
351 | this.options.width = this.container.width(); |
||
352 | }, |
||
353 | |||
354 | update: function() |
||
355 | { |
||
356 | this._updateContainerInfo() |
||
357 | this.setCoords(this.img_object.x(), this.img_object.y()); |
||
358 | }, |
||
359 | |||
360 | loadImage: function( src ) |
||
361 | { |
||
362 | this.current_zoom = this.options.zoom; |
||
363 | var me = this; |
||
364 | |||
365 | this._trigger('onStartLoad', 0, src); |
||
366 | |||
367 | this.container.addClass("iviewer_loading"); |
||
368 | this.img_object.load(src, function() { |
||
369 | me._imageLoaded(src); |
||
370 | }, function() { |
||
371 | me._trigger("onErrorLoad", 0, src); |
||
372 | }); |
||
373 | }, |
||
374 | |||
375 | _imageLoaded: function(src) { |
||
376 | this.container.removeClass("iviewer_loading"); |
||
377 | this.container.addClass("iviewer_cursor"); |
||
378 | |||
379 | if(this.options.zoom == "fit"){ |
||
380 | this.fit(true); |
||
381 | } |
||
382 | else { |
||
383 | this.set_zoom(this.options.zoom, true); |
||
384 | } |
||
385 | |||
386 | this._trigger('onFinishLoad', 0, src); |
||
387 | }, |
||
388 | |||
389 | /** |
||
390 | * fits image in the container |
||
391 | * |
||
392 | * @param {boolean} skip_animation |
||
393 | **/ |
||
394 | fit: function(skip_animation) |
||
395 | { |
||
396 | var aspect_ratio = this.img_object.orig_width() / this.img_object.orig_height(); |
||
397 | var window_ratio = this.options.width / this.options.height; |
||
398 | var choose_left = (aspect_ratio > window_ratio); |
||
399 | var new_zoom = 0; |
||
400 | |||
401 | if(choose_left){ |
||
402 | new_zoom = this.options.width / this.img_object.orig_width() * 100; |
||
403 | } |
||
404 | else { |
||
405 | new_zoom = this.options.height / this.img_object.orig_height() * 100; |
||
406 | } |
||
407 | |||
408 | this.set_zoom(new_zoom, skip_animation); |
||
409 | }, |
||
410 | |||
411 | /** |
||
412 | * center image in container |
||
413 | **/ |
||
414 | center: function() |
||
415 | { |
||
416 | this.setCoords(-Math.round((this.img_object.display_width() - this.options.width)/2), |
||
417 | -Math.round((this.img_object.display_height() - this.options.height)/2)); |
||
418 | }, |
||
419 | |||
420 | /** |
||
421 | * move a point in container to the center of display area |
||
422 | * @param x a point in container |
||
423 | * @param y a point in container |
||
424 | **/ |
||
425 | moveTo: function(x, y) |
||
426 | { |
||
427 | var dx = x-Math.round(this.options.width/2); |
||
428 | var dy = y-Math.round(this.options.height/2); |
||
429 | |||
430 | var new_x = this.img_object.x() - dx; |
||
431 | var new_y = this.img_object.y() - dy; |
||
432 | |||
433 | this.setCoords(new_x, new_y); |
||
434 | }, |
||
435 | |||
436 | /** |
||
437 | * Get container offset object. |
||
438 | */ |
||
439 | getContainerOffset: function() { |
||
440 | return jQuery.extend({}, this.container.offset()); |
||
441 | }, |
||
442 | |||
443 | /** |
||
444 | * set coordinates of upper left corner of image object |
||
445 | **/ |
||
446 | setCoords: function(x,y) |
||
447 | { |
||
448 | //do nothing while image is being loaded |
||
449 | if(!this.img_object.loaded()) { return; } |
||
450 | |||
451 | var coords = this._correctCoords(x,y); |
||
452 | this.img_object.x(coords.x); |
||
453 | this.img_object.y(coords.y); |
||
454 | }, |
||
455 | |||
456 | _correctCoords: function( x, y ) |
||
457 | { |
||
458 | x = parseInt(x, 10); |
||
459 | y = parseInt(y, 10); |
||
460 | |||
461 | //check new coordinates to be correct (to be in rect) |
||
462 | if(y > 0){ |
||
463 | y = 0; |
||
464 | } |
||
465 | if(x > 0){ |
||
466 | x = 0; |
||
467 | } |
||
468 | if(y + this.img_object.display_height() < this.options.height){ |
||
469 | y = this.options.height - this.img_object.display_height(); |
||
470 | } |
||
471 | if(x + this.img_object.display_width() < this.options.width){ |
||
472 | x = this.options.width - this.img_object.display_width(); |
||
473 | } |
||
474 | if(this.img_object.display_width() <= this.options.width){ |
||
475 | x = -(this.img_object.display_width() - this.options.width)/2; |
||
476 | } |
||
477 | if(this.img_object.display_height() <= this.options.height){ |
||
478 | y = -(this.img_object.display_height() - this.options.height)/2; |
||
479 | } |
||
480 | |||
481 | return { x: x, y:y }; |
||
482 | }, |
||
483 | |||
484 | |||
485 | /** |
||
486 | * convert coordinates on the container to the coordinates on the image (in original size) |
||
487 | * |
||
488 | * @return object with fields x,y according to coordinates or false |
||
489 | * if initial coords are not inside image |
||
490 | **/ |
||
491 | containerToImage : function (x,y) |
||
492 | { |
||
493 | var coords = { x : x - this.img_object.x(), |
||
494 | y : y - this.img_object.y() |
||
495 | }; |
||
496 | |||
497 | coords = this.img_object.toOriginalCoords(coords); |
||
498 | |||
499 | return { x : util.descaleValue(coords.x, this.current_zoom), |
||
500 | y : util.descaleValue(coords.y, this.current_zoom) |
||
501 | }; |
||
502 | }, |
||
503 | |||
504 | /** |
||
505 | * convert coordinates on the image (in original size, and zero angle) to the coordinates on the container |
||
506 | * |
||
507 | * @return object with fields x,y according to coordinates |
||
508 | **/ |
||
509 | imageToContainer : function (x,y) |
||
510 | { |
||
511 | var coords = { |
||
512 | x : util.scaleValue(x, this.current_zoom), |
||
513 | y : util.scaleValue(y, this.current_zoom) |
||
514 | }; |
||
515 | |||
516 | return this.img_object.toRealCoords(coords); |
||
517 | }, |
||
518 | |||
519 | /** |
||
520 | * get mouse coordinates on the image |
||
521 | * @param e - object containing pageX and pageY fields, e.g. mouse event object |
||
522 | * |
||
523 | * @return object with fields x,y according to coordinates or false |
||
524 | * if initial coords are not inside image |
||
525 | **/ |
||
526 | _getMouseCoords : function(e) |
||
527 | { |
||
528 | var containerOffset = this.container.offset(); |
||
529 | coords = this.containerToImage(e.pageX - containerOffset.left, e.pageY - containerOffset.top); |
||
0 ignored issues
–
show
|
|||
530 | |||
531 | return coords; |
||
532 | }, |
||
533 | |||
534 | /** |
||
535 | * set image scale to the new_zoom |
||
536 | * |
||
537 | * @param {number} new_zoom image scale in % |
||
538 | * @param {boolean} skip_animation |
||
539 | * @param {x: number, y: number} Coordinates of point the should not be moved on zoom. The default is the center of image. |
||
540 | **/ |
||
541 | set_zoom: function(new_zoom, skip_animation, zoom_center) |
||
542 | { |
||
543 | if (this._trigger('onZoom', 0, new_zoom) == false) { |
||
0 ignored issues
–
show
|
|||
544 | return; |
||
545 | } |
||
546 | |||
547 | //do nothing while image is being loaded |
||
548 | if(!this.img_object.loaded()) { return; } |
||
549 | |||
550 | zoom_center = zoom_center || { |
||
551 | x: Math.round(this.options.width/2), |
||
552 | y: Math.round(this.options.height/2) |
||
553 | } |
||
554 | |||
555 | if(new_zoom < this.options.zoom_min) |
||
556 | { |
||
557 | new_zoom = this.options.zoom_min; |
||
558 | } |
||
559 | else if(new_zoom > this.options.zoom_max) |
||
560 | { |
||
561 | new_zoom = this.options.zoom_max; |
||
562 | } |
||
563 | |||
564 | /* we fake these values to make fit zoom properly work */ |
||
565 | if(this.current_zoom == "fit") |
||
566 | { |
||
567 | var old_x = zoom_center.x + Math.round(this.img_object.orig_width()/2); |
||
568 | var old_y = zoom_center.y + Math.round(this.img_object.orig_height()/2); |
||
569 | this.current_zoom = 100; |
||
570 | } |
||
571 | else { |
||
572 | var old_x = -this.img_object.x() + zoom_center.x; |
||
0 ignored issues
–
show
Comprehensibility
Naming
Best Practice
introduced
by
The variable
old_x already seems to be declared on line 567 . Consider using another variable name or omitting the var keyword.
This check looks for variables that are declared in multiple lines. There may be several reasons for this. In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs. If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared. ![]() |
|||
573 | var old_y = -this.img_object.y() + zoom_center.y |
||
0 ignored issues
–
show
Comprehensibility
Naming
Best Practice
introduced
by
The variable
old_y already seems to be declared on line 568 . Consider using another variable name or omitting the var keyword.
This check looks for variables that are declared in multiple lines. There may be several reasons for this. In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs. If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared. ![]() |
|||
574 | } |
||
575 | |||
576 | var new_width = util.scaleValue(this.img_object.orig_width(), new_zoom); |
||
577 | var new_height = util.scaleValue(this.img_object.orig_height(), new_zoom); |
||
578 | var new_x = util.scaleValue( util.descaleValue(old_x, this.current_zoom), new_zoom); |
||
579 | var new_y = util.scaleValue( util.descaleValue(old_y, this.current_zoom), new_zoom); |
||
580 | |||
581 | new_x = zoom_center.x - new_x; |
||
582 | new_y = zoom_center.y - new_y; |
||
583 | |||
584 | new_width = Math.floor(new_width); |
||
585 | new_height = Math.floor(new_height); |
||
586 | new_x = Math.floor(new_x); |
||
587 | new_y = Math.floor(new_y); |
||
588 | |||
589 | this.img_object.display_width(new_width); |
||
590 | this.img_object.display_height(new_height); |
||
591 | |||
592 | var coords = this._correctCoords( new_x, new_y ), |
||
593 | self = this; |
||
594 | |||
595 | this.img_object.setImageProps(new_width, new_height, coords.x, coords.y, |
||
596 | skip_animation, function() { |
||
597 | self._trigger('onAfterZoom', 0, new_zoom ); |
||
598 | }); |
||
599 | this.current_zoom = new_zoom; |
||
600 | |||
601 | this.update_status(); |
||
602 | }, |
||
603 | |||
604 | /** |
||
605 | * changes zoom scale by delta |
||
606 | * zoom is calculated by formula: zoom_base * zoom_delta^rate |
||
607 | * @param Integer delta number to add to the current multiplier rate number |
||
608 | * @param {x: number, y: number=} Coordinates of point the should not be moved on zoom. |
||
609 | **/ |
||
610 | zoom_by: function(delta, zoom_center) |
||
611 | { |
||
612 | var closest_rate = this.find_closest_zoom_rate(this.current_zoom); |
||
613 | |||
614 | var next_rate = closest_rate + delta; |
||
615 | var next_zoom = this.options.zoom_base * Math.pow(this.options.zoom_delta, next_rate) |
||
616 | if(delta > 0 && next_zoom < this.current_zoom) |
||
617 | { |
||
618 | next_zoom *= this.options.zoom_delta; |
||
619 | } |
||
620 | |||
621 | if(delta < 0 && next_zoom > this.current_zoom) |
||
622 | { |
||
623 | next_zoom /= this.options.zoom_delta; |
||
624 | } |
||
625 | |||
626 | this.set_zoom(next_zoom, undefined, zoom_center); |
||
627 | }, |
||
628 | |||
629 | /** |
||
630 | * Rotate image |
||
631 | * @param {num} deg Degrees amount to rotate. Positive values rotate image clockwise. |
||
632 | * Currently 0, 90, 180, 270 and -90, -180, -270 values are supported |
||
633 | * |
||
634 | * @param {boolean} abs If the flag is true if, the deg parameter will be considered as |
||
635 | * a absolute value and relative otherwise. |
||
636 | * @return {num|null} Method will return current image angle if called without any arguments. |
||
637 | **/ |
||
638 | angle: function(deg, abs) { |
||
639 | if (arguments.length === 0) { return this.img_object.angle(); } |
||
640 | |||
641 | if (deg < -270 || deg > 270 || deg % 90 !== 0) { return; } |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
642 | if (!abs) { deg += this.img_object.angle(); } |
||
643 | if (deg < 0) { deg += 360; } |
||
644 | if (deg >= 360) { deg -= 360; } |
||
645 | |||
646 | if (deg === this.img_object.angle()) { return; } |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
647 | |||
648 | this.img_object.angle(deg); |
||
649 | //the rotate behavior is different in all editors. For now we just center the |
||
650 | //image. However, it will be better to try to keep the position. |
||
651 | this.center(); |
||
652 | this._trigger('angle', 0, { angle: this.img_object.angle() }); |
||
0 ignored issues
–
show
|
|||
653 | }, |
||
654 | |||
655 | /** |
||
656 | * finds closest multiplier rate for value |
||
657 | * basing on zoom_base and zoom_delta values from settings |
||
658 | * @param Number value zoom value to examine |
||
659 | **/ |
||
660 | find_closest_zoom_rate: function(value) |
||
661 | { |
||
662 | if(value == this.options.zoom_base) |
||
663 | { |
||
664 | return 0; |
||
665 | } |
||
666 | |||
667 | function div(val1,val2) { return val1 / val2 }; |
||
668 | function mul(val1,val2) { return val1 * val2 }; |
||
669 | |||
670 | var func = (value > this.options.zoom_base)?mul:div; |
||
671 | var sgn = (value > this.options.zoom_base)?1:-1; |
||
672 | |||
673 | var mltplr = this.options.zoom_delta; |
||
674 | var rate = 1; |
||
675 | |||
676 | while(Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate)) - value) > |
||
677 | Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate+1)) - value)) |
||
678 | { |
||
679 | rate++; |
||
680 | } |
||
681 | |||
682 | return sgn * rate; |
||
683 | }, |
||
684 | |||
685 | /* update scale info in the container */ |
||
686 | update_status: function() |
||
687 | { |
||
688 | if(!this.options.ui_disabled) |
||
689 | { |
||
690 | var percent = Math.round(100*this.img_object.display_height()/this.img_object.orig_height()); |
||
691 | if(percent) |
||
692 | { |
||
693 | this.zoom_object.html(percent + "%"); |
||
694 | } |
||
695 | } |
||
696 | }, |
||
697 | |||
698 | /** |
||
699 | * Get some information about the image. |
||
700 | * Currently orig_(width|height), display_(width|height), angle, zoom and src params are supported. |
||
701 | * |
||
702 | * @param {string} parameter to check |
||
703 | * @param {boolean} withoutRotation if param is orig_width or orig_height and this flag is set to true, |
||
704 | * method will return original image width without considering rotation. |
||
705 | * |
||
706 | */ |
||
707 | info: function(param, withoutRotation) { |
||
708 | if (!param) { return; } |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
709 | |||
710 | switch (param) { |
||
711 | case 'orig_width': |
||
712 | case 'orig_height': |
||
713 | if (withoutRotation) { |
||
714 | return (this.img_object.angle() % 180 === 0 ? this.img_object[param]() : |
||
715 | param === 'orig_width' ? this.img_object.orig_height() : |
||
716 | this.img_object.orig_width()); |
||
717 | } else { |
||
0 ignored issues
–
show
|
|||
718 | return this.img_object[param](); |
||
719 | } |
||
720 | case 'display_width': |
||
721 | case 'display_height': |
||
722 | case 'angle': |
||
723 | return this.img_object[param](); |
||
724 | case 'zoom': |
||
725 | return this.current_zoom; |
||
726 | case 'src': |
||
727 | return this.img_object.object().attr('src'); |
||
728 | case 'coords': |
||
729 | return { |
||
730 | x: this.img_object.x(), |
||
731 | y: this.img_object.y() |
||
732 | }; |
||
733 | } |
||
0 ignored issues
–
show
|
|||
734 | }, |
||
735 | |||
736 | /** |
||
737 | * callback for handling mousdown event to start dragging image |
||
738 | **/ |
||
739 | _mouseStart: function( e ) |
||
740 | { |
||
741 | $.ui.mouse.prototype._mouseStart.call(this, e); |
||
742 | if (this._trigger('onStartDrag', 0, this._getMouseCoords(e)) === false) { |
||
743 | return false; |
||
744 | } |
||
745 | |||
746 | /* start drag event*/ |
||
747 | this.container.addClass("iviewer_drag_cursor"); |
||
748 | |||
749 | //#10: fix movement quirks for ipad |
||
750 | this._dragInitialized = !(e.originalEvent.changedTouches && e.originalEvent.changedTouches.length==1); |
||
0 ignored issues
–
show
|
|||
751 | |||
752 | this.dx = e.pageX - this.img_object.x(); |
||
753 | this.dy = e.pageY - this.img_object.y(); |
||
754 | return true; |
||
755 | }, |
||
756 | |||
757 | _mouseCapture: function( e ) { |
||
0 ignored issues
–
show
|
|||
758 | return true; |
||
759 | }, |
||
760 | |||
761 | /** |
||
762 | * Handle mouse move if needed. User can avoid using this callback, because |
||
763 | * he can get the same information through public methods. |
||
764 | * @param {jQuery.Event} e |
||
765 | */ |
||
766 | _handleMouseMove: function(e) { |
||
767 | this._trigger('onMouseMove', e, this._getMouseCoords(e)); |
||
768 | }, |
||
769 | |||
770 | /** |
||
771 | * callback for handling mousemove event to drag image |
||
772 | **/ |
||
773 | _mouseDrag: function(e) |
||
774 | { |
||
775 | $.ui.mouse.prototype._mouseDrag.call(this, e); |
||
776 | |||
777 | //#10: imitate mouseStart, because we can get here without it on iPad for some reason |
||
778 | if (!this._dragInitialized) { |
||
779 | this.dx = e.pageX - this.img_object.x(); |
||
780 | this.dy = e.pageY - this.img_object.y(); |
||
781 | this._dragInitialized = true; |
||
782 | } |
||
783 | |||
784 | var ltop = e.pageY - this.dy; |
||
785 | var lleft = e.pageX - this.dx; |
||
786 | |||
787 | this.setCoords(lleft, ltop); |
||
788 | this._trigger('onDrag', e, this._getMouseCoords(e)); |
||
789 | return false; |
||
790 | }, |
||
791 | |||
792 | /** |
||
793 | * callback for handling stop drag |
||
794 | **/ |
||
795 | _mouseStop: function(e) |
||
796 | { |
||
797 | $.ui.mouse.prototype._mouseStop.call(this, e); |
||
798 | this.container.removeClass("iviewer_drag_cursor"); |
||
799 | this._trigger('onStopDrag', 0, this._getMouseCoords(e)); |
||
800 | }, |
||
801 | |||
802 | _click: function(e) |
||
803 | { |
||
804 | this._trigger('onClick', 0, this._getMouseCoords(e)); |
||
805 | }, |
||
806 | |||
807 | /** |
||
808 | * create zoom buttons info box |
||
809 | **/ |
||
810 | createui: function() |
||
811 | { |
||
812 | var me=this; |
||
813 | |||
814 | $("<div>", { 'class': "iviewer_zoom_in iviewer_common iviewer_button"}) |
||
815 | .bind('mousedown touchstart',function(){me.zoom_by(1); return false;}) |
||
816 | .appendTo(this.container); |
||
817 | |||
818 | $("<div>", { 'class': "iviewer_zoom_out iviewer_common iviewer_button"}) |
||
819 | .bind('mousedown touchstart',function(){me.zoom_by(- 1); return false;}) |
||
820 | .appendTo(this.container); |
||
821 | |||
822 | $("<div>", { 'class': "iviewer_zoom_zero iviewer_common iviewer_button"}) |
||
823 | .bind('mousedown touchstart',function(){me.set_zoom(100); return false;}) |
||
824 | .appendTo(this.container); |
||
825 | |||
826 | $("<div>", { 'class': "iviewer_zoom_fit iviewer_common iviewer_button"}) |
||
827 | .bind('mousedown touchstart',function(){me.fit(this); return false;}) |
||
828 | .appendTo(this.container); |
||
829 | |||
830 | this.zoom_object = $("<div>").addClass("iviewer_zoom_status iviewer_common") |
||
831 | .appendTo(this.container); |
||
832 | |||
833 | $("<div>", { 'class': "iviewer_rotate_left iviewer_common iviewer_button"}) |
||
834 | .bind('mousedown touchstart',function(){me.angle(-90); return false;}) |
||
835 | .appendTo(this.container); |
||
836 | |||
837 | $("<div>", { 'class': "iviewer_rotate_right iviewer_common iviewer_button" }) |
||
838 | .bind('mousedown touchstart',function(){me.angle(90); return false;}) |
||
839 | .appendTo(this.container); |
||
840 | |||
841 | this.update_status(); //initial status update |
||
842 | } |
||
843 | |||
844 | } ); |
||
845 | |||
846 | /** |
||
847 | * @class $.ui.iviewer.ImageObject Class represents image and provides public api without |
||
848 | * extending image prototype. |
||
849 | * @constructor |
||
850 | * @param {boolean} do_anim Do we want to animate image on dimension changes? |
||
851 | */ |
||
852 | $.ui.iviewer.ImageObject = function(do_anim) { |
||
853 | this._img = $("<img>") |
||
854 | //this is needed, because chromium sets them auto otherwise |
||
855 | .css({ position: "absolute", top :"0px", left: "0px"}); |
||
856 | |||
857 | this._loaded = false; |
||
858 | this._swapDimensions = false; |
||
859 | this._do_anim = do_anim || false; |
||
860 | this.x(0, true); |
||
861 | this.y(0, true); |
||
862 | this.angle(0); |
||
863 | }; |
||
864 | |||
865 | |||
866 | /** @lends $.ui.iviewer.ImageObject.prototype */ |
||
867 | (function() { |
||
868 | /** |
||
869 | * Restore initial object state. |
||
870 | * |
||
871 | * @param {number} w Image width. |
||
872 | * @param {number} h Image height. |
||
873 | */ |
||
874 | this._reset = function(w, h) { |
||
875 | this._angle = 0; |
||
876 | this._swapDimensions = false; |
||
877 | this.x(0); |
||
878 | this.y(0); |
||
879 | |||
880 | this.orig_width(w); |
||
881 | this.orig_height(h); |
||
882 | this.display_width(w); |
||
883 | this.display_height(h); |
||
884 | }; |
||
885 | |||
886 | /** |
||
887 | * Check if image is loaded. |
||
888 | * |
||
889 | * @return {boolean} |
||
890 | */ |
||
891 | this.loaded = function() { return this._loaded; }; |
||
892 | |||
893 | /** |
||
894 | * Load image. |
||
895 | * |
||
896 | * @param {string} src Image url. |
||
897 | * @param {Function=} loaded Function will be called on image load. |
||
898 | */ |
||
899 | this.load = function(src, loaded, error) { |
||
900 | var self = this; |
||
901 | |||
902 | loaded = loaded || jQuery.noop; |
||
903 | this._loaded = false; |
||
904 | |||
905 | //If we assign new image url to the this._img IE9 fires onload event and image width and |
||
906 | //height are set to zero. So, we create another image object and load image through it. |
||
907 | var img = new Image(); |
||
0 ignored issues
–
show
The variable
Image seems to be never declared. If this is a global, consider adding a /** global: Image */ comment.
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed. To learn more about declaring variables in Javascript, see the MDN. ![]() |
|||
908 | img.onload = function() { |
||
909 | self._loaded = true; |
||
910 | self._reset(this.width, this.height); |
||
911 | |||
912 | self._img |
||
913 | .removeAttr("width") |
||
914 | .removeAttr("height") |
||
915 | .removeAttr("style") |
||
916 | //max-width is reset, because plugin breaks in the twitter bootstrap otherwise |
||
917 | .css({ position: "absolute", top :"0px", left: "0px", maxWidth: "none"}) |
||
918 | |||
919 | self._img[0].src = src; |
||
920 | loaded(); |
||
921 | }; |
||
922 | |||
923 | img.onerror = error; |
||
924 | |||
925 | //we need this because sometimes internet explorer 8 fires onload event |
||
926 | //right after assignment (synchronously) |
||
927 | setTimeout(function() { |
||
928 | img.src = src; |
||
929 | }, 0); |
||
930 | |||
931 | this.angle(0); |
||
932 | }; |
||
933 | |||
934 | this._dimension = function(prefix, name) { |
||
935 | var horiz = '_' + prefix + '_' + name, |
||
936 | vert = '_' + prefix + '_' + (name === 'height' ? 'width' : 'height'); |
||
937 | return setter(function(val) { |
||
938 | this[this._swapDimensions ? horiz: vert] = val; |
||
939 | }, |
||
940 | function() { |
||
941 | return this[this._swapDimensions ? horiz: vert]; |
||
942 | }); |
||
943 | }; |
||
944 | |||
945 | /** |
||
946 | * Getters and setter for common image dimensions. |
||
947 | * display_ means real image tag dimensions |
||
948 | * orig_ means physical image dimensions. |
||
949 | * Note, that dimensions are swapped if image is rotated. It necessary, |
||
950 | * because as little as possible code should know about rotation. |
||
951 | */ |
||
952 | this.display_width = this._dimension('display', 'width'), |
||
0 ignored issues
–
show
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.
The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression. This operator is most often used in Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator. This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements. var a,b,c;
a = 1, b = 1, c= 3;
could just as well be written as: var a,b,c;
a = 1;
b = 1;
c = 3;
To learn more about the sequence operator, please refer to the MDN. ![]() |
|||
953 | this.display_height = this._dimension('display', 'height'), |
||
954 | this.display_diff = function() { return Math.floor( this.display_width() - this.display_height() ) }; |
||
955 | this.orig_width = this._dimension('orig', 'width'), |
||
0 ignored issues
–
show
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.
The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression. This operator is most often used in Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator. This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements. var a,b,c;
a = 1, b = 1, c= 3;
could just as well be written as: var a,b,c;
a = 1;
b = 1;
c = 3;
To learn more about the sequence operator, please refer to the MDN. ![]() |
|||
956 | this.orig_height = this._dimension('orig', 'height'), |
||
957 | |||
958 | /** |
||
959 | * Setter for X coordinate. If image is rotated we need to additionaly shift an |
||
960 | * image to map image coordinate to the visual position. |
||
961 | * |
||
962 | * @param {number} val Coordinate value. |
||
963 | * @param {boolean} skipCss If true, we only set the value and do not touch the dom. |
||
964 | */ |
||
965 | this.x = setter(function(val, skipCss) { |
||
966 | this._x = val; |
||
967 | if (!skipCss) { |
||
968 | this._finishAnimation(); |
||
969 | this._img.css("left",this._x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px"); |
||
970 | } |
||
971 | }, |
||
972 | function() { |
||
973 | return this._x; |
||
974 | }); |
||
975 | |||
976 | /** |
||
977 | * Setter for Y coordinate. If image is rotated we need to additionaly shift an |
||
978 | * image to map image coordinate to the visual position. |
||
979 | * |
||
980 | * @param {number} val Coordinate value. |
||
981 | * @param {boolean} skipCss If true, we only set the value and do not touch the dom. |
||
982 | */ |
||
983 | this.y = setter(function(val, skipCss) { |
||
984 | this._y = val; |
||
985 | if (!skipCss) { |
||
986 | this._finishAnimation(); |
||
987 | this._img.css("top",this._y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px"); |
||
988 | } |
||
989 | }, |
||
990 | function() { |
||
991 | return this._y; |
||
992 | }); |
||
993 | |||
994 | /** |
||
995 | * Perform image rotation. |
||
996 | * |
||
997 | * @param {number} deg Absolute image angle. The method will work with values 0, 90, 180, 270 degrees. |
||
998 | */ |
||
999 | this.angle = setter(function(deg) { |
||
1000 | var prevSwap = this._swapDimensions; |
||
1001 | |||
1002 | this._angle = deg; |
||
1003 | this._swapDimensions = deg % 180 !== 0; |
||
1004 | |||
1005 | if (prevSwap !== this._swapDimensions) { |
||
1006 | var verticalMod = this._swapDimensions ? -1 : 1; |
||
1007 | this.x(this.x() - verticalMod * this.display_diff() / 2, true); |
||
1008 | this.y(this.y() + verticalMod * this.display_diff() / 2, true); |
||
1009 | }; |
||
1010 | |||
1011 | var cssVal = 'rotate(' + deg + 'deg)', |
||
1012 | img = this._img; |
||
1013 | |||
1014 | jQuery.each(['', '-webkit-', '-moz-', '-o-', '-ms-'], function(i, prefix) { |
||
1015 | img.css(prefix + 'transform', cssVal); |
||
1016 | }); |
||
1017 | |||
1018 | if (useIeTransforms) { |
||
1019 | jQuery.each(['-ms-', ''], function(i, prefix) { |
||
1020 | img.css(prefix + 'filter', ieTransforms[deg].filter); |
||
1021 | }); |
||
1022 | |||
1023 | img.css({ |
||
1024 | marginLeft: ieTransforms[deg].marginLeft * this.display_diff() / 2, |
||
1025 | marginTop: ieTransforms[deg].marginTop * this.display_diff() / 2 |
||
1026 | }); |
||
1027 | } |
||
1028 | }, |
||
1029 | function() { return this._angle; }); |
||
1030 | |||
1031 | /** |
||
1032 | * Map point in the container coordinates to the point in image coordinates. |
||
1033 | * You will get coordinates of point on image with respect to rotation, |
||
1034 | * but will be set as if image was not rotated. |
||
1035 | * So, if image was rotated 90 degrees, it's (0,0) point will be on the |
||
1036 | * top right corner. |
||
1037 | * |
||
1038 | * @param {{x: number, y: number}} point Point in container coordinates. |
||
1039 | * @return {{x: number, y: number}} |
||
1040 | */ |
||
1041 | this.toOriginalCoords = function(point) { |
||
1042 | switch (this.angle()) { |
||
1043 | case 0: return { x: point.x, y: point.y } |
||
1044 | case 90: return { x: point.y, y: this.display_width() - point.x } |
||
1045 | case 180: return { x: this.display_width() - point.x, y: this.display_height() - point.y } |
||
1046 | case 270: return { x: this.display_height() - point.y, y: point.x } |
||
1047 | } |
||
0 ignored issues
–
show
|
|||
1048 | }; |
||
1049 | |||
1050 | /** |
||
1051 | * Map point in the image coordinates to the point in container coordinates. |
||
1052 | * You will get coordinates of point on container with respect to rotation. |
||
1053 | * Note, if image was rotated 90 degrees, it's (0,0) point will be on the |
||
1054 | * top right corner. |
||
1055 | * |
||
1056 | * @param {{x: number, y: number}} point Point in container coordinates. |
||
1057 | * @return {{x: number, y: number}} |
||
1058 | */ |
||
1059 | this.toRealCoords = function(point) { |
||
1060 | switch (this.angle()) { |
||
1061 | case 0: return { x: this.x() + point.x, y: this.y() + point.y } |
||
1062 | case 90: return { x: this.x() + this.display_width() - point.y, y: this.y() + point.x} |
||
1063 | case 180: return { x: this.x() + this.display_width() - point.x, y: this.y() + this.display_height() - point.y} |
||
1064 | case 270: return { x: this.x() + point.y, y: this.y() + this.display_height() - point.x} |
||
1065 | } |
||
0 ignored issues
–
show
|
|||
1066 | }; |
||
1067 | |||
1068 | /** |
||
1069 | * @return {jQuery} Return image node. this is needed to add event handlers. |
||
1070 | */ |
||
1071 | this.object = setter(jQuery.noop, |
||
1072 | function() { return this._img; }); |
||
1073 | |||
1074 | /** |
||
1075 | * Change image properties. |
||
1076 | * |
||
1077 | * @param {number} disp_w Display width; |
||
1078 | * @param {number} disp_h Display height; |
||
1079 | * @param {number} x |
||
1080 | * @param {number} y |
||
1081 | * @param {boolean} skip_animation If true, the animation will be skiped despite the |
||
1082 | * value set in constructor. |
||
1083 | * @param {Function=} complete Call back will be fired when zoom will be complete. |
||
1084 | */ |
||
1085 | this.setImageProps = function(disp_w, disp_h, x, y, skip_animation, complete) { |
||
1086 | complete = complete || jQuery.noop; |
||
1087 | |||
1088 | this.display_width(disp_w); |
||
1089 | this.display_height(disp_h); |
||
1090 | this.x(x, true); |
||
1091 | this.y(y, true); |
||
1092 | |||
1093 | var w = this._swapDimensions ? disp_h : disp_w; |
||
1094 | var h = this._swapDimensions ? disp_w : disp_h; |
||
1095 | |||
1096 | var params = { |
||
1097 | width: w, |
||
1098 | height: h, |
||
1099 | top: y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px", |
||
1100 | left: x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px" |
||
1101 | }; |
||
1102 | |||
1103 | if (useIeTransforms) { |
||
1104 | jQuery.extend(params, { |
||
1105 | marginLeft: ieTransforms[this.angle()].marginLeft * this.display_diff() / 2, |
||
1106 | marginTop: ieTransforms[this.angle()].marginTop * this.display_diff() / 2 |
||
1107 | }); |
||
1108 | } |
||
1109 | |||
1110 | var swapDims = this._swapDimensions, |
||
1111 | img = this._img; |
||
1112 | |||
1113 | //here we come: another IE oddness. If image is rotated 90 degrees with a filter, than |
||
1114 | //width and height getters return real width and height of rotated image. The bad news |
||
1115 | //is that to set height you need to set a width and vice versa. Fuck IE. |
||
1116 | //So, in this case we have to animate width and height manually. |
||
1117 | if(useIeTransforms && swapDims) { |
||
1118 | var ieh = this._img.width(), |
||
1119 | iew = this._img.height(), |
||
1120 | iedh = params.height - ieh; |
||
1121 | iedw = params.width - iew; |
||
0 ignored issues
–
show
|
|||
1122 | |||
1123 | delete params.width; |
||
1124 | delete params.height; |
||
1125 | } |
||
1126 | |||
1127 | if (this._do_anim && !skip_animation) { |
||
1128 | this._img.stop(true) |
||
1129 | .animate(params, { |
||
1130 | duration: 200, |
||
1131 | complete: complete, |
||
1132 | step: function(now, fx) { |
||
1133 | if(useIeTransforms && swapDims && (fx.prop === 'top')) { |
||
1134 | var percent = (now - fx.start) / (fx.end - fx.start); |
||
1135 | |||
1136 | img.height(ieh + iedh * percent); |
||
0 ignored issues
–
show
|
|||
1137 | img.width(iew + iedw * percent); |
||
0 ignored issues
–
show
|
|||
1138 | img.css('top', now); |
||
1139 | } |
||
1140 | } |
||
1141 | }); |
||
1142 | } else { |
||
1143 | this._img.css(params); |
||
1144 | setTimeout(complete, 0); //both if branches should behave equally. |
||
1145 | } |
||
1146 | }; |
||
1147 | |||
1148 | //if we set image coordinates we need to be sure that no animation is active atm |
||
1149 | this._finishAnimation = function() { |
||
1150 | this._img.stop(true, true); |
||
1151 | } |
||
1152 | |||
1153 | }).apply($.ui.iviewer.ImageObject.prototype); |
||
1154 | |||
1155 | |||
1156 | |||
1157 | var util = { |
||
1158 | scaleValue: function(value, toZoom) |
||
1159 | { |
||
1160 | return value * toZoom / 100; |
||
1161 | }, |
||
1162 | |||
1163 | descaleValue: function(value, fromZoom) |
||
1164 | { |
||
1165 | return value * 100 / fromZoom; |
||
1166 | } |
||
1167 | }; |
||
1168 | |||
1169 | } )( jQuery, undefined ); |
||
1170 |