PageSourceSearch

https://www.savingamericashorses.org/SpryAssets/SpryMenuBar.js

js savingamericashorses.org collected 2026-10-02 13:03:03 UTC 22,007 bytes, 759 lines download raw bytes

1// SpryMenuBar.js - version 0.12 - Spry Pre-Release 1.6.1
2//
3// Copyright (c) 2006. Adobe Systems Incorporated.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9//   * Redistributions of source code must retain the above copyright notice,
10//     this list of conditions and the following disclaimer.
11//   * Redistributions in binary form must reproduce the above copyright notice,
12//     this list of conditions and the following disclaimer in the documentation
13//     and/or other materials provided with the distribution.
14//   * Neither the name of Adobe Systems Incorporated nor the names of its
15//     contributors may be used to endorse or promote products derived from this
16//     software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29
30/*******************************************************************************
31
32 SpryMenuBar.js
33 This file handles the JavaScript for Spry Menu Bar.  You should have no need
34 to edit this file.  Some highlights of the MenuBar object is that timers are
35 used to keep submenus from showing up until the user has hovered over the parent
36 menu item for some time, as well as a timer for when they leave a submenu to keep
37 showing that submenu until the timer fires.
38
39 *******************************************************************************/
40
41var Spry; if (!Spry) Spry = {}; if (!Spry.Widget) Spry.Widget = {};
42
43Spry.BrowserSniff = function()
44{
45	var b = navigator.appName.toString();
46	var up = navigator.platform.toString();
47	var ua = navigator.userAgent.toString();
48
49	this.mozilla = this.ie = this.opera = this.safari = false;
50	var re_opera = /Opera.([0-9\.]*)/i;
51	var re_msie = /MSIE.([0-9\.]*)/i;
52	var re_gecko = /gecko/i;
53	var re_safari = /(applewebkit|safari)\/([\d\.]*)/i;
54	var r = false;
55
56	if ( (r = ua.match(re_opera))) {
57		this.opera = true;
58		this.version = parseFloat(r[1]);
59	} else if ( (r = ua.match(re_msie))) {
60		this.ie = true;
61		this.version = parseFloat(r[1]);
62	} else if ( (r = ua.match(re_safari))) {
63		this.safari = true;
64		this.version = parseFloat(r[2]);
65	} else if (ua.match(re_gecko)) {
66		var re_gecko_version = /rv:\s*([0-9\.]+)/i;
67		r = ua.match(re_gecko_version);
68		this.mozilla = true;
69		this.version = parseFloat(r[1]);
70	}
71	this.windows = this.mac = this.linux = false;
72
73	this.Platform = ua.match(/windows/i) ? "windows" :
74					(ua.match(/linux/i) ? "linux" :
75					(ua.match(/mac/i) ? "mac" :
76					ua.match(/unix/i)? "unix" : "unknown"));
77	this[this.Platform] = true;
78	this.v = this.version;
79
80	if (this.safari && this.mac && this.mozilla) {
81		this.mozilla = false;
82	}
83};
84
85Spry.is = new Spry.BrowserSniff();
86
87// Constructor for Menu Bar
88// element should be an ID of an unordered list (<ul> tag)
89// preloadImage1 and preloadImage2 are images for the rollover state of a menu
90Spry.Widget.MenuBar = function(element, opts)
91{
92	this.init(element, opts);
93};
94
95Spry.Widget.MenuBar.prototype.init = function(element, opts)
96{
97	this.element = this.getElement(element);
98
99	// represents the current (sub)menu we are operating on
100	this.currMenu = null;
101	this.showDelay = 250;
102	this.hideDelay = 600;
103	if(typeof document.getElementById == 'undefined' || (navigator.vendor == 'Apple Computer, Inc.' && typeof window.XMLHttpRequest == 'undefined') || (Spry.is.ie && typeof document.uniqueID == 'undefined'))
104	{
105		// bail on older unsupported browsers
106		return;
107	}
108
109	// Fix IE6 CSS images flicker
110	if (Spry.is.ie && Spry.is.version < 7){
111		try {
112			document.execCommand("BackgroundImageCache", false, true);
113		} catch(err) {}
114	}
115
116	this.upKeyCode = Spry.Widget.MenuBar.KEY_UP;
117	this.downKeyCode = Spry.Widget.MenuBar.KEY_DOWN;
118	this.leftKeyCode = Spry.Widget.MenuBar.KEY_LEFT;
119	this.rightKeyCode = Spry.Widget.MenuBar.KEY_RIGHT;
120	this.escKeyCode = Spry.Widget.MenuBar.KEY_ESC;
121
122	this.hoverClass = 'MenuBarItemHover';
123	this.subHoverClass = 'MenuBarItemSubmenuHover';
124	this.subVisibleClass ='MenuBarSubmenuVisible';
125	this.hasSubClass = 'MenuBarItemSubmenu';
126	this.activeClass = 'MenuBarActive';
127	this.isieClass = 'MenuBarItemIE';
128	this.verticalClass = 'MenuBarVertical';
129	this.horizontalClass = 'MenuBarHorizontal';
130	this.enableKeyboardNavigation = true;
131
132	this.hasFocus = false;
133	// load hover images now
134	if(opts)
135	{
136		for(var k in opts)
137		{
138			if (typeof this[k] == 'undefined')
139			{
140				var rollover = new Image;
141				rollover.src = opts[k];
142			}
143		}
144		Spry.Widget.MenuBar.setOptions(this, opts);
145	}
146
147	// safari doesn't support tabindex
148	if (Spry.is.safari)
149		this.enableKeyboardNavigation = false;
150
151	if(this.element)
152	{
153		this.currMenu = this.element;
154		var items = this.element.getElementsByTagName('li');
155		for(var i=0; i<items.length; i++)
156		{
157			if (i > 0 && this.enableKeyboardNavigation)
158				items[i].getElementsByTagName('a')[0].tabIndex='-1';
159
160			this.initialize(items[i], element);
161			if(Spry.is.ie)
162			{
163				this.addClassName(items[i], this.isieClass);
164				items[i].style.position = "static";
165			}
166		}
167		if (this.enableKeyboardNavigation)
168		{
169			var self = this;
170			this.addEventListener(document, 'keydown', function(e){self.keyDown(e); }, false);
171		}
172
173		if(Spry.is.ie)
174		{
175			if(this.hasClassName(this.element, this.verticalClass))
176			{
177				this.element.style.position = "relative";
178			}
179			var linkitems = this.element.getElementsByTagName('a');
180			for(var i=0; i<linkitems.length; i++)
181			{
182				linkitems[i].style.position = "relative";
183			}
184		}
185	}
186};
187Spry.Widget.MenuBar.KEY_ESC = 27;
188Spry.Widget.MenuBar.KEY_UP = 38;
189Spry.Widget.MenuBar.KEY_DOWN = 40;
190Spry.Widget.MenuBar.KEY_LEFT = 37;
191Spry.Widget.MenuBar.KEY_RIGHT = 39;
192
193Spry.Widget.MenuBar.prototype.getElement = function(ele)
194{
195	if (ele && typeof ele == "string")
196		return document.getElementById(ele);
197	return ele;
198};
199
200Spry.Widget.MenuBar.prototype.hasClassName = function(ele, className)
201{
202	if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
203	{
204		return false;
205	}
206	return true;
207};
208
209Spry.Widget.MenuBar.prototype.addClassName = function(ele, className)
210{
211	if (!ele || !className || this.hasClassName(ele, className))
212		return;
213	ele.className += (ele.className ? " " : "") + className;
214};
215
216Spry.Widget.MenuBar.prototype.removeClassName = function(ele, className)
217{
218	if (!ele || !className || !this.hasClassName(ele, className))
219		return;
220	ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
221};
222
223// addEventListener for Menu Bar
224// attach an event to a tag without creating obtrusive HTML code
225Spry.Widget.MenuBar.prototype.addEventListener = function(element, eventType, handler, capture)
226{
227	try
228	{
229		if (element.addEventListener)
230		{
231			element.addEventListener(eventType, handler, capture);
232		}
233		else if (element.attachEvent)
234		{
235			element.attachEvent('on' + eventType, handler);
236		}
237	}
238	catch (e) {}
239};
240
241// createIframeLayer for Menu Bar
242// creates an IFRAME underneath a menu so that it will show above form controls and ActiveX
243Spry.Widget.MenuBar.prototype.createIframeLayer = function(menu)
244{
245	var layer = document.createElement('iframe');
246	layer.tabIndex = '-1';
247	layer.src = 'javascript:""';
248	layer.frameBorder = '0';
249	layer.scrolling = 'no';
250	menu.parentNode.appendChild(layer);
251	
252	layer.style.left = menu.offsetLeft + 'px';
253	layer.style.top = menu.offsetTop + 'px';
254	layer.style.width = menu.offsetWidth + 'px';
255	layer.style.height = menu.offsetHeight + 'px';
256};
257
258// removeIframeLayer for Menu Bar
259// removes an IFRAME underneath a menu to reveal any form controls and ActiveX
260Spry.Widget.MenuBar.prototype.removeIframeLayer =  function(menu)
261{
262	var layers = ((menu == this.element) ? menu : menu.parentNode).getElementsByTagName('iframe');
263	while(layers.length > 0)
264	{
265		layers[0].parentNode.removeChild(layers[0]);
266	}
267};
268
269// clearMenus for Menu Bar
270// root is the top level unordered list (<ul> tag)
271Spry.Widget.MenuBar.prototype.clearMenus = function(root)
272{
273	var menus = root.getElementsByTagName('ul');
274	for(var i=0; i<menus.length; i++)
275		this.hideSubmenu(menus[i]);
276
277	this.removeClassName(this.element, this.activeClass);
278};
279
280// bubbledTextEvent for Menu Bar
281// identify bubbled up text events in Safari so we can ignore them
282Spry.Widget.MenuBar.prototype.bubbledTextEvent = function()
283{
284	return Spry.is.safari && (event.target == event.relatedTarget.parentNode || (event.eventPhase == 3 && event.target.parentNode == event.relatedTarget));
285};
286
287// showSubmenu for Menu Bar
288// set the proper CSS class on this menu to show it
289Spry.Widget.MenuBar.prototype.showSubmenu = function(menu)
290{
291	if(this.currMenu)
292	{
293		this.clearMenus(this.currMenu);
294		this.currMenu = null;
295	}
296	
297	if(menu)
298	{
299		this.addClassName(menu, this.subVisibleClass);
300		if(typeof document.all != 'undefined' && !Spry.is.opera && navigator.vendor != 'KDE')
301		{
302			if(!this.hasClassName(this.element, this.horizontalClass) || menu.parentNode.parentNode != this.element)
303			{
304				menu.style.top = menu.parentNode.offsetTop + 'px';
305			}
306		}
307		if(Spry.is.ie && Spry.is.version < 7)
308		{
309			this.createIframeLayer(menu);
310		}
311	}
312	this.addClassName(this.element, this.activeClass);
313};
314
315// hideSubmenu for Menu Bar
316// remove the proper CSS class on this menu to hide it
317Spry.Widget.MenuBar.prototype.hideSubmenu = function(menu)
318{
319	if(menu)
320	{
321		this.removeClassName(menu, this.subVisibleClass);
322		if(typeof document.all != 'undefined' && !Spry.is.opera && navigator.vendor != 'KDE')
323		{
324			menu.style.top = '';
325			menu.style.left = '';
326		}
327		if(Spry.is.ie && Spry.is.version < 7)
328			this.removeIframeLayer(menu);
329	}
330};
331
332// initialize for Menu Bar
333// create event listeners for the Menu Bar widget so we can properly
334// show and hide submenus
335Spry.Widget.MenuBar.prototype.initialize = function(listitem, element)
336{
337	var opentime, closetime;
338	var link = listitem.getElementsByTagName('a')[0];
339	var submenus = listitem.getElementsByTagName('ul');
340	var menu = (submenus.length > 0 ? submenus[0] : null);
341
342	if(menu)
343		this.addClassName(link, this.hasSubClass);
344
345	if(!Spry.is.ie)
346	{
347		// define a simple function that comes standard in IE to determine
348		// if a node is within another node
349		listitem.contains = function(testNode)
350		{
351			// this refers to the list item
352			if(testNode == null)
353				return false;
354
355			if(testNode == this)
356				return true;
357			else
358				return this.contains(testNode.parentNode);
359		};
360	}
361
362	// need to save this for scope further down
363	var self = this;
364	this.addEventListener(listitem, 'mouseover', function(e){self.mouseOver(listitem, e);}, false);
365	this.addEventListener(listitem, 'mouseout', function(e){if (self.enableKeyboardNavigation) self.clearSelection(); self.mouseOut(listitem, e);}, false);
366
367	if (this.enableKeyboardNavigation)
368	{
369		this.addEventListener(link, 'blur', function(e){self.onBlur(listitem);}, false);
370		this.addEventListener(link, 'focus', function(e){self.keyFocus(listitem, e);}, false);
371	}
372};
373Spry.Widget.MenuBar.prototype.keyFocus = function (listitem, e)
374{
375	this.lastOpen = listitem.getElementsByTagName('a')[0];
376	this.addClassName(this.lastOpen, listitem.getElementsByTagName('ul').length > 0 ? this.subHoverClass : this.hoverClass);
377	this.hasFocus = true;
378};
379Spry.Widget.MenuBar.prototype.onBlur = function (listitem)
380{
381	this.clearSelection(listitem);
382};
383Spry.Widget.MenuBar.prototype.clearSelection = function(el){
384	//search any intersection with the current open element
385	if (!this.lastOpen)
386		return;
387
388	if (el)
389	{
390		el = el.getElementsByTagName('a')[0];
391		
392		// check children
393		var item = this.lastOpen;
394		while (item != this.element)
395		{
396			var tmp = el;
397			while (tmp != this.element)
398			{
399				if (tmp == item)
400					return;
401				try{
402					tmp = tmp.parentNode;
403				}catch(err){break;}
404			}
405			item = item.parentNode;
406		}
407	}
408	var item = this.lastOpen;
409	while (item != this.element)
410	{
411		this.hideSubmenu(item.parentNode);
412		var link = item.getElementsByTagName('a')[0];
413		this.removeClassName(link, this.hoverClass);
414		this.removeClassName(link, this.subHoverClass);
415		item = item.parentNode;
416	}
417	this.lastOpen = false;
418};
419Spry.Widget.MenuBar.prototype.keyDown = function (e)
420{
421	if (!this.hasFocus)
422		return;
423
424	if (!this.lastOpen)
425	{
426		this.hasFocus = false;
427		return;
428	}
429
430	var e = e|| event;
431	var listitem = this.lastOpen.parentNode;
432	var link = this.lastOpen;
433	var submenus = listitem.getElementsByTagName('ul');
434	var menu = (submenus.length > 0 ? submenus[0] : null);
435	var hasSubMenu = (menu) ? true : false;
436
437	var opts = [listitem, menu, null, this.getSibling(listitem, 'previousSibling'), this.getSibling(listitem, 'nextSibling')];
438	
439	if (!opts[3])
440		opts[2] = (listitem.parentNode.parentNode.nodeName.toLowerCase() == 'li')?listitem.parentNode.parentNode:null;
441
442	var found = 0;
443	switch (e.keyCode){
444		case this.upKeyCode:
445			found = this.getElementForKey(opts, 'y', 1);
446			break;
447		case this.downKeyCode:
448			found = this.getElementForKey(opts, 'y', -1);
449			break;
450		case this.leftKeyCode:
451			found = this.getElementForKey(opts, 'x', 1);
452			break;
453		case this.rightKeyCode:
454			found = this.getElementForKey(opts, 'x', -1);
455			break;
456		case this.escKeyCode:
457		case 9:
458			this.clearSelection();
459			this.hasFocus = false;
460		default: return;
461	}
462	switch (found)
463	{
464		case 0: return;
465		case 1:
466			//subopts
467			this.mouseOver(listitem, e);
468			break;
469		case 2:
470			//parent
471			this.mouseOut(opts[2], e);
472			break;
473		case 3:
474		case 4:
475			// left - right
476			this.removeClassName(link, hasSubMenu ? this.subHoverClass : this.hoverClass);
477			break;
478	}
479	var link = opts[found].getElementsByTagName('a')[0];
480	if (opts[found].nodeName.toLowerCase() == 'ul')
481		opts[found] = opts[found].getElementsByTagName('li')[0];
482
483	this.addClassName(link, opts[found].getElementsByTagName('ul').length > 0 ? this.subHoverClass : this.hoverClass);
484	this.lastOpen = link;
485	opts[found].getElementsByTagName('a')[0].focus();
486  
487        //stop further event handling by the browser
488	return Spry.Widget.MenuBar.stopPropagation(e);
489};
490Spry.Widget.MenuBar.prototype.mouseOver = function (listitem, e)
491{
492	var link = listitem.getElementsByTagName('a')[0];
493	var submenus = listitem.getElementsByTagName('ul');
494	var menu = (submenus.length > 0 ? submenus[0] : null);
495	var hasSubMenu = (menu) ? true : false;
496	if (this.enableKeyboardNavigation)
497		this.clearSelection(listitem);
498
499	if(this.bubbledTextEvent())
500	{
501		// ignore bubbled text events
502		return;
503	}
504
505	if (listitem.closetime)
506		clearTimeout(listitem.closetime);
507
508	if(this.currMenu == listitem)
509	{
510		this.currMenu = null;
511	}
512
513	// move the focus too
514	if (this.hasFocus)
515		link.focus();
516
517	// show menu highlighting
518	this.addClassName(link, hasSubMenu ? this.subHoverClass : this.hoverClass);
519	this.lastOpen = link;
520	if(menu && !this.hasClassName(menu, this.subHoverClass))
521	{
522		var self = this;
523		listitem.opentime = window.setTimeout(function(){self.showSubmenu(menu);}, this.showDelay);
524	}
525};
526Spry.Widget.MenuBar.prototype.mouseOut = function (listitem, e)
527{
528	var link = listitem.getElementsByTagName('a')[0];
529	var submenus = listitem.getElementsByTagName('ul');
530	var menu = (submenus.length > 0 ? submenus[0] : null);
531	var hasSubMenu = (menu) ? true : false;
532	if(this.bubbledTextEvent())
533	{
534		// ignore bubbled text events
535		return;
536	}
537
538	var related = (typeof e.relatedTarget != 'undefined' ? e.relatedTarget : e.toElement);
539	if(!listitem.contains(related))
540	{
541		if (listitem.opentime) 
542			clearTimeout(listitem.opentime);
543		this.currMenu = listitem;
544
545		// remove menu highlighting
546		this.removeClassName(link, hasSubMenu ? this.subHoverClass : this.hoverClass);
547		if(menu)
548		{
549			var self = this;
550			listitem.closetime = window.setTimeout(function(){self.hideSubmenu(menu);}, this.hideDelay);
551		}
552		if (this.hasFocus)
553			link.blur();
554	}
555};
556Spry.Widget.MenuBar.prototype.getSibling = function(element, sibling)
557{
558	var child = element[sibling];
559	while (child && child.nodeName.toLowerCase() !='li')
560		child = child[sibling];
561
562	return child;
563};
564Spry.Widget.MenuBar.prototype.getElementForKey = function(els, prop, dir)
565{
566	var found = 0;
567	var rect = Spry.Widget.MenuBar.getPosition;
568	var ref = rect(els[found]);
569
570	var hideSubmenu = false;
571	//make the subelement visible to compute the position
572	if (els[1] && !this.hasClassName(els[1], this.MenuBarSubmenuVisible))
573	{
574		els[1].style.visibility = 'hidden';
575		this.showSubmenu(els[1]);
576		hideSubmenu = true;
577	}
578
579	var isVert = this.hasClassName(this.element, this.verticalClass);
580	var hasParent = els[0].parentNode.parentNode.nodeName.toLowerCase() == 'li' ? true : false;
581	
582	for (var i = 1; i < els.length; i++){
583		//when navigating on the y axis in vertical menus, ignore children and parents
584		if(prop=='y' && isVert && (i==1 || i==2))
585		{
586			continue;
587		}
588		//when navigationg on the x axis in the FIRST LEVEL of horizontal menus, ignore children and parents
589		if(prop=='x' && !isVert && !hasParent && (i==1 || i==2))
590		{
591			continue;
592		}
593			
594		if (els[i])
595		{
596			var tmp = rect(els[i]); 
597			if ( (dir * tmp[prop]) < (dir * ref[prop]))
598			{
599				ref = tmp;
600				found = i;
601			}
602		}
603	}
604	
605	// hide back the submenu
606	if (els[1] && hideSubmenu){
607		this.hideSubmenu(els[1]);
608		els[1].style.visibility =  '';
609	}
610
611	return found;
612};
613Spry.Widget.MenuBar.camelize = function(str)
614{
615	if (str.indexOf('-') == -1){
616		return str;	
617	}
618	var oStringList = str.split('-');
619	var isFirstEntry = true;
620	var camelizedString = '';
621
622	for(var i=0; i < oStringList.length; i++)
623	{
624		if(oStringList[i].length>0)
625		{
626			if(isFirstEntry)
627			{
628				camelizedString = oStringList[i];
629				isFirstEntry = false;
630			}
631			else
632			{
633				var s = oStringList[i];
634				camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
635			}
636		}
637	}
638
639	return camelizedString;
640};
641
642Spry.Widget.MenuBar.getStyleProp = function(element, prop)
643{
644	var value;
645	try
646	{
647		if (element.style)
648			value = element.style[Spry.Widget.MenuBar.camelize(prop)];
649
650		if (!value)
651			if (document.defaultView && document.defaultView.getComputedStyle)
652			{
653				var css = document.defaultView.getComputedStyle(element, null);
654				value = css ? css.getPropertyValue(prop) : null;
655			}
656			else if (element.currentStyle) 
657			{
658					value = element.currentStyle[Spry.Widget.MenuBar.camelize(prop)];
659			}
660	}
661	catch (e) {}
662
663	return value == 'auto' ? null : value;
664};
665Spry.Widget.MenuBar.getIntProp = function(element, prop)
666{
667	var a = parseInt(Spry.Widget.MenuBar.getStyleProp(element, prop),10);
668	if (isNaN(a))
669		return 0;
670	return a;
671};
672
673Spry.Widget.MenuBar.getPosition = function(el, doc)
674{
675	doc = doc || document;
676	if (typeof(el) == 'string') {
677		el = doc.getElementById(el);
678	}
679
680	if (!el) {
681		return false;
682	}
683
684	if (el.parentNode === null || Spry.Widget.MenuBar.getStyleProp(el, 'display') == 'none') {
685		//element must be visible to have a box
686		return false;
687	}
688
689	var ret = {x:0, y:0};
690	var parent = null;
691	var box;
692
693	if (el.getBoundingClientRect) { // IE
694		box = el.getBoundingClientRect();
695		var scrollTop = doc.documentElement.scrollTop || doc.body.scrollTop;
696		var scrollLeft = doc.documentElement.scrollLeft || doc.body.scrollLeft;
697		ret.x = box.left + scrollLeft;
698		ret.y = box.top + scrollTop;
699	} else if (doc.getBoxObjectFor) { // gecko
700		box = doc.getBoxObjectFor(el);
701		ret.x = box.x;
702		ret.y = box.y;
703	} else { // safari/opera
704		ret.x = el.offsetLeft;
705		ret.y = el.offsetTop;
706		parent = el.offsetParent;
707		if (parent != el) {
708			while (parent) {
709				ret.x += parent.offsetLeft;
710				ret.y += parent.offsetTop;
711				parent = parent.offsetParent;
712			}
713		}
714		// opera & (safari absolute) incorrectly account for body offsetTop
715		if (Spry.is.opera || Spry.is.safari && Spry.Widget.MenuBar.getStyleProp(el, 'position') == 'absolute')
716			ret.y -= doc.body.offsetTop;
717	}
718	if (el.parentNode)
719			parent = el.parentNode;
720	else
721		parent = null;
722	if (parent.nodeName){
723		var cas = parent.nodeName.toUpperCase();
724		while (parent && cas != 'BODY' && cas != 'HTML') {
725			cas = parent.nodeName.toUpperCase();
726			ret.x -= parent.scrollLeft;
727			ret.y -= parent.scrollTop;
728			if (parent.parentNode)
729				parent = parent.parentNode;
730			else
731				parent = null;
732		}
733	}
734	return ret;
735};
736
737Spry.Widget.MenuBar.stopPropagation = function(ev)
738{
739	if (ev.stopPropagation)
740		ev.stopPropagation();
741	else
742		ev.cancelBubble = true;
743	if (ev.preventDefault) 
744		ev.preventDefault();
745	else 
746		ev.returnValue = false;
747};
748
749Spry.Widget.MenuBar.setOptions = function(obj, optionsObj, ignoreUndefinedProps)
750{
751	if (!optionsObj)
752		return;
753	for (var optionName in optionsObj)
754	{
755		if (ignoreUndefinedProps && optionsObj[optionName] == undefined)
756			continue;
757		obj[optionName] = optionsObj[optionName];
758	}
759};

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.