1// jQuery Mobile Zoom by Denis Korovkin 2 3$(function(){ 4 $.fn.mobilezoom = function(options) { 5 var settings = $.extend({ 6 backbutton: 'ÐеÑнÑÑÑÑÑ', 7 marginbetween: 30 8 }, options ); 9 10 var touches = []; 11 var zoomStartTouches = []; 12 var zoomStarted = false; 13 var zoomStartDistance = false; 14 var zoomStartSize = false; 15 var moveStarted = false; 16 var moveStartPosition = false; 17 18 var next = false; 19 var prev = false; 20 21 var animating = false; 22 23 /* If many elements â do for each */ 24 if(this.length > 1){ 25 this.each(function(){ 26 $(this).mobilezoom(settings); 27 }); 28 return this; 29 } 30 /* If no elements â exit */ 31 if(this.length == 0){ 32 return this; 33 } 34 35 /* If already initialized â exit */ 36 if(this.is('.mobilezoom__element')) return this; 37 38 this.addClass('mobilezoom__element'); 39 initTouchEvents(); 40 41 /* If is gallery â get other elements */ 42 if(this.data('gallery')){ 43 var gallery = $('*[data-gallery="'+ this.data('gallery') +'"]'); 44 } 45 46 var current = this; 47 48 /* Handle click event */ 49 this.on('click', function(e){ 50 showImage(this); 51 e.preventDefault(); 52 return false; 53 }); 54 55 function showImage(element){ 56 element = $(element); 57 var url; 58 if(element.is('img')){ 59 url = element.attr('src'); 60 } else { 61 url = element.attr('href'); 62 } 63 $('body').append('<div class="mobilezoom__holder"><div class="mobilezoom__topbar"><div class="mobilezoom__backbutton">'+settings.backbutton+'</div></div><div class="mobilezoom__image"><img src="'+ url +'" /></div></div>'); 64 $('body').addClass('mobilezoom__opened'); 65 66 window.mobileZoomGallery = gallery; 67 window.mobileZoomCurrent = element; 68 69 defaultImagePosition(); 70 71 $('.mobilezoom__backbutton').on('click', function(e){ 72 $('.mobilezoom__holder').remove(); 73 $('body').removeClass('mobilezoom__opened'); 74 }); 75 $('.mobilezoom__holder').on('click', function(e){ 76 $('.mobilezoom__topbar').fadeToggle(300); 77 }); 78 79 prepareNext(); 80 } 81 82 function showNext(element){ 83 element = $(element); 84 var url; 85 if(element.is('img')){ 86 url = element.attr('src'); 87 } else { 88 url = element.attr('href'); 89 } 90 $('.mobilezoom__holder').append('<div class="mobilezoom__next-image"><img src="'+ url +'" /></div>'); 91 92 function setPosition(){ 93 var width = $('.mobilezoom__next-image').find('img').width(); 94 var height = $('.mobilezoom__next-image').find('img').height(); 95 var naturalWidth = $('.mobilezoom__next-image').find('img').get(0).naturalWidth; 96 var naturalHeight = $('.mobilezoom__next-image').find('img').get(0).naturalHeight; 97 98 if(naturalWidth > 0){ 99 $('.mobilezoom__next-image').data('nwidth', naturalWidth).data('nheight', naturalHeight); 100 $('.mobilezoom__next-image').width('width').height('height').css({ 101 'left': ($('.mobilezoom__holder').width() + 20) + 'px', 102 'top': (($('.mobilezoom__holder').height() - height) / 2) + 'px', 103 'position': 'absolute' 104 }); 105 } else { 106 $('.mobilezoom__next-image').find('img').on('load', setPosition); 107 } 108 } 109 setPosition(); 110 111 } 112 113 function showPrev(element){ 114 element = $(element); 115 var url; 116 if(element.is('img')){ 117 url = element.attr('src'); 118 } else { 119 url = element.attr('href'); 120 } 121 $('.mobilezoom__holder').append('<div class="mobilezoom__prev-image"><img src="'+ url +'" /></div>'); 122 123 function setPosition(){ 124 var width = $('.mobilezoom__prev-image').find('img').width(); 125 var height = $('.mobilezoom__prev-image').find('img').height();
126 var naturalWidth = $('.mobilezoom__prev-image').find('img').get(0).naturalWidth; 127 var naturalHeight = $('.mobilezoom__prev-image').find('img').get(0).naturalHeight; 128 129 if(naturalWidth > 0){ 130 $('.mobilezoom__prev-image').data('nwidth', naturalWidth).data('nheight', naturalHeight); 131 $('.mobilezoom__prev-image').width('width').height('height').css({ 132 'left': (- $('.mobilezoom__holder').width() - settings.marginbetween) + 'px', 133 'top': (($('.mobilezoom__holder').height() - height) / 2) + 'px', 134 'position': 'absolute' 135 }); 136 } else { 137 $('.mobilezoom__prev-image').find('img').on('load', setPosition); 138 } 139 } 140 setPosition(); 141 } 142 143 function prepareNext(){ 144 145 var gallery = window.mobileZoomGallery; 146 var current = window.mobileZoomCurrent; 147 148 if(!gallery) { 149 return; 150 } 151 152 var current_index = gallery.index(current); 153 154 if(current_index < gallery.length - 1){ 155 next = gallery.eq(current_index + 1); 156 showNext(next); 157 } else { 158 next = false; 159 } 160 if(current_index > 0){ 161 prev = gallery.eq(current_index - 1); 162 showPrev(prev); 163 } else { 164 prev = false; 165 } 166 } 167 168 function defaultImagePosition(){ 169 var width = $('.mobilezoom__image').find('img').width(); 170 var height = $('.mobilezoom__image').find('img').height(); 171 var naturalWidth = $('.mobilezoom__image').find('img').get(0).naturalWidth; 172 var naturalHeight = $('.mobilezoom__image').find('img').get(0).naturalHeight; 173 174 if(naturalWidth > 0){ 175 $('.mobilezoom__image').data('nwidth', naturalWidth).data('nheight', naturalHeight); 176 $('.mobilezoom__image').width('width').height('height').css({ 177 'left': 0, 178 'top': (($('.mobilezoom__holder').height() - height) / 2) + 'px' 179 }); 180 } else { 181 $('.mobilezoom__image').find('img').on('load', defaultImagePosition); 182 } 183 } 184 185 function initTouchEvents(){ 186 if($('body').is('.mobilezoom__ready')) return; 187 188 $('body').addClass('mobilezoom__ready'); 189 190 touches[0] = {x: false, y: false}; 191 touches[1] = {x: false, y: false}; 192 touches[99] = {x: false, y: false}; // that's middle point 193 194 $(document).on('touchstart', function(e){ 195 touches[0] = {x: e.originalEvent.touches[0].clientX, y: e.originalEvent.touches[0].clientY}; 196 touches[99] = touches[0]; 197 198 if(e.originalEvent.touches.length > 1){ 199 touches[1] = {x: e.originalEvent.touches[1].clientX, y: e.originalEvent.touches[1].clientY}; 200 touches[99] = { 201 x: (touches[0].x + touches[1].x) / 2, 202 y: (touches[0].y + touches[1].y) / 2 203 } 204 } else { 205 touches[1] = {x: false, y: false}; 206 } 207 208 }); 209 $(document).on('touchend', function(e){ 210 if(e.originalEvent.touches.length == 0){ 211 touches[0] = {x: false, y: false}; 212 touches[1] = {x: false, y: false}; 213 touches[99] = {x: false, y: false}; 214 215 if(moveStarted){ 216 fitBounds(); 217 } 218 219 zoomStarted = false; 220 moveStarted = false; 221 } 222 }); 223 224 $(document).on('touchmove', function(e){ 225 226 if($('body').is('.mobilezoom__opened')){ 227 228 var previous = $.extend({}, touches); 229 var zoomDelta = 0; 230 if(animating) return; 231 if(!moveStarted){ 232 moveStartPosition = { 233 x: $('.mobilezoom__image').position().left, 234 y: $('.mobilezoom__image').position().top 235 } 236 moveStarted = true; 237 } 238 239 touches[0] = {x: e.originalEvent.touches[0].clientX, y: e.originalEvent.touches[0].clientY}; 240 touches[99] = touches[0]; 241 242 if(e.originalEvent.touches.length > 1){ 243 touches[1] = {x: e.originalEvent.touches[1].clientX, y: e.originalEvent.touches[1].clientY}; 244 touches[99] = { 245 x: (touches[0].x + touches[1].x) / 2, 246 y: (touches[0].y + touches[1].y) / 2 247 } 248 249 if(!zoomStarted){ 250 zoomStarted = true; 251 zoomStartTouches = $.extend({}, touches); 252 zoomStartDistance = getZoomDistance(); 253 zoomStartSize = { 254 width: $('.mobilezoom__image').width(), 255 height: $('.mobilezoom__image').height(), 256 aspect: $('.mobilezoom__image').data('nwidth') / $('.mobilezoom__image').data('nheight') 257 } 258 } else { 259 zoomDelta = getZoomDistance() - zoomStartDistance; 260 } 261 262 } else { 263 if(zoomStarted){ 264 moveStartPosition = { 265 x: $('.mobilezoom__image').position().left, 266 y: $('.mobilezoom__image').position().top 267 } 268 previous = $.extend({}, touches); // prevent jumping 269 270 } 271 touches[1] = {x: false, y: false}; 272 zoomStarted = false;
273 } 274 275 var positionDeltaX = touches[99].x - previous[99].x; 276 var positionDeltaY = touches[99].y - previous[99].y; 277 278 if(zoomStarted) { 279 280 var zoomDeltaX = touches[99].x - zoomStartTouches[99].x; 281 var zoomDeltaY = touches[99].y - zoomStartTouches[99].y; 282 283 zoomImage(zoomDelta, zoomDeltaX, zoomDeltaY); 284 } else { 285 moveImage(positionDeltaX, positionDeltaY); 286 } 287 288 289 e.preventDefault(); 290 return false; 291 } 292 }); 293 294 } 295 296 function getZoomDistance(){ 297 if(touches[1].x != false){ 298 return Math.sqrt(Math.pow(touches[0].x - touches[1].x, 2) + Math.pow(touches[0].y - touches[1].y, 2)); 299 } else { 300 return false; 301 } 302 } 303 304 function moveImage(x, y){ 305 var left = $('.mobilezoom__image').position().left; 306 var top = $('.mobilezoom__image').position().top; 307 $('.mobilezoom__image').css({ 308 'left': (left + x) + 'px', 309 }); 310 if($('.mobilezoom__image').height() > $('.mobilezoom__holder').height()){ 311 $('.mobilezoom__image').css({ 312 'top': (top + y) + 'px' 313 }); 314 } 315 $('.mobilezoom__next-image').css({ 316 'left': ((left + x) + $('.mobilezoom__image').width() + settings.marginbetween) + 'px' 317 }); 318 $('.mobilezoom__prev-image').css({ 319 'left': ((left + x) - $('.mobilezoom__prev-image').width() - settings.marginbetween) + 'px' 320 }); 321 if($('.mobilezoom__next-image').length == 1 && $('.mobilezoom__next-image').position().left <= $('.mobilezoom__holder').width() / 1.5){ 322 switchToNext(); 323 } 324 if($('.mobilezoom__prev-image').length == 1 && $('.mobilezoom__prev-image').position().left >= - $('.mobilezoom__holder').width() / 1.5){ 325 switchToPrev(); 326 } 327 328 329 } 330 331 function zoomImage(distance, x, y){ 332 var xdelta = distance; 333 var ydelta = distance / zoomStartSize.aspect; 334 if(zoomStartSize.aspect < 1){ 335 ydelta = distance; 336 xdelta = distance * zoomStartSize.aspect; 337 } 338 339 // Tweaking 340 xdelta*=1.5; 341 ydelta*=1.5; 342 343 $('.mobilezoom__image').css({ 344 'width': (zoomStartSize.width + xdelta) + 'px', 345 'height': (zoomStartSize.height + ydelta) + 'px', 346 'left': (moveStartPosition.x - xdelta/2 + x) + 'px', 347 'top': (moveStartPosition.y - ydelta/2 + y) + 'px' 348 }); 349 } 350 351 function switchToNext(){ 352 353 moveStarted = false; 354 animating = true; 355 var left = $('.mobilezoom__next-image').position().left; 356 357 $('.mobilezoom__next-image').animate({left: 0}, 500); 358 $('.mobilezoom__image').animate({left: '-=' + left}, 500, function(){ 359 $('.mobilezoom__prev-image').remove(); 360 $('.mobilezoom__image').remove(); 361 $('.mobilezoom__next-image').removeClass('mobilezoom__next-image').addClass('mobilezoom__image'); 362 window.mobileZoomCurrent = getNext(); 363 prepareNext(); 364 animating = false; 365 }); 366 } 367 368 function getNext(){ 369 return window.mobileZoomGallery.eq(window.mobileZoomGallery.index(window.mobileZoomCurrent) + 1); 370 } 371 372 function getPrev(){ 373 return window.mobileZoomGallery.eq(window.mobileZoomGallery.index(window.mobileZoomCurrent) - 1); 374 } 375 376 function switchToPrev(){ 377 moveStarted = false; 378 animating = true; 379 var left = $('.mobilezoom__prev-image').position().left; 380 381 $('.mobilezoom__prev-image').animate({left: 0}, 500); 382 $('.mobilezoom__image').animate({left: '+=' + (0-left)}, 500, function(){ 383 $('.mobilezoom__next-image').remove(); 384 $('.mobilezoom__image').remove(); 385 $('.mobilezoom__prev-image').removeClass('mobilezoom__prev-image').addClass('mobilezoom__image'); 386 window.mobileZoomCurrent = getPrev(); 387 prepareNext(); 388 animating = false;
389 }); 390 } 391 392 function fitBounds(){ 393 var width = $('.mobilezoom__image').width(); 394 var height = $('.mobilezoom__image').height(); 395 var nwidth = $('.mobilezoom__image').data('nwidth'); 396 var nheight = $('.mobilezoom__image').data('nheight'); 397 var x = $('.mobilezoom__image').position().left; 398 var y = $('.mobilezoom__image').position().top; 399 var cwidth = $('.mobilezoom__holder').width(); 400 var cheight = $('.mobilezoom__holder').height(); 401 var aspect = nwidth/nheight; 402 var caspect = cwidth/cheight; 403 404 var maxZoom = 1; 405 406 if(width < cwidth && height < cheight){ 407 // To small. Fit to window. 408 409 if(aspect > caspect){ 410 $('.mobilezoom__image').animate({ 411 'width': cwidth + 'px', 412 'height': (cwidth / aspect) + 'px', 413 'left': 0, 414 'top': ((cheight - cwidth / aspect) / 2) + 'px' 415 }, 300); 416 } else { 417 $('.mobilezoom__image').animate({ 418 'height': cheight + 'px', 419 'width': (cheight * aspect) + 'px', 420 'top': 0, 421 'left': ((cwidth - cheight * aspect) / 2) + 'px' 422 }, 300); 423 } 424 } else { 425 // Fit to bounds 426 if(width >= cwidth) { 427 var xnew; 428 if(x > 0) xnew = 0; 429 if(x + width < cwidth) xnew = cwidth - width; 430 } else { 431 var xnew = (cwidth - width) / 2; 432 } 433 if(height >= cheight) { 434 var ynew; 435 if(y > 0) ynew = 0; 436 if(y + height < cheight) ynew = cheight - height; 437 } else { 438 var ynew = (cheight - height) / 2; 439 } 440 if(x != xnew || y != ynew){ 441 $('.mobilezoom__image').animate({'top': ynew + 'px', 'left': xnew + 'px'}, 300); 442 $('.mobilezoom__next-image').animate({'left': (cwidth + settings.marginbetween) + 'px'}, 300); 443 $('.mobilezoom__prev-image').animate({'left': (-cwidth - settings.marginbetween) + 'px'}, 300); 444 } 445 } 446 447 if(width > nwidth * maxZoom || height > nheight * maxZoom){ 448 // Too big. Zooming to maxZoom 449 $('.mobilezoom__image').animate({ 450 'width': nwidth * maxZoom + 'px', 451 'height': nheight * maxZoom + 'px', 452 'left': "+=" + (width - nwidth * maxZoom)/2, 453 'top': "+=" + (height - nheight * maxZoom)/2 454 }, 300); 455 } 456 457 } 458 459 }; 460});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.