1(function($) { 2 "use strict"; 3 4 function nplModal() { 5 6 var core = { 7 debug: false, 8 debug_level: 1, // 1-4 9 state: { 10 slug: null, 11 gallery_id: null, 12 image_id: null, 13 sidebar: null 14 }, 15 selector: nextgen_lightbox_filter_selector($, $(".nextgen_pro_lightbox")), 16 options: {}, 17 defaults: { 18 speed: 'medium', // see jQuery docs for setting 19 20 // the url is restored to this location when the lightbox closes 21 initial_url: window.location.toString().split('#')[0], 22 23 ajax_url: photocrati_ajax.rest_url, 24 router_slug: 'gallery' 25 }, 26 27 init: function(parameters) { 28 core.methods.log('nplModal.init()', { 29 parameters: parameters, 30 defaults: core.defaults, 31 selector: core.selector, 32 debug: core.debug, 33 debug_level: core.debug_level 34 }); 35 36 var overlay = $("<div id='npl_overlay'></div>"); 37 var wrapper = $("<div id='npl_wrapper'></div>"); 38 var spinner = $("<div id='npl_spinner_container' class='npl-loading-spinner hidden'><i id='npl_spinner' class='fa fa-spin fa-spinner'></i></div>"); 39 var btn_close = $("<div id='npl_button_close' class='hidden'><i class='fa fa-times'></i></div>"); 40 var content = $("<div id='npl_content'></div>"); 41 var sidebar = $("<div id='npl_sidebar'></div>"); 42 var s_overlay = $("<div id='npl_sidebar_overlay'><i class='fa fa-spin fa-spinner'/></div>"); 43 var toggle = $("<i id='npl_sidebar_toggle' class='fa fa-arrow-right'/>"); 44 45 if (core.methods.mobile.browser.ios()) { 46 overlay.addClass('npl_ios_no_opacity'); 47 wrapper.addClass('npl_ios_hack'); 48 } 49 if (core.methods.is_ie9()) { 50 wrapper.addClass('npl_ie9_flex_hack'); 51 } 52 53 // Provide a hook for third-parties to add their own methods 54 $(window).trigger('override_nplModal_methods', core.methods); 55 56 overlay.css({background: core.methods.get_setting('background_color')}); 57 spinner.css({color: core.methods.get_setting('icon_color')}); 58 s_overlay.css({color: core.methods.get_setting('icon_color')}); 59 btn_close.css({color: core.methods.get_setting('overlay_icon_color')}); 60 sidebar.css({background: core.methods.get_setting('sidebar_background_color')}); 61 toggle.css({color: core.methods.get_setting('overlay_icon_color')}); 62 63 var body = $('body'); 64 body.append(overlay); 65 body.append(wrapper); 66 wrapper.append(spinner); 67 wrapper.append(btn_close); 68 wrapper.append(toggle); 69 wrapper.append(content); 70 wrapper.append(sidebar); 71 wrapper.append(s_overlay); 72 73 // get_setting() isn't available when declaring the base defaults 74 parameters = $.extend(parameters, {router_slug: core.methods.get_setting('router_slug')}); 75 core.options = $.extend(core.defaults, parameters); 76 77 core.methods.bind_images(); 78 core.methods.set_events(); 79 core.methods.mobile.init(); 80 81 // Restrict the padding so that we at *least* have half of the screen to display on 82 if (parseInt(core.methods.get_setting('padding', '0')) > 0) { 83 var space = core.methods.get_setting('padding', '0'); 84 var space_unit = core.methods.get_setting('padding_unit', 'px'); 85 var maxWidth = window.innerWidth / 4; 86 var maxHeight = window.innerHeight / 4; 87 var maxDimension = Math.min(maxWidth, maxHeight); 88 89 if (space_unit === 'px' && space > maxDimension) { 90 space = maxDimension; 91 }
92 else if (space_unit === '%' && space > 25) { 93 space = 25; 94 } 95 96 space = space + space_unit; 97 98 $("<style type='text/css'>#npl_wrapper.npl_open_with_padding {" 99 + 'top: ' + space + ';' 100 + 'bottom: ' + space + ';' 101 + 'left: ' + space + ';' 102 + 'right: ' + space + ';' 103 + " } </style>").appendTo("head"); 104 } 105 106 core.methods.router.routes.push({ 107 re: new RegExp('^' + core.options.router_slug + '\/(.*)\/(.*)\/(.*)$', 'i'), 108 handler: core.methods.url_handler 109 }); 110 111 core.methods.router.routes.push({ 112 re: new RegExp('^' + core.options.router_slug + '\/(.*)\/(.*)$', 'i'), 113 handler: core.methods.url_handler 114 }); 115 116 core.methods.router.routes.push({ 117 re: new RegExp('^' + core.options.router_slug + '$', 'i'), 118 handler: core.methods.close_modal 119 }); 120 121 core.methods.router.routes.push({ 122 re: '', 123 handler: core.methods.close_modal 124 }); 125 126 // Ask the router to listen for routing requests 127 // Safari and Opera don't fire the load event when the cache 128 // has been cached, and the pageshow event should be used instead 129 /** 130 SEE: 131 ------ 132 Webkit: http://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/ 133 Firefox: https://developer.mozilla.org/En/Using_Firefox_1.5_caching. 134 Chrome: https://code.google.com/p/chromium/issues/detail?id=2879 135 */ 136 ['load', 'pageshow'].map(function(eventType){ 137 setTimeout(function() { 138 core.methods.router.listen(); 139 }, 200); 140 }) 141 142 // Hack for iOS and some Android browsers that can't handle position:fixed when the keyboard is open 143 if (core.methods.mobile.browser.ios() 144 || core.methods.mobile.browser.android()) { 145 wrapper.addClass('npl_mobile'); 146 } 147 148 $(window).trigger('npl_initialization_complete'); 149 }, 150 151 methods: { 152 _pre_open_callbacks: [], 153 _is_open: false, 154 155 getDPIRatio: function() { 156 var ratio = 1; 157 158 // To account for zoom, change to use deviceXDPI instead of systemXDPI 159 if (window.screen.systemXDPI !== undefined 160 && window.screen.logicalXDPI !== undefined 161 && window.screen.systemXDPI > window.screen.logicalXDPI) { 162 // Only allow for values > 1 163 ratio = window.screen.systemXDPI / window.screen.logicalXDPI; 164 } else if (window.devicePixelRatio !== undefined) { 165 ratio = window.devicePixelRatio; 166 } 167 168 core.methods.log('nplModal.getDPIRatio()', { 169 result: ratio 170 }); 171 return ratio; 172 }, 173 174 url_handler: function() { 175 var slug = arguments[0]; 176 var image_id = arguments[1]; 177 var sidebar = null; 178 if (arguments.length === 3) { 179 sidebar = arguments[2]; 180 if (sidebar === '1') { 181 sidebar = 'comments'; 182 } 183 } 184 185 // need to get slug, image_id, and sidebar 186 // determine the ID from our slug. if nothing comes back, assume we're already looking at the ID 187 var gallery_id = this.get_id_from_slug(slug); 188 if (!gallery_id) { 189 gallery_id = slug; 190 } 191 192 // Image_ID should remain an integer for all NGG provided images
193 // but it's passed to this method as a string 194 var old_state = this.get_state(); 195 if (parseInt(image_id) === old_state.image_id) { 196 image_id = parseInt(image_id); 197 } 198 199 var state = { 200 gallery_id: gallery_id, 201 image_id: image_id, 202 sidebar: sidebar, 203 slug: slug 204 }; 205 206 this.set_state(state); 207 208 $('#npl_content').trigger('npl_url_handler', [state]); 209 210 if (this.is_open() && gallery_id === core.state.gallery_id) { 211 return; 212 } 213 214 this.open_modal(gallery_id, image_id, sidebar); 215 }, 216 217 run_pre_open_lightbox_callbacks: function(link, params) { 218 for (var i = 0; i < this._pre_open_callbacks.length; i++) { 219 var callback = this._pre_open_callbacks[i]; 220 params = callback(link, params); 221 } 222 return params; 223 }, 224 225 add_pre_open_callback: function(callback) { 226 this._pre_open_callbacks.push(callback); 227 }, 228 229 get_state: function() { 230 return core.state; 231 }, 232 233 set_state: function(state) { 234 core.methods.log("nplModal.set_state()", { 235 state: state 236 }); 237 core.state = state; 238 }, 239 240 get_setting: function (name, def) { 241 var tmp = ''; 242 if (typeof nplModalSettings !== 'undefined' 243 && typeof nplModalSettings[name] !== 'undefined' 244 && nplModalSettings[name] !== '') { 245 tmp = window.nplModalSettings[name]; 246 } else { 247 tmp = def; 248 } 249 if (tmp === 1) tmp = true; 250 if (tmp === 0) tmp = false; 251 if (tmp === '1') tmp = true; 252 if (tmp === '0') tmp = false; 253 254 core.methods.log('nplModal.get_setting()', { 255 name: name, 256 result: tmp 257 }, 3); 258 return tmp; 259 }, 260 261 get_slug: function (gallery_id) { 262 var slug = gallery_id; 263 if ('undefined' === typeof window.galleries) { return slug; } 264 265 $.each(galleries, function(index, gallery) { 266 if (gallery.slug && gallery.ID === gallery_id) { 267 slug = gallery.slug; 268 } 269 }); 270 271 core.methods.log('nplModal.get_slug()', { 272 gallery_id: gallery_id, 273 result: slug 274 }); 275 return slug; 276 }, 277 278 open: function($el) { 279 core.methods.log('nplModal.open()', { 280 el: $el 281 }); 282 283 // Define parameters for opening the Pro Lightbox 284 var params = { 285 show_sidebar: '', 286 gallery_id: '!', 287 image_id: '!', 288 slug: null, 289 revert_image_id: '!', 290 open_the_lightbox: true 291 }; 292 293 // Determine if we should show the comment sidebar 294 if ($el.data('nplmodal-show-comments')) { 295 params.show_sidebar = '/comments'; 296 } 297 298 // Determine the gallery id 299 if ($el.data('nplmodal-gallery-id')) { 300 params.gallery_id = $el.data('nplmodal-gallery-id'); 301 } 302 303 // Determine the image id 304 if ($el.data('nplmodal-image-id')) { 305 params.image_id = parseInt($el.data('nplmodal-image-id')); 306 } else if ($el.data('image-id')) { 307 params.image_id = parseInt($el.data('image-id')); 308 } else if (params.gallery_id === '!') { 309 310 var $image = $el.find('img'); 311 params.image_id = $image.attr('src'); 312 if ($image.attr('srcset')) { 313 var sizes = parseSrcset($image.attr('srcset')); 314 var largest_w = 0; 315 _.each(sizes, function (row) { 316 if (typeof row.w !== undefined && row.w > largest_w) { 317 largest_w = row.w; 318 params.image_id = row.url; 319 } 320 }); 321 } 322 } 323 324 // Determine the slug 325 if (params.gallery_id !== '!') { 326 params.slug = this.get_slug(params.gallery_id); 327 } 328 329 // Run any registered callbacks for modifying lightbox params 330 params = this.run_pre_open_lightbox_callbacks($el, params); 331 332 // Are we to still open the lightbox? 333 if (params.open_the_lightbox) { 334 // open the pro-lightbox manually 335 if (params.gallery_id === '!' || !this.get_setting('enable_routing')) { 336 this.open_modal(params.gallery_id, params.image_id, null); 337 } else { 338 // open the pro-lightbox through our backbone.js router 339 core.methods.router.front_page_pushstate(params.gallery_id, params.image_id); 340 341 core.methods.set_state({ 342 gallery_id: params.gallery_id, 343 image_id: params.image_id, 344 sidebar: params.show_sidebar, 345 slug: params.slug 346 }); 347 348 this.router.navigate( 349 core.options.router_slug 350 + '/' + params.slug 351 + '/' + params.image_id 352 + params.show_sidebar 353 ); 354 355 // some displays (random widgets) may need to disable routing 356 // but still pass an image-id to display on startup 357 if (params.revert_image_id !== '!') { 358 core.state.image_id = params.revert_image_id; 359 } 360 } 361 } 362 }, 363 364 bind_images: function() { 365 // to handle ajax-pagination events this method is called on the 'refreshed' signal 366 var selector = nextgen_lightbox_filter_selector($, $(".nextgen_pro_lightbox")); 367 368 // Modify the selector to exclude any Photocrati Lightboxes 369 var new_selector = []; 370 for (var index = 0; index < selector.length; index++) { 371 var el = selector[index]; 372 if (!$(el).hasClass('photocrati_lightbox_always') && !$(el).hasClass('decoy')) { 373 new_selector.push(el); 374 } 375 } 376 377 // Ensure that we're attaching the event to the A tag, not the img, if 378 // there is one. 379 // TODO: Should this be moved to nextgen_lightbox_filter_selector() ? 380 new_selector = new_selector.map(function(el) { 381 return $(el).hasClass('nextgen_pro_lightbox') && el.nodeName != 'A' && $(el).parents('a').length 382 ? $(el).parents('a')[0] 383 : el; 384 }); 385 386 core.selector = $(new_selector); 387 core.selector.on('click', function (event) { 388 // pass these by 389 if ($.inArray($(this).attr('target'), ['_blank', '_parent', '_top']) > -1) { 390 return; 391 } 392 393 // NextGEN Basic Thumbnails has an option to link to an imagebrowser display; this disables the effect
394 // code (we have no gallery-id) but we may be asked to open it anyway if lightboxes are set to apply 395 // to all images. Check for and do nothing in that scenario: 396 if ($(this).data('src') 397 && $(this).data('src').indexOf(core.methods.get_setting('router_slug') + '/image') !== -1 398 && !$(this).data('nplmodal-gallery-id')) { 399 return; 400 } 401 402 event.stopPropagation(); 403 event.preventDefault(); 404 405 if (event.handled !== true) { 406 event.handled = true; 407 core.methods.open($(this)); 408 } 409 }); 410 }, 411 412 // establishes bindings of events to actions 413 set_events: function() { 414 var self = this; 415 416 $(window).on('refreshed', self.bind_images); 417 $(window).on('keydown', self.handle_keyboard_input); 418 419 $('#npl_content').on('npl_images_ready', self.open_modal_final); 420 421 // handle exit clicks/touch events 422 $('#npl_overlay, #npl_button_close').on('touchstart click', function(event) { 423 event.stopPropagation(); 424 event.preventDefault(); 425 if (event.handled !== true) { 426 event.handled = true; 427 self.close_modal(); 428 } 429 }); 430 }, 431 432 open_modal: function(gallery_id, image_id, sidebar) { 433 core.methods.log('nplModal.open_modal()', { 434 gallery_id: gallery_id, 435 image_id: image_id, 436 sidebar: sidebar 437 }); 438 439 this._is_open = true; 440 441 // allow for cleanup handlers to run 442 $('#npl_content').trigger('npl_opening'); 443 444 // disables browser scrollbar display 445 $('html, body').toggleClass('nextgen_pro_lightbox_open'); 446 core.state.image_id = image_id; 447 core.state.gallery_id = gallery_id; 448 449 $('#npl_spinner_container').removeClass('hidden'); 450 $('#npl_button_close').removeClass('hidden'); 451 452 this.fullsize.exit(); 453 this.mobile.open(); 454 455 // fetch_images(), when done building a list of images to feed to Galleria, will trigger 456 // an event on #npl_content that is handled by open_modal_final() 457 core.methods.fetch_images.fetch_images(gallery_id, image_id); 458 }, 459 460 preload_image: function(image_obj) { 461 return new Promise(resolve => { 462 const image = new Image(); 463 image.addEventListener('load', () => { 464 resolve(); 465 }); 466 image.src = image_obj.use_hdpi ? image_obj.srcsets.hdpi : image_obj.image; 467 }); 468 }, 469 470 open_modal_final: function(event, gallery_id) { 471 var show_ndx = 0; 472 var show_hdpi = core.methods.getDPIRatio() > 1; 473 var images = core.methods.fetch_images.gallery_image_cache[core.state.gallery_id]; 474 var sidebar = core.state.sidebar; 475 476 $.each(images, function(index, element) { 477 // Mark the requested image as the one to show at startup 478 if (parseInt(core.state.image_id) === parseInt(element.image_id)) { 479 show_ndx = index; 480 } 481 482 // A WP media library or 'other' / non-nextgen image 483 if (typeof core.state.image_id == 'string' && typeof element.image_id == 'string') { 484 if (core.state.image_id === element.image_id) { 485 show_ndx = index; 486 } 487 } 488 489 // In case we're viewing a WP or non-NGG image 490 if (typeof element.full_use_hdpi !== 'undefined') { 491 // Massage our data for High-DPI screens 492 if (show_hdpi && element.full_use_hdpi) { 493 element.image = element.full_srcsets.hdpi; 494 } else { 495 // In case the plain 'image' is a dynamically-shrunk version: 496 // we always want to use the 'full' size image when available 497 element.image = element.full_image; 498 } 499 } 500 }); 501 502 // Determine if carousel thumbnails should be enabled 503 var thumbnails = core.methods.get_setting('enable_carousel', 'always'); 504 var thumbnails_limit = core.methods.get_setting('carousel_thumbnails_limit', 250); 505 var gallery = core.methods.get_gallery_from_id(gallery_id); 506 if (thumbnails === 'always') { 507 thumbnails = 'lazy'; 508 } else if (thumbnails === 'never') { 509 thumbnails = false;
510 } else if (thumbnails === 'nomobile') { 511 if (core.methods.mobile.browser.any()) { 512 thumbnails = false; 513 } else { 514 thumbnails = 'lazy'; 515 } 516 } 517 518 // Very large galleries can severely impact performance. Disabling carousel thumbnails 519 // can greatly relieve that impact however, so we automatically change for very large galleries 520 if (gallery && gallery.images_list_count >= thumbnails_limit) { 521 thumbnails = false; 522 } 523 524 if (!thumbnails) { 525 $('#npl_wrapper').addClass('nggpl-carousel-hidden'); 526 } 527 528 if (sidebar 529 || (core.methods.get_setting('display_cart', false) && core.methods.get_displayed_gallery_setting(gallery_id, 'is_ecommerce_enabled', false)) 530 || (core.methods.get_setting('display_comments', false) && core.methods.get_setting('enable_comments', false))) { 531 $('#npl_wrapper').addClass('npl-sidebar-open npl-sidebar-overlay-open'); 532 } 533 534 if (core.methods.get_setting('display_captions', false)) { 535 $('#npl_wrapper').addClass('npl-info-open'); 536 } 537 538 if (core.methods.get_setting('style')) { 539 $('#npl_wrapper').addClass('npl-variant-' + core.methods.get_setting('style')) 540 } 541 542 if (!core.methods.get_setting('display_carousel', true) || core.methods.mobile.browser.any()) { 543 $('#npl_wrapper').addClass('npl-carousel-closed'); 544 } 545 546 if (images.length >= thumbnails_limit) { 547 thumbnails = false; 548 } 549 550 core.methods.log('nplModal.open_modal() about to invoke Galleria.run()', { 551 thumbnails: thumbnails, 552 images: images, 553 show: show_ndx, 554 sidebar: sidebar 555 }); 556 557 // Preload the first six images ourselves, THEN start Galleria. This is done to mitigate Galleria.js 558 // positioning images incorrectly when they are slow to load at startup and during transitions. 559 const preloads = images.slice((show_ndx - 3), (show_ndx + 3)); 560 const promises = preloads.map(image => core.methods.preload_image(image)); 561 562 Promise.all(promises).then((values) => { 563 Galleria.run('#npl_content', { 564 responsive: true, 565 thumbQuality: false, 566 thumbnails: thumbnails, 567 preload: 0, 568 theme: 'nextgen_pro_lightbox', 569 dataSource: images, 570 show: show_ndx, 571 variation: 'nggpl-variant-' + core.methods.get_setting('style', ''), 572 transition: core.methods.get_setting('transition_effect', 'slide'), 573 touchTransition: core.methods.get_setting('touch_transition_effect', 'slide'), 574 imagePan: core.methods.get_setting('image_pan', false), 575 pauseOnInteraction: core.methods.get_setting('interaction_pause', true), 576 imageCrop: core.methods.get_setting('image_crop', true), 577 transitionSpeed: (core.methods.get_setting('transition_speed', 0.4) * 1000), 578 nggSidebar: sidebar 579 }); 580 581 // Set the background color right away, so that we don't have to wait for the theme init 582 $('#npl_content .galleria-container').css({background: core.methods.get_setting('background_color')}); 583 }); 584 585 }, 586 587 // When rotaning or opening the keyboard some mobile browsers increase the user zoom level beyond the default. 588 // To handle this we update the viewport setting to disable zooming when open_modal is run and restore it to 589 // the original value when calling close_modal() 590 mobile: { 591 meta: null, 592 original: null, // original viewport setting; it's restored at closing 593 adjust: true, 594 ontouch: ('ontouchstart' in window), 595 init: function() { 596 // suppress a warning in desktop chrome (provided no touch input devices are attached) that the following 597 // content meta-attribute we're about to set is invali
597d. it technically is, but it's the only way 598 // to make every mobile browser happy without ridiculous user agent matching that I've come across so far 599 if (!this.ontouch) { 600 this.adjust = false; 601 } 602 var doc = window.document; 603 if (!doc.querySelector) { return; } // this isn't available on pre 3.2 safari 604 this.meta = doc.querySelector("meta[name=viewport]"); 605 this.original = this.meta && this.meta.getAttribute("content"); 606 }, 607 open: function() { 608 if (this.adjust && this.meta) { 609 core.methods.log('nplModal.mobile.open()'); 610 this.meta.setAttribute("content", this.original + ', width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no'); 611 } 612 }, 613 close: function() { 614 if (this.adjust && this.meta) { 615 core.methods.log('nplModal.mobile.close()'); 616 this.meta.setAttribute("content", this.original); 617 } 618 }, 619 browser: { 620 any: function() { 621 return core.methods.mobile.browser.android() 622 || core.methods.mobile.browser.ios() 623 || core.methods.mobile.browser.windowsphone() 624 || core.methods.mobile.browser.blackberry(); 625 }, 626 android: function() { 627 return /Android/i.test(navigator.userAgent); 628 }, 629 ios: function() { 630 return /crios|iP(hone|od|ad)/i.test(navigator.userAgent); 631 }, 632 windowsphone: function() { 633 return /(iemobile|Windows Phone)/i.test(navigator.userAgent); 634 }, 635 blackberry: function() { 636 return /(blackberry|RIM Tablet|BB10; )/i.test(navigator.userAgent); 637 } 638 } 639 }, 640 641 is_ie9: function() { 642 return navigator.appVersion.indexOf("MSIE 9.") !== -1; 643 }, 644 645 // hide our content and close up 646 close_modal: function() { 647 if (!this._is_open) { 648 return; 649 } 650 651 core.methods.log('nplModal.close_modal()'); 652 653 var content = $('#npl_content'); 654 655 // allow for cleanup handlers to run 656 content.trigger('npl_closing'); 657 658 // kill Galleria so it won't suck up memory in the background 659 const innerGalleria = content.data('galleria'); 660 if ('undefined' !== typeof innerGalleria) { 661 innerGalleria.destroy(); 662 } 663 664 this.fullsize.enter(); 665 666 // for use with Galleria it is important that npl_content never have display:none set 667 $('#npl_spinner_container, #npl_button_close').addClass('hidden'); 668 669 // enables displaying browser scrollbars 670 $('html, body').toggleClass('nextgen_pro_lightbox_open'); 671 672 // Reset all statuses such as whether the sidebar has been triggered 673 $('#npl_wrapper').removeClass(); 674 675 this.mobile.close(); 676 677 // reset our modified url to our original state 678 if (this.get_setting('enable_routing')) { 679 if (history.pushState) { 680 history.pushState('', document.title, window.location.pathname + window.location.search); 681 } else { 682 window.location.hash = ''; 683 } 684 if (this.get_setting('is_front_page') && history.pushState) { 685 history.pushState({}, document.title, core.options.initial_url); 686 } 687 } 688 689 this._is_open = false;
690 }, 691 692 fullsize: { 693 _is_fullsize: false, 694 695 active: function() { 696 return this.fullsize._is_fullsize; 697 }, 698 699 enter: function() { 700 core.methods.log('nplModal.fullsize.enter()'); 701 702 $('#npl_wrapper').removeClass('npl_open_with_padding'); 703 this._is_fullsize = true; 704 }, 705 706 exit: function() { 707 core.methods.log('nplModal.fullsize.exit()'); 708 709 if (parseInt(core.methods.get_setting('padding', '0')) > 0 710 && !core.methods.mobile.browser.ios()) { 711 $('#npl_wrapper').addClass('npl_open_with_padding'); 712 } 713 714 this._is_fullsize = false; 715 }, 716 717 toggle: function() { 718 core.methods.log('nplModal.fullsize.toggle()'); 719 720 if (this.fullsize._is_fullsize) { 721 this.fullsize.exit(); 722 } else { 723 this.fullsize.enter(); 724 } 725 $(window).trigger('resize'); 726 } 727 }, 728 729 handle_keyboard_input: function(event) { 730 if (core.methods.is_open()) { 731 // escape key closes the modal 732 if (event.which === 27) { 733 core.methods.close_modal(); 734 } 735 } 736 }, 737 738 is_open: function() { 739 return this._is_open; 740 }, 741 742 log: function(message, table, level) { 743 if (!core.debug) { 744 return; 745 } 746 747 if (typeof level === 'undefined') { 748 level = 1; 749 } 750 751 if (level > core.debug_level) { 752 return; 753 } 754 755 if (typeof table === 'undefined') { 756 console.log("NPL Debug:", message) 757 } else { 758 console.log("NPL Debug:", message, table); 759 } 760 761 }, 762 763 logging: { 764 enable: function() { 765 console.log("Enabling NextGen Pro Lightbox debugging"); 766 core.debug = true; 767 }, 768 disable: function() { 769 console.log("Disabling NextGen Pro Lightbox debugging"); 770 core.debug = false; 771 }, 772 set_level: function(level) { 773 console.log("Setting NextGen Pro Lightbox debug level to " + level); 774 core.level = parseInt(level); 775 } 776 }, 777 778 fetch_images: { 779 gallery_image_cache: [], 780 ajax_info: [], 781 ajax_interval: null, 782 ajax_delay: 1400, 783 784 is_cached: function(gallery_id, image_id) { 785 var found = false; 786 $.each(this.gallery_image_cache[gallery_id], function (ndx, image) { 787 if (image_id === image.image_id) { 788 found = true; 789 } 790 }); 791 792 core.methods.log("nplModal.fetch_images.is_cached()", { 793 gallery_id: gallery_id, 794 image_id: image_id, 795 gallery_cache: this.gallery_image_cache[gallery_id], 796 found: found 797 }, 4); 798 799 return found; 800 }, 801 802 fetch_images: function(gallery_id, image_id) { 803 core.methods.log('nplModal.fetch_images.fetch_images() beginning'); 804 var self = this; 805 806 this.ajax_delay = core.methods.get_setting('ajax_delay', 1400); 807 808 if (typeof this.gallery_image_cache[gallery_id] === 'undefined') { 809 this.gallery_image_cache[gallery_id] = []; 810 } 811 812 var gallery = core.methods.get_gallery_from_id(gallery_id); 813 814 if (gallery === null) { 815 // It's not a NextGen gallery, just read from the page 816 return this.fetch_non_ngg_images(gallery_id); 817 } 818 819 // Gallery is already cached - just trigger the ready event 820 if (this.gallery_image_cache[gallery_id].length === gallery.images_list_count) { 821 return $('#npl_content').trigger('npl_images_ready', [gallery_id]); 822 } 823 824 // Build the cache from the list 'localized' on the page 825 $.each(gallery.images_list, function(ndx, image) { 826 if (!self.is_cached(gallery_id, image.image_id)) { 827 self.gallery_image_cache[gallery_id].push(image); 828 } 829 }); 830 831 // Again check if our cache is full 832 if (this.gallery_image_cache[gallery_id].length === gallery.images_list_count) { 833 return $('#npl_content').trigger('npl_images_ready', [gallery_id]); 834 } 835 836 // Not all images are on this page: fetch by XHR - which handles the ready event 837 if (this.gallery_image_cache[gallery_id].length < gallery.images_list_count) { 838 return this.fetch_images_from_ajax(gallery_id); 839 } 840 }, 841 842 fetch_non_ngg_images: function (gallery_id) { 843 core.methods.log('nplModal.fetch_images.fetch_non_ngg_images() beginning', { 844 gallery_id: gallery_id 845 }); 846 847 var self = this; 848 849 core.selector.each(function() { 850 var anchor = $(this); 851 852 if (anchor.hasClass('ngg-trigger')) { 853 return true; // exclude NextGEN trigger icons 854 } 855 856 if (gallery_id !== '!' && gallery_id !== anchor.data('nplmodal-gallery-id')) { 857 return true; // exclude images from other galleries 858 } 859 860 861 if (gallery_id !== core.methods.get_state().gallery_id) { 862 return true; // exclude images from other galleries 863 } 864 865 if (core.methods.get_state().gallery_id === '!' && anchor.data('nplmodal-gallery-id')) { 866 return true; // when viewing non-nextgen images; exclude nextgen-images 867 } 868 869 var image = $(this).find('img').first(); 870 var gallery_image = {}; 871 var expr = /\.(jpeg|jpg|gif|png|bmp)$/i; 872 873 gallery_image.image = (anchor.data('fullsize') === undefined) ? anchor.attr('href') : anchor.data('fullsize'); 874 875 if (typeof gallery_image.image !== 'undefined' 876 && !gallery_image.image.match(expr) 877 && image.attr('srcset')) { 878 var sizes = parseSrcset(image.attr('srcset')); 879 var largest_w = 0; 880 881 _.each(sizes, function (row) { 882 if (typeof row.w !== undefined && row.w > largest_w) { 883 largest_w = row.w; 884 gallery_image.image = row.url; 885 } 886 }); 887 } 888 889 // Workaround WP' "link to attachment page" feature 890 if (!gallery_image.image.match(expr)) { 891 gallery_image.image = image.attr('src'); 892 } 893 894 // When in doubt we id images by their href 895 gallery_image.image_id = (anchor.data('image-id') === undefined) ? gallery_image.image : anchor.data('image-id'); 896 897 // no need to continue 898 if (self.is_cached(gallery_id, gallery_image.image_id)) { 899 return true; 900 } 901 902 // optional attributes 903 if (anchor.data('thumb') !== undefined) gallery_image.thumb = anchor.data('thumb'); 904 else if (anchor.data('thumbnail') !== 'undefined') gallery_image.thumb = anchor.data('thumbnail'); 905 906 if (anchor.data('title') !== undefined) {
907 gallery_image.title = anchor.data('title'); 908 } else if (typeof image.attr('title') !== 'undefined') { 909 gallery_image.title = image.attr('title'); 910 } else if (typeof anchor.siblings('.wp-caption-text').html() !== 'undefined') { 911 gallery_image.title = anchor.siblings('.wp-caption-text').html(); 912 } 913 914 if (anchor.data('description') !== undefined) { 915 gallery_image.description = anchor.data('description'); 916 } else { 917 gallery_image.description = image.attr('alt'); 918 } 919 920 self.gallery_image_cache[gallery_id].push(gallery_image); 921 }); 922 923 core.methods.log('nplModal.fetch_images.fetch_non_ngg_images() result', { 924 result: self.gallery_image_cache[gallery_id] 925 }); 926 927 $('#npl_content').trigger('npl_images_ready', [gallery_id]) 928 }, 929 930 create_deferred_ajax: function(gallery_id, gallery, page) { 931 var self = this; 932 return $.ajax({ 933 async: true, 934 url: core.options.ajax_url + 'nggpro/v1/Galleria/GetImages', 935 method: 'POST', 936 data: { 937 id: gallery_id, 938 gallery: gallery, 939 lang: core.methods.get_setting('lang', null), 940 page: page 941 }, 942 dataType: 'json', 943 success: function(data) { 944 core.methods.log('nplModal.fetch_images.create_deferred_ajax() response', { 945 response: data 946 }); 947 $.each(data, function(ndx, newimage) { 948 if (!self.is_cached(gallery_id, newimage.image_id)) { 949 self.gallery_image_cache[gallery_id].push(newimage); 950 } 951 }); 952 } 953 }); 954 }, 955 956 fetch_images_from_ajax: function(gallery_id, image_id) { 957 if (!core.methods.is_open()) { 958 return; 959 } 960 961 core.methods.log('nplModal.fetch_images.fetch_images_from_ajax()', { 962 gallery_id: gallery_id, 963 image_id: image_id 964 }); 965 966 var self = this; 967 var original_gallery = core.methods.get_gallery_from_id(gallery_id); 968 var gallery = $.extend({}, original_gallery); 969 delete gallery.images_list; 970 delete gallery.display_settings; 971 972 var defers = []; 973 for (i = 0; i <= Math.ceil(gallery.images_list_count / core.methods.get_setting('localize_limit')); i++) { 974 defers.push(core.methods.fetch_images.create_deferred_ajax(gallery_id, gallery, i)); 975 } 976 977 $.when.apply($, defers).then(function() { 978 $('#npl_content').trigger('npl_images_ready', [gallery_id]); 979 }); 980 981 return self.gallery_image_cache[gallery_id]; 982 } 983 }, 984 985 get_gallery_from_id: function (gallery_id) { 986 if ('undefined' === typeof window.galleries) { return null; } 987 var retval = null; 988 $.each(window.galleries, function(index, gallery) { 989 if (gallery.ID === gallery_id || gallery.ID === parseInt(gallery_id)) { 990 retval = gallery; 991 } 992 }); 993 return retval; 994 }, 995 996 get_id_from_slug: function (slug) { 997 var id = slug; 998 if ('undefined' === typeof window.galleries) { return id; } 999 1000 $.each(window.galleries, function(index, gallery) { 1001 if (gallery.slug === slug) { 1002 id = gallery.ID; 1003 } 1004 }); 1005 return id; 1006 }, 1007 1008 get_displayed_gallery_setting: function(gallery_id, name, def) { 1009 var tmp = ''; 1010 var gallery = this.get_gallery_from_id(gallery_id); 1011 if (gallery && typeof gallery.display_settings[name] !== 'undefined') { 1012 tmp = gallery.display_settings[name]; 1013 } else { 1014 tmp = def; 1015 } 1016 if (tmp === '1') tmp = true; 1017 if (tmp === '0') tmp = false;
1018 if (tmp === 1) tmp = true; 1019 if (tmp === 0) tmp = false; 1020 1021 core.methods.log('nplModal.get_displayed_gallery_setting()', { 1022 gallery_id: gallery_id, 1023 name: name, 1024 result: tmp 1025 }); 1026 1027 return tmp; 1028 }, 1029 1030 router: { 1031 routes: [], 1032 interval: null, 1033 1034 listen: function(current) { 1035 var self = this; 1036 current = current || ''; 1037 1038 var listener = function() { 1039 if (current !== self.get_fragment()) { 1040 current = self.get_fragment(); 1041 self.match(current); 1042 } 1043 }; 1044 clearInterval(this.interval); 1045 this.interval = setInterval(listener, 50); 1046 }, 1047 1048 get_fragment: function(url) { 1049 url = url || window.location.href; 1050 var match = url.match(/#(.*)$/); 1051 var fragment = match ? match[1] : ''; 1052 return fragment.toString().replace(/\/$/, '').replace(/^\//, ''); 1053 }, 1054 1055 navigate: function(path, notrigger) { 1056 notrigger = notrigger || false; 1057 if (notrigger) { 1058 clearInterval(this.interval); 1059 } 1060 1061 if (!core.methods.get_setting('enable_routing', false)) { 1062 return; 1063 } 1064 1065 path = path ? path : ''; 1066 window.location.href.match(/#(.*)$/); 1067 window.location.href = window.location.href.replace(/#(.*)$/, '') + '#' + path; 1068 1069 if (notrigger) { 1070 this.router.listen(this.router.get_fragment()) 1071 } 1072 }, 1073 1074 match: function(f) { 1075 var fragment = f || this.get_fragment(); 1076 for (var i = 0; i < this.routes.length; i++) { 1077 var match = fragment.match(this.routes[i].re); 1078 if (match) { 1079 match.shift(); 1080 this.routes[i].handler.apply(core.methods, match); 1081 return this; 1082 } 1083 } 1084 }, 1085 1086 front_page_pushstate: function(gallery_id, image_id) { 1087 if (!core.methods.get_setting('is_front_page') || gallery_id === undefined) { 1088 return false; 1089 } 1090 1091 if ('undefined' === typeof window.galleries) { 1092 return false; 1093 } 1094 1095 core.methods.log("beginning nplModal.router.front_page_pushstate()", { 1096 gallery_id: gallery_id, 1097 image_id: image_id 1098 }); 1099 1100 var url = ''; 1101 var slug = gallery_id; 1102 1103 $.each(galleries, function(index, gallery) { 1104 if (gallery.ID === gallery_id && typeof gallery.wordpress_page_root !== 'undefined') { 1105 url = gallery.wordpress_page_root; 1106 if (gallery.slug) { 1107 slug = gallery.slug; 1108 } 1109 } 1110 }); 1111 1112 url += '#' + this.get_fragment(core.methods.get_setting('router_slug') + '/' + slug + '/' + image_id); 1113 1114 // redirect those browsers that don't support history.pushState 1115 if (history.pushState) { 1116 history.pushState({}, document.title, url); 1117 return true; 1118 } else { 1119 window.location = url; 1120 return false;
1121 } 1122 } 1123 } 1124 } 1125 }; 1126 1127 this.core = core; 1128 } 1129 1130 var nplModalObj = new nplModal(); 1131 1132 $.nplModal = function(param) { 1133 function getDescendantProp(obj, desc) { 1134 var arr = desc.split("."); 1135 while(arr.length) { 1136 obj = obj[arr.shift()]; 1137 } 1138 return obj; 1139 } 1140 1141 if (typeof param === 'undefined') { 1142 return nplModalObj.core.init.apply(nplModalObj, {}); 1143 } else if (typeof param === 'object') { 1144 return nplModalObj.core.init.apply(nplModalObj, param); 1145 } else { 1146 var method = getDescendantProp(nplModalObj.core.methods, param); 1147 if (method) { 1148 return method.apply(nplModalObj.core.methods, Array.prototype.slice.call(arguments, 1)); 1149 } else { 1150 console.error('Method ' + param + ' does not exist on jQuery.nplModal'); 1151 } 1152 } 1153 }; 1154 1155})(jQuery); 1156 1157jQuery(document).ready(function($) { 1158 $.nplModal(); 1159});
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.