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.