1/* poptrox 2.2 | n33.co | MIT/GPLv2 */ 2 3(function(jQuery) { 4 5 jQuery.fn.poptrox_disableSelection = function() { return jQuery(this).css('user-select', 'none').css('-khtml-user-select', 'none').css('-moz-user-select', 'none').css('-o-user-select', 'none').css('-webkit-user-select', 'none'); } 6 7 jQuery.fn.poptrox = function(options) { 8 9 // Settings 10 11 var settings = jQuery.extend({ 12 preload: false, // If true, preload fullsize images in the background 13 baseZIndex: 1000, // Base Z-Index 14 fadeSpeed: 300, // Global fade speed 15 overlayColor: '#000000', // Overlay color 16 overlayOpacity: 0.6, // Overlay opacity 17 windowMargin: 50, // Window margin size (in pixels; only comes into play when an image is larger than the viewport) 18 windowHeightPad: 0, // Window height pad 19 selector: 'a', // Anchor tag selector 20 popupSpeed: 300, // Popup (resize) speed 21 popupWidth: 200, // Popup width 22 popupHeight: 100, // Popup height 23 popupIsFixed: false, // If true, popup won't resize to fit images 24 useBodyOverflow: true, // If true, the BODY tag is set to overflow: hidden when the popup is visible 25 usePopupEasyClose: true, // If true, popup can be closed by clicking on it anywhere 26 usePopupLoader: true, // If true, show the popup loader 27 usePopupCloser: true, // If true, show the popup closer button/link 28 usePopupCaption: false, // If true, show the popup image caption 29 usePopupNav: false, // If true, show (and use) popup navigation 30 usePopupDefaultStyling: true, // If true, default popup styling will be applied (background color, text color, etc) 31 popupBackgroundColor: '#FFFFFF', // (Default Style) Popup background color (when usePopupStyling = true) 32 popupTextColor: '#000000', // (Default Style) Popup text color (when usePopupStyling = true) 33 popupLoaderTextSize: '2em', // (Default Style) Popup loader text size 34 popupCloserBackgroundColor: '#000000', // (Default Style) Popup closer background color (when usePopupStyling = true) 35 popupCloserTextColor: '#FFFFFF', // (Default Style) Popup closer text color (when usePopupStyling = true) 36 popupCloserTextSize: '20px', // (Default Style) Popup closer text size 37 popupPadding: 10, // (Default Style) Popup padding (when usePopupStyling = true) 38 popupCaptionHeight: 60, // (Default Style) Popup height of caption area 39 popupCaptionTextSize: null, // (Default Style) Popup caption text size 40 popupBlankCaptionText: '(untitled)', // Applied to images that don't have captions (when captions are enabled) 41 popupCloserText: '×', // Popup closer text 42 popupLoaderText: '••••', // Popup loader text 43 popupClass: 'poptrox-popup', // Popup class 44 popupSelector: null, // (Advanced) Popup selector (use this if you want to replace the built-in popup) 45 popupLoaderSelector: '.loader', // (Advanced) Popup Loader selector 46 popupCloserSelector: '.closer', // (Advanced) Popup Closer selector 47 popupCaptionSelector: '.caption', // (Advanced) Popup Caption selector 48 popupNavPreviousSelector: '.nav-previous', // (Advanced) Popup Nav Previous selector 49 popupNavNextSelector: '.nav-next', // (Advanced) Popup Nav Next selector 50 onPopupClose: null, // On Popup Close Callback 51 onPopupOpen: null // On Popup Open Callback 52 }, options); 53 54 // Variables 55 56 var __msie = navigator.userAgent.match(/MSIE ([0-9]+)\./), __msie6 = __msie && (RegExp.$1 == 6), __msie67 = __msie && (RegExp.$1 < 8); 57 var __pos = (__msie6 ? 'absolute' : 'fixed'); 58 var _isTouch = !!('ontouchstart' in window), _eventType = 'click';
59 var isLocked = false, cache = new Array(); 60 61 var _top = jQuery(this); 62 var _body = jQuery('body'); 63 var _overlay = jQuery('<div></div>'); 64 var _window = jQuery(window); 65 var windowWidth, windowHeight, queue = [], navPos = 0; 66 67 function updateWH() 68 { 69 windowWidth = jQuery(window).width(); 70 windowHeight = jQuery(window).height() + settings.windowHeightPad; 71 } 72 73 // Disable unused features 74 if (!settings.usePopupLoader) 75 settings.popupLoaderSelector = null; 76 77 if (!settings.usePopupCloser) 78 settings.popupCloserSelector = null; 79 80 if (!settings.usePopupCaption) 81 settings.popupCaptionSelector = null; 82 83 if (!settings.usePopupNav) 84 { 85 settings.popupNavPreviousSelector = null; 86 settings.popupNavNextSelector = null; 87 } 88 89 // Get popup 90 if (settings.popupSelector) 91 var _popup = jQuery(settings.popupSelector); 92 else 93 var _popup = jQuery('<div class="' + settings.popupClass + '">' + (settings.popupLoaderSelector ? '<div class="loader">' + settings.popupLoaderText + '</div>' : '') + '<div class="pic"></div>' + (settings.popupCaptionSelector ? '<div class="caption"></div>' : '') + (settings.popupCloserSelector ? '<span class="closer">' + settings.popupCloserText + '</span>' : '') + (settings.popupNavPreviousSelector ? '<div class="nav-previous"></div>' : '') + (settings.popupNavNextSelector ? '<div class="nav-next"></div>' : '') + '</div>'); 94 95 // Get popup components 96 var _pic = _popup.find('.pic'); 97 var _x = jQuery(); 98 var _loader = _popup.find(settings.popupLoaderSelector); 99 var _caption = _popup.find(settings.popupCaptionSelector); 100 var _closer = _popup.find(settings.popupCloserSelector); 101 var _nav_next = _popup.find(settings.popupNavNextSelector); 102 var _nav_previous = _popup.find(settings.popupNavPreviousSelector); 103 var _nav = _nav_next.add(_nav_previous); 104 105 // Apply default styling? 106 if (settings.usePopupDefaultStyling) 107 { 108 _popup.css('background', settings.popupBackgroundColor); 109 _popup.css('color', settings.popupTextColor); 110 _popup.css('padding', settings.popupPadding + 'px'); 111 112 if (_caption.length > 0) 113 { 114 _popup.css('padding-bottom', settings.popupCaptionHeight + 'px'); 115 _caption 116 .css('position', 'absolute') 117 .css('left', '0') 118 .css('bottom', '0') 119 .css('width', '100%') 120 .css('text-align', 'center') 121 .css('height', settings.popupCaptionHeight + 'px') 122 .css('line-height', settings.popupCaptionHeight + 'px'); 123 124 if (settings.popupCaptionTextSize) 125 _caption.css('font-size', popupCaptionTextSize); 126 } 127 128 if (_closer.length > 0) 129 _closer 130 .html(settings.popupCloserText) 131 .css('font-size', settings.popupCloserTextSize) 132 .css('background', settings.popupCloserBackgroundColor) 133 .css('color', settings.popupCloserTextColor) 134 .css('display', 'block') 135 .css('width', '40px') 136 .css('height', '40px') 137 .css('line-height', '40px') 138 .css('text-align', 'center') 139 .css('position', 'absolute') 140 .css('text-decoration', 'none') 141 .css('outline', '0') 142 .css('top', '0') 143 .css('right', '-40px'); 144 145 if (_loader.length > 0) 146 { 147 _loader 148 .html('') 149 .css('position', 'relative') 150 .css('font-size', settings.popupLoaderTextSize) 151 .bind('startSpinning', function(e) { 152 var x = jQuery('<div>' + settings.popupLoaderText + '</div>'); 153 x 154 .css('height', Math.floor(settings.popupHeight / 2) + 'px') 155 .css('overflow', 'hidden') 156 .css('line-height', Math.floor(settings.popupHeight / 2) + 'px') 157 .css('text-align', 'center') 158 .css('margin-top', Math.floor((_popup.height() - x.height() + (_caption.length > 0 ? _caption.height() : 0)) / 2)) 159 .css('color', (settings.popupTextColor ? settings.popupTextColor : '')) 160 .bind('xfin', function() { x.fadeTo(300, 0.5, function() { x.trigger('xfout'); }); }) 161 .bind('xfout', function() { x.fadeTo(300, 0.05, function() { x.trigger('xfin'); }); }) 162 .trigger('xfin'); 163 _loader.append(x); 164 }) 165 .bind('stopSpinning', function(e) { 166 var x = _loader.find('div'); 167 x.remove(); 168 }); 169 } 170 171 if (_nav.length == 2) 172 { 173 _nav 174 .css('font-size', '75px') 175 .css('text-align', 'center') 176 .css('color', '#fff') 177 .css('text-shadow', 'none') 178 .css('height', '100%') 179 .css('position', 'absolute') 180 .css('top', '0') 181 .css('opacity', '0.35') 182 .css('cursor', 'pointer') 183 .css('box-shadow', 'inset 0px 0px 10px 0px rgba(0,0,0,0)') 184 .poptrox_disableSelection(); 185 186 var wn, wp; 187 188 if (settings.usePopupEasyClose) 189 { 190 wn = '100px'; 191 wp = '100px'; 192 } 193 else 194 { 195 wn = '75%'; 196 wp = '25%'; 197 } 198 199 _nav_next 200 .css('right', '0') 201 .css('width', wn) 202 .html('<div style="position: absolute; height: 100px; width: 125px; top: 50%; right: 0; margin-top: -50px;">></div>'); 203 204 _nav_previous 205 .css('left', '0') 206 .css('width', wp) 207 .html('<div style="position: absolute; height: 100px; width: 125px; top: 50%; left: 0; margin-top: -50px;"><</div>'); 208 } 209 } 210 211 // Main 212 _window 213 .bind('orientationchange', function() { 214 _window.trigger('resize'); 215 }) 216 .resize(function() { 217 updateWH(); 218 _popup.trigger('poptrox_close'); 219 }); 220 221 _caption 222 .bind('update', function(e, s) { 223 if (!s || s.length == 0) 224 s = settings.popupBlankCaptionText; 225 _caption.html(s); 226 }); 227 228 _closer 229 .css('cursor', 'pointer') 230 .bind(_eventType, function(e) { 231 e.preventDefault(); 232 e.stopPropagation(); 233 _popup.trigger('poptrox_close'); 234 return true; 235 }); 236 237 _nav_next 238 .click(function() { 239 _popup.trigger('poptrox_next'); 240 }); 241 242 _nav_previous 243 .click(function() { 244 _popup.trigger('poptrox_previous'); 245 }); 246 247 _overlay 248 .prependTo(__msie67 ? 'body' : 'html') 249 .hide(); 250 251 if (__msie6) 252 _overlay.css('position', 'absolute'); 253 else 254 _overlay 255 .css('position', __pos) 256 .css('left', 0) 257 .css('top', 0) 258 .css('z-index', settings.baseZIndex) 259 .css('width', '200%') 260 .css('height', '200%') 261 .css('background-color', settings.overlayColor); 262 263 _overlay 264 .css('cursor', 'pointer') 265 .bind(_eventType, function(e) { 266 e.preventDefault(); 267 e.stopPropagation(); 268 _popup.trigger('poptrox_close'); 269 }); 270 271 if (settings.usePopupEasyClose) 272 { 273 _pic 274 .css('cursor', 'pointer') 275 .bind(_eventType, function(e) { 276 e.preventDefault(); 277 e.stopPropagation(); 278 _popup.trigger('poptrox_close'); 279 }); 280 } 281 282 _popup 283 .bind('poptrox_next', function() { 284 var x = navPos + 1; 285 if (x >= queue.length) 286 x = 0; 287 _popup.trigger('poptrox_switch', [x]); 288 }) 289 .bind('poptrox_previous', function() { 290 var x = navPos - 1; 291 if (x < 0) 292 x = queue.length - 1; 293 _popup.trigger('poptrox_switch', [x]); 294 }) 295 .bind('poptrox_reset', function() { 296 updateWH(); 297 298 _popup 299 .css('position', __pos) 300 .css('z-index', settings.baseZIndex + 1) 301 .css('width', settings.popupWidth + 'px') 302 .css('height', settings.popupHeight + 'px') 303 .css('left', (windowWidth / 2) + 'px') 304 .css('top', (windowHeight / 2) + 'px') 305 .css('top', (windowHeight / 2) + 'px') 306 .css('margin-left', (-1 * (_popup.outerWidth() / 2)) + 'px') 307 .css('margin-top', (-1 * (_popup.outerHeight() / 2)) + 'px') 308 _loader.hide().trigger('stopSpinning'); 309 _caption.hide(); 310 _closer.hide(); 311 _nav.hide(); 312 _pic.hide(); 313 _x.detach(); 314 }) 315 .bind('poptrox_open', function(e, index) { 316 if (isLocked) 317 return true;
318 isLocked = true; 319 if (settings.useBodyOverflow) 320 _body.css('overflow', 'hidden'); 321 if (settings.onPopupOpen) 322 (settings.onPopupOpen)(); 323 _overlay 324 .fadeTo(settings.fadeSpeed, settings.overlayOpacity, function() { 325 _popup.trigger('poptrox_switch', [index, true]); 326 }); 327 }) 328 .bind('poptrox_switch', function(e, index, ignoreLock) { 329 var x, img; 330 331 if (!ignoreLock && isLocked) 332 return true; 333 334 isLocked = true; 335 336 // Cleanup from previous 337 _caption.hide(); 338 if (_x.attr('src')) 339 _x.attr('src', ''); 340 _x.detach(); 341 342 // Activate new object 343 x = queue[index]; 344 _x = x.object; 345 _x.unbind('load'); 346 347 _pic 348 .css('text-indent', '-9999em') 349 .show() 350 .append(_x); 351 352 if (x.type == 'ajax') 353 { 354 jQuery.get(x.src, function(data) { 355 _x.html(data); 356 _x.trigger('load'); 357 }); 358 } 359 else 360 _x.attr('src', x.src); 361 362 if (x.type != 'image') 363 _x 364 .css('position', 'relative') 365 .css('outline', '0') 366 .css('z-index', settings.baseZIndex + 100) 367 .width(x.width) 368 .height(x.height); 369 370 // Initialize 371 _loader.trigger('startSpinning').fadeIn(300); 372 _popup.show(); 373 374 if (settings.popupIsFixed) 375 { 376 _popup 377 .width(settings.popupWidth) 378 .height(settings.popupHeight) 379 .css('margin-left', (-1 * (_popup.innerWidth() / 2)) + 'px') 380 .css('margin-top', (-1 * (_popup.innerHeight() / 2)) + 'px'); 381 382 _x.load(function() { 383 _x.unbind('load'); 384 _loader.hide().trigger('stopSpinning'); 385 _caption.trigger('update', [x.captionText]).fadeIn(settings.fadeSpeed); 386 _closer.fadeIn(settings.fadeSpeed); 387 _pic.css('text-indent', 0).hide().fadeIn(settings.fadeSpeed, function() { isLocked = false; }); 388 navPos = index; 389 _nav.fadeIn(settings.fadeSpeed); 390 }); 391 } 392 else 393 { 394 _x.load(function() { 395 _x.unbind('load'); 396 397 updateWH(); 398 399 var dw = Math.abs(_popup.width() - _popup.outerWidth()), dh = Math.abs(_popup.height() - _popup.outerHeight()); 400 var nw = _x.width(), nh = _x.height(); 401 var maxw = windowWidth - (settings.windowMargin * 2) - dw, maxh = windowHeight - (settings.windowMargin * 2) - dh; 402 403 _loader.hide().trigger('stopSpinning'); 404 405 if (nw > maxw || nh > maxh) 406 { 407 var multW, multH, m; 408 409 multW = maxw / nw; 410 multH = maxh / nh; 411 m = Math.min(multW, multH); 412 413 nw = Math.floor(m * nw); 414 nh = Math.floor(m * nh); 415 416 _x.width(nw).height(nh); 417 } 418 419 if (_popup.innerWidth() == nw + dw 420 && _popup.innerHeight() == nh + dh) 421 { 422 _caption.trigger('update', [x.captionText]).fadeIn(settings.fadeSpeed); 423 _closer.fadeIn(settings.fadeSpeed); 424 _pic.css('text-indent', 0).hide().fadeIn(settings.fadeSpeed, function() { isLocked = false; }); 425 navPos = index; 426 } 427 else 428 _popup 429 .animate({ 430 width: nw, 431 height: nh, 432 marginLeft: (-1 * (nw / 2)) - (dw / 2), 433 marginTop: (-1 * (nh / 2)) - (dh / 2) 434 }, settings.popupSpeed, 'swing', function() { 435 _caption.trigger('update', [x.captionText]).fadeIn(settings.fadeSpeed); 436 _closer.fadeIn(settings.fadeSpeed); 437 _pic.css('text-indent', 0).hide().fadeIn(settings.fadeSpeed, function() { isLocked = false; }); 438 navPos = index; 439 _nav.fadeIn(settings.fadeSpeed); 440 }); 441 }); 442 } 443 444 if (x.type != 'image') 445 _x.trigger('load'); 446 }) 447 .bind('poptrox_close', function() { 448 if (isLocked) 449 return true; 450 isLocked = true; 451 _popup 452 .hide() 453 .trigger('poptrox_reset'); 454 if (settings.onPopupClose) 455 (settings.onPopupClose)(); 456 _overlay 457 .fadeOut(settings.fadeSpeed, function() { 458 if (settings.useBodyOverflow) 459 _body.css('overflow', 'auto'); 460 isLocked = false; 461 }); 462 }) 463 .prependTo('body') 464 .hide() 465 .trigger('poptrox_reset'); 466 467 _window 468 .keydown(function(e) { 469 if (_popup.is(':visible')) 470 { 471 switch (e.keyCode) 472 { 473 case 37: 474 case 32: 475 if (settings.usePopupNav) 476 { 477 _popup.trigger('poptrox_previous'); 478 return false;
479 } 480 break; 481 482 case 39: 483 if (settings.usePopupNav) 484 { 485 _popup.trigger('poptrox_next'); 486 return false; 487 } 488 break; 489 490 case 27: 491 _popup.trigger('poptrox_close'); 492 return false; 493 494 break; 495 } 496 } 497 }); 498 499 _top.find(settings.selector).each(function(index) { 500 501 var x, tmp, a = jQuery(this), i = a.find('img'), data = a.data('poptrox'); 502 503 x = { 504 src: a.attr('href'), 505 captionText: i.attr('title'), 506 width: a.attr('width'), 507 height: a.attr('height'), 508 type: null, 509 object: null 510 }; 511 512 // If a data attribute exists, use it 513 if (data) 514 { 515 var k, b = data.split(','); 516 517 for (k in b) 518 { 519 tmp = b[k].match(/([0-9]+)x([0-9]+)/); 520 521 // Size 522 if (tmp && tmp.length == 3) 523 { 524 x.width = tmp[1]; 525 x.height = tmp[2]; 526 } 527 // Type 528 else 529 x.type = b[k]; 530 } 531 } 532 533 // No type? Attempt to guess it based on the href's domain 534 if (!x.type) 535 { 536 tmp = x.src.match(/http[s]?:\/\/([a-z0-9\.]+)\/.*/); 537 538 if (!tmp || tmp.length < 3) 539 tmp = [false]; 540 541 switch (tmp[1]) 542 { 543 case 'api.soundcloud.com': 544 x.type = 'soundcloud'; 545 break; 546 547 case 'youtu.be': 548 x.type = 'youtube'; 549 break; 550 551 case 'vimeo.com': 552 x.type = 'vimeo'; 553 break; 554 555 default: 556 x.type = 'image'; 557 break; 558 } 559 } 560 561 // Create object (based on type) 562 tmp = x.src.match(/http[s]?:\/\/[a-z0-9\.]+\/(.*)/); 563 564 switch (x.type) 565 { 566 case 'ignore': 567 break; 568 569 case 'iframe': 570 x.object = jQuery('<iframe src="" frameborder="0"></iframe>'); 571 x.object 572 .bind(_eventType, function(e) { e.stopPropagation(); }) 573 .css('cursor', 'auto'); 574 break; 575 576 case 'ajax': 577 x.object = jQuery('<div class="poptrox-ajax"></div>'); 578 x.object 579 .bind(_eventType, function(e) { e.stopPropagation(); }) 580 .css('cursor', 'auto') 581 .css('overflow', 'auto'); 582 break; 583 584 case 'soundcloud': 585 x.object = jQuery('<iframe scrolling="no" frameborder="no" src=""></iframe>'); 586 x.src = 'https://w.soundcloud.com/player/?url=' + escape(x.src); 587 x.width = '600'; 588 x.height = "166"; 589 break; 590 591 case 'youtube': 592 x.object = jQuery('<iframe src="" frameborder="0" allowfullscreen="1"></iframe>'); 593 x.src = 'http://www.youtube.com/embed/' + tmp[1]; 594 break; 595 596 case 'vimeo': 597 x.object = jQuery('<iframe src="" frameborder="0" allowFullScreen="1"></iframe>'); 598 x.src = 'http://player.vimeo.com/video/' + tmp[1]; 599 break; 600 601 default: 602 x.object = jQuery('<img src="" alt="" />'); 603 if (settings.preload) { var tmp = document.createElement('img'); tmp.src = x.src; cache.push(tmp); } 604 break; 605 } 606 607 queue.push(x); 608 609 i 610 .attr('title', ''); 611 612 if (x.type != 'ignore') 613 { 614 a 615 .attr('href', '') 616 .css('outline', 0) 617 .click(function(e) { 618 e.preventDefault(); 619 e.stopPropagation(); 620 _popup.trigger('poptrox_open', [index]); 621 }); 622 } 623 }); 624 625 return jQuery(this); 626 }; 627})(jQuery);
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.