1/** 2 *------------------------------------------------------------------------------ 3 * @package T3 Framework for Joomla! 4 *------------------------------------------------------------------------------ 5 * @copyright Copyright (C) 2004-2013 JoomlArt.com. All Rights Reserved. 6 * @license GNU General Public License version 2 or later; see LICENSE.txt 7 * @authors JoomlArt, JoomlaBamboo, (contribute to this project at github 8 * & Google group to become co-author) 9 * @Google group: https://groups.google.com/forum/#!forum/t3fw 10 * @Link: http://t3-framework.org 11 *------------------------------------------------------------------------------ 12 */ 13 14;(function($){ 15 16 17 var T3Menu = function(elm, options){ 18 this.$menu = $(elm); 19 if (!this.$menu.length){ 20 return; 21 } 22 23 this.options = $.extend({}, $.fn.t3menu.defaults, options); 24 this.child_open = []; 25 this.loaded = false; 26 27 this.start(); 28 }; 29 30 T3Menu.prototype = { 31 constructor: T3Menu, 32 33 start: function () { 34 //init once 35 if (this.loaded){ 36 return; 37 } 38 this.loaded = true; 39 40 //start 41 var self = this, 42 options = this.options, 43 $menu = this.$menu; 44 45 this.$items = $menu.find('li'); 46 this.$items.each(function (idx, li) { 47 48 var $item = $(this), 49 $child = $item.children('.dropdown-menu'), 50 $link = $item.children('a'), 51 item = { 52 $item: $item, 53 child: $child.length, 54 link: $link.length, 55 clickable: !($link.length && $child.length), 56 mega: $item.hasClass('mega'), 57 status: 'close', 58 timer: null, 59 atimer: null 60 }; 61 62 //store 63 $item.data('t3menu.item', item); 64 65 //click action 66 if ($child.length && !options.hover) { 67 $item.on('click', function (e) { 68 e.stopPropagation(); 69 70 if ($item.hasClass('group')) { 71 return; 72 } 73 74 if (item.status == 'close') { 75 e.preventDefault(); 76 self.show(item); 77 } 78 }); 79 } else { 80 81 //stop if click on menu item - prevent bubble event 82 $item.on('click', function (e) { 83 e.stopPropagation() 84 }); 85 } 86 87 if (options.hover) { 88 $item.on('mouseover', function (e) { 89 if ($item.hasClass('group')) return ; 90 91 // check and handle only once - replace for stopPropagation 92 var $target = $(e.target); 93 if ($target.data('show-processed')) return ; 94 $target.data('show-processed', true); 95 setTimeout(function(){$target.data('show-processed', false);}, 10); 96 97 self.show(item); 98 99 }).on('mouseleave', function (e) { 100 if ($item.hasClass('group')) return ; 101 102 // check and handle only once - replace for stopPropagation 103 var $target = $(e.target); 104 if ($target.data('hide-processed')) return ; 105 $target.data('hide-processed', true); 106 setTimeout(function(){$target.data('hide-processed', false);}, 10); 107 108 self.hide(item); 109 }); 110 111 //if has child, don't goto link before open child - fix for touch screen 112 if ($link.length && $child.length) { 113 $link.on('click', function (e) { 114 return item.clickable; 115 }); 116 } 117 } 118 119 }); 120 121 $(document.body).on('tap hideall.t3menu', function(e){ 122 clearTimeout(self.timer); 123 self.timer = setTimeout($.proxy(self.hide_alls, self), e.type == 'tap' ? 500 : self.options.hidedelay); 124 }); 125 126 // ignore click on direct child 127 $menu.find('.mega-dropdown-menu').on('tap hideall.t3menu', function(e) { 128 e.stopPropagation(); 129 e.preventDefault(); 130 return false;
131 }); 132 }, 133 134 show: function (item) { 135 136 // hide all others menu of this instance 137 if($.inArray(item, this.child_open) < this.child_open.length -1){ 138 this.hide_others(item); 139 } 140 141 // hide all for other instances as well 142 $(document.body).trigger('hideall.t3menu', [this]); 143 144 clearTimeout(this.timer); //hide alls 145 clearTimeout(item.timer); //hide this item 146 clearTimeout(item.ftimer); //on hidden 147 clearTimeout(item.ctimer); //on hidden 148 149 if(item.status != 'open' || !item.$item.hasClass('open') || !this.child_open.length){ 150 if(item.mega){ 151 //remove timer 152 clearTimeout(item.astimer); //animate 153 clearTimeout(item.atimer); //animate 154 155 //place menu 156 this.position(item.$item); 157 158 // add class animate 159 item.astimer = setTimeout(function(){item.$item.addClass('animating')}, 10); 160 item.atimer = setTimeout(function(){item.$item.removeClass('animating')}, this.options.duration + 50); 161 item.timer = setTimeout(function(){item.$item.addClass('open')}, 100); 162 163 } else { 164 item.$item.addClass('open'); 165 } 166 167 item.status = 'open'; 168 if (item.child && $.inArray(item, this.child_open) == -1) { 169 this.child_open.push(item); 170 } 171 } 172 173 item.ctimer = setTimeout($.proxy(this.clickable, this, item), 300); 174 }, 175 176 hide: function (item) { 177 178 clearTimeout(this.timer); //hide alls 179 clearTimeout(item.timer); //hide this item 180 clearTimeout(item.astimer); //animate timer 181 clearTimeout(item.atimer); //animate timer 182 clearTimeout(item.ftimer); //on hidden 183 184 if(item.mega){ 185 //animate out 186 item.$item.addClass('animating'); 187 item.atimer = setTimeout(function(){item.$item.removeClass('animating')}, this.options.duration); 188 item.timer = setTimeout(function(){item.$item.removeClass('open')}, 100); 189 } else { 190 item.$item.removeClass('open'); 191 } 192 193 item.status = 'close'; 194 for (var i = this.child_open.length; i--;){ 195 if (this.child_open[i] === item){ 196 this.child_open.splice(i, 1); 197 } 198 } 199 200 item.ftimer = setTimeout($.proxy(this.hidden, this, item), this.options.duration); 201 this.timer = setTimeout($.proxy(this.hide_alls, this), this.options.hidedelay); 202 }, 203 204 hidden: function (item) { 205 //hide done 206 if (item.status == 'close') { 207 item.clickable = false; 208 } 209 }, 210 211 hide_others: function (item) { 212 var self = this; 213 $.each(this.child_open.slice(), function (idx, open) { 214 if (!item || (open != item && !open.$item.has(item.$item).length)) { 215 self.hide(open); 216 } 217 }); 218 }, 219 220 hide_alls: function (e, inst) { 221 if(!e || e.type == 'tap' || (e.type == 'hideall' && this != inst)){ 222 var self = this; 223 $.each(this.child_open.slice(), function (idx, item) { 224 item && self.hide(item); 225 }); 226 } 227 }, 228 229 clickable: function (item) { 230 item.clickable = true; 231 }, 232 233 position: function ($item) { 234 var sub = $item.children('.mega-dropdown-menu'), 235 is_show = sub.is(':visible'); 236 237 if(!is_show){ 238 sub.show(); 239 } 240 241 var offset = $item.offset(), 242 width = $item.outerWidth(), 243 screen_width = $(window).width() - this.options.sb_width, 244 sub_width = sub.outerWidth(), 245 level = $item.data('level'); 246 247 if(!is_show){ 248 sub.css('display', ''); 249 } 250 251 //reset custom align 252 sub.css({left : '', right : ''}); 253 254 if(level == 1){ 255 256 var align = $item.data('alignsub'), 257 align_offset = 0, 258 align_delta = 0, 259 align_trans = 0; 260 261 if(align == 'justify'){ 262 return; //do nothing 263 } 264 265 if(!align){ 266 align = 'left'; 267 } 268 269 if(align == 'center'){ 270 align_offset = offset.left + (width /2); 271 272 if(!$.support.t3transform){ 273 align_trans = -sub_width /2; 274 sub.css(this.options.rtl ? 'right' : 'left', align_trans + width /2); 275 } 276 277 } else { 278 align_offset = offset.left + ((align == 'left' && this.options.rtl || al
278ign == 'right' && !this.options.rtl) ? width : 0); 279 } 280 281 if (this.options.rtl) { 282 283 if(align == 'right'){ 284 if(align_offset + sub_width > screen_width){ 285 align_delta = screen_width - align_offset - sub_width; 286 sub.css('left', align_delta); 287 288 if(screen_width < sub_width){ 289 sub.css('left', align_delta + sub_width - screen_width); 290 } 291 } 292 } else { 293 if(align_offset < (align == 'center' ? sub_width /2 : sub_width)){ 294 align_delta = align_offset - (align == 'center' ? sub_width /2 : sub_width); 295 sub.css('right', align_delta + align_trans); 296 } 297 298 if(align_offset + (align == 'center' ? sub_width /2 : 0) - align_delta > screen_width){ 299 sub.css('right', align_offset + (align == 'center' ? (sub_width + width) /2 : 0) + align_trans - screen_width); 300 } 301 } 302 303 } else { 304 305 if(align == 'right'){ 306 if(align_offset < sub_width){ 307 align_delta = align_offset - sub_width; 308 sub.css('right', align_delta); 309 310 if(sub_width > screen_width){ 311 sub.css('right', sub_width - screen_width + align_delta); 312 } 313 } 314 } else { 315 316 if(align_offset + (align == 'center' ? sub_width /2 : sub_width) > screen_width){ 317 align_delta = screen_width - align_offset -(align == 'center' ? sub_width /2 : sub_width); 318 sub.css('left', align_delta + align_trans); 319 } 320 321 if(align_offset - (align == 'center' ? sub_width /2 : 0) + align_delta < 0){ 322 sub.css('left', (align == 'center' ? (sub_width + width) /2 : 0) + align_trans - align_offset); 323 } 324 } 325 } 326 } else { 327 328 if (this.options.rtl) { 329 if ($item.closest('.mega-dropdown-menu').parent().hasClass('mega-align-right')) { 330 331 //should be align to the right as parent 332 // $item.removeClass('mega-align-left').addClass('mega-align-right'); 333 334 // check if not able => revert the direction 335 if (offset.left + width + sub_width > screen_width) { 336 $item.removeClass('mega-align-right'); //should we add align left ? it is th default now 337 338 if(offset.left - sub_width < 0){ 339 sub.css('right', offset.left + width - sub_width); 340 } 341 } 342 } else { 343 if (offset.left - sub_width < 0) { 344 $item.removeClass('mega-align-left').addClass('mega-align-right'); 345 346 if(offset.left + width + sub_width > screen_width){ 347 sub.css('left', screen_width - offset.left - sub_width); 348 } 349 } 350 } 351 } else { 352 353 if ($item.closest('.mega-dropdown-menu').parent().hasClass('mega-align-right')) { 354 //should be align to the right as parent 355 // $item.removeClass('mega-align-left').addClass('mega-align-right'); 356 357 // check if not able => revert the direction 358 if (offset.left - sub_width < 0) { 359 $item.removeClass('mega-align-right'); //should we add align left ? it is th default now 360 361 if(offset.left + width + sub_width > screen_width){ 362 sub.css('left', screen_width - offset.left - sub_width); 363 } 364 } 365 } else { 366 367 if (offset.left + width + sub_width > screen_width) { 368 $item.removeClass('mega-align-left').addClass('mega-align-right'); 369 370 if(offset.left - sub_width < 0){ 371 sub.css('right', offset.left + width - sub_width); 372 } 373 } 374 } 375 } 376 } 377 } 378 }; 379 380 $.fn.t3menu = function (option) { 381 return this.each(function () { 382 var $this = $(this), 383 data = $this.data('megamenu'), 384 options = typeof option == 'object' && option; 385 386 if (!data) { 387 $this.data('megamenu', (data = new T3Menu(this, options))); 388 389 } else { 390 if (typeof option == 'string' && data[option]){ 391 data[option]() 392 } 393 } 394 }) 395 }; 396 397 $.fn.t3menu.defaults = { 398 duration: 400, 399 timeout: 100, 400 hidedelay: 200, 401 hover: true, 402 sb_width: 20 403 }; 404 405 406 //apply script 407 $(document).ready(function(){ 408 409 //detect settings 410 var mm_duration = $('.t3-megamenu').data('duration') || 0; 411 if (mm_duration) { 412 413 $('<style type="text/css">' + 414 '.t3-megamenu.animate .animating > .mega-dropdown-menu,' + 415 '.t3-megamenu.animate.slide .animating > .mega-dropdown-menu > div {' + 416 'transition-duration: ' + mm_duration + 'ms !important;' +
417 '-webkit-transition-duration: ' + mm_duration + 'ms !important;' + 418 '}' + 419 '</style>').appendTo ('head'); 420 } 421 422 var mm_timeout = mm_duration ? 100 + mm_duration : 500, 423 mm_rtl = $(document.documentElement).attr('dir') == 'rtl', 424 mm_trigger = $(document.documentElement).hasClass('mm-hover'), 425 sb_width = (function () { 426 var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'), 427 child = parent.children(), 428 width = child.innerWidth() - child.height(100).innerWidth(); 429 430 parent.remove(); 431 432 return width; 433 })(); 434 435 //lt IE 10 436 if(!$.support.transition){ 437 //it is not support animate 438 $('.t3-megamenu').removeClass('animate'); 439 440 mm_timeout = 100; 441 } 442 443 //get ready 444 $('ul.nav').has('.dropdown-menu').t3menu({ 445 duration: mm_duration, 446 timeout: mm_timeout, 447 rtl: mm_rtl, 448 sb_width: sb_width, 449 hover: mm_trigger 450 }); 451 452 453 $(window).load(function(){ 454 455 //check we miss any nav 456 $('ul.nav').has('.dropdown-menu').t3menu({ 457 duration: mm_duration, 458 timeout: mm_timeout, 459 rtl: mm_rtl, 460 sb_width: sb_width, 461 hover: mm_trigger 462 }); 463 464 }); 465 }); 466 467})(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.