1/** 2 * ------------------------------------------------------------------------------ 3 * 4 * @package T3 Framework for Joomla! 5 * ------------------------------------------------------------------------------ 6 * @copyright Copyright (C) 2004-2013 JoomlArt.com. All Rights Reserved. 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 * @authors JoomlArt, JoomlaBamboo, (contribute to this project at github & 9 * Google group to become co-author) 10 * @Google group: https://groups.google.com/forum/#!forum/t3fw 11 * @Link: http://t3-framework.org 12 * ------------------------------------------------------------------------------ 13 */ 14 15; 16(function($) { 17 18 var T3Menu = function(elm, options) { 19 this.$menu = $(elm); 20 if (!this.$menu.length) { 21 return; 22 } 23 24 this.options = $.extend({}, $.fn.t3menu.defaults, options); 25 this.child_open = []; 26 this.loaded = false; 27 28 this.start(); 29 }; 30 31 T3Menu.prototype = { 32 constructor : T3Menu, 33 34 start : function() { 35 // init once 36 if (this.loaded) { 37 return; 38 } 39 this.loaded = true; 40 41 // start 42 var self = this, options = this.options, $menu = this.$menu; 43 44 this.$items = $menu.find('li'); 45 this.$items 46 .each(function(idx, li) { 47 48 var $item = $(this), $child = $item 49 .children('.dropdown-menu'), $link = $item 50 .children('a'), item = { 51 $item : $item, 52 child : $child.length, 53 link : $link.length, 54 clickable : !($link.length && $child.length), 55 mega : $item.hasClass('mega'), 56 status : 'close', 57 timer : null, 58 atimer : null 59 }; 60 61 // store 62 $item.data('t3menu.item', item); 63 64 // click action 65 if ($child.length && !options.hover) { 66 $item.on('click', function(e) { 67 e.stopPropagation(); 68 69 if ($item.hasClass('group')) { 70 return; 71 } 72 73 if (item.status == 'close') { 74 e.preventDefault(); 75 self.show(item); 76 } 77 }); 78 } else { 79 80 // stop if click on menu item - prevent bubble event 81 $item.on('click', function(e) { 82 // ignore if this is toggle button 83 if ($(e.target).data('toggle')) return; 84 e.stopPropagation() 85 }); 86 } 87 88 // click on caret, no action on link 89 $item.find('a > .caret').on('click tap', function(e) { 90 item.clickable = false; 91 }); 92 93 if (options.hover) { 94 $item.on('mouseover', function(e) { 95 if ($item.hasClass('group')) 96 return; 97 98 // check and handle only once - replace for 99 // stopPropagation 100 var $target = $(e.target); 101 if ($target.data('show-processed')) 102 return; 103 $target.data('show-processed', true); 104 setTimeout(function() { 105 $target.data('show-processed', false); 106 }, 10); 107 108 self.show(item); 109 110 }).on('mouseleave', function(e) { 111 if ($item.hasClass('group')) 112 return; 113 114 // check and handle only once - replace for 115 // stopPropagation 116 var $target = $(e.target); 117 if ($target.data('hide-processed')) 118 return; 119 $target.data('hide-processed', true); 120 setTimeout(function() { 121 $target.data('hide-processed', false); 122 }, 10); 123 124 self.hide(item, $target); 125 }); 126 127 // if has child, don't goto link before open child - 128 // fix for touch screen 129 if ($link.length && $child.length) { 130 $link.on('click', function(e) { 131 if (item.clickable) { 132 e.stopPropagation(); 133 } 134 return item.clickable; 135 }); 136 } 137 } 138 139 }); 140 141 $(document.body) 142 .on( 143 'tap hideall.t3menu', 144 function(e) { 145 clearTimeout(self.timer); 146 self.timer = setTimeout($.proxy(self.hide_alls, 147 self), e.type == 'tap' ? 500 148 : self.options.hidedelay); 149 }); 150 151 // ignore click on direct child 152 $menu.find('.mega-dropdown-menu').on('hideall.t3menu', function(e) { 153 e.stopPropagation(); 154 e.preventDefault(); 155 return false; 156 }); 157 158 // prevent close menu if click on form element 159 $menu.find('input, select, textarea, label').on('click tap', 160 function(e) { 161 e.stopPropagation(); 162 }); 163 164 // update mega-tab height 165 var $megatab = $menu.find('.mega-tab'); 166 if ($megatab.length) { 167 $megatab.each(function() { 168 var $tabul = $(this).find('>div>ul'), 169 $tabItems = $tabul.children('.dropdown-submenu'), 170 $tabs = $tabul.find('>li>.dropdown-menu'), 171 tabheight = 0, 172 $parentItem = $(this).closest('li'); 173 // mark item as tab-item 174 $tabItems.data('mega-tab-item', 1); 175 // add this tabs to parent item 176 var megatabs = $parentItem.data('mega-tabs') ? $parentItem.data('mega-tabs') : []; 177 megatabs.push($tabul); 178 $parentItem.data('mega-tabs', megatabs); 179 180 // default active the first 181 // $tabul.data('mega-tab', 0); 182 $tabItems.first().data('mega-tab-active', true).addClass('open'); 183 // make all parent visible to get height 184 var $p = $tabul.parents('.dropdown-menu'); 185 $p.each(function() { 186 var $this = $(this); 187 $this.data('prev-style', $this.attr('style')).css({ 188 visibility : "visible", 189 display : "block" 190 }); 191 }) 192 $tabs.each(function() { 193 var $this = $(this), thisstyle = $this.attr('style'); 194 $this.css({ 195 visibility : "hidden", 196 display : "block" 197 }); 198 tabheight = Math.max(tabheight, $this.children()
199 .innerHeight()); 200 // restore style 201 if (thisstyle) { 202 $this.attr('style', thisstyle); 203 } else { 204 $this.removeAttr('style'); 205 } 206 }); 207 $tabul.css('min-height', tabheight); 208 // restore 209 $p.each(function() { 210 var $this = $(this); 211 if ($this.data('prev-style')) 212 $this.attr('style', $this.data('prev-style')); 213 else 214 $this.removeAttr('style'); 215 $this.removeData('prev-style'); 216 }) 217 }) 218 } 219 // fix for modal in menu 220 $menu.find('.modal').appendTo('body'); 221 }, 222 223 show : function(item) { 224 // check if current item is mega-tab 225 if (item.$item.data('mega-tab-item')) { 226 item.$item.parent().children().removeClass('open').data('mega-tab-active', false); 227 item.$item.addClass('open').data('mega-tab-active', true); 228 } 229 // hide all others menu of this instance 230 if ($.inArray(item, this.child_open) < this.child_open.length - 1) { 231 this.hide_others(item); 232 } 233 234 // hide all for other instances as well 235 $(document.body).trigger('hideall.t3menu', [ this ]); 236 237 clearTimeout(this.timer); // hide alls 238 clearTimeout(item.timer); // hide this item 239 clearTimeout(item.ftimer); // on hidden 240 clearTimeout(item.ctimer); // on hidden 241 242 if (item.status != 'open' || !item.$item.hasClass('open') 243 || !this.child_open.length) { 244 if (item.mega) { 245 // remove timer 246 clearTimeout(item.astimer); // animate 247 clearTimeout(item.atimer); // animate 248 249 // place menu 250 this.position(item.$item); 251 252 // add class animate 253 item.astimer = setTimeout(function() { 254 item.$item.addClass('animating') 255 }, 10); 256 item.atimer = setTimeout(function() { 257 item.$item.removeClass('animating') 258 }, this.options.duration + 50); 259 item.timer = setTimeout(function() { 260 item.$item.addClass('open'); 261 }, 100); 262 } else { 263 item.$item.addClass('open'); 264 } 265 266 item.status = 'open'; 267 if (item.child && $.inArray(item, this.child_open) == -1) { 268 this.child_open.push(item); 269 } 270 } 271 272 item.ctimer = setTimeout($.proxy(this.clickable, this, item), 300); 273 274 }, 275 276 hide : function(item, $target) { 277 clearTimeout(this.timer); // hide alls 278 clearTimeout(item.timer); // hide this item 279 clearTimeout(item.astimer); // animate timer 280 clearTimeout(item.atimer); // animate timer 281 clearTimeout(item.ftimer); // on hidden 282 283 // cancel hide if still in menu 284 if ($target && $target.is('input', item.$item)) { 285 return; 286 } 287 288 if (item.mega) { 289 // animate out 290 item.$item.addClass('animating'); 291 item.atimer = setTimeout(function() { 292 item.$item.removeClass('animating') 293 }, this.options.duration); 294 item.timer = setTimeout(function() { 295 if (!item.$item.data('mega-tab-active')) 296 item.$item.removeClass('open') 297 }, 100); 298 } else { 299 item.timer = setTimeout(function() { 300 if (!item.$item.data('mega-tab-active')) 301 item.$item.removeClass('open'); 302 }, 100); 303 } 304 305 item.status = 'close'; 306 for (var i = this.child_open.length; i--;) { 307 if (this.child_open[i] === item) { 308 this.child_open.splice(i, 1); 309 } 310 } 311 312 item.ftimer = setTimeout($.proxy(this.hidden, this, item), 313 this.options.duration); 314 this.timer = setTimeout($.proxy(this.hide_alls, this), 315 this.options.hidedelay); 316 }, 317 318 hidden : function(item) { 319 // hide done 320 if (item.status == 'close') { 321 item.clickable = false; 322 } 323 }, 324 325 hide_others : function(item) { 326 var self = this; 327 $ 328 .each(this.child_open.slice(), 329 function(idx, open) { 330 if (!item 331 || (open != item && !open.$item 332 .has(item.$item).length)) { 333 self.hide(open); 334 } 335 }); 336 }, 337 338 hide_alls : function(e, inst) { 339 if (!e || e.type == 'tap' || (e.type == 'hideall' && this != inst)) { 340 var self = this; 341 $.each(this.child_open.slice(), function(idx, item) { 342 item && self.hide(item); 343 }); 344 } 345 }, 346 347 clickable : function(item) { 348 item.clickable = true; 349 }, 350 351 position : function($item) { 352 var sub = $item.children('.mega-dropdown-menu'), is_show = sub 353 .is(':visible'); 354 355 if (!is_show) { 356 sub.show(); 357 } 358 359 var offset = $item.offset(), width = $item.outerWidth(), screen_width = $( 360 window).width() 361 - this.options.sb_width, sub_width = sub.outerWidth(), level = $item 362 .data('level'); 363 364 if (!is_show) { 365 sub.css('display', ''); 366 } 367 368 // reset custom align 369 sub.css({ 370 left : '', 371 right : '' 372 }); 373 374 if (level == 1) { 375 376 var align = $item.data('alignsub'), align_offset = 0, align_delta = 0, align_trans = 0; 377 378 if (align == 'justify') { 379 return; // do nothing 380 } 381 382 if (!align) {
383 align = 'left'; 384 } 385 386 if (align == 'center') { 387 align_offset = offset.left + (width / 2); 388 389 if (!$.support.t3transform) { 390 align_trans = -sub_width / 2; 391 sub.css(this.options.rtl ? 'right' : 'left', 392 align_trans + width / 2); 393 } 394 395 } else { 396 align_offset = offset.left 397 + ((align == 'left' && this.options.rtl || align == 'right' 398 && !this.options.rtl) ? width : 0); 399 } 400 401 if (this.options.rtl) { 402 403 if (align == 'right') { 404 if (align_offset + sub_width > screen_width) { 405 align_delta = screen_width - align_offset 406 - sub_width; 407 sub.css('left', align_delta); 408 409 if (screen_width < sub_width) { 410 sub.css('left', align_delta + sub_width 411 - screen_width); 412 } 413 } 414 } else { 415 if (align_offset < (align == 'center' ? sub_width / 2 416 : sub_width)) { 417 align_delta = align_offset 418 - (align == 'center' ? sub_width / 2 419 : sub_width); 420 sub.css('right', align_delta + align_trans); 421 } 422 423 if (align_offset 424 + (align == 'center' ? sub_width / 2 : 0) 425 - align_delta > screen_width) { 426 sub 427 .css( 428 'right', 429 align_offset 430 + (align == 'center' ? (sub_width + width) / 2 431 : 0) + align_trans 432 - screen_width); 433 } 434 } 435 436 } else { 437 438 if (align == 'right') { 439 if (align_offset < sub_width) { 440 align_delta = align_offset - sub_width; 441 sub.css('right', align_delta); 442 443 if (sub_width > screen_width) { 444 sub.css('right', sub_width - screen_width 445 + align_delta); 446 } 447 } 448 } else { 449 450 if (align_offset 451 + (align == 'center' ? sub_width / 2 452 : sub_width) > screen_width) { 453 align_delta = screen_width 454 - align_offset 455 - (align == 'center' ? sub_width / 2 456 : sub_width); 457 sub.css('left', align_delta + align_trans); 458 } 459 460 if (align_offset 461 - (align == 'center' ? sub_width / 2 : 0) 462 + align_delta < 0) { 463 sub 464 .css( 465 'left', 466 (align == 'center' ? (sub_width + width) / 2 467 : 0) 468 + align_trans 469 - align_offset); 470 } 471 } 472 } 473 } else { 474 475 if (this.options.rtl) { 476 if ($item.closest('.mega-dropdown-menu').parent().hasClass( 477 'mega-align-right')) { 478 479 // should be align to the right as parent 480 // $item.removeClass('mega-align-left').addClass('mega-align-right'); 481 482 // check if not able => revert the direction 483 if (offset.left + width + sub_width > screen_width) { 484 $item.removeClass('mega-align-right'); // should we 485 // add align 486 // left ? it 487 // is th 488 // default 489 // now 490 491 if (offset.left - sub_width < 0) { 492 sub.css('right', offset.left + width 493 - sub_width); 494 } 495 } 496 } else { 497 if (offset.left - sub_width < 0) { 498 $item.removeClass('mega-align-left').addClass( 499 'mega-align-right'); 500 501 if (offset.left + width + sub_width > screen_width) { 502 sub.css('left', screen_width - offset.left 503 - sub_width); 504 } 505 } 506 } 507 } else { 508 509 if ($item.closest('.mega-dropdown-menu').parent().hasClass( 510 'mega-align-right')) { 511 // should be align to the right as parent 512 // $item.removeClass('mega-align-left').addClass('mega-align-right'); 513 514 // check if not able => revert the direction 515 if (offset.left - sub_width < 0) { 516 $item.removeClass('mega-align-right'); // should we 517 // add align 518 // left ? it 519 // is th 520 // default 521 // now 522 523 if (offset.left + width + sub_width > screen_width) { 524 sub.css('left', screen_width - offset.left 525 - sub_width); 526 } 527 } 528 } else { 529 530 if (offset.left + width + sub_width > screen_width) { 531 $item.removeClass('mega-align-left').addClass( 532 'mega-align-right'); 533 534 if (offset.left - sub_width < 0) { 535 sub.css('right', offset.left + width 536 - sub_width); 537 } 538 } 539 } 540 } 541 } 542 } 543 }; 544 545 $.fn.t3menu = function(option) { 546 return this 547 .each(function() { 548 var $this = $(this), data = $this.data('megamenu'), options = typeof option == 'object' 549 && option; 550 551 // Ignore off-canvas navigation 552 if ($this.parents('#off-canvas-nav').length) 553 return; 554 if ($this.parents('#t3-off-canvas').length) 555 return; 556 557 if (!data) { 558 $this.data('megamenu', 559 (data = new T3Menu(this, options))); 560 561 } else { 562 if (typeof option == 'string' && data[option]) { 563 data[option]() 564 } 565 } 566 }) 567 }; 568 569 $.fn.t3menu.defaults = { 570 duration : 400, 571 timeout : 100, 572 hidedelay : 200, 573 hover : true, 574 sb_width : 20 575 }; 576 577 // apply script 578 $(document) 579 .ready( 580 function() { 581 582 // detect settings 583 var mm_duration = $('.t3-megamenu').data('duration') || 0; 584 if (mm_duration) { 585 586 $( 587 '<style type="text/css">' 588 + '.t3-megamenu.animate .animating > .mega-dropdown-menu,' 589 + '.t3-megamenu.animate.slide .animating > .mega-dropdown-menu > div {' 590 + 'transition-duration: ' 591 + mm_duration + 'ms !important;' 592 + '-webkit-transition-duration: ' 593 + mm_duration + 'ms !important;' 594 + '}' + '</style>') 595 .appendTo('head'); 596 } 597 598 var mm_timeout = mm_duration ? 100 + mm_duration : 500, mm_rtl = $( 599 document.documentElement).attr('dir') == 'rtl', mm_trigger = $( 600 document.documentElement).hasClass('mm-hover'), sb_width = (function() { 601 var parent = $( 602 '<div style="width:50px;height:50px;overflow:auto"><div/></div>') 603 .appendTo('body'), child = parent 604 .children(), width = child.innerWidth() 605 - child.height(100).innerWidth(); 606 607 parent.remove(); 608 609 return width; 610 })(); 611 612 // lt IE 10 613 if (!$.support.transition) { 614 // it is not support animate 615 $('.t3-megamenu').removeClass('animate'); 616 617 mm_timeout = 100; 618 } 619 620 // get ready 621 $('ul.nav').has('.dropdown-menu').t3menu({ 622 duration : mm_duration, 623 timeout : mm_timeout, 624 rtl : mm_rtl, 625 sb_width : sb_width, 626 hover : mm_trigger 627 }); 628 629 $(window).load(function() { 630 631 // check we miss any nav 632 $('ul.nav').has('.dropdown-menu').t3menu({ 633 duration : mm_duration, 634 timeout : mm_timeout, 635 rtl : mm_rtl, 636 sb_width : sb_width, 637 hover : mm_trigger 638 }); 639 640 }); 641 }); 642 643})(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.