PageSourceSearch

https://www.kla.tv/js/fg.menu.js?v=2026092401

js kla.tv collected 2026-09-24 09:00:09 UTC 32,204 bytes, 913 lines download raw bytes

1/*-------------------------------------------------------------------- 
2Scripts for creating and manipulating custom menus based on standard <ul> markup
3Version: 3.0, 03.31.2009
4
5By: Maggie Costello Wachs ([email protected]) and Scott Jehl ([email protected])
6	http://www.filamentgroup.com
7	* reference articles: http://www.filamentgroup.com/lab/jquery_ipod_style_drilldown_menu/
8		
9Copyright (c) 2009 Filament Group
10Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
11--------------------------------------------------------------------*/
12
13
14var allUIMenus = [];
15
16$.fn.menu = function(options){
17	var caller = this;
18	var options = options;
19	var m = new Menu(caller, options);	
20	allUIMenus.push(m);
21	
22	$(this)
23	.mousedown(function(){
24		if (!m.menuOpen) { m.showLoading(); };
25	})	
26	.click(function(){
27		if (m.menuOpen == false) { m.showMenu(); }
28		else { m.kill(); };
29		return false;
30	});	
31};
32
33function Menu(caller, options){
34	var menu = this;
35	var caller = $(caller);
36	var container = $('<div class="fg-menu-container ui-widget ui-widget-content ui-corner-all">'+options.content+'</div>');
37	
38	this.menuOpen = false;
39	this.menuExists = false;
40	
41	var options = jQuery.extend({
42		content: null,
43		width: 180, // width of menu container, must be set or passed in to calculate widths of child menus
44		maxHeight: 180, // max height of menu (if a drilldown: height does not include breadcrumb)
45		positionOpts: {
46			posX: 'left', 
47			posY: 'bottom',
48			offsetX: 0,
49			offsetY: 0,
50			directionH: 'right',
51			directionV: 'down', 
52			detectH: true, // do horizontal collision detection  
53			detectV: true, // do vertical collision detection
54			linkToFront: false
55		},
56		showSpeed: 200, // show/hide speed in milliseconds
57		callerOnState: 'ui-state-active', // class to change the appearance of the link/button when the menu is showing
58		loadingState: 'ui-state-loading', // class added to the link/button while the menu is created
59		linkHover: 'ui-state-hover', // class for menu option hover state
60		linkHoverSecondary: 'li-hover', // alternate class, may be used for multi-level menus		
61	// ----- multi-level menu defaults -----
62		crossSpeed: 200, // cross-fade speed for multi-level menus
63		crumbDefaultText: 'Choose an option:',
64		backLink: true, // in the ipod-style menu: instead of breadcrumbs, show only a 'back' link
65		backLinkText: 'Back',
66		flyOut: false, // multi-level menus are ipod-style by default; this parameter overrides to make a flyout instead
67		flyOutOnState: 'ui-state-default',
68		nextMenuLink: 'ui-icon-triangle-1-e', // class to style the link (specifically, a span within the link) used in the multi-level menu to show the next level
69		topLinkText: 'All',
70		nextCrumbLink: 'ui-icon-carat-1-e'	
71	}, options);
72	
73	var killAllMenus = function(){
74		$.each(allUIMenus, function(i){
75			if (allUIMenus[i].menuOpen) { allUIMenus[i].kill(); };	
76		});
77	};
78	
79	this.kill = function(){
80		caller
81			.removeClass(options.loadingState)
82			.removeClass('fg-menu-open')
83			.removeClass(options.callerOnState);	
84		container.find('li').removeClass(options.linkHoverSecondary).find('a').removeClass(options.linkHover);		
85		if (options.flyOutOnState) { container.find('li a').removeClass(options.flyOutOnState); };	
86		if (options.callerOnState) { 	caller.removeClass(options.callerOnState); };			
87		if (container.is('.fg-menu-ipod')) { menu.resetDrilldownMenu(); };
88		if (container.is('.fg-menu-flyout')) { menu.resetFlyoutMenu(); };	
89		container.parent().hide();	
90		menu.menuOpen = false;
91		$(document).unbind('click', killAllMenus);
92		$(document).unbind('keydown');
93	};
94	
95	this.showLoading = function(){
96		caller.addClass(options.loadingState);
97	};
98
99	this.showMenu = function(){
100		killAllMenus();
101		if (!menu.menuExists) { menu.create() };
102		caller
103			.addClass('fg-menu-open')
104			.addClass(options.callerOnState);
105		container.parent().show().click(function(){ menu.kill(); return false; });
106		container.hide().slideDown(options.showSpeed).find('.fg-menu:eq(0)');
107		menu.menuOpen = true;
108		caller.removeClass(options.loadingState);
109		$(document).click(killAllMenus);
110		
111		// assign key events
112		$(document).keydown(function(event){
113			var e;
114			if (event.which !="") { e = event.which; }
115			else if (event.charCode != "") { e = event.charCode; }
116			else if (event.keyCode != "") { e = event.keyCode; }
117			
118			var menuType = ($(event.target).parents('div').is('.fg-menu-flyout')) ? 'flyout' : 'ipod' ;
119			
120			switch(e) {
121				case 37: // left arrow 
122					if (menuType == 'flyout') {
123						$(event.target).trigger('mouseout');
124						if ($('.'+options.flyOutOnState).size() > 0) { $('.'+options.flyOutOnState).trigger('mouseover'); };
125					};
126					
127					if (menuType == 'ipod') {
128						$(event.target).trigger('mouseout');
129						if ($('.fg-menu-footer').find('a').size() > 0) { $('.fg-menu-footer').find('a').trigger('click'); };
130						if ($('.fg-menu-header').find('a').size() > 0) { $('.fg-menu-current-crumb').prev().find('a').trigger('click'); };
131						if ($('.fg-menu-current').prev().is('.fg-menu-indicator')) {
132							$('.fg-menu-current').prev().trigger('mouseover');							
133						};						
134					};
135					return false;
136					break;
137					
138				case 38: // up arrow 
139					if ($(event.target).is('.' + options.linkHover)) {	
140						var prevLink = $(event.target).parent().prev().find('a:eq(0)');						
141						if (prevLink.size() > 0) {
142							$(event.target).trigger('mouseout');
143							prevLink.trigger('mouseover');
144						};						
145					}
146					else { container.find('a:eq(0)').trigger('mouseover'); }
147					return false;
148					break;
149					
150				case 39: // right arrow 
151					if ($(event.target).is('.fg-menu-indicator')) {						
152						if (menuType == 'flyout') {
153							$(event.target).next().find('a:eq(0)').trigger('mouseover');
154						}
155						else if (menuType == 'ipod') {
156							$(event.target).trigger('click');						
157							setTimeout(function(){
158								$(event.target).next().find('a:eq(0)').trigger('mouseover');
159							}, options.crossSpeed);
160						};				
161					}; 
162					return false;
163					break;
164					
165				case 40: // down arrow 
166					if ($(event.target).is('.' + options.linkHover)) {
167						var nextLink = $(event.target).parent().next().find('a:eq(0)');						
168						if (nextLink.size() > 0) {							
169							$(event.target).trigger('mouseout');
170							nextLink.trigger('mouseover');
171						};				
172					}
173					else { container.find('a:eq(0)').trigger('mouseover'); }		
174					return false;						
175					break;
176					
177				case 27: // escape
178					killAllMenus();
179					break;
180					
181				case 13: // enter
182					if ($(event.target).is('.fg-menu-indicator') && menuType == 'ipod') {							
183						$(event.target).trigger('click');						
184						setTimeout(function(){
185							$(event.target).next().find('a:eq(0)').trigger('mouseover');
186						}, options.crossSpeed);					
187					}; 
188					break;
189			};			
190		});
191	};
192	
193	this.create = function(){	
194		container.css({ width: options.width }).appendTo('body').find('ul:first').not('.fg-menu-breadcrumb').addClass('fg-menu');
195		container.find('ul, li a').addClass('ui-corner-all');
196		
197		// aria roles & attributes
198		container.find('ul').attr('role', 'menu').eq(0).attr('aria-activedescendant','active-menuitem').attr('aria-labelledby', caller.attr('id'));
199		container.find('li').attr('role', 'menuitem');
200		container.find('li:has(ul)').attr('aria-haspopup', 'true').find('ul').attr('aria-expanded', 'false');
201		container.find('a').attr('tabindex', '-1');
202		
203		// when there are multiple levels of hierarchy, create flyout or drilldown menu
204		if (container.find('ul').size() > 1) {
205			if (options.flyOut) { menu.flyout(container, options); }
206			else { menu.drilldown(container, options); }	
207		}
208		else {
209			container.find('a').click(function(){
210				menu.chooseItem(this);
211				return false;
212			});
213		};	
214		
215		if (options.linkHover) {
216			var allLinks = container.find('.fg-menu li a');
217			allLinks.hover(
218				function(){
219					var menuitem = $(this);
220					$('.'+options.linkHover).removeClass(options.linkHover).blur().parent().removeAttr('id');
221					$(this).addClass(options.linkHover).focus().parent().attr('id','active-menuitem');
222				},
223				function(){
224					$(this).removeClass(options.linkHover).blur().parent().removeAttr('id');
225				}
226			);
227		};
228		
229		if (options.linkHoverSecondary) {
230			container.find('.fg-menu li').hover(
231				function(){
232					$(this).siblings('li').removeClass(options.linkHoverSecondary);
233					if (options.flyOutOnState) { $(this).siblings('li').find('a').removeClass(options.flyOutOnState); }
234					$(this).addClass(options.linkHoverSecondary);
235				},
236				function(){ $(this).removeClass(options.linkHoverSecondary); }
237			);
238		};	
239		
240		menu.setPosition(container, caller, options);
241		menu.menuExists = true;
242	};
243	
244	this.chooseItem = function(item){
245		menu.kill();
246		
247		
248		//Welche Aktion soll durchgeführt werden? (aktion*tabelle*id) 
249		//aRel[0] -> aktion | aRel[1] -> tabelle | aRel[2] -> id
250		var cRel = $(item).attr("rel");
251		var aRel = cRel.split("*");
252		console.log(aRel);
253                
254		if(aRel[0] == 'check')
255		{
256			jConfirm('Wollen Sie diese Klage wirklich freistellen und somit der Öffentlichkeit zugänglich machen?', 'Klage freistellen', function(r) 
257			{
258	   			
259				if(r)
260	   			{
261		   			//Eingabe &uuml;berpr&uuml;fen & in Datenbank schreiben
262					jQuery.ajax({
263			            type: "POST",
264			            url: "ajax.settings.php",
265			            data: {action:aRel[0], table : aRel[1], id : aRel[2] },
266			            dataType: "html"
267			          }).done(function( data ) {
268			          	//Fehlermeldung ausgeben, falls nicht erfolgreich
269			          	if(data == 0)
270			          	{	
271							$("#status")
272							.addClass("message_red")
273							.html("Fehler beim Freistellen der Klage!")
274							.fadeIn('fast')
275							.delay(3000)
276							.fadeOut('slow');	
277				        }
278				        else
279				        {	
280				   				jAlert('Die Klage wurde erfolgreich freigestellt!');
281				   				window.location.reload();
282
283				        }
284			
285			          });
286	   			
287   				}
288
289
290			});			
291
292		}
293		else if (aRel[0] == 'del')
294		{
295			jConfirm('Wollen Sie diese Klage wirklich UNWIEDERRUFLICH löschen?', 'Klage löschen', function(r) 
296			{
297	   			
298				if(r)
299	   			{
300	   				//Eingabe &uuml;berpr&uuml;fen & in Datenbank schreiben
301					jQuery.ajax({
302			            type: "POST",
303			            url: "ajax.settings.php",
304			            data: {action:aRel[0], table : aRel[1], id : aRel[2], date:aRel[3] },
305			            dataType: "html"
306			          }).done(function( data ) {
307			          	//Fehlermeldung ausgeben, falls nicht erfolgreich
308			          	if(data == 0)
309			          	{	
310							$("#status")
311							.addClass("message_red")
312							.html("Fehler beim Löschen der Klage!")
313							.fadeIn('fast')
314							.delay(3000)
315							.fadeOut('slow');	
316				        }
317				        else
318				        {	
319				   				//Alert(data);
320				   				jAlert('Die Klage wurde erfolgreich gelöscht!');
321				   				window.location.reload();
322
323				        }
324			
325			          });
326	   			
327   				}
328
329			});		
330		}
331		else if (aRel[0] == 'copy')
332		{
333			jConfirm('Wollen Sie diese Klage wirklich kopieren?', 'Klage kopieren', function(r) 
334			{
335	   			
336				if(r)
337	   			{
338		   			//Eingabe &uuml;berpr&uuml;fen & in Datenbank schreiben
339					jQuery.ajax({
340			            type: "POST",
341			            url: "ajax.settings.php",
342			            data: {action:aRel[0], table : aRel[1], id : aRel[2] },
343			            dataType: "html"
344			          }).done(function( data ) {
345			          	//Fehlermeldung ausgeben, falls nicht erfolgreich
346			          	if(data == 0)
347			          	{	
348							$("#status")
349							.addClass("message_red")
350							.html("Fehler beim Kopieren der Klage!")
351							.fadeIn('fast')
352							.delay(3000)
353							.fadeOut('slow');	
354				        }
355				        else
356				        {	
357				   				jAlert('Die Klage wurde erfolgreich kopiert!');
358				   				window.location.reload();
359
360				        }
361			
362			          });
363	   			
364   				}
365
366			});		
367		} 
368		else if (aRel[0] == 'order')
369		{
370			
371			/*jPrompt('Reihenfolge-Nr:', '0', 'Reihenfolge ändern', function(r) {
372    			if( r ) alert('You entered ' + r);
373			});*/
374			
375			jAlert('Die Reihenfolge wird durch das abgedruckte Datum festgelegt!<br/> Um die Reihenfolge zu ändern, mutieren Sie das entsprechende Datum <br/><b>in absteigender Reihenfolge</b>.', 'Reihenfolge ändern');
376
377		} 
378		else if (aRel[0] == 'lock')
379		{
380			jConfirm('Wollen Sie diese Klage wirklich SPERREN und somit der Öffentlichkeit nicht mehr zugänglich machen?', 'Klage sperren', function(r) 
381			{
382	   			
383				if(r)
384	   			{
385		   			//Eingabe &uuml;berpr&uuml;fen & in Datenbank schreiben
386					jQuery.ajax({
387			            type: "POST",
388			            url: "ajax.settings.php",
389			            data: {action:aRel[0], table : aRel[1], id : aRel[2] },
390			            dataType: "html"
391			          }).done(function( data ) {
392			          	//Fehlermeldung ausgeben, falls nicht erfolgreich
393			          	if(data == 0)
394			          	{	
395							$("#status")
396							.addClass("message_red")
397							.html("Fehler beim Sperren der Klage!")
398							.fadeIn('fast')
399							.delay(3000)
400							.fadeOut('slow');	
401				        }
402				        else
403				        {	
404				   				jAlert('Die Klage wurde erfolgreich gesperrt!');
405				   				window.location.reload();
406
407				        }
408			
409			          });
410	   			
411   				}
412
413
414
415			});	
416
417		}
418		else if (aRel[0] == 'edit')
419		{
420			//Eingabe &uuml;berpr&uuml;fen & in Datenbank schreiben
421			jQuery.ajax({
422	            type: "POST",
423	            url: "ajax.settings.php",
424	            data: {action:aRel[0], table : aRel[1], id : aRel[2] },
425	            dataType: "html"
426	          }).done(function( data ) {
427	          	//Fehlermeldung ausgeben, falls nicht erfolgreich
428	          	if(data == 0)
429	          	{	
430					$("#status")
431					.addClass("message_red")
432					.html("Fehler beim Bearbeiten des Elementes!")
433					.fadeIn('fast')
434					.delay(3000)
435					.fadeOut('slow');	
436		        }
437		        else
438		        {	
439		   			//jAlert('Die Klage wurde erfolgreich angepasst!');
440	   				window.location.reload();
441	
442		        }
443	        });
444		}
445		else if (aRel[0] == 'setVimeoId')
446		{
447			bootbox.prompt("Gib die Vimeo-ID ein!", function(result){
448                            var retVal = true;
449                            var tempResult = $.trim(result);
450                            
451                            if(tempResult.length > 0)
452                            {
453                                if(!isNaN(parseInt(tempResult)))
454                                {
455                                    $.ajax({
456                                        type: "POST",
457                                        url: "ajax.settings.php",
458                                        data: { action:"setVimeoId",
459                                                json:Helper.Encoding.JSON.Encode({
460                                                    vidId: aRel[1],
461                                                    vimeoId: parseInt(tempResult)
462                                               })
463                                        },
464                                        success: function(data){
465                                            if(!(1*data)){
466                                                bootbox.alert('<span style="color:red;font-weight:bold">Leider konnte die Vimeo-ID nicht gespeichert werden. Versuche es erneut!</span>');
467                                            }
468                                        }
469                                    })
470                                }else{
471                                    bootbox.alert('<span style="color:red;font-weight:bold">
471Das ist leider keine ID. Versuche es nocheinmals!</span>');
472                                    retVal = false;
473                                }
474                            }
475                            return retVal;
476                        });
477		}
478        else if (aRel[0] == 'setYouTubeId')
479        {
480            bootbox.prompt("Gib den YouTube Kurzlink zu dieser Kla.TV Sendung ein!", function(result){
481                var retVal = true;
482                var tempResult = $.trim(result);
483                if(tempResult.length > 0)
484                {
485                        $.ajax({
486                            type: "POST",
487                            url: "ajax.settings.php",
488                            data: { action:"setYouTubeId",
489                                json:Helper.Encoding.JSON.Encode({
490                                    vidId: aRel[1],
491									youTubeShortLink: tempResult
492                                })
493                            },
494                            success: function(data){
495                                if(!(1*data)){
496                                    bootbox.alert('<span style="color:red;font-weight:bold">
496Diese Eingabe ist leider kein YouTube Link. Versuche es nocheinmal!</span>');
497                                    retVal = false;
498                                }
499								else{
500									bootbox.alert('<span style="color:green;font-weight:bold">Super. Diese Eingabe ist ein YouTube Link. Vielen Dank für deine Mithilfe!</span>');
501								}
502                            }
503
504                        })
505                }
506                return retVal;
507            });
508        }
509
510
511		//$('#menuSelection').text($(item).text());	
512		
513		//Seite neu laden, damit neue Einträge sichtbar werden
514		//window.location.reload();
515	};
516};
517
518
519Menu.prototype.flyout = function(container, options) {
520	var menu = this;
521	
522	this.resetFlyoutMenu = function(){
523		var allLists = container.find('ul ul');
524		allLists.removeClass('ui-widget-content').hide();	
525	};
526	
527	container.addClass('fg-menu-flyout').find('li:has(ul)').each(function(){
528		var linkWidth = container.width();
529		var showTimer, hideTimer;
530		var allSubLists = $(this).find('ul');		
531		
532		allSubLists.css({ left: linkWidth, width: linkWidth }).hide();
533			
534		$(this).find('a:eq(0)').addClass('fg-menu-indicator').html('<span>' + $(this).find('a:eq(0)').text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>').hover(
535			function(){
536				clearTimeout(hideTimer);
537				var subList = $(this).next();
538				if (!fitVertical(subList, $(this).offset().top)) { subList.css({ top: 'auto', bottom: 0 }); };
539				if (!fitHorizontal(subList, $(this).offset().left + 100)) { subList.css({ left: 'auto', right: linkWidth, 'z-index': 999 }); };
540				showTimer = setTimeout(function(){
541					subList.addClass('ui-widget-content').show(options.showSpeed).attr('aria-expanded', 'true');	
542				}, 300);	
543			},
544			function(){
545				clearTimeout(showTimer);
546				var subList = $(this).next();
547				hideTimer = setTimeout(function(){
548					subList.removeClass('ui-widget-content').hide(options.showSpeed).attr('aria-expanded', 'false');
549				}, 400);	
550			}
551		);
552
553		$(this).find('ul a').hover(
554			function(){
555				clearTimeout(hideTimer);
556				if ($(this).parents('ul').prev().is('a.fg-menu-indicator')) {
557					$(this).parents('ul').prev().addClass(options.flyOutOnState);
558				}
559			},
560			function(){
561				hideTimer = setTimeout(function(){
562					allSubLists.hide(options.showSpeed);
563					container.find(options.flyOutOnState).removeClass(options.flyOutOnState);
564				}, 500);	
565			}
566		);	
567	});
568	
569	container.find('a').click(function(){
570		menu.chooseItem(this);
571		return false;
572	});
573};
574
575
576Menu.prototype.drilldown = function(container, options) {
577	var menu = this;	
578	var topList = container.find('.fg-menu');	
579	var breadcrumb = $('<ul class="fg-menu-breadcrumb ui-widget-header ui-corner-all ui-helper-clearfix"></ul>');
580	var crumbDefaultHeader = $('<li class="fg-menu-breadcrumb-text">'+options.crumbDefaultText+'</li>');
581	var firstCrumbText = (options.backLink) ? options.backLinkText : options.topLinkText;
582	var firstCrumbClass = (options.backLink) ? 'fg-menu-prev-list' : 'fg-menu-all-lists';
583	var firstCrumbLinkClass = (options.backLink) ? 'ui-state-default ui-corner-all' : '';
584	var firstCrumbIcon = (options.backLink) ? '<span class="ui-icon ui-icon-triangle-1-w"></span>' : '';
585	var firstCrumb = $('<li class="'+firstCrumbClass+'"><a href="#" class="'+firstCrumbLinkClass+'">'+firstCrumbIcon+firstCrumbText+'</a></li>');
586	
587	container.addClass('fg-menu-ipod');
588	
589	if (options.backLink) { breadcrumb.addClass('fg-menu-footer').appendTo(container).hide(); }
590	else { breadcrumb.addClass('fg-menu-header').prependTo(container); };
591	breadcrumb.append(crumbDefaultHeader);
592	
593	var checkMenuHeight = function(el){
594		if (el.height() > options.maxHeight) { el.addClass('fg-menu-scroll') };	
595		el.css({ height: options.maxHeight });
596	};
597	
598	var resetChildMenu = function(el){ el.removeClass('fg-menu-scroll').removeClass('fg-menu-current').height('auto'); };
599	
600	this.resetDrilldownMenu = function(){
601		$('.fg-menu-current').removeClass('fg-menu-current');
602		topList.animate({ left: 0 }, options.crossSpeed, function(){
603			$(this).find('ul').each(function(){
604				$(this).hide();
605				resetChildMenu($(this));				
606			});
607			topList.addClass('fg-menu-current');			
608		});		
609		$('.fg-menu-all-lists').find('span').remove();	
610		breadcrumb.empty().append(crumbDefaultHeader);		
611		$('.fg-menu-footer').empty().hide();	
612		checkMenuHeight(topList);		
613	};
614	
615	topList
616		.addClass('fg-menu-content fg-menu-current ui-widget-content ui-helper-clearfix')
617		.css({ width: container.width() })
618		.find('ul')
619			.css({ width: container.width(), left: container.width() })
620			.addClass('ui-widget-content')
621			.hide();		
622	checkMenuHeight(topList);	
623	
624	topList.find('a').each(function(){
625		// if the link opens a child menu:
626		if ($(this).next().is('ul')) {
627			$(this)
628				.addClass('fg-menu-indicator')
629				.each(function(){ $(this).html('<span>' + $(this).text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>'); })
630				.click(function(){ // ----- show the next menu			
631					var nextList = $(this).next();
632		    		var parentUl = $(this).parents('ul:eq(0)');   		
633		    		var parentLeft = (parentUl.is('.fg-menu-content')) ? 0 : parseFloat(topList.css('left'));    		
634		    		var nextLeftVal = Math.round(parentLeft - parseFloat(container.width()));
635		    		var footer = $('.fg-menu-footer');
636		    		
637		    		// show next menu   		
638		    		resetChildMenu(parentUl);
639		    		checkMenuHeight(nextList);
640					topList.animate({ left: nextLeftVal }, options.crossSpeed);						
641		    		nextList.show().addClass('fg-menu-current').attr('aria-expanded', 'true');    
642		    		
643		    		var setPrevMenu = function(backlink){
644		    			var b = backlink;
645		    			var c = $('.fg-menu-current');
646			    		var prevList = c.parents('ul:eq(0)');
647			    		c.hide().attr('aria-expanded', 'false');
648		    			resetChildMenu(c);
649		    			checkMenuHeight(prevList);
650			    		prevList.addClass('fg-menu-current').attr('aria-expanded', 'true');
651			    		if (prevList.hasClass('fg-menu-content')) { b.remove(); footer.hide(); };
652		    		};		
653		
654					// initialize "back" link
655					if (options.backLink) {
656						if (footer.find('a').size() == 0) {
657							footer.show();
658							$('<a href="#"><span class="ui-icon ui-icon-triangle-1-w"></span> <span>Back</span></a>')
659								.appendTo(footer)
660								.click(function(){ // ----- show the previous menu
661									var b = $(this);
662						    		var prevLeftVal = parseFloat(topList.css('left')) + container.width();		    						    		
663						    		topList.animate({ left: prevLeftVal },  options.crossSpeed, function(){
664						    			setPrevMenu(b);
665						    		});			
666									return false;
667								});
668						}
669					}
670					// or initialize top breadcrumb
671		    		else { 
672		    			if (breadcrumb.find('li').size() == 1){				
673							breadcrumb.empty().append(firstCrumb);
674							firstCrumb.find('a').click(function(){
675								menu.resetDrilldownMenu();
676								return false;
677							});
678						}
679						$('.fg-menu-current-crumb').removeClass('fg-menu-current-crumb');
680						var crumbText = $(this).find('span:eq(0)').text();
681						var newCrumb = $('<li class="fg-menu-current-crumb"><a href="javascript://" class="fg-menu-crumb">'+crumbText+'</a></li>');	
682						newCrumb
683							.appendTo(breadcrumb)
684							.find('a').click(function(){
685								if ($(this).parent().is('.fg-menu-current-crumb')){
686									menu.chooseItem(this);
687								}
688								else {
689									var newLeftVal = - ($('.fg-menu-current').parents('ul').size() - 1) * 180;
690									topList.animate({ left: newLeftVal }, options.crossSpeed, function(){
691										setPrevMenu();
692									});
693								
694									// make this the current crumb, delete all breadcrumbs after this one, and navigate to the relevant menu
695									$(this).parent().addClass('fg-menu-current-crumb').find('span').remove();
696									$(this).parent().nextAll().remove();									
697								};
698								return false;
699							});
700						newCrumb.prev().append(' <span class="ui-icon '+options.nextCrumbLink+'"></span>');
701		    		};			
702		    		return false;    		
703    			});
704		}
705		// if the link is a leaf node (doesn't open a child menu)
706		else {
707			$(this).click(function(){
708				menu.chooseItem(this);
709				return false;
710			});
711		};
712	});
713};
714
715
716/* Menu.prototype.setPosition parameters (defaults noted with *):
717	referrer = the link (or other element) used to show the overlaid object 
718	settings = can override the defaults:
719		- posX/Y: where the top left corner of the object should be positioned in relation to its referrer.
720				X: left*, center, right
721				Y: top, center, bottom*
722		- offsetX/Y: the number of pixels to be offset from the x or y position.  Can be a positive or negative number.
723		- directionH/V: where the entire menu should appear in relation to its referrer.
724				Horizontal: left*, right
725				Vertical: up, down*
726		- detectH/V: detect the viewport horizontally / vertically
727		- linkToFront: copy the menu link and place it on top of the menu (visual effect to make it look like it overlaps the object) */
728
729Menu.prototype.setPosition = function(widget, caller, options) { 
730	var el = widget;
731	var referrer = caller;
732	var dims = {
733		refX: referrer.offset().left,
734		refY: referrer.offset().top,
735		refW: referrer.getTotalWidth(),
736		refH: referrer.getTotalHeight()
737	};	
738	var options = options;
739	var xVal, yVal;
740	
741	var helper = $('<div class="positionHelper"></div>');
742	helper.css({ position: 'absolute', left: dims.refX, top: dims.refY, width: dims.refW, height: dims.refH });
743	el.wrap(helper);
744	
745	// get X pos
746	switch(options.positionOpts.posX) {
747		case 'left': 	xVal = 0; 
748			break;				
749		case 'center': xVal = dims.refW / 2;
750			break;				
751		case 'right': xVal = dims.refW;
752			break;
753	};
754	
755	// get Y pos
756	switch(options.positionOpts.posY) {
757		case 'top': 	yVal = 0;
758			break;				
759		case 'center': yVal = dims.refH / 2;
760			break;				
761		case 'bottom': yVal = dims.refH;
762			break;
763	};
764	
765	// add the offsets (zero by default)
766	xVal += options.positionOpts.offsetX;
767	yVal += options.positionOpts.offsetY;
768	
769	// position the object vertically
770	if (options.positionOpts.directionV == 'up') {
771		el.css({ top: 'auto', bottom: yVal });
772		if (options.positionOpts.detectV && !fitVertical(el)) {
773			el.css({ bottom: 'auto', top: yVal });
774		}
775	} 
776	else {
777		el.css({ bottom: 'auto', top: yVal });
778		if (options.positionOpts.detectV && !fitVertical(el)) {
779			el.css({ top: 'auto', bottom: yVal });
780		}
781	};
782	
783	// and horizontally
784	if (options.positionOpts.directionH == 'left') {
785		el.css({ left: 'auto', right: xVal });
786		if (options.positionOpts.detectH && !fitHorizontal(el)) {
787			el.css({ right: 'auto', left: xVal });
788		}
789	} 
790	else {
791		el.css({ right: 'auto', left: xVal });
792		if (options.positionOpts.detectH && !fitHorizontal(el)) {
793			el.css({ left: 'auto', right: xVal });
794		}
795	};
796	
797	// if specified, clone the referring element and position it so that it appears on top of the menu
798	if (options.positionOpts.linkToFront) {
799		referrer.clone().addClass('linkClone').css({
800			position: 'absolute', 
801			top: 0, 
802			right: 'auto', 
803			bottom: 'auto', 
804			left: 0, 
805			width: referrer.width(), 
806			height: referrer.height()
807		}).insertAfter(el);
808	};
809};
810
811
812/* Utilities to sort and find viewport dimensions */
813
814function sortBigToSmall(a, b) { return b - a; };
815
816jQuery.fn.getTotalWidth = function(){
817	return $(this).width() + parseInt($(this).css('paddingRight')) + parseInt($(this).css('paddingLeft')) + parseInt($(this).css('borderRightWidth')) + parseInt($(this).css('borderLeftWidth'));
818};
819
820jQuery.fn.getTotalHeight = function(){
821	return $(this).height() + parseInt($(this).css('paddingTop')) + parseInt($(this).css('paddingBottom')) + parseInt($(this).css('borderTopWidth')) + parseInt($(this).css('borderBottomWidth'));
822};
823
824function getScrollTop(){
825	return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
826};
827
828function getScrollLeft(){
829	return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
830};
831
832function getWindowHeight(){
833	var de = document.documentElement;
834	return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight;
835};
836
837function getWindowWidth(){
838	var de = document.documentElement;
839	return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
840};
841
842/* Utilities to test whether an element will fit in the viewport
843	Parameters:
844	el = element to position, required
845	leftOffset / topOffset = optional parameter if the offset cannot be calculated (i.e., if the object is in the DOM but is set to display: 'none') */
846	
847function fitHorizontal(el, leftOffset){
848	var leftVal = parseInt(leftOffset) || $(el).offset().left;
849	return (leftVal + $(el).width() <= getWindowWidth() + getScrollLeft() && leftVal - getScrollLeft() >= 0);
850};
851
852function fitVertical(el, topOffset){
853	var topVal = parseInt(topOffset) || $(el).offset().top;
854	return (topVal + $(el).height() <= getWindowHeight() + getScrollTop() && topVal - getScrollTop() >= 0);
855};
856
857/*-------------------------------------------------------------------- 
858 * javascript method: "pxToEm"
859 * by:
860   Scott Jehl ([email protected]) 
861   Maggie Wachs ([email protected])
862   http://www.filamentgroup.com
863 *
864 * Copyright (c) 2008 Filament Group
865 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
866 *
867 * Description: Extends the native Number and String objects with pxToEm method. pxToEm converts a pixel value to ems depending on inherited font size.  
868 * Article: http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/
869 * Demo: http://www.filamentgroup.com/examples/pxToEm/	 	
870 *							
871 * Options:  	 								
872 		scope: string or jQuery selector for font-size scoping
873 		reverse: Boolean, true reverses the conversion to em-px
874 * Dependencies: jQuery library						  
875 * Usage Example: myPixelValue.pxToEm(); or myPixelValue.pxToEm({'scope':'#navigation', reverse: true});
876 *
877 * Version: 2.0, 08.01.2008 
878 * Changelog:
879 *		08.02.2007 initial Version 1.0
880 *		08.01.2008 - fixed font-size calculation for IE
881--------------------------------------------------------------------*/
882
883Number.prototype.pxToEm = String.prototype.pxToEm = function(settings){
884	//set defaults
885	settings = jQuery.extend({
886		scope: 'body',
887		reverse: false
888	}, settings);
889	
890	var pxVal = (this == '') ? 0 : parseFloat(this);
891	var scopeVal;
892	var getWindowWidth = function(){
893		var de = document.documentElement;
894		return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
895	};	
896	
897	/* When a percentage-based font-size is set on the body, IE returns that percent of the window width as the font-size. 
898		For example, if the body font-size is 62.5% and the window width is 1000px, IE will return 625px as the font-size. 	
899		When this happens, we calculate the correct body font-size (%) and multiply it by 16 (the standard browser font size) 
900		to get an accurate em value. */
901				
902	if (settings.scope == 'body' && $.browser.msie && (parseFloat($('body').css('font-size')) / getW
902indowWidth()).toFixed(1) > 0.0) {
903		var calcFontSize = function(){		
904			return (parseFloat($('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16;
905		};
906		scopeVal = calcFontSize();
907	}
908	else { scopeVal = parseFloat(jQuery(settings.scope).css("font-size")); };
909			
910	var result = (settings.reverse == true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em';
911	return result;
912};
913

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.