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