1/** 2 * Themify Scroll to element based on its class and highlight it when a menu item is clicked. 3 * Copyright (c) Themify 4 */ 5;(function( $, window, document ) { 6 7 'use strict'; 8 9 if ( ! String.prototype.trim ) { 10 String.prototype.trim = function () { 11 return this.replace( /^\s+|\s+$/g, '' ); 12 }; 13 } 14 15 var pluginName = 'themifyScrollHighlight', 16 defaults = { 17 speed: 900, 18 prefix: '.tb_section-', 19 navigation: '#main-nav', 20 context: 'body', 21 element: '.themify_builder_row', 22 scrollRate: 250, 23 considerHeader: false 24 }; 25 26 function Plugin( element, options ) { 27 this.element = element; 28 this.options = $.extend( {}, defaults, options ); 29 this._defaults = defaults; 30 this.init(); 31 } 32 33 Plugin.prototype = { 34 35 getOffset: function(){ 36 var $wpAdminBar = $('#wpadminbar'), $headerWrap = $('#headerwrap'), 37 scrollOffset = 10; 38 if ( this.options.considerHeader && $headerWrap.length > 0 && $('body').hasClass('has-fixed-header') ) { 39 scrollOffset = $headerWrap.outerHeight(); 40 } 41 if ( $wpAdminBar.length > 0 ) { 42 scrollOffset += $wpAdminBar.outerHeight(); 43 } 44 return scrollOffset; 45 }, 46 47 highlightLink: function( hash ){ 48 this.dehighlightLinks(); 49 if ( '' != hash ) { 50 var $linkHash = $(this.options.navigation).find( 'a[href*=' + hash + ']' ); 51 if ( $linkHash.length > 0 ) { 52 $linkHash.each(function(){ 53 var $link = $(this); 54 if ( $link.prop('hash') == hash ) { 55 $link.parent().addClass( 'current_page_item' ); 56 /** 57 * Fires event scrollhighlight.themify 58 * Receives anchor with hash 59 */ 60 $('body').trigger( 'scrollhighlight.themify', [ hash ] ); 61 return; 62 } 63 }); 64 } 65 } 66 }, 67 68 dehighlightLinks: function() { 69 $(this.options.navigation).find( 'a[href*=#]' ).each(function(){ 70 $(this).parent().removeClass( 'current_page_item' ).removeClass( 'current-menu-item' ); 71 }); 72 }, 73 74 isInViewport: function ( obj ) { 75 var $t = $(obj), 76 $window = $(window), 77 windowHeight = $window.height(), 78 windowTop = $window.scrollTop(), 79 // Divided by X to tell it's visible when the section is half way into viewport 80 windowBottom = windowTop + (windowHeight/4), 81 eleTop = $t.offset().top, 82 eleBottom = eleTop + $t.height(); 83 return ((eleTop <= windowBottom) && (eleBottom >= windowTop)); 84 }, 85 86 isHash: function( hash ) { 87 return hash && '' != hash && '#' != hash; 88 }, 89 90 removeHash: function() { 91 var windowLocation = window.location; 92 if ( this.isCorrectHash() && this.isHash( windowLocation.hash ) ) { 93 if ( 'replaceState' in history ) { 94 history.replaceState( '', document.title, windowLocation.pathname + windowLocation.search ); 95 } 96 } 97 }, 98 99 changeHash: function ( href ) { 100 if ( 'replaceState' in history ) { 101 history.replaceState( null, null, href ); 102 } else { 103 var section = href.replace(/^.*#/, ''); 104 if ( section && '' != section ) { 105 var $elem = $('.tb_section-' + section); 106 if ( $elem.length > 0 ) { 107 var realID = $elem.attr('id'); 108 $elem.attr('id', realID + 'tmpobjxyz5783a'); 109 window.location.hash = section; 110 $elem.attr('id', realID); 111 } 112 } 113 } 114 }, 115 116 isCorrectHash: function() { 117 var hash = location.hash.slice(1); 118 // Compatiblity with Ecwid Plugin 119 return ! ! (hash != '' && hash.indexOf('!') === - 1); 120 }, 121 122 linkScroll: function( obj, href ) { 123 var self = this; 124 // Set offset from top 125 var to = $( obj ).offset().top - this.getOffset(); 126 // Animate scroll 127 $('html,body').stop().animate({ 128 scrollTop: to 129 }, this.options.speed, function() { 130 // Highlight link 131 self.highlightLink( obj.replace( self.options.prefix, '#' ) ); 132 133 if ( href != window.location.hash ) { 134 // Change URL hash 135 self.changeHash( href ); 136 } 137 138 // Set scrolling state 139 self.scrolling = false; 140 }); 141 }, 142 143 manualScroll: function( elementsToCheck ) { 144 if ( elementsToCheck.length > 0 ) { 145 if ( $(window).scrollTop() < 50 ) { 146 this.dehighlightLinks(); 147 this.removeHash(); 148 } else { 149 var self = this, 150 didHighlight = false, 151 href = ''; 152 $.each(elementsToCheck, function( i, val ){ 153 if ( self.isInViewport( val ) ) { 154 var elemsFirstPass = val.split('.tb_section-'); 155 if ( elemsFirstPass[1] ) { 156 var elemsSndPass = elemsFirstPass[1].split('.' ); 157 158 href = ''; 159 if ( elemsSndPass.length > 1 && elemsSndPass[0] ) { 160 href = '#' + elemsSndPass[0]; 161 } else { 162 href = '#' + elemsSndPass; 163 } 164 165 // Set highlight state 166 didHighlight = true; 167
168 if ( '' != href ) { 169 return; 170 } 171 } 172 } 173 }); 174 if ( '#' != href && href != window.location.hash ) { 175 // Highlight link 176 self.highlightLink( href ); 177 178 // Change URL hash 179 self.changeHash( href ); 180 } 181 if ( ! didHighlight ) { 182 self.dehighlightLinks(); 183 } 184 } 185 } 186 }, 187 188 scrolling: false, 189 190 init: function () { 191 var self = this; 192 193 // Smooth Scroll and Link Highlight 194 $( this.options.context ).find( 'a[href*=#]' ).not( 'a[href=#]' ).on( 'click', function (e) { 195 // Build class to scroll to 196 var href = $(this).prop('hash'), 197 classToScroll = href.replace(/#/, self.options.prefix); 198 199 // If the section exists in this page 200 if ( 1 == $(classToScroll).length ) { 201 // Set state 202 self.scrolling = true; 203 // Perform scroll 204 self.linkScroll( classToScroll, href ); 205 // Avoid link behaviour 206 e.preventDefault(); 207 } 208 }); 209 $('#wpadminbar').find('a').off('click'); 210 211 212 // Highlight Link when scroll over element 213 var elementsToCheck = []; 214 // Build list of elements to check visibility 215 $('div[class*=' + self.options.prefix.replace('.', '') + ']').not(self.options.exclude).each(function(){ 216 elementsToCheck.push( '.' + $(this).attr('class').trim().replace(/ /g, '.') ); 217 }); 218 219 // Setup scroll event 220 var didScroll = false; 221 $(window).scroll(function() { 222 didScroll = true; 223 }); 224 setInterval(function() { 225 if ( didScroll && ! self.scrolling ) { 226 didScroll = false; 227 self.manualScroll( elementsToCheck ); 228 } 229 }, self.options.scrollRate); 230 231 // Initial section visibility check and link highlight 232 $(window).load(function(){ 233 if ( self.isHash( window.location.hash ) ) { 234 // If there's a hash, scroll to it 235 var hash = window.location.hash, 236 $linkHash = $( self.options.context ).find( 'a[href*=' + hash + ']' ); 237 if ( $linkHash.length > 0 ) { 238 $linkHash.each(function(){ 239 var $link = $(this); 240 if ( $link.prop('hash') == hash ) { 241 $link.trigger( 'click' ); 242 return; 243 } 244 }); 245 } else { 246 self.manualScroll( elementsToCheck ); 247 } 248 } else { 249 self.manualScroll( elementsToCheck ); 250 } 251 }); 252 } 253 }; 254 255 $.fn[pluginName] = function ( options ) { 256 return this.each( function () { 257 if ( ! $.data( this, 'plugin_' + pluginName ) ) { 258 $.data( this, 'plugin_' + pluginName, new Plugin( this, options ) ); 259 } 260 }); 261 }; 262 263})( jQuery, window, document );
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.