1/** 2 * Shortcode Anchor 3 * 4 * @package ThemeREX Addons 5 * @since v1.2 6 */ 7 8/* global jQuery, TRX_ADDONS_STORAGE */ 9 10// Init handlers 11jQuery(document).on('action.init_hidden_elements', function(e, container) { 12 13 "use strict"; 14 15 // Build toc menu 16 var toc_menu = jQuery('#toc_menu'); 17 if (toc_menu.length == 0) { 18 trx_addons_build_page_toc(); 19 toc_menu = jQuery('#toc_menu'); 20 if (toc_menu.length == 0) return; 21 } else if (toc_menu.hasClass('inited')) { 22 return; 23 } 24 toc_menu.addClass('inited'); 25 26 var toc_menu_items = toc_menu.find('.toc_menu_item'); 27 28 // One page mode for menu links (scroll to anchor) 29 // Old case: toc_menu.on('click', 'a', function(e) { 30 // New case (allow add class 'toc_menu_item' in any menu to enable scroll): 31 jQuery('.toc_menu_item > a').on('click', function(e) { 32 var link_obj = jQuery(this), 33 href = link_obj.attr('href'), 34 pos = href.indexOf('#'); 35 if (pos >= 0 && href.length > 1 && trx_addons_is_local_link(href)) { 36 e.preventDefault(); 37 trx_addons_scroll_to_anchor(jQuery(this), true); 38 return false; 39 } 40 }); 41 42 // Mouse wheel handler 43 var wheel_busy = false, 44 wheel_time = 0, 45 wheel_stop = false; 46 47 if ( TRX_ADDONS_STORAGE['scroll_to_anchor'] == 1 && !TRX_ADDONS_STORAGE['scroll_to_anchor_wheel'] ) { 48 TRX_ADDONS_STORAGE['scroll_to_anchor_wheel'] = true; 49 jQuery(document).on('action.stop_wheel_handlers', function(e) { 50 wheel_stop = true; 51 }); 52 jQuery(document).on('action.start_wheel_handlers', function(e) { 53 wheel_stop = false; 54 }); 55 56 // To smoothing scroll in the Chrome 56+ use native event with parameter 'passive=false' 57 // to enable calls e.preventDefault inside the event's handler 58 window.addEventListener('mousewheel', trx_addons_mouse_wheel, { passive: false } ); // WebKit: native event 59 //jQuery(window).on('mousewheel', trx_addons_mouse_wheel); // WebKit: jquery wrapper 60 61 // Mozilla Firefox already have a smooth scroll - use jQuery 62 //window.addEventListener('DOMMouseScroll', trx_addons_mouse_wheel, { passive: false } ); // Mozilla Firefox: native event 63 jQuery(window).on('DOMMouseScroll', trx_addons_mouse_wheel); // Mozilla Firefox: jquery wrapper 64 } 65 66 function trx_addons_mouse_wheel(e) { 67 if (screen.width < 960 || jQuery(window).width() < 960 || wheel_stop || trx_addons_browser_is_ios()) { 68 return true; 69 } 70 if (wheel_busy || wheel_time == e.timeStamp) { 71 e.preventDefault(); 72 return false; 73 } 74 wheel_time = e.timeStamp; 75 var wheel_dir = e.originalEvent 76 ? e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0 ? -1 : 1 77 : e.wheelDelta > 0 || e.detail < 0 ? -1 : 1; 78 79 toc_menu_items = jQuery('#toc_menu .toc_menu_item'); 80 var items = trx_addons_detect_active_toc(true); 81 if ( items ) { 82 var doit = false; 83 var scroll_offset = parseInt(jQuery(window).scrollTop(), 10); 84 var wh = jQuery(window).height(); 85 var ah = trx_addons_fixed_rows_height(); 86 if (wheel_dir == -1) { // scroll up 87 doit = true; 88 setTimeout( function() { 89 if (items.prev >= 0 && items.prevOffset >= scroll_offset-wh-ah) { 90 trx_addons_scroll_to_anchor( toc_menu_items.eq(items.prev).find('a'), false ); 91 } else { 92 trx_addons_document_animate_to( Math.max(0, scroll_offset-wh) ); 93 } 94 }, 10 ); 95 } else { // scroll down 96 doit = true; 97 setTimeout( function() { 98 if (items.next >= 0 && items.nextOffset <= scroll_offset+wh+ah) { 99 trx_addons_scroll_to_anchor( toc_menu_items.eq(items.next).find('a'), false ); 100 } else { 101 trx_addons_document_animate_to( Math.min( jQuery(document).height(), scroll_offset+wh ) ); 102 } 103 }, 10 ); 104 } 105 // Set busy flag while animating 106 if (doit) { 107 wheel_busy = true; 108 setTimeout( function() { wheel_busy = false; }, trx_addons_browser_is_ios() ? 1200 : 100 ); 109 e.preventDefault(); 110 return false; 111 } 112 } 113 } 114 115 // Detect active TOC item 116 var last_scroll_offset = -1; 117 118 function trx_addons_detect_active_toc( force ) { 119 var scroll_offset = parseInt(jQuery(window).scrollTop(), 10); 120 if ( !force && scroll_offset == last_scroll_offset ) { 121 return false; 122 } else { 123 last_scroll_offset = scroll_offset; 124 } 125 var items = { 126 loc: '', 127 current: [], 128 prev: -1, 129 prevOffset: -1, 130 next: -1, 131 nextOffset: -1 132 };
133 var fixed_rows_height = Math.ceil( trx_addons_fixed_rows_height() ); 134 135 toc_menu_items.each(function(idx) { 136 var id = '#'+jQuery(this).data('id'); 137 var pos = id.indexOf('#'); 138 if (pos < 0 || id.length == 1) return; 139 var href = jQuery(this).find('a').attr('href'); 140 if (!trx_addons_is_local_link(href) || jQuery(id).length==0) return; 141 var off = jQuery(id).offset().top; 142 var id_next = jQuery(this).next().find('a').attr('href'); 143 var off_next = id_next && idx < toc_menu_items.length-1 && jQuery(id_next).length > 0 144 ? parseInt(jQuery(id_next).offset().top, 10) 145 : 1000000; 146 if (off > scroll_offset + fixed_rows_height + 20) { 147 if (items.next < 0) { 148 items.next = idx; 149 items.nextOffset = off; 150 } 151 } else if (off < scroll_offset - fixed_rows_height - 20) { 152 items.prev = idx; 153 items.prevOffset = off; 154 } 155 if (off < scroll_offset + jQuery(window).height()*0.8 && scroll_offset < off_next - fixed_rows_height) { 156 items.current.push(idx); 157 if (items.loc == '') { 158 var loc = window.location.href; 159 var loc_pos = loc.indexOf('#'); 160 if (loc_pos > 0) loc = loc.substring(0, loc_pos); 161 items.loc = href.indexOf('#')==0 ? loc + id : id; 162 } 163 } 164 }); 165 return items; 166 } 167 168 // Change active element then page is scrolled 169 jQuery(window).on('scroll', function() { 170 // Mark current item 171 trx_addons_mark_active_toc(); 172 }); 173 setTimeout( function() { 174 trx_addons_mark_active_toc(); 175 }, 500); 176 trx_addons_mark_active_toc(); 177 178 // Mark active TOC item 179 function trx_addons_mark_active_toc() { 180 var items = trx_addons_detect_active_toc(); 181 if ( items ) { 182 toc_menu_items.removeClass('toc_menu_item_active'); 183 for (var i=0; i<items.current.length; i++) { 184 toc_menu_items.eq(items.current[i]).addClass('toc_menu_item_active'); 185 // Comment next line if on your device page jump when scrolling 186 if (items.loc !== '' && TRX_ADDONS_STORAGE['update_location_from_anchor']==1 && !trx_addons_browser_is_mobile() && !trx_addons_browser_is_ios() && !wheel_busy) { 187 trx_addons_document_set_location(items.loc); 188 } 189 } 190 jQuery(document).trigger('action.toc_menu_item_active', [items.current]); 191 } 192 } 193 194 // Scroll to the anchor 195 function trx_addons_scroll_to_anchor(link_obj, click_event) { 196 var href = click_event ? link_obj.attr('href') : '#'+link_obj.parent().data('id'); 197 var pos = href.indexOf('#'); 198 if (pos >= 0 && href.length > 1 && trx_addons_is_local_link(href)) { 199 wheel_busy = true; 200 setTimeout(function() { wheel_busy = false; }, trx_addons_browser_is_ios() ? 1200 : 100); 201 trx_addons_document_animate_to(href.substr(pos), function() { 202 if (TRX_ADDONS_STORAGE['update_location_from_anchor']==1) { 203 var loc = window.location.href; 204 var loc_pos = loc.indexOf('#'); 205 if (loc_pos > 0) loc = loc.substring(0, loc_pos); 206 trx_addons_document_set_location(pos==0 ? loc + href : href); 207 } 208 }); 209 return true; 210 } 211 return false; 212 } 213 214 215 // Build page TOC from the tag's id 216 function trx_addons_build_page_toc() { 217 218 var toc = '', toc_count = 0; 219 220 jQuery('[id^="toc_menu_"],.sc_anchor').each(function(idx) { 221 var obj = jQuery(this); 222 var obj_id = obj.attr('id') || ('sc_anchor_'+Math.random()).replace('.', ''); 223 var row = obj.closest('.wpb_row,.elementor-row,.elementor-section').eq(0); 224 if (row.length == 0) row = !obj.parent().hasClass('entry-content') ? obj.parent() : obj; 225 var row_id = row.length>0 && row.attr('id') !== undefined && row.attr('id') !== '' ? row.attr('id') : ''; 226 var id = row_id || obj_id.substr(10); 227 if (row.length>0 && row_id == '') { 228 row.attr('id', id); 229 } 230 var url = obj.data('url'); 231 var icon = obj.data('vc-icon') || 'toc_menu_icon_default'; 232 var title = obj.attr('title'); 233 var description = obj.data('description'); 234 var separator = obj.data('separator'); 235 toc_count++; 236 toc += '<div class="toc_menu_item'+(separator=='yes' ? ' toc_menu_separator' : '')+'" data-id="'+id+'">' 237 + (title || description 238 ? '<a href="' + (url ? url : '#'+id) + '" class="toc_menu_description">' 239 + (title ? '<span class="toc_menu_description_title">' + title + '</span>' : '') 240 + (description ? '<span class="toc_menu_description_text">' + description + '</span>' : '') 241 + '</a>' 242 : '') 243 + '<a href="' + (url ? url : '#'+id) + '" class="toc_menu_icon '+icon+'"></a>' 244 + '</div>'; 245 }); 246 247 if (toc_count > 0) { 248 jQuery('body').append('<div id="toc_menu" class="toc_menu"><div class="toc_menu_inner">'+toc+'</div></div>'); 249 } 250 } 251 252});
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.