PageSourceSearch

http://www.fcmaid.com.sg/templates/lifestyle/src/mouseover13.js

js fcmaid.com.sg collected 2026-10-08 21:58:41 UTC 13,598 bytes, 420 lines download raw bytes

1/*======================================================================*\
2|| #################################################################### ||
3|| # Package - Joomla Template based on YJSimpleGrid Framework          ||
4|| # Copyright (C) 2010  Youjoomla.com. All Rights Reserved.            ||
5|| # Authors - Dragan Todorovic and Constantin Boiangiu                 ||
6|| # license - PHP files are licensed under  GNU/GPL V2                 ||
7|| # license - CSS  - JS - IMAGE files  are Copyrighted material        ||
8|| # bound by Proprietary License of Youjoomla.com                      ||
9|| # for more information visit http://www.youjoomla.com/license.html   ||
10|| # Redistribution and  modification of this software                  ||
11|| # is bounded by its licenses                                         ||
12|| # websites - http://www.youjoomla.com | http://www.yjsimplegrid.com  ||
13|| #################################################################### ||
14\*======================================================================*/
15var SmoothDrop = new Class({
16	Implements: [Options],
17	
18	options: {
19		container:null,
20		contpoz: false,
21		horizLeftOffset: 10, // submenus, left offset
22		horizRightOffset: -10, // submenus opening into the opposite direction
23		horizTopOffset: 20, // submenus, top offset
24		verticalTopOffset: 30, // main menus top offset
25		verticalLeftOffset: 10, // main menus, left offset
26		maxOutside: 50 // maximum pixels a panel can go outside the window and get pushed back
27	},
28	
29	initialize: function(options) {
30		
31		this.setOptions(options);
32		if( !this.options.container ) return;
33		this.container = $(this.options.container);
34		this.start();	
35	},
36	
37	start: function(){
38		
39		this.injectIn = document.body;
40		this.dir = $(document.body).getStyle('direction');
41		this.isIe7 = this.options.contpoz;
42		if( this.dir!=='rtl' ) this.isIe7 = false;
43		
44		/* get first level of parents */
45		var list = this.container.getElement('ul.menunav');	
46		this.container.removeClass('horiz_rtl');
47		/* store menu tree */
48		this.menuTree = new Hash();
49		/* used to give unique id to each li.haschild element */
50		this.parentCount = 0;
51		/* go into the lists and get all li.haschild and ul's assigned to each one */
52		this.parseLists( list, 0, false );
53		
54		this.parent = null;
55		this.element = null;
56		
57		this.pathOver = null;
58		this.pathOut = null;
59		
60		this.menuTree.each( function( elements, key ){			
61			var level = key;
62			
63			elements.each(function(info, i){
64				if( info.trigger.hasClass('active') ){
65					info.trigger.addClass('is_active')
66				}
67				info.trigger.addEvent('mouseenter', function(event){
68					this.getPath(key);
69					this.pathOver = this.path.join('|');
70					
71					if( this.parent == key && i!==this.element ){
72						
73						var t = this.menuTree.get( key );
74						t.each(function(m, k){
75							if( k!==i ){
76								m.fx.slideOut();
77							}
78						})
79					}
80					
81					this.parent = key;
82					this.element = i;					
83					this.showMenu( info );
84					
85				}.bind(this))
86				
87				// mouseover UL
88				info.list.addEvent('mousemove', function(event){
89					this.getPath(key);
90					this.pathOver = this.path.join('|');
91					
92					this.parent = key;
93					this.element = i;					
94				}.bind(this))
95				
96				// mouse out LI
97				info.trigger.addEvent('mouseleave', function(){
98					this.getPath(key);
99					var liOutPath = this.pathOut = this.path.join('|');
100					this.element = false;
101					var f = function(){
102						
103						// if path is the same, do element index check to see if user navigates in same parent element
104						if( this.pathOver == liOutPath ){							
105							
106							var m = this.menuTree.get( this.parent );
107							m.each( function(e, k){
108								if( k !== this.element ){
109									m[k].fx.slideOut();
110									if( !m[k].trigger.hasClass('is_active') )
111										m[k].trigger.removeClass('active');
112								}
113							}.bind(this))								
114														
115						}else{
116							
117							var pathIn = this.pathOver.split('|');
118							var pathOut = liOutPath.split('|');
119							
120							pathOut.each( function(k, i){
121								if( !pathIn.contains( k ) ){
122									var m = this.menuTree.get( k );
123									m.each( function(e, x){
124										m[x].fx.slideOut();	
125										if( !m[x].trigger.hasClass('is_active') )
126											m[x].trigger.removeClass('active');
127									}.bind(this))
128								}								
129							}.bind(this));							
130						}						
131					}					
132					f.delay(100, this);
133					
134				}.bind(this))			
135				
136				// mouseout UL
137				info.list.addEvent('mouseleave', function(){
138					this.getPath(key);
139					var ulOutPath = this.pathOut = this.path.join('|');					
140					var f = function(){
141						// if path is the same, do element index check to see if user navigates in same parent element
142						if( this.pathOver == ulOutPath ){
143							var m = this.menuTree.get( this.parent );
144							m.each( function(e, k){
145								if( k !== this.element ){
146									m[k].fx.slideOut();
147									if( !m[k].trigger.hasClass('is_active') )
148										m[k].trigger.removeClass('active');
149								}
150							}.bind(this))				
151						}else{
152							var pathIn = this.pathOver.split('|');
153							var pathOut = ulOutPath.split('|');
154							
155							pathOut.each( function(k, i){
156								if( !pathIn.contains( k ) ){
157									var m = this.menuTree.get( k );
158									m.each( function(e, x){
159										m[x].fx.slideOut();	
160										if( !m[x].trigger.hasClass('is_active') )
161											m[x].trigger.removeClass('active');
162									}.bind(this))
163								}								
164							}.bind(this));
165						}				
166					}					
167					f.delay(200, this);					
168					
169				}.bind(this))
170				
171				// stop body mouseover event when mouse is over li or ul's in menu 
172				info.trigger.addEvent('mouseover', this.stopDefault);
173				info.trigger.addEvent('mousemove', this.stopDefault);
174				info.list.addEvent('mouseover', this.stopDefault);		
175				info.positioner.addEvent('mouseover', this.stopDefault);
176				// stop mouse wheel on lists when ie7 because of position fixed on elements
177				if( this.isIe7 )
178					info.list.addEvent('mousewheel', this.stopDefault);
179				
180			}.bind(this))			
181		}.bind(this))
182		
183		// hide all menus on body mouseover
184		//*
185		this.injectIn.addEvent('mouseover', function(event){														
186			this.menuTree.each( function( elements, key ){
187				elements.each( function(c){
188					c.fx.slideOut();
189					if( !c.trigger.hasClass('is_active') )
190						c.trigger.removeClass('active');
191				})
192			})
193		}.bind(this))
194		//*/
195	},
196	
197	stopDefault: function( event ){
198		//new Event(event).stop();  yj 25-30
199		//new Event(event).preventDefault();
200		event.preventDefault();
201		return false;
202	},
203	
204	showMenu: function( nodeInfo ){		
205		var d = this.dir == 'rtl' ? this.showRtl(nodeInfo) : this.showLtr(nodeInfo);
206		
207		nodeInfo.positioner.setStyles({'top':d.top, 'left':d.left, 'z-index':2000});
208		nodeInfo.trigger.addClass('active');
209		nodeInfo.fx.slideIn( d.toLeft );		
210	},
211	
212	showLtr: function(info){
213		
214		var c = info.trigger.getCoordinates();	
215		var top = info.level == 0 ? c.top + this.options.verticalTopOffset.toInt() : c.top - this.options.horizTopOffset.toInt();
216		var left = info.level == 0 ? c.left - this.options.verticalLeftOffset.toInt() : c.left + c.width - this.options.horizLeftOffset.toInt();
217		
218		// get window size
219		var winSize = window.getSize();
220		// get list width
221		var listWidth = info.size.x + 20;
222		var toLeft = false;
223		
224		var outside = (left + listWidth) - winSize.x;
225		
226		if( outside > this.options.maxOutside ){
227			var extra = winSize.x - (left + listWidth) ;
228			left = info.level == 0 ? c.left - this.options.verticalLeftOffset.toInt() + extra : 
229				   c.left - this.options.horizRightOffset.toInt();
230			toLeft = info.level == 0 ? false : true;	   
231		}else if( outside > 0 ){
232			left -= outside;
233		}		
234		return {'top':top, 'left':left, 'toLeft':toLeft};	
235	},
236	
237	showRtl: function(info){
238		
239		var c = info.trigger.getCoordinates();		
240		var top = info.level == 0 ? c.top + this.options.verticalTopOffset.toInt() : c.top - this.options.horizTopOffset.toInt();
241		var left = info.level == 0 ? c.left - ( info.size.x - c.width ) - this.options.verticalLeftOffset.toInt() : c.left - this.options.horizRightOffset.toInt();
242		
243		// set default to open to left		
244		var toLeft = info.level == 0 ? false : true;
245		// check level for positioning
246		if( info.level == 0 ){
247			// level 0, simple check, if left is outside window(negative), set it to 0
248			if( left < 0 ) left = 0;			
249		}else{
250			// subsequent levels
251			if( left - info.size.x < 0 ){	
252				left =  c.left + c.width - this.options.horizLeftOffset.toInt();
253				toLeft = false;	   
254			}
255		}		
256		return {'top':top, 'left':left, 'toLeft':toLeft};		
257	},
258	
259	/* starting with any key, returns the complete path to the root */
260	getPath: function( key, path ){
261		
262		if( !path ){
263			this.path = new Array();
264			this.path.include(key);
265		}else{
266			this.path = path;
267		}
268		
269		this.menuTree.each( function(items, k){
270			
271			items.each( function(data, i){
272				if( data.id == key ){
273					this.path.include( k );
274					this.getPath( k, this.path );
275					return;
276				}
277			}.bind(this))			
278		}.bind(this))		
279	},
280	
281	parseLists: function( li, level, parent, prev_parent ){
282		
283		var mainParents = li.getChildren();
284		mainParents.each( function(el, i){
285			// only elements with class haschild have submenus
286			if( !el.hasClass('haschild') ) return;
287			
288			// set unique id and add level class to li.haschild element
289			var id = 'level'+level+'-'+this.parentCount;
290			el.set({'rel': 'level-'+level});
291			var list = el.getElement('ul.subul_main');
292			
293			// get list parent and check if it is group holder
294			var p = list.getParent().getParent();			
295			// if menu is group holder it gets to keep his children
296			if( p.hasClass('group_holder') ){
297				this.parseLists( list, level+1, id, prev_parent );
298				return;
299			}
300			else{
301				// menuWrap returns an object containing the div that positions the submenu and the fx instance
302				var listDetails = this.menuWrap( list, level );
303			}
304			
305			// construct the menu tree
306			var key = prev_parent || parent||'root';
307			
308			var mtKeys = this.menuTree.getKeys();
309			
310			if( !mtKeys.contains( key ) ){
311				this.menuTree.set( key, new Array() );
312			}			
313			this.menuTree.get(key).include({
314				'list' : list,						   
315				'trigger' : el,
316				'fx' : listDetails.fx,
317				'positioner' : listDetails.positioner,
318				'size':listDetails.size,
319				'level' : level,
320				'id' : id
321			});
322			
323			// if menu is group holder, the next level list is part of this menu so pass the id to the script to make it descent from group holder
324			var prev_p = list.hasClass('group_holder') ? id : null;			
325			// this variable is used to generate unique ids
326			this.parentCount++;
327			// search the next level
328			this.parseLists( list, level+1, id, prev_p );			
329			
330		}.bind(this))	
331	},
332	
333	menuWrap: function( list, level ){
334		
335		var listSize = list.getSize();		
336		// create markup for list
337		var topParent = new Element('div').setStyles({
338			'position': this.isIe7 ? 'fixed' : 'absolute', 
339			'left':0,
340			'top':-3000, 
341			'display':'block', 
342			'z-index':1000, 
343			'font-size':YJSG_topmenu_font,
344			'height':1,
345			'width':'auto',
346			'padding':0,
347			'margin':0
348		}).addClass('top_menu YJSG_listContainer');			
349		
350		var inner = new Element('div').set({
351			'class':'YJSG-inner horiznav'
352		}).setStyles({
353			'width':listSize.x, 
354			'height': level == 0 ? listSize.y + 20 : 'auto',
355			'line-height':'normal',
356			'padding':'13px 10px', // padding is added because of round corners positioned absolute that go outside the list by 13 pixels top-bottom and 10 pixels left-right
357			'background':'none',
358			'display':'block',
359			'position':'relative'
360		});	
361		
362		var clear = new Element('div').setStyles({
363			'display':'block', 
364			'clear':'both', 
365			'position':'relative', 
366			'width':'100%'
367		}).set({
368			'html':'<!--clear-->'
369		});
370		
371		// inject all content in body
372		topParent.adopt(inner.adopt(list, clear)).inject( this.injectIn );//injectInside = inject  yj 25-30
373		// set fx on elements
374		var slide_mode = level ? 'horizontal' : 'vertical';
375		var fx = new YJFx(inner, {duration: 250, mode: slide_mode, link:'cancel'});
376		fx.hide();
377		//fx.slideIn();
378		
379		return {'positioner':topParent, 'fx': fx, 'size':listSize};
380	}
381	
382});
383
384var YJFx = new Class({	
385	Extends: Fx.Slide,
386	initialize: function(el, options){
387		this.parent(el, options);
388		// for ie7, if content wrap doesn't have display and position, slide don't work
389		this.wrapper.setStyles({'display':'block', 'position':'relative'});
390		
391		if( this.options.mode == 'horizontal' ){		
392			this.wrapFx = new Fx.Morph( this.wrapper, {wait:this.options.wait, duration:this.options.duration});
393			this.elemFx = new Fx.Morph( this.element,  {wait:this.options.wait, duration:this.options.duration});
394		}
395		this.leftSlide = false;
396	},
397	
398	slideIn: function( leftSlide ){
399		
400		if( leftSlide ){			
401			this.elemFx.set({'margin-left':0});
402			this.wrapFx.start({'width':this.offset, 'margin-left':-this.offset});
403			this.leftSlide = true;
404			return;
405		}		
406		
407		return this.start('in', this.options.mode);
408	},
409
410	slideOut: function(){
411		
412		if( this.leftSlide ){
413			this.wrapFx.start({'width':0, 'margin-left':0});
414			return;
415		}
416		
417		return this.start('out', this.options.mode);
418	}
419})
420

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.