1(function($) { 2 3 4 var add_nggpl_theme = function() { 5 6 Galleria.addTheme({ 7 name: 'nextgen_pro_lightbox', 8 author: 'Imagely', 9 version: 2.0, 10 defaults: { 11 debug: false, 12 responsive: true, 13 carousel: true, 14 thumbnails: 'lazy', 15 fullscreen: false, 16 trueFullscreen: false, 17 fullscreenDoubleTap: false, 18 maxScaleRatio: 1 19 }, 20 init: function(options) { 21 var self = this; 22 Galleria.requires(1.41, 'This version of the NextGEN Pro Lightbox theme requires Galleria 1.4.1 or later'); 23 24 $.nplModal('log', 'theme initialization', { 25 options: options 26 }); 27 28 // Some objects have aip variables - animation-in-progress - and are used to make jQuery animations smoother 29 var methods = { 30 sidebar: { 31 _is_open: false, 32 _type: '', 33 is_open: function(state) { 34 if (typeof state !== 'undefined') { 35 this._is_open = state; 36 } else { 37 return this._is_open; 38 } 39 }, 40 toggle: function(type) { 41 $.nplModal('log', 'theme sidebar.toggle()', { 42 type: type 43 }); 44 if (this.is_open() && type === this.get_type()) { 45 this.close(); 46 } else { 47 this.open(type); 48 } 49 }, 50 open: function(type) { 51 $.nplModal('log', 'theme sidebar.open()', { 52 type: type 53 }); 54 55 $('#npl_wrapper').addClass('npl-sidebar-open npl-sidebar-overlay-open'); 56 57 this.render(type); 58 methods.sidebar.is_open(true); 59 60 var state = $.nplModal('get_state'); 61 state.sidebar = type; 62 63 $.nplModal( 64 'router.navigate', 65 $.nplModal('get_setting', 'router_slug') 66 + '/' + state.slug 67 + '/' + state.image_id 68 + '/' + type, 69 true 70 ); 71 72 self.resize(); 73 self.trigger('npl_sidebar_opened'); 74 }, 75 close: function() { 76 $.nplModal('log', 'theme sidebar.close()'); 77 78 $('#npl_wrapper').removeClass('npl-sidebar-open npl-sidebar-overlay-open'); 79 80 methods.sidebar.is_open(false); 81 82 var state = $.nplModal('get_state'); 83 state.sidebar = null; 84 $.nplModal( 85 'router.navigate', 86 $.nplModal('get_setting', 'router_slug') 87 + '/' + state.slug 88 + '/' + state.image_id, 89 true 90 ); 91 92 self.resize(); 93 self.trigger('npl_sidebar_closed'); 94 }, 95 render: function(type) { 96 $.nplModal('log', 'theme sidebar.render()', { 97 type: type 98 }); 99 100 // switching to another sidebar type; flash the overlay 101 if (type !== this.get_type()) { 102 this._type = type; 103 $.nplModal('get_state').sidebar = type; 104 } 105 106 methods.sidebars[type].render(methods.galleria.get_current_image_id()); 107 methods.sidebars[type].init(); 108 }, 109 get_type: function() { 110 return this._type; 111 }, 112 events: { 113 bind: function() { 114 $.nplModal('log', 'theme sidebar.events.bind()'); 115 $('#npl_content').on('npl_sidebar_rendered', this.rendered); 116 $('#npl_sidebar_toggle').on('click', function() { 117 methods.sidebar.close(); 118 }); 119 }, 120 rendered: function() { 121 $.nplModal('log', 'theme sidebar.events.rendered()'); 122 123 // This is hidden except for narrow viewports by default, allows phone users to remember what photo they are 'on' 124 $('#nggpl-sidebar-thumbnail-img').attr('src', self.getData(self.getIndex()).image); 125 } 126 } 127 }, 128 sidebars: { 129 datacache: { 130 _cache: [], 131 _current_image_ndx: null, 132 _last_image_ndx: null, 133 134 events: { 135 bind: function() { 136 $.nplModal('log', 'theme sidebars.datacache.events.bind()'); 137 self.bind('loadstart', this.loadstart); 138 }, 139 140 // Used to track which direction users are navigating in so we can intelligently 141 // pre-load sidebar data in advance of the image being selected 142 loadstart: function() { 143 $.nplModal('log', 'theme sidebars.datacache.events.image()'); 144 // Initial value at startup 145 if (methods.sidebars.datacache._current_image_ndx === null) { 146 methods.sidebars.datacache._last_image_ndx = methods.sidebars.datacache._current_image_ndx = self.getIndex(); 147 } else { 148 // Store the current index and shift the old value 149 methods.sidebars.datacache._last_image_ndx = methods.sidebars.datacache._current_image_ndx; 150 methods.sidebars.datacache._current_image_ndx = self.getIndex(); 151 } 152 } 153 }, 154 155 get_carousel_navigation_direction: function() { 156 if (this._current_image_ndx === this._last_image_ndx) { 157 return 'same'; 158 } else { 159 if (this._last_image_ndx === 0 && this._current_image_ndx === (self.getDataLength() - 1)) { 160 return 'left'; 161 } else if (this._current_image_ndx === 0 && this._last_image_ndx === (self.getDataLength() -1)) { 162 return 'right'; 163 } else { 164 return (this._current_image_ndx < this._last_image_ndx) ? 'left' : 'right'; 165 } 166 } 167 }, 168 169 // because the .length operator isn't accurate 170 get_cache_size: function() { 171 var size = this._cache.length; 172 173 $.nplModal('log', 'theme sidebars.comments.get_cache_size()', { 174 result: size 175 }); 176 177 return size; 178 }, 179 180 // returns the image-id field of the first preceeding image found whose comments aren't cached 181 get_prev_uncached_image_id: function(id, step) { 182 step = step || 0; 183 var prev_image_id = self.getData(self.getPrev(methods.galleria.get_index_from_id(id) - step)).image_id; 184 if (this._cache[prev_image_id] && this.get_cache_size() < self.getDataLength()) { 185 prev_image_id = this.get_prev_uncached_image_id(prev_image_id); 186 } 187 188 $.nplModal('log', 'theme sidebars.comments.get_prev_uncached_image_id()', { 189 id: id, 190 result: prev_image_id 191 }); 192 193 return prev_image_id; 194 }, 195 196 // returns the image-id field of the first following image found whose comments aren't cached 197 get_next_uncached_image_id: function(id, step) { 198 step = step || 0; 199 var next_image_id = self.getData(self.getNext(methods.galleria.get_index_from_id(id) + step)).image_id; 200 if (this._cache[next_image_id] && this.get_cache_size() < self.getDataLength()) { 201 next_image_id = this.get_next_uncached_image_id(next_image_id); 202 } 203 204 $.nplModal('log', 'theme sidebars.comments.get_next_uncached_image_id()', { 205 id: id, 206 result: next_image_id 207 }); 208 209 return next_image_id; 210 }, 211 212 // expanded request method: adds first pre-ceding and following uncached id to the request 213 expanded_request: function(id, finished) { 214 $.nplModal('log', 'theme sidebars.comments.expanded_request()', { 215 id: id 216 }); 217 218 var id_array = (id instanceof Array) ? id : id.toString().split(','); 219 220 // a single ID was requested, so inject some extras so they can be cached in advance 221 if (id_array.length === 1) { 222 var key = id_array[0]; 223 var prev = this.get_prev_uncached_image_id(key); 224 var next = this.get_next_uncached_image_id(key); 225 if (!this._cache[prev]) { 226 this._cache[prev] = 'Placeholder stub'; 227 id_array.unshift(prev); 228 } 229 if (!this._cache[next] && prev !== next && id !== next) { 230 this._cache[next] = 'Placeholder stub'; 231 id_array.push(next); 232 } 233 } 234 235 id_array = this.sort_uniq(id_array); 236 this.request(id_array, 0, finished); 237 }, 238 239 // handles the HTTP request to load comments & cache the results 240 request: function(id, page, finished) { 241 $.nplModal('log', 'theme sidebars.comments.request()', { 242 id: id, 243 page: page 244 }); 245 246 var myself = this; // self is taken 247 var postdata = { 248 type: 'image', 249 page: page, 250 id: id.join(','), 251 from: window.parent.location.toString(), 252 }; 253 if ($.nplModal('get_setting', 'lang', false)) { 254 postdata.lang = $.nplModal('get_setting', 'lang'); 255 } 256 257 $.ajax({ 258 url: photocrati_ajax.rest_url + '
258nggpro/v1/Galleria/GetSidebarData', 259 method: 'POST', 260 beforeSend: function (xhr) { 261 xhr.setRequestHeader('X-WP-Nonce', window.nextgen_pro_lightbox_authentication.nonce); 262 }, 263 xhrFields: { 264 withCredentials: true 265 }, 266 data: postdata, 267 success: function(data) { 268 $.nplModal('log', 'theme sidebars.comments.request() response', { 269 response: data 270 }); 271 272 if (typeof(data) !== 'object') { 273 data = JSON.parse(data); 274 } 275 for (var ndx in data) { 276 myself._cache[ndx] = data[ndx]; 277 } 278 if (typeof finished === 'function') { 279 finished(data); 280 } 281 } 282 }); 283 }, 284 285 // find and load the next un-cached results 286 load_more: function(id) { 287 $.nplModal('log', 'theme sidebars.comments.load_more()', { 288 id: id 289 }); 290 291 if (methods.nplModal.is_nextgen_gallery() 292 && $.nplModal('get_setting', 'enable_routing', false) 293 && $.nplModal('get_setting', 'enable_comments', false)) { 294 var precache_ids = []; 295 296 var direction = methods.sidebars.datacache.get_carousel_navigation_direction(); 297 var count = 3; 298 299 // Retrieve X images in the same direction the user is navigating 300 for (var i = 0; i <= count; i++) { 301 if (direction === 'left') { 302 var uncached_id = this.get_prev_uncached_image_id(id, i); 303 } else { 304 var uncached_id = this.get_next_uncached_image_id(id, i); 305 } 306 307 // Push the recently found IDs to this._cache so they can't be included again 308 if (!this._cache[uncached_id]) { 309 this._cache[uncached_id] = 'Placeholder stub'; 310 precache_ids.push(uncached_id); 311 } 312 } 313 314 precache_ids = this.sort_uniq(precache_ids); 315
316 if (precache_ids.length !== 0) { 317 this.expanded_request(precache_ids); 318 } 319 } 320 }, 321 322 sort_uniq: function(ids) { 323 return ids.sort().filter(function(item, pos, ary) { 324 return !pos || item !== ary[pos - 1]; 325 }) 326 }, 327 328 get_cache_by_id: function(id) { 329 return this._cache[id]; 330 } 331 }, 332 comments: { 333 // called after render(), initialize logic & events 334 init: function() { 335 $.nplModal('log', 'theme sidebars.comments.init()'); 336 337 if ($('#nggpl-comments-wrapper').length !== 1) { return; } 338 339 // jquery's .val() fails with hidden fields 340 var origin_url = document.getElementById("ngg_comment_origin_url"); 341 if (typeof origin_url !== 'undefined' && origin_url !== null) { 342 origin_url.value = window.location.href.toString(); 343 } 344 345 // It is much faster to change the target attribute globally here than through WP hooks 346 $('#npl_sidebar').find('a').each(function() { 347 if ($(this).attr('id') === 'nggpl-comment-logout') { 348 $(this).attr('href', $(this).attr('href') + '?redirect_to=' + window.location.toString()); 349 } else { 350 $(this).attr('target', '_blank'); 351 } 352 }); 353 354 $('#nggpl-respond-form').on('submit', function (event) { 355 event.preventDefault(); 356 var commentstatus = $('#nggpl-comment-status'); 357 $('#npl_wrapper').addClass('npl-sidebar-overlay-open'); 358 $.ajax({ 359 type: $(this).attr('method'), 360 url: $(this).attr('action'), 361 data: $(this).serialize(), 362 dataType: 'json', 363 success: function (data) { 364 if (data.success === true) { 365 $('#nggpl-comment').val(''); 366 $('#nggpl-comments-title').val(''); 367 var image_id = methods.galleria.get_current_image_id(); 368 methods.sidebars.datacache.expanded_request(image_id, function() { 369 methods.sidebar.render(methods.sidebars.comments.get_type(), image_id); 370 }); 371 } else { 372 commentstatus.addClass('error') 373 .html(data); 374 $('#npl_wrapper').removeClass('npl-sidebar-overlay-open'); 375 } 376 }, 377 complete: function (jqXHR, status) { 378 }, 379 error: function (jqXHR) { 380 commentstatus.addClass('error').html(jqXHR.responseText); 381 $('#npl_wrapper').removeClass('npl-sidebar-overlay-open'); 382 } 383 }); 384 }); 385 386 $("#npl_sidebar .nggpl-button, #nggpl-comment-form-wrapper input[type='submit']").each(function() { 387 var $this = $(this); 388 $this.css({ 389 'color': $.nplModal('get_setting', 'sidebar_button_color'), 390 'background-color': $.nplModal('get_setting', 'sidebar_button_background') 391 }); 392 }); 393 394 // handles 'Reply' links 395 $('.nggpl-reply-to-comment').on('click', function(event) { 396 event.preventDefault(); 397 // all that wordpress needs is the comment_parent value 398 $('#nggpl-comment_parent').val($(this).data('comment-id')); 399 $('#nggpl-comment-reply-status').removeClass('hidden'); 400 401 // IE has issues setting focus on invisible elements. Be wary 402 $('#nggpl-commentform').find(':input').filter(':visible').first().trigger('focus'); 403 $('#npl_sidebar').scrollTop($('#nggpl-comments-bottom').offset().top); 404 }); 405 406 // handles "cancel reply" link 407 $('#nggpl-comment-reply-status a').on('click', function(event) { 408 event.preventDefault(); 409 $('#nggpl-comment_parent').val('0'); 410 $('#nggpl-comment-reply-status').addClass('hidden'); 411 }); 412 413 // handles comment AJAX pagination 414 $('#nggpl-comment-nav-below a').on('click', function(event) { 415 event.preventDefault(); 416 $('#npl_wrapper').addClass('npl-sidebar-overlay-open'); 417 var page_id = $(this).data('page-id'); 418 methods.sidebars.datacache.request( 419 [methods.galleria.get_current_image_id()], 420 page_id, 421 function() { 422 methods.sidebar.render('comments', methods.galleria.get_current_image_id()); 423 } 424 ); 425 }); 426 427 self.trigger('npl_sidebar_rendered'); 428 429 if (methods.nplModal.is_nextgen_gallery() 430 && $.nplModal('get_setting', 'enable_routing', false) 431 && $.nplModal('get_setting', 'enable_sharing', false)) { 432 $('#nggpl-comments-image-share-icons').removeClass('disabled'); 433 methods.share_icons.create( 434 '#nggpl-comments-image-share-icons', 435 methods.icons.get_overlay_color() 436 ); 437 } 438 439 methods.sidebars.comments.wait_for_image_to_reveal(); 440 }, 441 442 wait_for_image_to_reveal: function() { 443 if (!methods.sidebars.comments.events.between_loadstart_and_finish) { 444 $('#npl_wrapper').removeClass('npl-sidebar-overlay-open'); 445 } else { 446 methods.sidebars.comments.events.waiting_for_image_to_load = true; 447 } 448 }, 449 450 // returns the display area content from cache 451 render: function(id) { 452 $.nplModal('log', 'theme sidebars.comments.render()', { 453 id: id 454 }); 455 456 var cache = methods.sidebars.datacache.get_cache_by_id(id); 457 458 if (!cache) { 459 $('#npl_wrapper').addClass('npl-sidebar-overlay-open'); 460 methods.sidebars.datacache.expanded_request(id, function() { 461 cache = methods.sidebars.datacache.get_cache_by_id(id); 462 $('#npl_sidebar').html(cache.comments['rendered_view']); 463 methods.sidebars.comments.init(); 464 }); 465 } else if (cache === 'Placeholder stub') { 466 $('#npl_wrapper').addClass('npl-sidebar-overlay-open'); 467 var interval = setInterval(function() { 468 cache = methods.sidebars.datacache.get_cache_by_id(id); 469 if (cache !== 'Placeholder stub') { 470 $('#npl_sidebar').html(cache.comments['rendered_view']); 471 methods.sidebars.comments.init(); 472 clearInterval(interval); 473 } 474 }, 250); 475 } else { 476 $('#npl_sidebar').html(cache.comments['rendered_view']); 477 $('#npl_wrapper').removeClass('npl-sidebar-overlay-open'); 478 } 479 }, 480 481 get_type: function() { 482 return 'comments'; 483 }, 484 485 events: { 486 waiting_for_image_to_load: false, 487 between_loadstart_and_finish: false, 488 489 bind: function() { 490 $.nplModal('log', 'theme sidebars.comments.events.bind()'); 491 492 if (methods.nplModal.is_nextgen_gallery() 493 && $.nplModal('get_setting', 'enable_routing', false) 494 && $.nplModal('get_setting', 'enable_comments', false) 495 && !methods.nplModal.is_random_source()) { 496 self.bind('loadstart', this.loadstart); 497 self.bind('npl_init', this.npl_init); 498 self.bind('npl_init_keys', this.npl_init_keys); 499 self.bind('image', this.image); 500 } 501 }, 502 503 npl_init: function() { 504 $.nplModal('log', 'theme sidebars.comments.events.npl_init()'); 505 506 // Adds comment toolbar button 507 var comment_button = $('<i/>') 508 .addClass('nggpl-toolbar-button-comment fa fa-comment') 509 .attr({'title': $.nplModal('get_setting', 'i18n').toggle_social_sidebar}); 510 methods.thumbnails.register_button( 511 comment_button, 512 function(event) { 513 methods.sidebar.toggle(methods.sidebars.comments.get_type()); 514 event.preventDefault(); 515 } 516 ); 517 }, 518 519 image: function() { 520 methods.sidebars.comments.events.between_loadstart_and_finish = false;
521 522 if (methods.sidebars.comments.events.waiting_for_image_to_load) { 523 methods.sidebars.comments.events.waiting_for_image_to_load = false; 524 $('#npl_wrapper').removeClass('npl-sidebar-overlay-open'); 525 } 526 }, 527 528 _loadstart_run_once: false, 529 loadstart: function(e) { 530 $.nplModal('log', 'theme sidebars.comments.events.npl_init_complete()'); 531 532 methods.sidebars.comments.events.between_loadstart_and_finish = true; 533 534 if (methods.nplModal.is_nextgen_gallery() && !methods.sidebars.comments._loadstart_run_once) { 535 // possibly display the comments sidebar at startup 536 if (($.nplModal('get_state').sidebar && $.nplModal('get_state').sidebar === methods.sidebars.comments.get_type()) 537 || $.nplModal('get_setting', 'display_comments')) { 538 methods.sidebar.open(methods.sidebars.comments.get_type()); 539 } 540 methods.sidebars.comments._loadstart_run_once = true; 541 } else if (methods.nplModal.is_nextgen_gallery() 542 && $.nplModal('get_setting', 'enable_routing', false) 543 && $.nplModal('get_setting', 'enable_comments', false)) { 544 // updates the sidebar 545 methods.sidebars.datacache.load_more(methods.galleria.get_current_image_id()); 546 if (methods.sidebar.is_open() && methods.sidebar.get_type() === methods.sidebars.comments.get_type()) { 547 methods.sidebar.render(methods.sidebars.comments.get_type()); 548 } 549 } 550 }, 551 552 npl_init_keys: function() { 553 $.nplModal('log', 'theme sidebars.comments.events.npl_init_keys()'); 554 var input_types = methods.galleria.get_keybinding_exclude_list(); 555 if (methods.nplModal.is_nextgen_gallery() 556 && $.nplModal('get_setting', 'enable_routing', false) 557 && $.nplModal('get_setting', 'enable_comments', false)) 558 { 559 self.attachKeyboard({ 560 // spacebar 561 32: function () { 562 if (!$(document.activeElement).is(input_types)) { 563 methods.sidebar.toggle(methods.sidebars.comments.get_type()); 564 } 565 } 566 }); 567 } 568 } 569 } 570 } 571 }, 572 thumbnails: { 573 is_open: function() { 574 return !$('#npl_wrapper').hasClass('npl-carousel-closed'); 575 }, 576 toggle: function() { 577 $.nplModal('log', 'theme thumbnails.toggle()'); 578 579 if (this.is_open()) { 580 this.close(); 581 } else { 582 this.open(); 583 } 584 }, 585 open: function() { 586 $.nplModal('log', 'theme thumbnails.open()'); 587 588 $('#npl_wrapper').removeClass('npl-carousel-closed'); 589 $('.galleria-dock-toggle-container i').toggleClass('fa-angle-up fa-angle-down'); 590 $('.galleria-dock-toggle-container').find('[data-fa-i2svg]').toggleClass('fa-angle-up fa-angle-down'); 591 $(window).trigger('resize'); 592 }, 593 close: function() { 594 $.nplModal('log', 'theme thumbnails.close()'); 595 596 $('#npl_wrapper').addClass('npl-carousel-closed'); 597 $('.galleria-dock-toggle-container i').toggleClass('fa-angle-up fa-angle-down'); 598 $('.galleria-dock-toggle-container').find('[data-fa-i2svg]').toggleClass('fa-angle-up fa-angle-down'); 599 $(window).trigger('resize'); 600 }, 601 adjust_container: function() { 602 $.nplModal('log', 'theme thumbnails.adjust_container()'); 603 // Important: this must be delayed for a short while after Galleria.resize() is invoked to allow 604 // Galleria to finish repositioning itself and prevent possible race scenario. 605 setTimeout(function() { 606 var available_width = self.$('thumbnails-container').width() 607 - self.$('nextgen-buttons').width() 608 - self.$('thumb-nav-left').width() 609 - self.$('thumb-nav-right').width(); 610 if (available_width <= (70 * 4)) { 611 self.$('container').addClass('nggpl-carousel-too-small'); 612 } else { 613 self.$('container').removeClass('nggpl-carousel-too-small'); 614 } 615 }, 250); 616 }, 617 _buttons: [], 618 register_button: function(button, callback) { 619 $.nplModal('log', 'theme thumbnails.register_button()', { 620 button: button 621 }); 622 623 var wrapper = $('<span class="nggpl-button nggpl-toolbar-button"/>'); 624 if ($.nplModal('get_setting', 'icon_background_enabled', false) 625 && $.nplModal('get_setting', 'icon_background_rounded', false)) { 626 wrapper.addClass('nggpl-rounded'); 627 } 628 wrapper.html(button); 629 this._buttons.push(wrapper); 630 $(self._dom.stage).append(wrapper); 631 632 wrapper.on('click', function(event) { 633 callback(event) 634 }); 635 }, 636 get_registered_buttons: function() { 637 $.nplModal('log', 'theme thumbnails.get_registered_buttons', { 638 buttons: this._buttons 639 }); 640 return this._buttons; 641 }, 642 events: { 643 bind: function() { 644 $.nplModal('log', 'theme thumbnails.events.bind()'); 645 646 self.bind('loadfinish', methods.thumbnails.adjust_container); 647 self.bind('loadfinish', this.loadfinish); 648 self.bind('npl_sidebar_opened', methods.thumbnails.adjust_container); 649 self.bind('npl_sidebar_closed', methods.thumbnails.adjust_container); 650 self.bind('npl_init', this.npl_init); 651 self.bind('npl_init_complete', this.npl_init_complete); 652 653 // This prevents multiple handlers from running simultaneously, and multiple 654 // events pile up when listening to 'resize' - only the last handler is invoked 655 // if 250ms pass after the last triggering. 656 methods.galleria.bind_once('resize', methods.thumbnails.adjust_container, 250); 657 }, 658 npl_init: function() { 659 $.nplModal('log', 'theme thumbnails.events.npl_init()'); 660 661 if ('numbers' === options.thumbnails) { 662 self.$('container').addClass('nggpl-carousel-numbers'); 663 self.$('thumbnails-list').css('color', methods.icons.get_color()); 664 665 // Because numeric entries have a different width than at startup we 666 // must manually invoke updateCarousel() here so that we don't start 667 // with the carousel in the wrong position 668 self.updateCarousel(); 669 670 } else if ('lazy' === options.thumbnails) { 671 // load all thumbnails, 10 at a time, until all have been retrieved 672 self.lazyLoadChunks(10); 673 } 674 675 self.$('thumbnails-container').css({background: $.nplModal('get_setting', 'carousel_background_color')}); 676 677 // create carousel next/prev links 678 var next_thumbs_button = $('<i/>') 679 .addClass('fa fa-angle-right') 680 .css({color: methods.icons.get_color()}); 681 var prev_thumbs_button = $('<i/>') 682 .addClass('fa fa-angle-left') 683 .css({color: methods.icons.get_color()}); 684 $(self._dom.stage).append(next_thumbs_button); 685 $(self._dom.stage).append(prev_thumbs_button); 686 self.append({'thumb-nav-left': prev_thumbs_button}); 687 self.append({'thumb-nav-right': next_thumbs_button}); 688 689 // Create thumbnails-container toggle button 690 self.addElement('dock-toggle-container'); 691 var dock_toggle_container = self.$('dock-toggle-container') 692 .css({background: $.nplModal('get_setting', 'carousel_background_color')}); 693 var dock_toggle_button = $('<i/>').addClass('fa fa-angle-down') 694 .css({color: $.nplModal('get_setting', 'carousel_text_color')}); 695 696 // the container was marked hidden by the parent wrapper, adjust the angle-icon accordingly 697 if (!methods.thumbnails.is_open()) { 698 dock_toggle_button.toggleClass('fa-angle-up fa-angle-down'); 699 } 700 701 $(self._dom.stage).append(dock_toggle_button); 702 self.append({'dock-toggle-container': dock_toggle_button}); 703 dock_toggle_container.on('click', self.proxy(function() { 704 methods.thumbnails.toggle(); 705 })); 706 707 // Add playback controls 708 var play_button = $('<i/>') 709 .addClass('nggpl-toolbar-button-play fa fa-play') 710 .attr({'title': $.nplModal('get_setting', 'i18n').play_pause}); 711 if (this._playing) { 712 play_button.removeClass('fa-play').addClass('fa-pause'); 713 } 714 methods.thumbnails.register_button( 715 play_button, 716 function(event) { 717 event.preventDefault();
718 self.playToggle(); 719 var $target = $(event.currentTarget); 720 $target.find('i').toggleClass('fa-play fa-pause'); 721 $target.find('[data-fa-i2svg]').toggleClass('fa-play fa-pause'); 722 } 723 ); 724 725 // add info controls; handles animation of both the info & dock-toggle-container divs 726 var info_button = $('<i/>') 727 .addClass('nggpl-toolbar-button-info fa fa-info') 728 .attr({'title': $.nplModal('get_setting', 'i18n').toggle_image_info}); 729 methods.thumbnails.register_button( 730 info_button, 731 function(event) { 732 event.preventDefault(); 733 methods.info.toggle(); 734 } 735 ); 736 }, 737 npl_init_complete: function() { 738 $.nplModal('log', 'theme thumbnails.events.npl_init_complete()'); 739 740 var display_buttons = methods.thumbnails.get_registered_buttons(); 741 // assign all of our buttons a (possibly custom) color 742 for (i = 0; i <= (display_buttons.length - 1); i++) { 743 display_buttons[i].css({ 744 'color': methods.icons.get_color(), 745 'background-color': methods.icons.get_background() 746 }); 747 } 748 self.addElement('nextgen-buttons'); 749 self.append({'nextgen-buttons': display_buttons}); 750 self.prependChild('thumbnails-container', 'nextgen-buttons'); 751 self.prependChild('info', 'dock-toggle-container'); 752 753 if (!$.nplModal('mobile.browser.any')) { 754 self.addIdleState(self.get('dock-toggle-button'), {opacity: 0}); 755 } 756 }, 757 // Hide the parent lightbox's spinner 758 _loadfinish_ran_once: false, 759 loadfinish: function() { 760 $.nplModal('log', 'theme thumbnails.events.loadfinish()'); 761 762 if (methods.thumbnails.events._loadfinish_ran_once) { 763 return; 764 } 765 766 $('#npl_spinner_container').addClass('hidden'); 767 methods.thumbnails.events._loadfinish_ran_once = true; 768 } 769 } 770 }, 771 info: { 772 is_open: function() { 773 return $('#npl_wrapper').hasClass('npl-info-open'); 774 }, 775 776 toggle: function() { 777 $.nplModal('log', 'theme info.toggle()'); 778 779 if (this.is_open()) { 780 this.close(); 781 } else { 782 this.open(); 783 } 784 }, 785 786 open: function() { 787 $.nplModal('log', 'theme info.open()'); 788 789 $('#npl_wrapper').addClass('npl-info-open'); 790 }, 791 792 close: function() { 793 $.nplModal('log', 'theme info.close()'); 794 795 $('#npl_wrapper').removeClass('npl-info-open'); 796 }, 797 798 events: { 799 bind: function() { 800 $.nplModal('log', 'theme info.events.bind()'); 801 802 self.bind('npl_init', this.npl_init); 803 self.bind('loadfinish', this.loadfinish); 804 }, 805 806 npl_init: function() { 807 $.nplModal('log', 'theme info.events.npl_init()'); 808 809 var needsnewparent = self.$('info').detach(); 810 self.$('thumbnails-container').append(needsnewparent); 811 812 // Add social share icons to the infobar. ID is important, sidebars could add their own icons 813 self.prependChild( 814 'info-text', 815 $('<div/>') 816 .attr('id', 'galleria-image-share-icons') 817 .attr('class', 'galleria-image-share-icons') 818 ); 819 if (carousel_text_color = $.nplModal('get_setting', 'carousel_text_color')) { 820 self.$('info-title').css({color: carousel_text_color}); 821 self.$('info-description').css({color: carousel_text_color}); 822 } 823 self.$('info, info-text, info-title, info-description').css({background: $.nplModal('get_setting', 'carousel_background_color')}); 824 }, 825 826 _loadfinish_ran_once: false, 827 loadfinish: function() { 828 $.nplModal('log', 'theme info.events.loadfinish()'); 829 // anchors in our image captions / descriptions must have target=_blank 830 self.$('info-title, info-description').find('a').each(function() { 831 $(this).attr('target', '_blank'); 832 $(this).css('color', methods.icons.get_color()); 833 }); 834 835 methods.info.events._loadfinish_ran_once = true; 836 } 837 } 838 }, 839 icons: { 840 get_color: function() { 841 return $.nplModal('get_setting', 'icon_color'); 842 }, 843 get_background: function() { 844 var iconcolor = $.nplModal('get_setting', 'carousel_background_color'); 845 if ($.nplModal('get_setting', 'icon_background_enabled', false)) { 846 iconcolor = $.nplModal('get_setting', 'icon_background'); 847 } 848 return iconcolor; 849 }, 850 get_overlay_color: function() { 851 return $.nplModal('get_setting', 'overlay_icon_color'); 852 } 853 }, 854 nplModal: { 855 close: function() { 856 $.nplModal('close_modal'); 857 }, 858 is_random_source: function() { 859 var gallery = $.nplModal('get_gallery_from_id', $.nplModal('get_state').gallery_id); 860 var result = ($.inArray(gallery.source, ['random', 'random_images']) !== -1); 861 862 $.nplModal('log', 'theme nplModal.is_random_source()', { 863 result: result 864 }); 865 866 return result; 867 }, 868 is_nextgen_gallery: function() { 869 var retval = $.nplModal('get_state').gallery_id !== '!'; 870 871 $.nplModal('log', 'theme nplModal.is_nextgen_gallery()', { 872 result: retval 873 }); 874 875 return retval; 876 }, 877 is_nextgen_widget: function() { 878 var retval = false;
879 var gallery = $.nplModal('get_gallery_from_id', $.nplModal('get_state').gallery_id); 880 var slug = gallery.slug; 881 if (slug) { 882 retval = slug.indexOf('widget-ngg-images') !== -1; 883 } 884 885 $.nplModal('log', 'theme nplModal.is_nextgen_widget()', { 886 result: retval 887 }); 888 889 return retval; 890 }, 891 events: { 892 bind: function() { 893 $.nplModal('log', 'theme nplModal.bind()'); 894 895 if (Galleria.IPAD || Galleria.IPHONE) { 896 self.$('container').addClass('nggpl-ios-browser'); 897 } 898 899 // update the parent url when a new image has been chosen or the slideshow advances 900 if (methods.nplModal.is_nextgen_gallery()) { 901 self.bind('image', this.image); 902 } 903 904 // handle updates to the current url once opened; most likely due to the back/forward button 905 if (methods.nplModal.is_nextgen_gallery() 906 && $.nplModal('get_setting', 'enable_routing', false) 907 && $.nplModal('get_setting', 'enable_comments', false)) { 908 $('#npl_content').on('npl_url_handler', this.unhandled_url_change); 909 } 910 911 if ($.nplModal('get_setting', 'protect_images', false)) { 912 $('.galleria-image').on('dragstart', function(event) { 913 event.preventDefault(); 914 }); 915 self.bind('npl_init', this.npl_init); 916 self.bind('npl_init_complete', this.npl_init_complete); 917 } 918 919 jQuery('#npl_content').on('npl_closing', this.closing); 920 }, 921 npl_init: function() { 922 $.nplModal('log', 'theme nplModal.events.npl_init()'); 923 924 self.addElement('image-protection'); 925 document.oncontextmenu = function(event) { 926 event = event || window.event; 927 event.preventDefault(); 928 }; 929 }, 930 npl_init_complete: function() { 931 $.nplModal('log', 'theme nplModal.events.npl_init_complete()'); 932 self.prependChild('images', 'image-protection'); 933 }, 934 _image_ran_once: false, 935 image: function() { 936 $.nplModal('log', 'theme nplModal.events.image()'); 937 if (methods.nplModal.events._image_ran_once) { 938 if (!methods.nplModal.is_random_source()) { 939 var image_id = self.getData(self.getIndex()).image_id; 940 var sidebar_string = methods.sidebar.is_open() ? '/' + methods.sidebar.get_type() : ''; 941 var state = $.nplModal('get_state'); 942 state.image_id = image_id; 943 $.nplModal('set_state', state); 944 if ($.nplModal('get_setting', 'enable_routing', false)) { 945 $.nplModal( 946 'router.navigate', 947 $.nplModal('get_setting', 'router_slug') + '/' + $.nplModal('get_state').slug + '/' + image_id + sidebar_string, 948 true 949 ); 950 } 951 } 952 } 953 methods.nplModal.events._image_ran_once = true; 954 }, 955 unhandled_url_change: function(event, state) { 956 $.nplModal('log', 'theme nplModal.unhandled_url_change()', { 957 event: event, 958 state: state 959 }); 960 for (var i = 0; i <= (self.getDataLength() - 1); i++) { 961 if (state.image_id === self.getData(i).image_id) { 962 self.show(i); 963 } 964 } 965 if (methods.sidebar.is_open() && state.sidebar == null) { 966 methods.sidebar.close(); 967 } else if (!methods.sidebar.is_open() 968 && typeof state.sidebar !== 'undefined' 969 && state.sidebar !== null) { 970 methods.sidebar.open(state.sidebar); 971 } 972 }, 973 closing: function() { 974 // without this our bound keys will continue to activate even aften 975 // Galleria.destroy() has been called and the container div emptied 976 self.detachKeyboard(); 977 } 978 } 979 }, 980 galleria: { 981 bind_once: function(event, callback, timeout) { 982 var timer_id = undefined; 983 window.addEventListener(event, function() { 984 if (typeof timer_id === 'undefined') { 985 clearTimeout(timer_id); 986 timer_id = undefined; 987 } 988 timer_id = setTimeout(function() { 989 timer_id = undefined; 990 callback(); 991 }, timeout); 992 }); 993 }, 994 get_displayed_gallery_setting: function(name, def) { 995 var tmp = ''; 996 var gallery = $.nplModal('get_gallery_from_id', $.nplModal('get_state').gallery_id); 997 if (gallery && typeof gallery.display_settings[name] !== 'undefined') { 998 tmp = gallery.display_settings[name]; 999 } else { 1000 tmp = def; 1001 } 1002 if (tmp === '1') tmp = true; 1003 if (tmp === '0') tmp = false;
1004 if (tmp === 1) tmp = true; 1005 if (tmp === 0) tmp = false; 1006 1007 $.nplModal('log', 'theme galleria.get_displayed_gallery_setting()', { 1008 name: name, 1009 result: tmp 1010 }); 1011 1012 return tmp; 1013 }, 1014 get_keybinding_exclude_list: function() { 1015 return 'textarea, input'; 1016 }, 1017 get_current_image_id: function() { 1018 return self.getData(self.getIndex()).image_id; 1019 }, 1020 // returns the Galleria image-index based on the provided image id 1021 get_index_from_id: function(id) { 1022 var retval = null; 1023 for (var i = 0; i <= (self.getDataLength() - 1); i++) { 1024 if (id === self.getData(i).image_id) { 1025 retval = i; 1026 } 1027 } 1028 return retval; 1029 }, 1030 events: { 1031 bind: function() { 1032 $.nplModal('log', 'theme galleria.events.bind()'); 1033 self.bind('touchmove', this.touchmove); 1034 self.bind('npl_init', this.npl_init); 1035 self.bind('npl_init_keys', this.npl_init_keys); 1036 self.bind('npl_init_complete', this.npl_init_complete); 1037 self.bind('loadstart', this.loadstart); 1038 self.bind('loadfinish', this.loadfinish); 1039 $(window).on('resize orientationchange', this.browserchanged); 1040 }, 1041 browserchanged: function() { 1042 $.nplModal('log', 'theme galleria.events.browserchanged()'); 1043 setTimeout(function() { 1044 self.rescale(); 1045 }, 200); 1046 }, 1047 npl_init: function() { 1048 $.nplModal('log', 'theme galleria.events.npl_init()'); 1049 // for some reason this isn't an option that can be passed at startup 1050 self.setPlaytime(($.nplModal('get_setting', 'slideshow_speed', 5) * 1000)); 1051 1052 // Create next / back links 1053 var next_image_button = $('<i/>') 1054 .addClass('fa fa-angle-right') 1055 .css({color: methods.icons.get_overlay_color()}); 1056 var prev_image_button = $('<i/>') 1057 .addClass('fa fa-angle-left') 1058 .css({color: methods.icons.get_overlay_color()}); 1059 $(self._dom.stage).append(next_image_button); 1060 $(self._dom.stage).append(prev_image_button); 1061 self.append({'image-nav-left': prev_image_button}); 1062 self.append({'image-nav-right': next_image_button}); 1063 1064 self.$('counter').css({color: methods.icons.get_overlay_color()}); 1065 }, 1066 npl_init_keys: function() { 1067 $.nplModal('log', 'theme galleria.events.npl_init_keys()'); 1068 var input_types = methods.galleria.get_keybinding_exclude_list(); 1069 self.attachKeyboard({ 1070 left: function() { 1071 if (!$(document.activeElement).is(input_types)) { 1072 this.prev(); 1073 } 1074 }, 1075 right: function() { 1076 if (!$(document.activeElement).is(input_types)) { 1077 this.next(); 1078 } 1079 }, 1080 down: function() { 1081 if (!$(document.activeElement).is(input_types)) { 1082 methods.thumbnails.toggle(); 1083 } 1084 }, 1085 up: function() { 1086 if (!$(document.activeElement).is(input_types)) { 1087 methods.info.toggle(); 1088 } 1089 }, 1090 // escape key 1091 27: function(event) { 1092 event.preventDefault(); 1093 methods.nplModal.close(); 1094 } 1095 }); 1096 }, 1097 npl_init_complete: function() { 1098 $.nplModal('log', 'theme galleria.events.npl_init_complete()'); 1099 if (!$.nplModal('mobile.browser.any')) { 1100 self.addIdleState(self.get('counter'), {opacity: 0}); 1101 self.addIdleState(self.get('image-nav-left'), {opacity: 0}); 1102 self.addIdleState(self.get('image-nav-right'), {opacity: 0}); 1103 } 1104 }, 1105 touchmove: function(event) { 1106 // prevent scrolling on elements without the 'scrollable' class 1107 if (!$('.scrollable').has($(event.target)).length) { 1108 $.nplModal('log', 'theme galleria.events.touchmove() prevented scrolling'); 1109 event.preventDefault(); 1110 } 1111 }, 1112 loadstart: function(event) { 1113 $.nplModal('log', 'theme galleria.events.loadstart()', { 1114 event: event 1115 }); 1116 1117 if (!event.cached) { 1118 var button = $('#npl_button_close').find('i'); 1119 button.removeClass('fa-times-circle'); 1120 } 1121 }, 1122 loadfinish: function() { 1123 $.nplModal('log', 'theme galleria.events.loadfinish()'); 1124 1125 var button = $('#npl_button_close').find('i'); 1126 button.addClass('fa-times'); 1127 } 1128 } 1129 }, 1130 share_icons: {
1131 strip_html: function(html) { 1132 var tmp = document.createElement('div'); 1133 tmp.innerHTML = html; 1134 return tmp.textContent || tmp.innerText || ""; 1135 }, 1136 create: function(target, iconcolor) { 1137 $.nplModal('log', 'theme share_icons.create()'); 1138 if (methods.nplModal.is_random_source() 1139 || methods.nplModal.is_nextgen_widget() 1140 || !methods.nplModal.is_nextgen_gallery() 1141 || !$.nplModal('get_setting', 'enable_routing', false)) { 1142 return false; 1143 } 1144 1145 var id = self.getData(self.getIndex()).image_id; 1146 var data = self.getData(self.getIndex()); 1147 var url = encodeURIComponent(window.location.toString()); 1148 1149 var twitter_icon = $('<li/>').html( 1150 $('<a/>', {'href': 'https://twitter.com/share?url=' + methods.share_icons.get_share_url(id, 'full'), 1151 'target': '_blank', 1152 'class': 'nggpl-comment-tweet-button', 1153 'title': $.nplModal('get_setting', 'i18n').share.twitter}) 1154 .css({color: iconcolor}) 1155 .html($('<i/>', {'class': 'fa-brands fa-square-x-twitter'})) 1156 ); 1157 1158 var facebook_icon = $('<li/>').html( 1159 $('<a/>', { 1160 'class': 'nggpl-comment-facebook-button', 1161 'title': $.nplModal('get_setting', 'i18n').share.facebook 1162 }).css({color: iconcolor}) 1163 .html($('<i/>', {'class': 'fa fa-facebook-square'})) 1164 ); 1165 1166 if (typeof $.nplModal('get_setting', 'facebook_app_id') !== 'undefined') { 1167 facebook_icon.on('click', function(event) { 1168 event.preventDefault(); 1169 FB.ui({ 1170 method: 'share', 1171 href: methods.share_icons.get_share_url(id, 'full'), 1172 link: window.location.toString() 1173 }, function(response){ 1174 // Debug response (optional) 1175 }); 1176 }); 1177 } else { 1178 var facebook_url = 'https://www.facebook.com/share.php'; 1179 facebook_url += '?u=' + encodeURIComponent(methods.share_icons.get_share_url(id, 'full')); 1180 var anchor = facebook_icon.find('a'); 1181 anchor.attr('href', facebook_url); 1182 anchor.attr('target', '_blank'); 1183 } 1184 1185 var pinterest_url = encodeURIComponent(methods.share_icons.get_share_url(id, 'full')); 1186 1187 // Pinterest restricts description length, and we must avoid making the request longer than browsers will allow 1188 var summary = methods.share_icons.strip_html(data.description); 1189 if (summary.length >= 446) { 1190 summary = summary.substring(0, 492); 1191 summary += '...'; 1192 } 1193 1194 pinterest_url += '&url=' + url; 1195 pinterest_url += '&media=' + data.image; 1196 pinterest_url += '&description=' + summary; 1197 var pinterest_icon = $('<li/>').html( 1198 $('<a/>', {'href': 'http://pinterest.com/pin/create/button/?s=100' + pinterest_url, 1199 'target': '_blank', 1200 'class': 'nggpl-comment-pinterest-button', 1201 'title': $.nplModal('get_setting', 'i18n').share.pinterest}) 1202 .css({color: iconcolor}) 1203 .html($('<i/>', {'class': 'fa fa-pinterest-square'})) 1204 ); 1205 1206 var icons = [twitter_icon, facebook_icon, pinterest_icon]; 1207 1208 target = $(target); 1209 target.html(''); 1210 $('<ul/>').appendTo(target); 1211 target.find('ul').append(icons); 1212 }, 1213 get_share_url: function(id, named_size) { 1214 if (typeof(named_size) === 'undefined') { 1215 named_size = 'thumb'; 1216 } 1217 1218 var gallery_id = $.nplModal('get_state').gallery_id; 1219 var base_url = $.nplModal('get_setting', 'share_url') 1220 .replace('{gallery_id}', gallery_id) 1221 .replace('{image_id}', id) 1222 .replace('{named_size}', named_size); 1223 var site_url_link = $('<a/>').attr('href', $.nplModal('get_setting', 'wp_site_url'))[0]; 1224 var parent_link = $('<a/>').attr('href', window.location.toString())[0]; 1225 var base_link = $('<a/>').attr('href', base_url)[0]; 1226 1227 // check if site is in a sub-directory and shorten the prefix 1228 if (parent_link.pathname.indexOf(site_url_link.pathname) >= 0) { 1229 parent_link.pathname = parent_link.pathname.substr(site_url_link.pathname.length); 1230 } 1231 // shorten url by removing their common prefix 1232 if (parent_link.pathname.indexOf(base_link.pathname) >= 0) { 1233 parent_link.pathname = parent_link.pathname.substr(parent_link.pathname.length); 1234 } 1235 1236 // this is odd but it's just how the 'share' controller expects it 1237 base_link.search = parent_link.search; 1238 if (base_link.search.length > 0) { 1239 base_link.search += '&'; 1240 } 1241 base_link.search += 'uri=' + parent_link.pathname; 1242 1243 $.nplModal('log', 'theme share_icons.get_share_url() result', { 1244 id: id, 1245 named_size: named_size, 1246 result: base_link.href 1247 }); 1248 1249 return base_link.href; 1250 }, 1251 events: { 1252 bind: function() { 1253 $.nplModal('log', 'theme share_icons.events.bind()'); 1254 self.bind('loadfinish', this.loadfinish); 1255 self.bind('npl_init', this.npl_init); 1256 }, 1257 npl_init: function() { 1258 if (typeof $.nplModal('get_setting', 'facebook_app_id') !== 'undefined') { 1259 if (typeof window.fbAsyncInit === 'undefined') { 1260 window.fbAsyncInit = function() { 1261 FB.init({ 1262 appId: $.nplModal('get_setting', 'facebook_app_id'), 1263 autoLogAppEvents: true, 1264 xfbml: true, 1265 version: 'v2.12' 1266 }); 1267 }; 1268 1269 (function(d, s, id) { 1270 var js, fjs = d.getElementsByTagName(s)[0]; 1271 if (d.getElementById(id)) { return; } 1272 js = d.createElement(s); js.id = id; 1273 js.src = "https://connect.facebook.net/en_US/sdk.js"; 1274 fjs.parentNode.insertBefore(js, fjs); 1275 }(document, 'script', 'facebook-jssdk')); 1276 } 1277 } 1278 }, 1279 loadfinish: function() { 1280 $.nplModal('log', 'theme share_icons.events.loadfinish()'); 1281 if (methods.nplModal.is_nextgen_gallery() 1282 && $.nplModal('get_setting', 'enable_routing', false) 1283 && $.nplModal('get_setting', 'enable_sharing', false)) { 1284 var iconcolor = $.nplModal('get_setting', 'carousel_text_color') ? $.nplModal('get_setting', 'carousel_text_color') : methods.icons.get_color(); 1285 methods.share_icons.create( 1286 '#galleria-image-share-icons', 1287 iconcolor 1288 ); 1289 } 1290 } 1291 } 1292 }, 1293 tiktok: { 1294 cleanup: function() { 1295 $('#npl_content .ngg-tiktok-container').remove(); 1296 $('#npl_content .ngg-tiktok-error').remove(); 1297 $('#npl_wrapper').removeClass('npl-tiktok-mode'); 1298 }, 1299 1300 handle_content: function(data) { 1301 this.cleanup(); 1302 if (!data.tiktok_play_url && !data.tiktok_share_url) return; 1303 1304 // Check if NextGEN_TikTok helper is available 1305 if (typeof NextGEN_TikTok === 'undefined' || !NextGEN_TikTok.handle_content) { 1306 console.warn('NextGEN_TikTok helper not available.'); 1307 return; 1308 } 1309 1310 $('#npl_wrapper').addClass('npl-tiktok-mode'); 1311 1312 var $img = $('#npl_content .galleria-image img:visible'); 1313 1314 NextGEN_TikTok.handle_content({ 1315 playUrl: data.tiktok_play_url, 1316 shareUrl: data.tiktok_share_url, 1317 container: $('#npl_content .galleria-stage'), 1318 width: $img.width(), 1319 height: $img.height(), 1320 }); 1321 }, 1322 1323 events: { 1324 bind: function() { 1325 self.bind('loadstart', function() { 1326 methods.tiktok.cleanup(); 1327 }); 1328 self.bind('loadfinish', function(e) { 1329 var data = e.data || self.getData(self.getIndex()); 1330 // Check if this is a TikTok video 1331 var isTikTok = (data.is_tiktok == 1 || data.is_tiktok == '1' || data.is_tiktok === true) 1332 || (data.tiktok_play_url || data.tiktok_share_url); 1333 if (isTikTok) { 1334 methods.tiktok.handle_content(data); 1335 } 1336 }); 1337 } 1338 } 1339 }, 1340 video: { 1341 cleanup: function() { 1342 $('#npl_content .ngg-video-container').remove(); 1343 $('#npl_content .ngg-video-error').remove(); 1344 $('#npl_wrapper').removeClass('npl-video-mode'); 1345 }, 1346 1347 getVideoEmbedInfo: function(url, autoplay) { 1348 if (!url || typeof url !== 'string') { 1349 return { isEmbed: false, embedUrl: null, useIframe: false }; 1350 } 1351 1352 var embedUrl = null; 1353 var useIframe = false;
1354 var isEmbed = false; 1355 var autoplayParam = autoplay ? '1' : '0'; 1356 1357 var youtubeRegex = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/; 1358 var youtubeMatch = url.match(youtubeRegex); 1359 if (youtubeMatch) { 1360 embedUrl = 'https://www.youtube.com/embed/' + youtubeMatch[1] + '?autoplay=' + autoplayParam + '&rel=0'; 1361 useIframe = true; 1362 isEmbed = true; 1363 } 1364 1365 var vimeoRegex = /(?:vimeo\.com\/)(?:.*\/)?(\d+)/; 1366 var vimeoMatch = url.match(vimeoRegex); 1367 if (vimeoMatch && !isEmbed) { 1368 embedUrl = 'https://player.vimeo.com/video/' + vimeoMatch[1] + '?autoplay=' + autoplayParam; 1369 useIframe = true; 1370 isEmbed = true; 1371 } 1372 1373 var dailymotionRegex = /(?:dailymotion\.com\/(?:embed\/)?video\/|dai\.ly\/)([a-zA-Z0-9]+)/; 1374 var dailymotionMatch = url.match(dailymotionRegex); 1375 if (dailymotionMatch && !isEmbed) { 1376 embedUrl = 'https://www.dailymotion.com/embed/video/' + dailymotionMatch[1] + '?autoplay=' + autoplayParam; 1377 useIframe = true; 1378 isEmbed = true; 1379 } 1380 1381 var twitchRegex = /(?:twitch\.tv\/videos\/|twitch\.tv\/)(\d+|[a-zA-Z0-9_]+)/; 1382 var twitchMatch = url.match(twitchRegex); 1383 if (twitchMatch && !isEmbed) { 1384 var twitchId = twitchMatch[1]; 1385 var autoplayStr = autoplay ? 'true' : 'false'; 1386 if (/^\d+$/.test(twitchId)) { 1387 embedUrl = 'https://player.twitch.tv/?video=' + twitchId + '&autoplay=' + autoplayStr + '&parent=' + window.location.hostname; 1388 } else { 1389 embedUrl = 'https://player.twitch.tv/?channel=' + twitchI
1389d + '&autoplay=' + autoplayStr + '&parent=' + window.location.hostname; 1390 } 1391 useIframe = true; 1392 isEmbed = true; 1393 } 1394 1395 var videopressRegex = /(?:videopress\.com\/v\/|video\.wordpress\.com\/v\/)([a-zA-Z0-9]+)/; 1396 var videopressMatch = url.match(videopressRegex); 1397 if (videopressMatch && !isEmbed) { 1398 embedUrl = 'https://videopress.com/embed/' + videopressMatch[1] + '?autoplay=' + autoplayParam; 1399 useIframe = true; 1400 isEmbed = true; 1401 } 1402 1403 var wistiaRegex = /(?:wistia\.com\/medias\/|wistia\.net\/embed\/)([a-zA-Z0-9]+)/; 1404 var wistiaMatch = url.match(wistiaRegex); 1405 if (wistiaMatch && !isEmbed) { 1406 embedUrl = 'https://fast.wistia.net/embed/iframe/' + wistiaMatch[1] + '?autoplay=' + autoplayParam; 1407 useIframe = true; 1408 isEmbed = true; 1409 } 1410 1411 return { 1412 isEmbed: isEmbed, 1413 embedUrl: embedUrl, 1414 useIframe: useIframe, 1415 originalUrl: url 1416 }; 1417 }, 1418 1419 handle_content: function(data) { 1420 this.cleanup(); 1421 if (!data.video_link) return; 1422 1423 $('#npl_wrapper').addClass('npl-video-mode'); 1424 1425 // Get video control properties from data 1426 var isAutoplay = (data.is_video_autoplay == 1 || data.is_video_autoplay == '1' || data.is_video_autoplay === true); 1427 var showControls = (data.show_video_controls == 1 || data.show_video_controls == '1' || data.show_video_controls === true); 1428 var showPlayPause = (data.show_play_pause_controls == 1 || data.show_play_pause_controls == '1' || data.show_play_pause_controls === true); 1429 1430 // Default to true if not specified 1431 if (typeof data.is_video_autoplay === 'undefined') { 1432 isAutoplay = true; 1433 } 1434 if (typeof data.show_video_controls === 'undefined') { 1435 showControls = true; 1436 } 1437 1438 var $container = $('#npl_content .galleria-stage');
1439 var $videoContainer = $('<div class="ngg-video-container"></div>'); 1440 1441 var videoInfo = this.getVideoEmbedInfo(data.video_link, isAutoplay); 1442 var $videoElement; 1443 1444 if (videoInfo.useIframe && videoInfo.embedUrl) { 1445 // For iframe embeds, controls are handled by the platform 1446 $videoElement = $('<iframe>', { 1447 src: videoInfo.embedUrl, 1448 frameborder: '0', 1449 allow: 'autoplay; fullscreen; picture-in-picture', 1450 allowfullscreen: true, 1451 webkitallowfullscreen: true, 1452 mozallowfullscreen: true 1453 }); 1454 1455 if (!showControls && videoInfo.embedUrl.indexOf('youtube.com') !== -1) { 1456 videoInfo.embedUrl += (videoInfo.embedUrl.indexOf('?') === -1 ? '?' : '&') + 'controls=0'; 1457 $videoElement.attr('src', videoInfo.embedUrl); 1458 } 1459 } else { 1460 var videoAttrs = { 1461 playsinline: true, 1462 preload: 'auto' 1463 }; 1464 1465 if (showControls) { 1466 videoAttrs.controls = true; 1467 } 1468 1469 if (isAutoplay) { 1470 videoAttrs.autoplay = true; 1471 videoAttrs.muted = true; // Required for autoplay in modern browsers 1472 } 1473 1474 $videoElement = $('<video>', videoAttrs); 1475 $videoElement.attr('src', data.video_link); 1476 1477 if (showPlayPause && !showControls) { 1478 var $playPauseBtn = $('<button>', { 1479 class: 'ngg-video-play-pause-btn', 1480 type: 'button', 1481 html: '<i class="fa fa-play"></i>' 1482 }); 1483 1484 $playPauseBtn.on('click', function() { 1485 var video = $videoElement[0]; 1486 if (video.paused) { 1487 video.play(); 1488 $playPauseBtn.html('<i class="fa fa-pause"></i>'); 1489 } else { 1490 video.pause(); 1491 $playPauseBtn.html('<i class="fa fa-play"></i>'); 1492 } 1493 }); 1494 1495 $videoElement.on('play', function() { 1496 $playPauseBtn.html('<i class="fa fa-pause"></i>'); 1497 }); 1498 1499 $videoElement.on('pause', function() { 1500 $playPauseBtn.html('<i class="fa fa-play"></i>'); 1501 }); 1502 1503 $videoContainer.append($playPauseBtn); 1504 } 1505 1506 if (isAutoplay) { 1507 $videoElement.on('playing', function() { 1508 try { 1509 $videoElement.prop('muted', false); 1510 } catch (e) { 1511 console.debug('Could not unmute video automatically:', e); 1512 } 1513 }); 1514 1515 setTimeout(function() { 1516 if ($videoElement[0] && $videoElement[0].paused) { 1517 $videoElement[0].play().catch(function(err) { 1518 console.warn('Video auto
1518play failed:', err); 1519 }); 1520 } 1521 }, 100); 1522 } 1523 } 1524 1525 1526 // Size iframe to match lightbox image sizing behavior 1527 // Use responsive aspect ratio (16:9 default for most platforms) 1528 const aspectRatio = 16 / 9; 1529 const maxWidth = window.innerWidth * 0.9; 1530 const maxHeight = window.innerHeight * 0.9; 1531 let width = Math.min(maxWidth, 1080); 1532 let height = width / aspectRatio; 1533 1534 if (height > maxHeight) { 1535 height = maxHeight; 1536 width = height * aspectRatio; 1537 } 1538 1539 $videoContainer.css({ 1540 width: width + "px", 1541 height: height + "px", 1542 maxWidth: "100%", 1543 maxHeight: "90vh" 1544 }); 1545 1546 $videoContainer.append($videoElement); 1547 $container.append($videoContainer); 1548 }, 1549 1550 events: { 1551 bind: function() { 1552 self.bind('loadstart', function() { 1553 methods.video.cleanup(); 1554 }); 1555 self.bind('loadfinish', function(e) { 1556 var data = e.data || self.getData(self.getIndex()); 1557 // Check if this is a generic video (not TikTok) 1558 var isTikTok = (data.is_tiktok == 1 || data.is_tiktok == '1' || data.is_tiktok === true) 1559 || (data.tiktok_play_url || data.tiktok_share_url); 1560 var hasVideoLink = (data.is_video_link == 1 || data.is_video_link == '1' || data.is_video_link === true) 1561 || (data.video_link && data.video_link.length > 0); 1562 if (!isTikTok && hasVideoLink) { 1563 methods.video.handle_content(data); 1564 } 1565 }); 1566 } 1567 } 1568 } 1569 }; 1570 1571 $.nplModal('log', 'theme initialization - about to bind events'); 1572 1573 // Load our modules 1574 methods.galleria.events.bind(); 1575 methods.nplModal.events.bind(); 1576 methods.thumbnails.events.bind(); 1577 methods.info.events.bind(); 1578 methods.share_icons.events.bind(); 1579 methods.sidebar.events.bind(); 1580 methods.sidebars.datacache.events.bind(); 1581 methods.sidebars.comments.events.bind(); 1582 methods.tiktok.events.bind(); 1583 methods.video.events.bind(); 1584 1585 $.nplModal('log', 'theme initialization - done binding events'); 1586 1587 $.nplModal('log', 'theme initialization - about to trigger npl_ready'); 1588 $(self._target).trigger('npl_ready', {galleria_theme: self, methods: methods}); 1589 1590 $.nplModal('log', 'theme initialization - about to trigger npl_init'); 1591 self.trigger('npl_init'); 1592 1593 $.nplModal('log', 'theme initialization - about to trigger npl_init_keys'); 1594 self.trigger('npl_init_keys'); 1595 1596 $.nplModal('log', 'theme initialization - about to trigger npl_init_complete'); 1597 self.trigger('npl_init_complete'); 1598 } 1599 }); 1600 }; 1601 1602 // In case this theme is enqueued before Galleria.js is loaded we 1603 // will periodically check if Galleria exists before calling 1604 // Galleria.addTheme() 1605 var interval = setInterval(function() { 1606 if (typeof window.Galleria !== 'undefined') { 1607 clearInterval(interval); 1608 add_nggpl_theme(); 1609 } 1610 }, 10); 1611 1612}(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.