PageSourceSearch

https://www.gavelife.org/editor/libraries/flyout_menus_jq_1357869174.js

js gavelife.org collected 2026-09-25 02:12:58 UTC 22,963 bytes, 802 lines download raw bytes

1/*
2 * Responsible for flyout menus within the editor + on a published page.
3 * Also responsible for condensing overflowing nav and making a "more..." link.
4 *
5
6 * Author: Adam Shaw
7 */
8
9(function($) {
10	
11
12	/****************************** publicly available functions ****************************/
13
14	var moreItemHTML;
15	var activeLiId;
16	var currentPageId;
17	var stylePrefix = window.STYLE_PREFIX || 'weebly';
18	var SLIDE_DURATION = 300;
19
20	// called from a published page
21	window.initPublishedFlyoutMenus = function(topLevelSummary, cpid, moreItemHTML, aLiId, isPreview) {
22		currentPageId = cpid;
23		if (topLevelSummary.length > 0) {
24			var go = function() {
25				activeLiId = aLiId;
26				var container = $("<div id='" + stylePrefix + "-menus' />").appendTo('body');
27				var firstItem = navElm(topLevelSummary[0].id);
28				if (firstItem) {
29					window.navFlyoutMenu = new FlyoutMenu(firstItem.parent(), {
30						relocate: container,
31						aLiId: aLiId
32					});
33					condenseNav(topLevelSummary, moreItemHTML);
34				}
35			}
36			if (isPreview) {
37				go(); // css has been written in html <style> tag, no need to check if loaded
38			}else{
39				whenThemeCSSLoaded(go);
40			}
41		}
42	};
43
44	// called from the editor
45	window.initEditorFlyoutMenus = function() {
46		whenThemeCSSLoaded(function() {
47			function go() {
48				var topLevelSummary = Weebly.PageManager.getTopLevelSummary();
49				if (topLevelSummary.length > 0) {
50					var listItem0 = navElm(topLevelSummary[0].id);
51					if (listItem0) {
52						var listElement = listItem0.parent();
53						if (!listElement.is('table,tbody,thead,tr')) {
54							window.navFlyoutMenu = new FlyoutMenu(listElement, {
55								relocate: '#' + stylePrefix + '-menus'
56							});
57
58							moreItemHTML = renderItem({ title: /*tl(*/'more...'/*)tl*/ }, false, currentNormalItem);
59							moreItemHTML =
60								"<span class='" + stylePrefix + "-nav-handle " + stylePrefix + "-nav-more'>" +
61								moreItemHTML +
62								"</span>";
63							condenseNav(topLevelSummary, moreItemHTML);
64						}else{
65							window.navFlyoutMenu = null;
66						}
67					}else{
68						window.navFlyoutMenu = null;
69					}
70				}else{
71					window.navFlyoutMenu = null;
72				}
73			}
74			if ($.browser.webkit) {
75				// this solves a webkit bug where the <span>s within the <ul> are displayed as block
76				// this problem has nothing to do with the flyout code, but this was the most convenient place to put it ~ashaw
77				var handles = $('#icontent span.' + stylePrefix + '-nav-handle');
78				handles.hide();
79				setTimeout(function() {
80					handles.show();
81					go();
82				},0);
83			}else{
84				go();
85			}
86		});
87	};
88
89	// called from the editor when nav positioning might have changed
90	window.refreshNavCondense = function(callback) {
91		if (window.navFlyoutMenu) {
92			//console.log('refresh');
93			condenseNav(Weebly.PageManager.getTopLevelSummary(), moreItemHTML);
94		}
95	};
96
97	window.disableFlyouts = false;
98
99
100
101	/*********************************** flyout menu class ************************************/
102
103	window.FlyoutMenu = function(mainList, options) {
104
105		mainList = $(mainList); // the element that contains all the nav elements
106		options = options || {};
107
108		// settings (an attempt at making FlyoutMenu portable)
109		var listTag = options.listTag ? options.listTag.toLowerCase() : 'ul';
110		var itemTag = options.itemTag ? options.itemTag.toLowerCase() : 'li';
111		var delay = (options.delay || 0.5) * 1000;
112
113		// if specified, all submenus will be detached from original place in DOM and put in here
114		var relocate = options.relocate ? $(options.relocate) : false;
115
116		// FYI
117		// a 'handle' is an element that contains the templatable HTML for each page's nav link
118		// a 'handle' may be a wrapping SPAN element (with className 'PREFIX-nav-handle')
119		//   OR it may be the item itself (such as an LI)
120
121		var allItems; // list of all nav items
122						// (the first child within a handle OR the handle itself)
123
124
125		//
126		// attach all event handlers and do state-keeping for flyout menus
127		//
128
129		function initItem(item) {
130
131			item.css('position', 'relative'); // this gives more accurate offsets
132			item.find('a').css('position', 'relative'); // more accurate offset (prevents IE bug)
133
134			// states
135			var isSliding = false;
136			var isExpanded = false;
137			var isMouseoverItem = false;
138			var mouseoverCnt = 0;
139
140			var slidVertically = false;
141			var slidRight = false;
142
143			var sublistWrapper; // a DIV.PREFIX-menu-wrap OR null
144			var sublist;        // a UL.PREFIX-menu OR null
145
146
147			//
148			// expand a sublist on mouseover
149			//
150
151			function itemMouseover() {
152				if (disableFlyouts) return false;
153				mouseoverCnt++;
154				isMouseoverItem = true;
155				if (!isExpanded && !isSliding) {
156					if (sublist) {
157						// when a sublist is expanded, immediately contract all siblings' sublists
158						getSiblings(item).each(function(i, siblingNode) {
159							if (siblingNode._flyoutmenu_contract) {
160								siblingNode._flyoutmenu_contract();
161							}
162						});
163						expandSublist();
164					}
165				}
166			}
167
168
169			//
170			// contract sublist on mouseout (after delay)
171			//
172
173			function itemMouseout() {
174				if (disableFlyouts) return false;
175				isMouseoverItem = false;
176				if (isExpanded) {
177					var mouseoverCnt0 = mouseoverCnt;
178					setTimeout(function() {
179						if (mouseoverCnt == mouseoverCnt0 && isExpanded && !isSliding) {
180							contractSublist();
181						}
182					}, delay);
183				}
184			}
185
186
187			//
188			// prevent contracting when sublist is moused over
189			//
190
191			function sublistWrapperMouseover() {
192				if (disableFlyouts) return false;
193				mouseoverCnt++;
194			}
195
196
197			//
198			// do item's sublist's expand animation
199			//
200
201			function expandSublist() {
202				isSliding = true;
203				var opts = {
204					wrapper: sublistWrapper,
205					duration: SLIDE_DURATION,
206					complete: function() { // when animation has finished
207						isSliding = false;
208						isExpanded = true;
209						if (!isMouseoverItem) {
210							// if mouse was not over when animation finished, immediately contract
211							contractSublist();
212						}else{
213							// attach methods for later hiding/contracting
214							item[0]._flyoutmenu_contract = contractSublist; // assign to DOM node
215							item[0]._flyoutmenu_hide = function() {         //
216								isSliding = false;
217								isExpanded = false;
218								isMouseoverItem = false;
219								item[0]._flyoutmenu_contract = null;
220								item[0]._flyoutmenu_hide = null;
221								sublistWrapper.hide();
222							};
223						}
224					}
225				};
226				var massCoords = getItemMassCoords(item);
227
228				// need to show it for IE8 to get the correct offsetParent
229				sublistWrapper.css('left', -10000);
230				sublistWrapper.show();
231
232				var localOriginElement = sublistWrapper.offsetParent();
233				var localOrigin = localOriginElement.is('body') ? {top:0,left:0} : localOriginElement.offset();
234					// ^ special case body. jQuery provides inaccurate offset for body. always 0,0
235
236				sublistWrapper.hide();
237				sublist.show(); // so calls to sublistWrapper.outerWidth() are correct
238
239				if (inVerticalList(item, true, options.aLiId)) {
240					// slide right/left on vertical nav
241					slidVertically = false;
242					sublistWrapper.css('top', -localOrigin.top + massCoords[0].top);
243					var w = sublistWrapper.outerWidth();
244					if (massCoords[1].left + w > $('body').outerWidth()) {
245						slidRight = false;
246						sublistWrapper.css('left', -localOrigin.left + massCoords[0].left - w);
247						opts.direction = 'right';
248						sublist.show('slide', opts);
249					}else{
250						slidRight = true;
251						sublistWrapper.css('left', -localOrigin.left + massCoords[1].left);
252						opts.direction = 'left';
253						sublist.show('slide', opts);
254					}
255				}else{
256					// slide down on horizontal nav
257					slidVertically = true;
258					sublistWrapper.css('top', -localOrigin.top + massCoords[1].top);
259					var w = sublistWrapper.outerWidth();
260					if (massCoords[0].left + w > $('body').outerWidth()) {
261						sublistWrapper.css('left', -localOrigin.left + massCoords[1].left - w);
262					}else{
263						sublistWrapper.css('left', -localOrigin.left + massCoords[0].left);
264					}
265					opts.direction = 'up';
266					sublist.show('slide', opts);
267				}
268			}
269
270
271			//
272			// do item's sublist's contract animation
273			//
274
275			function contractSublist(mouseoverHack) {
276				if (disableFlyouts || !item.parent().length) { // no parentNode?? removed from dom already? wtf!?
277					// contractSublist is often called from a delay, might have been disabled in that time
278					return;
279				}
280				if (mouseoverHack) {
281					// IE6 wasn't registering the mouseout
282					isMouseoverItem = false;
283				}
284				isSliding = true;
285				item[0]._flyoutmenu_contract = null;
286				item[0]._flyoutmenu_hide = null;
287				var opts = {
288					wrapper: sublistWrapper,
289					duration: SLIDE_DURATION,
290					complete: function() {
291						isSliding = false;
292						isExpanded = false;
293						if (isMouseoverItem) {
294							// if mouseleft, but re-entered before animation finished
295							// immediately expand sublist again
296							expandSublist();
297						}
298					}
299				}
300				if (slidVertically) {
301					opts.direction = 'up';
302					sublist.hide('slide', opts);
303				}else{
304					if (slidRight) {
305						opts.direction = 'left';
306						sublist.hide('slide', opts);
307					}else{
308						opts.direction = 'right';
309						sublist.hide('slide', opts);
310					}
311				}
312			}
313
314
315			//
316			// initialize submenu and attach events
317			//
318
319			sublist = getSublist(item, listTag);
320			if (sublist) {
321				sublistWrapper = sublist.parent();
322				sublistWrapper.css('position', 'absolute');
323				sublistWrapper.hide(); // should already be display:none, but just in case
324				if (relocate) {
325					// since sublist is no longer a descendant of the item, mouse events
326					// wont cascade. simulate this
327					sublistWrapper.on('mouseover', itemMouseover);
328					sublistWrapper.on('mouseout', itemMouseout);
329				}else{
330					// keep the submenu alive...
331					sublistWrapper.on('mouseover', sublistWrapperMouseover);
332				}
333			}
334			item.on('mouseover', itemMouseover);
335			item.on('mouseout', itemMouseout);
336
337
338			//
339			// attach a method for removing registered events
340			// (returns the sublist wrapper)
341			//
342
343			item[0]._flyoutmenu_destroy = function(removeSublist) { // attach to raw DOM node
344				item.off('mouseover', itemMouseover);
345				item.off('mouseout', itemMouseout);
346				if (removeSublist) {
347					if (sublistWrapper) {
348						return sublistWrapper.remove(); // detach before returning
349					}
350				}
351				else if (sublistWrapper) {
352					if (relocate) {
353						sublistWrapper.off('mouseover', itemMouseover);
354						sublistWrapper.off('mouseout', itemMouseout);
355					}else{
356						sublistWrapper.off('mouseover', sublistWrapperMouseover);
357					}
358					return sublistWrapper;
359				}
360			};
361
362		}
363
364
365		//
366		// methods for the FlyoutMenu object
367		//
368
369		// close all submenus with an animation
370		this.contract = function() {
371			allItems.each(function(i, itemNode) {
372				if (itemNode._flyoutmenu_contract) {
373					itemNode._flyoutmenu_contract(true);
374				}
375			});
376		};
377
378		// hide all submenus immediately
379		this.hideSubmenus = function() {
380			allItems.each(function(i, itemNode) {
381				if (itemNode._flyoutmenu_hide) {
382					itemNode._flyoutmenu_hide();
383				}
384			});
385		};
386
387		// detach all event handlers
388		this.destroy = function() {
389			allItems.each(function(i, itemNode) {
390				if (itemNode._flyoutmenu_destroy) {
391					itemNode._flyoutmenu_destroy();
392				}
393			});
394		};
395
396		// initialize a top level item that has already been placed into mainList
397		this.addItem = function(handle) { // todo: rename initTopLevelItem()
398			handle = $(handle);
399			var item = getRealTopLevelItem(handle);
400			if (item.length) {
401				initItem(item);
402				var sublist = getSublist(item, listTag);
403				if (sublist) {
404					sublist.find(itemTag).each(function(i, itemNode) { // init all subitems
405						initItem($(itemNode));
406					});
407				}
408				if (relocate && sublist) {
409					relocate.append(sublist.parent()); // relocate sublist's wrap
410				}
411				allItems = allItems.add(item);
412				writeOrderingClassNames();
413			}
414		};
415
416		// detach an item's event handlers and remove from DOM
417		this.removeItem = function(handle) { // todo: rename
418			handle = $(handle);
419			var item = getRealTopLevelItem(handle);
420			if (item.length) {
421				if (item[0]._flyoutmenu_destroy) {
422					item[0]._flyoutmenu_destroy(true);
423				}
424				item.remove();
425				allItems = allItems.not(item);
426				writeOrderingClassNames();
427			}
428		};
429
430		// accessor
431		this.getMainList = function() {
432			return mainList;
433		};
434
435
436		//
437		// initialize allItems and relocate
438		//
439		
440		function writeOrderingClassNames() {
441			var i = 1;
442			getTopLevelItems(mainList).each(function(i, itemNode) {
443				itemNode.className = itemNode.className.replace(/wsite-nav-\w+/, '');
444				var item = $(itemNode);
445				if (item.css('display') != 'none') {
446					item.addClass('wsite-nav-' + i);
447					i++;
448				}
449			});
450		}
451
452		allItems = getAllItems(mainList, itemTag);
453		allItems.each(function(i, itemNode) {
454			initItem($(itemNode));
455		});
456		writeOrderingClassNames();
457
458		if (relocate) {
459			getTopLevelItems(mainList).each(function(i, itemNode) {
460				var sublist = getSublist($(itemNode), listTag);
461				if (sublist) {
462					relocate.append(sublist.parent());
463				}
464			});
465		}
466
467	};
468
469
470
471
472
473	/****************************** more... link and menu *****************************/
474
475	function condenseNav(topLevelSummary, moreItemHTML) { // can be called repeatedly for updating
476		if (window.DISABLE_NAV_MORE) return;
477		//console.log('condenseNav');
478		var cpid = window.currentPage || currentPageId;
479		var mainList = navFlyoutMenu.getMainList();
480		var mainListChildren = mainList.children();
481		var moreHandle;
482		if (mainListChildren.length > 0) {
483			moreHandle = mainListChildren.eq(-1).filter('.' + stylePrefix + '-nav-more');
484			if (!moreHandle.length) {
485				moreHandle = undefined;
486			}
487		}
488		var alreadyMore = false;
489		if (moreHandle) {
490			moreHandle.hide();
491			alreadyMore = true;
492		}
493		var isVertical;
494		var handles = []; // holds all the handles up til the breaking element
495		var itemCoords = [];
496		var breakingHandle;
497		var breakingIndex;
498		var verticalContainer;
499		var verticalMaxY;
500		for (var i=0; i<topLevelSummary.length; i++) {
501			var handle = navElm(topLevelSummary[i].id);
502			handle.show();
503		}
504		for (var i=0; i<topLevelSummary.length; i++) {
505			var handle = navElm(topLevelSummary[i].id);
506			var item = getRealTopLevelItem(handle);
507			if (!item) continue;
508			var coords = getItemMassCoords(item);
509			if (i == 1) {
510				isVertical = Math.abs(coords[0].top - itemCoords[0][0].top) > Math.abs(coords[0].left - itemCoords[0][0].left);
511				if (isVertical) {
512					verticalContainer = item.closest('.wsite-nav-vertical');
513					if (verticalContainer.length) {
514						verticalMaxY = verticalContainer.offset().top + (parseInt(verticalContainer.css('padding-top')) || 0) + verticalContainer.height();
515					}
516				}
517			}
518			else if (!isVertical) {
519				if (i > 1 && Math.abs(coords[0].top - itemCoords[i-1][0].top) > 5) {
520					breakingHandle = handle;
521					breakingIndex = i;
522					break;
523				}
524			}
525			else { // is vertical
526				if (coords[1].top > verticalMaxY) {
527					breakingHandle = handle;
528					breakingIndex = i;
529					break;
530				}
531			}
532			handles.push(handle);
533			itemCoords.push(coords);
534		}
535		if (breakingHandle) {
536			if (moreHandle) {
537				moreHandle.show();
538			}else{
539				var temp = $("<div/>");
540				temp.html(moreItemHTML);
541				moreHandle = temp.children().first();
542				moreHandle.find('a').each(function(i, moreAnchorNode) {
543					$(moreAnchorNode)
544						.on('click', function() { return false })
545						.css('position', 'relative') // match what initItem does
546						.attr('id', stylePrefix + '-nav-more-a');
547				});
548				mainList.append(moreHandle);
549			}
550			var moreItem = getRealTopLevelItem(moreHandle);
551			moreItem.css('position', 'relative'); // match what initItem does
552			var hiddenItemIndices = [];
553			for (var i=breakingIndex; i<topLevelSummary.length; i++) {
554				navElm(topLevelSummary[i].id).hide();
555				hiddenItemIndices.push(i);
556			}
557			if (!isVertical) {
558				var firstItem = getRealTopLevelItem(navElm(topLevelSummary[0].id));
559				for (var i=breakingIndex-1; i>=0; i--) {
560					var firstItemCoords = getItemMassCoords(firstItem);
561					var moreCoords = getItemMassCoords(moreItem);
562					if (Math.abs(moreCoords[0].top - firstItemCoords[0].top) > 5) {
563						handles[i].hide();
564						hiddenItemIndices.unshift(i);
565					}else{
566						break;
567					}
568				}
569			}
570			if (hiddenItemIndices.length == 0) {
571				// no items were hidden, no need for more...
572				moreHandle.remove();
573			}
574			else if (hiddenItemIndices.length == topLevelSummary.length) {
575				// all items were hidden, revert back
576				for (var i=0; i<hiddenItemIndices.length; i++) {
577					navElm(topLevelSummary[hiddenItemIndices[i]].id).show();
578				}
579				moreHandle.remove();
580			}
581			else {
582				if (!alreadyMore) {
583					var wrap = $("<div/>");
584					wrap.addClass(stylePrefix+'-menu-wrap');
585					var ul = $("<ul/>");
586					ul.addClass(stylePrefix+'-menu');
587					wrap.append(ul);
588					for (var j=0; j<hiddenItemIndices.length; j++) {
589						var pageSummary = topLevelSummary[hiddenItemIndices[j]];
590						var liID = stylePrefix + '-nav-' + pageSummary.id;
591						var li = $("<li id='" + liID + "' />");
592						if (liID == cpid) {
593							li.addClass(stylePrefix + '-nav-current');
594						}
595						var a = $("<a/>");
596						if (pageSummary.onclick) {
597							a.attr('href', '#');
598							a.on('click', pageSummary.onclick);
599						}else{
600							var url = pageSummary.url;
601							if (window.IS_ARCHIVE || url.match(/^http:\/\//)) {
602								a.attr('href', url);
603							}else{
604								a.attr('href', '/' + url);
605							}
606						}
607						if (pageSummary.onmouseover) {
608							a.on('mouseover', pageSummary.onmouseover);
609						}
610						if (pageSummary.onmouseout) {
611							a.on('mouseout', pageSummary.onmouseout);
612						}
613						li.append(a);
614						var submenu = getRealTopLevelItem(navElm(topLevelSummary[hiddenItemIndices[j]].id))[0]._flyoutmenu_destroy();
615						a.html(
616							"<span class='" + stylePrefix + "-menu-title'>" +
617								pageSummary.title +
618							"</span>" +
619							(submenu ? "<span class='" + stylePrefix + "-menu-arrow'>&gt;</span>" : '')
620						);
621						if (submenu) {
622							li.append(submenu);
623						}
624						ul.append(li);
625					}
626					moreItem.append(wrap);
627					navFlyoutMenu.addItem(moreItem);
628					if (window.showEvent) {
629						showEvent('navMore');
630					}
631				}
632			}
633		}
634	}
635
636
637
638
639
640	/************************ helpers for navigating and querying items/sublists/etc ********************/
641
642	function inVerticalList(item, strict, aLiId) {
643		var list = item.parent();
644		if (list.hasClass(stylePrefix + '-nav-handle')) {
645			list = list.parent();
646		}
647		var allItems = getTopLevelItems(list, strict, aLiId);
648		if (allItems.length >= 2) {
649			var o1 = allItems.eq(0).offset();
650			var o2 = allItems.eq(1).offset();
651			var diff = Math.abs(o1.left - o2.left) - Math.abs(o1.top - o2.top);
652			if (diff != 0) {
653				return diff < 0;
654			}
655		}
656		return !isItemTopLevel(item);
657			// default to returning false for top level user-defined css
658			// and true for weebly-created submenus
659	}
660
661	function getTopLevelItems(list, strict, aLiId) {
662		var res = [];
663		list.children().each(function(i, handleNode) {
664			var handle = $(handleNode);
665			if (!strict ||
666				handle.hasClass(stylePrefix + '-nav-handle') ||
667				handle.hasClass(stylePrefix + '-nav-more') ||
668				handleNode.id.match(/^pg/) ||
669				(aLiId && handleNode.id==aLiId)) {
670					var item = getRealTopLevelItem(handle);
671					if (item.length) {
672						res.push(item[0]);
673					}
674				}
675		});
676		return $(res);
677	}
678
679	function getRealTopLevelItem(item) { // todo: rename to getItemFromHandle()
680		if (item.hasClass(stylePrefix + '-nav-handle')) {
681			item = item.children().first();
682		}
683		if (!item.hasClass(stylePrefix + '-menu-wrap')) {
684			// sometimes with SPAN handles, markup was invalid and DOM messed up
685			// so make sure item is not a menu
686			return item;
687		}
688	}
689
690	function getAllItems(list, itemTag) {
691		// get top level and all descendant items
692		return list.find(itemTag).add(getTopLevelItems(list));
693		// we want this list to be unique. jQuery already does this for us (for elements in DOM)
694	}
695
696	function getSiblings(item) {
697		if (item.parent().hasClass(stylePrefix + '-nav-handle')) {
698			return item.parent().siblings().children(':first-child');
699		}else{
700			// items aren't wrapped by separate handles
701			return item.siblings();
702		}
703	}
704
705	function getSublist(item, listTag) {
706		var sublist = item.find(listTag).first();
707		if (!sublist.length) {
708			var next = item.next();
709			if (next.hasClass(stylePrefix + '-menu-wrap')) {
710				// sometimes with SPAN handles, markup is invalid, and it
711				// makes the sublist a sibling AFTER the item
712				sublist = next.children().first();
713			}
714		}
715		if (!sublist.length) {
716			sublist = undefined;
717		}
718		return sublist;
719	}
720
721	function isItemTopLevel(item) {
722		var list = item.parent();
723		if (list.hasClass(stylePrefix + '-nav-handle')) {
724			list = list.parent();
725		}
726		return !list.hasClass(stylePrefix + '-menu');
727	}
728
729	function getItemMassCoords(item) {
730		// look at the item and its A tag and return the largest rectangle of space it takes up
731		// NOTE: we are still using offsetHeight/offsetWidth because jQuery 1.7.2 had a bug where
732		//   getting curCSS on zero-height inline-displayed elements returned wrong value
733		//   (because it converted to block first)
734		var anchor = item.is('a') ? item : item.find('a');
735		var p1 = item.offset();
736		var p2 = { top:p1.top+item[0].offsetHeight, left:p1.left+item[0].offsetWidth };
737		if (!anchor) {
738			// messed up DOM (SPAN's around TD's and such) sometimes pushes A tag outside of item
739			return [p1, p2];
740		}
741		var p3 = anchor.offset();
742		var p4 = { top:p3.top+anchor[0].offsetHeight, left:p3.left+anchor[0].offsetWidth };
743		var p5, p6;
744		if (Math.abs(p1.left - p2.left) < 10) { // a tag is really small, doen't have any mass..
745			// the inner A tag is probably floated and the LI isn't. lame. just use A tag's coords
746			p5 = p3;
747			p6 = p4;
748		}else{
749			p5 = { top:Math.min(p1.top, p3.top), left:Math.min(p1.left, p3.left) };
750			p6 = { top:Math.max(p2.top, p4.top), left:Math.max(p2.left, p4.left) };
751		}
752		return [p5, p6];
753	}
754
755	function navElm(id) { // todo: rename to getHandle()
756		var elm = $('#pg' + id);
757		if (!elm.length && activeLiId) {
758			elm = $('#' + activeLiId);
759		}
760		if (elm.length) {
761			return elm;	
762		}
763	}
764
765
766
767
768	/************************** helpers for theme-css-loaded detection ***********************/
769
770	function isThemeCSSLoaded() {
771		for (var i=0; i<document.styleSheets.length; i++) {
772			try {
773				if (document.styleSheets[i].title == stylePrefix+'-theme-css') {
774					var sheet = document.styleSheets[i];
775					var rules = sheet.cssRules || sheet.rules;
776					return rules && rules.length > 0;
777				}
778			}
779			catch (err) {}
780		}
781		return false;
782	}
783
784	function whenThemeCSSLoaded(callback) {
785		if (isThemeCSSLoaded()) {
786			callback();
787		}else{
788			var intervalID = setInterval(function() {
789				if (isThemeCSSLoaded()) {
790					clearInterval(intervalID);
791					callback();
792				}
793			}, 200);
794		}
795	}
796	
797	if (!window.whenThemeCSSLoaded) {
798		window.whenThemeCSSLoaded = whenThemeCSSLoaded;
799	}
800
801
802})(Weebly.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.