1/** 2 * Frontend controller. 3 * 4 * This file is entitled to manage all the interactions in the frontend. 5 * 6 * --- 7 * 8 * The Happy Framework: WordPress Development Framework 9 * Copyright 2014, Andrea Gandino & Simone Maranzana 10 * 11 * Licensed under The MIT License 12 * Redistribuitions of files must retain the above copyright notice. 13 * 14 * @package Assets\Frontend\JS 15 * @author The Happy Bit <[email protected]> 16 * @copyright Copyright 2014, Andrea Gandino & Simone Maranzana 17 * @link http:// 18 * @since The Happy Framework v 2.0 19 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) 20 */ 21 22/** 23 * Video shortcodes 24 * ----------------------------------------------------------------------------- 25 */ 26 window.thb_loaded_videos = 0; 27 28(function($) { 29 "use strict"; 30 31 window.thb_video_holder = function( holder ) { 32 var context = holder.parent(), 33 context_height = context.outerHeight(), 34 context_width = context.outerWidth(), 35 ratio_x = holder.data( "ratio-x" ) !== undefined ? holder.data( "ratio-x" ) : 16, 36 ratio_y = holder.data( "ratio-y" ) !== undefined ? holder.data( "ratio-y" ) : 9, 37 y_alignment = holder.data( "y-alignment" ) !== undefined ? holder.data( "y-alignment" ) : "middle", 38 projected_width = 0, 39 projected_height = 0; 40 41 if ( context_height < ( context_width * ratio_y / ratio_x ) ) { 42 projected_height = context_width * ratio_y / ratio_x; 43 44 holder.css( "width", context_width ); 45 holder.css( "height", projected_height ); 46 holder.css( "margin-left", 0 ); 47 holder.css( "margin-top", 0 ); 48 49 if ( y_alignment == "middle" ) { 50 holder.css( "margin-top", ( context_height - projected_height ) / 2 ); 51 } 52 } 53 else { 54 projected_width = context_height * ratio_x / ratio_y; 55 56 holder.css( "width", projected_width ); 57 holder.css( "height", context_height ); 58 holder.css( "margin-top", 0 ); 59 holder.css( "margin-left", ( context_width - projected_width ) / 2 ); 60 } 61 }; 62 63 window.thb_video_holders = function( context, holder_selector ) { 64 if ( holder_selector === undefined ) { 65 holder_selector = '.thb-video-holder[data-fill="1"]'; 66 } 67 68 $( holder_selector, context ).each(function(){ 69 thb_video_holder( $( this ) ); 70 }); 71 72 $(window).on( "resize.thb_video_holders", function() { 73 $( holder_selector, context ).each(function(){ 74 thb_video_holder( $( this ) ); 75 }); 76 }.debounce(200) ); 77 }; 78 79 window.thb_video_holders_off = function( context, holder_selector ) { 80 if ( holder_selector === undefined ) { 81 holder_selector = '.thb-video-holder[data-fill="1"]'; 82 } 83 84 $( window ).off( ".thb_video_holders" ); 85 86 $( holder_selector, context ).each(function(){ 87 $( this ).removeAttr( "style" ); 88 }); 89 }; 90 91 window.THB_Video = function( id, obj, type ) { 92 var self = this; 93 94 this.id = id; 95 this.obj = obj; 96 this.type = type; 97 98 /** 99 * State 100 */ 101 this.state = function( code ) { 102 var state = ""; 103 104 switch( code ) { 105 case 0: 106 state = "finished"; 107 break; 108 case 1: 109 state = "playing"; 110 break; 111 default: 112 state = "paused"; 113 break; 114 } 115 116 return state; 117 }; 118 119 /** 120 * Videos loaded callback 121 */ 122 this.callbackCheck = function() { 123 window.thb_loaded_videos++; 124 125 this.obj.addClass("thb-video-loaded"); 126 self.obj.trigger( "thb-video-loaded" ); 127 128 if ( window.thb_loaded_videos === window.thb_total_videos ) { 129 $(window).trigger("thb-loaded-videos"); 130 } 131 }; 132 133 /** 134 * Init 135 */ 136 this.init = function() { 137 var self = this; 138 139 switch( this.type ) { 140 case "youtube": 141 this.api = new YT.Player("youtube-" + this.id, { 142 events: { 143 onStateChange: function(state) { 144 self.obj.trigger( "change", [ self.state(state.data) ] ); 145 }, 146 onReady: function() { 147 self.callbackCheck(); 148 } 149 } 150 }); 151 152 this.play = function() { this.api.playVideo(); }; 153 this.pause = function() { this.api.pauseVideo(); }; 154 this.stop = function() { this.api.stopVideo(); }; 155 this.isMuted = function() { return this.api.isMuted(); }; 156 this.mute = function() { this.api.mute(); }; 157 this.unMute = function() { this.api.unMute(); }; 158 this.toggleVolume = function() { 159 if ( this.isMuted() ) { 160 this.unMute(); 161 } 162 else { 163 this.mute(); 164 } 165 }; 166 167 break; 168 case "vimeo": 169 this.api = new Froogaloop(this.obj.get(0)); 170 171 this.api.addEvent("ready", function(player_id) { 172 self.api.addEvent("play", function() { 173 self.obj.trigger("change", [self.state(1)]); 174 }); 175 self.api.addEvent("pause", function() { 176 self.obj.trigger("change", [self.state(2)]); 177 }); 178 self.api.addEvent("finish", function() { 179 self.obj.trigger("change", [self.state(0)]); 180 }); 181 182 self.callbackCheck(); 183 }); 184 185 this.play = function() { this.api.api("play"); }; 186 this.pause = function() { this.api.api("pause"); }; 187 this.stop = function() { this.api.api("pause"); }; 188 this.isMuted = function() { 189 var muted = false;
190 191 this.api.api( "getVolume", function( vol ) { 192 if ( vol == 0 ) { 193 muted = true; 194 } 195 } ); 196 197 return muted; 198 }; 199 this.mute = function() { self.api.api( "setVolume", 0 ); }; 200 this.unMute = function() { self.api.api( "setVolume", 1 ); }; 201 this.toggleVolume = function() { 202 var self = this; 203 204 this.api.api( "getVolume", function( vol ) { 205 if ( vol == 0 ) { 206 self.unMute(); 207 } 208 else { 209 self.mute(); 210 } 211 } ); 212 }; 213 214 break; 215 default: 216 this.api = this.obj.get(0); 217 218 this.api.addEventListener("loadedmetadata", function() { 219 self.obj.data('width', self.obj.get(0).videoWidth); 220 self.obj.data('height', self.obj.get(0).videoHeight); 221 222 if( self.obj.attr("autoplay") ) { 223 self.play(); 224 } 225 226 self.callbackCheck(); 227 }, false); 228 this.api.addEventListener("play", function() { 229 self.obj.trigger("change", [self.state(1)]); 230 }, false); 231 this.api.addEventListener("pause", function() { 232 self.obj.trigger("change", [self.state(2)]); 233 }, false); 234 this.api.addEventListener("ended", function() { 235 self.obj.trigger("change", [self.state(0)]); 236 }, false); 237 238 this.play = function() { this.api.play(); }; 239 this.pause = function() { this.api.pause(); }; 240 this.stop = function() { this.api.pause(); }; 241 this.isMuted = function() { return self.obj.get( 0 ).muted; }; 242 this.mute = function() { self.obj.get( 0 ).muted = true; }; 243 this.unMute = function() { self.obj.get( 0 ).muted = false; }; 244 this.toggleVolume = function() { 245 self.obj.get( 0 ).muted = ! self.obj.get( 0 ).muted; 246 }; 247 248 break; 249 } 250 }; 251 252 /** 253 * Change 254 */ 255 this.change = function(state) {}; 256 257 this.init(); 258 }; 259 260 window.thb_total_videos = 0; 261 window.thb_video_ids = 0; 262 window.thb_youtube_ready = false; 263 264 $(document).ready(function() { 265 window.thb_total_videos = $("iframe.thb-video-api, video.wp-video-shortcode").length; 266 267 if ( window.thb_total_videos == 0 ) { 268 $( window ).trigger( "thb-loaded-videos" ); 269 } 270 271 $("iframe[src^='//player.vimeo'].thb-video-api").each(function() { 272 // window.thb_boot_iframe_video( $( this ) ); 273 $(this).data( "player", new THB_Video( window.thb_video_ids++, $(this), 'vimeo' ) ); 274 }); 275 276 $("iframe.thb-video-api").each(function() { 277 // window.thb_boot_iframe_video( $( this ) ); 278 $(this).data( "player", new THB_Video( window.thb_video_ids++, $(this), 'vimeo' ) ); 279 }); 280 281 if( $("iframe[src*='youtu'].thb-video-api").length ) { 282 window.thb_load_youtube(); 283 } 284 285 $("video.wp-video-shortcode").each(function() { 286 $(this).data( "player", new THB_Video( window.thb_video_ids++, $(this), 'selfhosted' ) ); 287 }); 288 }); 289 290 window.thb_load_youtube = function() { 291 var tag = document.createElement("script"); 292 tag.src = "//www.youtube.com/iframe_api"; 293 var firstScriptTag = document.getElementsByTagName('script')[0]; 294 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 295 }; 296 297 window.thb_boot_iframe_video = function( iframe ) { 298 var src = iframe.attr( "src" ); 299 300 if ( ! src ) { 301 return; 302 } 303 304 if ( src.indexOf( "youtu" ) > -1 ) { 305 if ( window.thb_youtube_ready ) { 306 var id = window.thb_video_ids++; 307 iframe.attr( "id", "youtube-" + id ); 308 iframe.data( "player", new THB_Video( id, iframe, 'youtube' ) ); 309 } 310 else { 311 $( window ).on( "thb-youtube-ready", function() { 312 var id = window.thb_video_ids++; 313 iframe.attr( "id", "youtube-" + id ); 314 iframe.data( "player", new THB_Video( id, iframe, 'youtube' ) ); 315 } ); 316 317 window.thb_load_youtube(); 318 } 319 } 320 else if ( src.indexOf( "//player.vimeo" ) > -1 ) { 321 iframe.data( "player", new THB_Video( window.thb_video_ids++, iframe, 'vimeo' ) ); 322 } 323 }; 324 325 window.onYouTubeIframeAPIReady = function() { 326 window.thb_youtube_ready = true; 327 $( window ).trigger( "thb-youtube-ready" ); 328 329 $("iframe[src*='youtu'].thb-video-api").each(function() { 330 // window.thb_boot_iframe_video( $( this ) ); 331 var id = window.thb_video_ids++; 332 333 $(this).attr( "id", "youtube-" + id ); 334 $(this).data( "player", new THB_Video( id, $(this), 'youtube' ) ); 335 }); 336 }; 337})(jQuery); 338 339/** 340 * Translations 341 * ----------------------------------------------------------------------------- 342 */ 343(function($) { 344 "use strict"; 345 346 $.thb.translate = function( key ) { 347 if( $.thb.translations[key] ) { 348 return $.thb.translations[key]; 349 } 350 351 return key; 352 }; 353})(jQuery); 354 355/** 356 * Remove empty paragraphs 357 * ----------------------------------------------------------------------------- 358 */ 359(function($) { 360 "use strict"; 361 362 $( document ).ready( function() { 363 $('p') 364 .filter(function() { 365 return $.trim($(this).html()) === ''; 366 }) 367 .remove(); 368 } ); 369})(jQuery); 370 371/** 372 * **************************************************************************** 373 * THB menu 374 * 375 * $("#menu-container").menu(); 376 * **************************************************************************** 377 */ 378(function($) { 379 "use strict"; 380 381 $.fn.menu = function(params) { 382 383 // Parameters 384 // -------------------------------------------------------------------- 385 var settings = { 386 animate: true, 387 speed: 350, 388 display: 'block', 389 easing: 'linear', 390 openClass: 'current-menu-item', 391 megaMenu: { 392 fixed: true, 393 sentinel: null 394 }, 395 availableRightSpaceClass: 'available-space-right', 396 availableLeftSpaceClass: 'available-space-left', 397 'showCallback': function() {}, 398 'hideCallback': function() {} 399 }; 400 401 // Parameters 402 $.extend(settings, params); 403 404 // Menu instance 405 // -------------------------------------------------------------------- 406 var instance = { 407 el: null, 408 409 destroy: function() { 410 $( instance.el ).find( "*" ).off( ".thb_menu" ); 411 $( instance.el ).find( "ul.sub-menu" ).removeAttr( "style" ); 412 $( window ).off( ".thb_menu" ); 413 }, 414 415 init: function( subMenu, item, root ) { 416 instance.el = root; 417 418 item.removeClass( settings.availableRightSpaceClass ); 419 item.removeClass( settings.availableLeftSpaceClass ); 420 421 var itemOffset = item.offset().left; 422 423 if ( item.parent().hasClass( "sub-menu" ) ) { 424 itemOffset += item.outerWidth(); 425 } 426 427 var subMenuWidth = subMenu.outerWidth(), 428 availableRightSpace = $( window ).width() - itemOffset, 429 availableLeftSpace = itemOffset; 430 431 if ( availableRightSpace > subMenuWidth ) { 432 item.addClass( settings.availableRightSpaceClass ); 433 } 434 435 if ( availableLeftSpace > subMenuWidth ) { 436 item.addClass( settings.availableLeftSpaceClass ); 437 } 438 }, 439 440 showMegaSubMenu: function( subMenu, item ) { 441 if ( settings.megaMenu && settings.megaMenu.fixed ) { 442 subMenu 443 .css({ 444 'top': item.offset().top + item.outerHeight() 445 }); 446 } 447 448 this.showSubMenu( subMenu, item ); 449 }, 450 451 showSubMenu: function( subMenu, item ) { 452 item.addClass( settings.openClass ); 453 454 instance.init( subMenu, item, instance.el ); 455 456 var css_start = { 457 opacity: 0, 458 display: settings.display 459 }, 460 css_end = { 461 opacity: 1 462 }; 463 464 if ( settings.animate ) { 465 subMenu 466 .stop(true, true) 467 .css( css_start ) 468 .animate( css_end, settings.speed, settings.easing, function() { 469 settings.showCallback(); 470 }); 471 } 472 else { 473 subMenu.css( "display", settings.display ); 474 settings.showCallback(); 475 } 476 }, 477 478 hideSubMenu: function( subMenu, item ) { 479 item.removeClass( settings.openClass ); 480 481 var css_end = { 482 opacity: 0 483 }; 484 485 if ( settings.animate ) { 486 subMenu 487 .stop(true, true) 488 .animate( css_end, settings.speed / 2, settings.easing, function() { 489 $(this).hide(); 490 settings.hideCallback(); 491 } ); 492 } 493 else { 494 subMenu.hide(); 495 settings.hideCallback(); 496 } 497 } 498 }; 499 500 return this.each(function() { 501 var self = this, 502 menuContainer = $(this), 503 menu = menuContainer.find("> ul"), 504 menuItems = menu.find("> li"), 505 subMenuItems = menuItems.find('li').andSelf(); 506 507 $( this ).data( "thb-menu", instance ); 508 509 menuItems.each(function() { 510 if ( $( this ).parents( '.thb-is-mega' ).length ) { 511 return; 512 } 513 514 if ( settings.megaMenu && settings.megaMenu.fixed && $( this ).hasClass( "thb-is-mega" ) ) { 515 $( this ).addClass( 'thb-megamenu-fixed' ); 516 } 517 518 $(this).find('> a').addClass('needsclick'); 519 520 var subMenu = $(this).find('> ul'); 521 522 if( subMenu.length ) { 523 subMenu.css({ 524 display: 'none' 525 }); 526 } 527 }); 528 529 // Binding events 530 subMenuItems.each(function() { 531 var item = $(this), 532 subMenu = item.find("> ul"); 533 534 if ( item.parents( '.thb-is-mega' ).length ) { 535 return; 536 } 537 538 if( subMenu.length ) { 539 item 540 .find('> a') 541 .addClass('w-sub needsclick'); 542 543 instance.init( subMenu, item, self ); 544 545 item 546 .on( "mouseenter.thb_menu", function() { 547 if ( item.hasClass( "thb-is-mega" ) ) { 548 instance.showMegaSubMenu( subMenu, $(this) ); 549 } 550 else { 551 instance.showSubMenu( subMenu, $(this) ); 552 } 553 }) 554 .on( "mouseleave.thb_menu", function() { 555 instance.hideSubMenu( subMenu, $(this) ); 556 }); 557 558 $( window ).on( "resize.thb_menu", function() { 559 instance.init( subMenu, item, self ); 560 } ); 561 } 562 }); 563 }); 564 565 }; 566 567})(jQuery); 568 569/** 570 * Scroll in page. 571 */ 572;( function( $ ) { 573 window.thb_scroll_in_page = function( smoothScrollSelectors, scrollOptions, offset, preScrollCallback ) { 574 if ( offset === undefined ) { 575 offset = 0; 576 } 577 578 scrollOptions = $.extend( { 579 speed: 350, 580 easing: "easeInOutCubic" 581 }, scrollOptions ); 582 583 $( document ).on( "click", smoothScrollSelectors, function() { 584 var href = $( this ).attr( "href" ), 585 target = $( this ).attr( "target" ); 586 587 if ( href.indexOf( "#" ) > -1 ) { 588 var url = href.split("#"), 589 current_url = window.location.href.split("#"), 590 is_same_page = url[0] == "" || ( url[0] != "" && url[0] == current_url[0] ), 591 href = "#" + url[1]; 592 593 if ( is_same_page ) { 594 if ( ! $( href ).length ) { 595 return false;
596 } 597 598 if ( preScrollCallback !== undefined ) { 599 preScrollCallback(); 600 } 601 602 $.scrollTo( $( href ), scrollOptions.speed, { 603 easing: scrollOptions.easing, 604 offset: ( offset ) * -1 605 } ); 606 607 return false; 608 } 609 else { 610 return true; 611 } 612 } 613 } ); 614 } 615} )( jQuery ); 616 617/** 618 * Fullscreen. 619 */ 620;( function( $ ) { 621 window.thb_fullscreen_check = function() { 622 return document.documentElement.requestFullscreen || document.documentElement.mozRequestFullScreen || document.documentElement.webkitRequestFullScreen || document.documentElement.msRequestFullscreen; 623 }; 624 625 window.thb_is_fullscreen = function() { 626 return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement; 627 }; 628 629 window.thb_exit_fullscreen = function() { 630 if ( document.exitFullscreen ) { 631 document.exitFullscreen(); 632 } 633 else if ( document.msExitFullscreen ) { 634 document.msExitFullscreen(); 635 } 636 else if ( document.mozCancelFullScreen ) { 637 document.mozCancelFullScreen(); 638 } 639 else if ( document.webkitExitFullscreen ) { 640 document.webkitExitFullscreen(); 641 } 642 }; 643 644 window.thb_go_fullscreen = function( elem ) { 645 elem = $( elem ).get( 0 ); 646 647 if ( elem.requestFullscreen ) { 648 elem.requestFullscreen(); 649 } 650 else if ( elem.msRequestFullscreen ) { 651 elem.msRequestFullscreen(); 652 } 653 else if ( elem.mozRequestFullScreen ) { 654 elem.mozRequestFullScreen(); 655 } 656 else if ( elem.webkitRequestFullscreen ) { 657 elem.webkitRequestFullscreen(); 658 } 659 }; 660 661 window.thb_fullscreen_transition = function( on ) { 662 if ( on ) { 663 $( "html" ).addClass( "thb-full-screen" ); 664 } 665 else { 666 $( "html" ).removeClass( "thb-full-screen" ); 667 } 668 }; 669 670 document.addEventListener( "fullscreenchange", function () { 671 thb_fullscreen_transition( document.fullscreen ); 672 }, false ); 673 674 document.addEventListener( "mozfullscreenchange", function () { 675 thb_fullscreen_transition( document.mozFullScreen ); 676 }, false ); 677 678 document.addEventListener( "webkitfullscreenchange", function () { 679 thb_fullscreen_transition( document.webkitIsFullScreen ); 680 }, false ); 681 682 document.addEventListener( "msfullscreenchange", function () { 683 thb_fullscreen_transition( document.msFullscreenElement ); 684 }, false ); 685} )( jQuery ); 686 687/** 688 * Parallax. 689 */ 690;( function( $ ) { 691 var $window = $( window ), 692 windowHeight = $window.height(); 693 694 var THB_Parallax = function( $el, options ) { 695 var parallax = this; 696 697 options = $.extend( {}, { 698 speed: 0.6, 699 xpos: "50%" 700 }, options ); 701 702 this.update = function() { 703 var offset = $el.offset().top, 704 pos = $window.scrollTop(), 705 height = $el.outerHeight(); 706 707 if ( offset + height < pos || offset > pos + windowHeight ) { 708 return; 709 } 710 711 $el.css( "backgroundPosition", options.xpos + " " + Math.round( ( offset - pos ) * options.speed ) + "px" ); 712 }; 713 714 $window.on( "scroll", this.update ); 715 $window.on( "resize", function() { 716 windowHeight = $window.height(); 717 parallax.update(); 718 } ); 719 720 this.update(); 721 }; 722 723 $.fn.thbParallax = function( options ) { 724 return this.each( function() { 725 if ( ! $( this ).data( "thbParallax" ) ) { 726 $( this ).data( "thbParallax", new THB_Parallax( $( this ), options ) ); 727 } 728 } ); 729 }; 730} )( jQuery ); 731 732/** 733 * Scroll to include. 734 */ 735;( function( $ ) { 736 $.scrollToInclude = function( element, options ) { 737 element = $( element ); 738 739 options = $.extend( { 740 speed: 350, 741 easing: "easeInOutCubic", 742 offset: 0 743 }, options ); 744 745 var element_height = element.outerHeight(), 746 element_offset = element.position().top, 747 endOfScroll = parseInt( element_offset + element_height + options.offset, 10 ); 748 749 $.scrollTo( endOfScroll, options.speed, { 750 easing: options.easing, 751 offset: ( options.offset ) * -1 752 } ); 753 }; 754} )( jQuery ); 755 756/** 757 * Frontend conditional controller. 758 */ 759;( function( $ ) { 760 if( ! $.thb ) { 761 $.thb = {}; 762 } 763 764 $.thb.wp = { 765 is_body_class: function( classname ) { 766 return $( "body" ).hasClass( classname ); 767 }, 768 is_post_type: function( post_type ) { 769 return $( "body" ).hasClass( "single-" + post_type ); 770 }, 771 is_single_post: function() { 772 return $.thb.wp.is_post_type( "post" ); 773 }, 774 is_page: function( arg ) { 775 if ( $( "body" ).hasClass( "page" ) ) { 776 if ( typeof arg === 'string' ) { 777 // Template 778 arg = arg.replace( /./g, '-' ); 779 return $( "body" ).hasClass( "page-template-" + arg ); 780 } 781 else if ( typeof arg === 'number' ) { 782 // Page ID 783 return $( "body" ).hasClass( "page-id-" + arg ); 784 } 785 } 786 787 return false;
788 }, 789 is_mobile: function() { 790 return $( "body" ).hasClass( "thb-mobile" ); 791 }, 792 is_desktop: function() { 793 return $( "body" ).hasClass( "thb-desktop" ); 794 }, 795 is_larger_than: function( width ) { 796 return Math.max(document.documentElement.clientWidth, window.innerWidth || 0) >= width; 797 }, 798 is_smaller_than: function( width ) { 799 return Math.max(document.documentElement.clientWidth, window.innerWidth || 0) <= width; 800 }, 801 is_between: function( min, max ) { 802 var viewport = Math.max(document.documentElement.clientWidth, window.innerWidth || 0) 803 804 return viewport >= min && viewport <= max; 805 } 806 } 807} )( 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.