1/*! CLICK NAVIGATION FUNCTIONALITY 2* Version: 0.9.8.4 3* Author: Nick Goodrum 4* Licensed under MIT: 5* http://www.opensource.org/licenses/mit-license.php 6* Followed WAI-ARIA spec except for typing a letter key keyboard functionality (optional) and left/right moving to next previous main tiers 7* TO DO - CONFIRM DATA-ATTRIBUTE APPROACH, EXTEND MEGA / SLIDING TO REDUCE CODE BASE, DETERMINE IF MORE OR LESS OF THE WAI-ARIA SPEC IS NEEDED */ 8 9(function(window, factory) { 10 'use strict'; 11 if (typeof define === 'function' && define.amd) { 12 define(['jquery'], function($) { 13 return factory(window, $); 14 }); 15 } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') { 16 module.exports = factory(window, require('jquery')); 17 } else { 18 factory(window, jQuery); 19 } 20}(typeof window !== "undefined" ? window : this, function(window, $) { 21 'use strict'; 22 var ClickMenu = window.ClickMenu || {}; 23 24 /*----------- ADD DEBOUNCER -----------*/ 25 26 // Code from Underscore.js 27 28 var debounce = function (func, wait, immediate) { 29 var timeout; 30 return function () { 31 var context = this, args = arguments; 32 var later = function () { 33 timeout = null; 34 if (!immediate) func.apply(context, args); 35 }; 36 var callNow = immediate && !timeout; 37 clearTimeout(timeout); 38 timeout = setTimeout(later, wait); 39 if (callNow) func.apply(context, args); 40 }; 41 }; 42 43 /*----------- ADD PROTOTYPE FOR OLDER BROWSERS -----------*/ 44 if (!Function.prototype.bind) { 45 Function.prototype.bind = function(){ 46 var fn = this, args = Array.prototype.slice.call(arguments), 47 object = args.shift(); 48 return function(){ 49 return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); 50 }; 51 }; 52 } 53 54 ClickMenu = (function() { 55 56 function ClickMenu(element, settings) { 57 var _ = this, 58 dataSettings; 59 60 _.defaults = { 61 menutype : "dropdown", 62 animationSpeed : 400, 63 toggle : "toggle-menu", 64 menu: "cm-menu", 65 htmlClass: "cm-js-menu-active", 66 expanderText: "expand / collapse", 67 //TODO: Eventually add parentLi Selector option so they aren't only lis 68 landings : false, 69 expanders: false, 70 singleClick : true, 71 isAutoClose: true, 72 isRTL : false 73 }; 74 75 dataSettings = $(element).data() || {}; 76 77 _.options = $.extend({}, _.defaults, dataSettings, settings); 78 79 _.menu = element; 80 _.$menu = $(element); 81 _.$menuBar = _.$menu.find("." + _.options.menu); 82 _.$menuToggle = _.$menu.find("." + _.options.toggle); 83 _.$html = $("html"); 84 _.touchStart = false; 85 _.isActive = false; 86 _.isToggled = false; 87 _.leavingMenu = false; 88 _.currentFocus = 0; 89 _.initialLinks = []; 90 _.currentLinks = []; 91 92 // Add in proxies so _ scope ties to this function even when called via outside event bindings, etc. 93 _.keyHandler = $.proxy(_.keyHandler, _); 94 _.findCurrentLinks = $.proxy(_.findCurrentLinks, _); 95 _.resetMenus = $.proxy(_.resetMenus, _); 96 _.cleanUpEvents = $.proxy(_.cleanUpEvents, _); 97 _.destroy = $.proxy(_.destroy, _); 98 _.showMenu = $.proxy(_.showMenu, _); 99 _.hideMenu = $.proxy(_.hideMenu, _); 100 _.menuToggle = $.proxy(_.menuToggle, _); 101 _.subMenuToggle = $.proxy(_.subMenuToggle, _); 102 _.menuHandler = $.proxy(_.menuHandler, _); 103 _.menuToggleHandler = $.proxy(_.menuToggleHandler, _); 104 105 if ( _.$menuBar.length > 0 ) {
106 _.init(); 107 } 108 } 109 110 return ClickMenu; 111 }()); 112 113 ClickMenu.prototype.init = function() { 114 var _ = this; 115 116 //Bind Toggle Function to expand/collapse menu in small screens 117 _.$menuToggle.on("touchstart click", _.menuToggle); 118 119 // Add Aria Aspects and initial classes to menu wrap and menu 120 _.$menu.addClass("cm-js-enabled").attr({"role" : "navigation"}); 121 _.$menuBar.attr("role", "menubar"); 122 123 //If there are prior dropdowns you want to get the highest one and add to the numbers 124 var idNum = 1; 125 126 if ( $("[id^='cm-dropdown']").last().length > 0 ) { 127 var highestNum = 0; 128 129 $("[id^='cm-dropdown']").each(function(){ 130 var currentNum = $(this).attr("id").split("dropdown")[1]; 131 132 highestNum = currentNum && highestNum < parseInt(currentNum, 10) ? parseInt(currentNum, 10) : highestNum; 133 }); 134 135 idNum = highestNum + 1; 136 } 137 138 _.$menu.on('keydown', _.keyHandler); 139 //With Firefox 52 support coming in - this is a clean solution for tab users to toggle open/close menus - but will need to possibly consider if focusin is worth the fighting 140 _.$menuBar.on('focusin', _.showMenu); 141 142 _.$menu.find("." + _.options.menu + " a").each(function () { 143 var $anchor = $(this), 144 $parentLi = $anchor.closest('li'), 145 $sibling; 146 147 $anchor.attr({"role" : "menuitem", "tabindex" : "-1" }); 148 $parentLi.attr("role", "presentation"); 149 150 if ( ! $parentLi.data("type") && $parentLi.parent().hasClass(_.options.menu)) { 151 $parentLi.attr('data-type', _.options.menutype); 152 } 153 154 // Have anchor do what it normally would do unless it has subs 155 156 if ( $anchor.siblings().not("a").length > 0 && $parentLi.attr("data-option") !== "openSubs" ) { 157 //Style it up via class 158 var $expandable = $anchor.siblings(), 159 newID = "cm-dropdown" + idNum; 160 161 if (_.options.expanders) { 162 $sibling = $("<a id='"+ newID +"' href='#' role='menuitem' aria-haspopup='true' class='has-sub' tabindex='-1'><span><span class='visually-hidden'>" + _.options.expanderText + " " + $anchor.text() + "</span></span></a>"); 163 $anchor.wrap("<div class='expander-wrap'></div>").after($sibling); 164 165 $sibling.on("click", _.subMenuToggle); 166 } else { 167 //if there is an ID use it and make sure the expandable item gets it otherwise add the new id created 168 if ( $anchor.attr("id") ) { 169 newID = $anchor.attr("id"); 170 } else { 171 $anchor.attr("id", "cm-dropdown" + idNum); 172 } 173 // bind click functionality for anchors as well as aria / class 174 $anchor.attr({ "aria-haspopup" : "true" }).addClass("has-sub").on("click", _.subMenuToggle); 175 } 176 177 var visibleAlready = $expandable.height() > 0 ? true : false; 178 $expandable.attr({"role": "menu", "aria-expanded" : visibleAlready, "aria-hidden" : !visibleAlready, "aria-labelledby" : newID }); 179 180 if (_.options.landings && !_.options.expanders) { 181 var $duplicate = $expandable.is("ul") ? $("<li class='link-landing' role='presentation'>" + $anchor.get(0).outerHTML + "</li>") : $("<div class='link-landing' role='presentation'>" + $anchor.get(0).outerHTML + "</div>"); 182 $duplicate.children().removeAttr("aria-haspopup class id"); 183 $duplicate.find("a").removeClass("has-sub"); 184 $expandable.prepend($duplicate); 185 } 186 187 if ( $parentLi.data("type") && $parentLi.data("type") === "sliding") { 188 var $subMenu = $("<div class='sub-menu cm-js-inactive'></div>"); 189 190 $expandable.wrap($subMenu); 191 192 var adjustMenu = function(){ 193 var maxWidth = _.$menu.innerWidth(), 194 leftPosition = $parentLi.position().left, 195 $adjustable; 196 197 $adjustable = $parentLi.children(".sub-menu"); 198 $adjustable.find("> ul > li > ul").innerWidth(maxWidth); 199 200 $adjustable.innerWidth(maxWidth).css("left", "-" + leftPosition + "px"); 201 }; 202 203 var debounceAdjustments = debounce(adjustMenu, 300); 204 205 $(window).load(function(){ 206 adjustMenu(); 207 208 $(window).resize(debounceAdjustments); 209 }); 210 211 } 212 213 if (newID === "cm-dropdown" + idNum) { 214 idNum++; 215 } 216 } 217 218 // ADD In Initial Links for main tier 219 if ( $anchor.closest("[role]:not(a)").is("[data-type]") && $anchor.is(":visible") ) { 220 _.initialLinks.push($anchor); 221 222 if (_.options.expanders && $sibling) { 223 _.initialLinks.push($sibling); 224 } 225 } 226 227 }); 228 229 // Focus Search Input on Search Icon Click and remove input field from tab sequence. 230 231 $("#search-button > button").click(function () { 232 $("#search-keywords").focus(); 233 }); 234 235 $('#search-keywords').each(function () { 236 $(this).attr('tabindex', '-1'); 237 }); 238 239 _.currentLinks = _.initialLinks; 240 241 if ( _.currentLinks[_.currentFocus] ) { 242 _.currentLinks[_.currentFocus].attr("tabindex", "0"); 243 } 244 245 _.$menu.trigger("init", [_]); 246 247 }; 248 249 250 ClickMenu.prototype.keyHandler = function(e) { 251 var _ = this, 252 keyPress = e.keyCode; 253 254 if ( ! _.$menu.hasClass("cm-js-inFocus") && keyPress !== 9 ) { 255 _.$menu.addClass("cm-js-inFocus").attr("tabindex", "-1"); 256 } 257 switch (keyPress) { 258 //TAB 259 case 9: 260 _.$menu.removeClass("cm-js-inFocus"); 261 break;
262 //LEFT UP RIGHT DOWN 263 case 37: 264 case 38: 265 case 39: 266 case 40: 267 //Prevent Scrolling aspects from browser 268 e.preventDefault(); 269 270 //Maintain currentLink since it will potentially be overwritten with the next focus 271 var oldLink = _.currentLinks[_.currentFocus]; 272 273 //Don't do anything if in mid transition 274 if (oldLink) { 275 var inMainTier = oldLink.closest("[role]:not(a)").is("[data-type]"), 276 next, direction, close, open; 277 278 //IF LEFT / UP (Depending on TIER) change next item to rotate to 279 280 if (inMainTier) { 281 // IF LEFT / RIGHT rotate to new item 282 if (keyPress === 37) { 283 direction = _.options.isRTL ? "next" : "prev"; 284 } else if (keyPress === 39) { 285 direction = _.options.isRTL ? "prev" : "next"; 286 } else if (keyPress === 40 || keyPress === 38) { 287 open = true; 288 } 289 } else { 290 // IF UP / DOWN rotate to new item - IF LEFT on sub subs close menu 291 if (keyPress === 38) { 292 direction = "prev"; 293 } else if (keyPress === 40) { 294 direction = "next"; 295 } else if ( keyPress === 39) { 296 if (_.options.isRTL) { 297 close = true; 298 } else { 299 open = true; 300 } 301 //} else if ( ! inSecondTier && keyPress === 37 ) { 302 } else if ( keyPress === 37 ) { 303 if (_.options.isRTL) { 304 open = true; 305 } else { 306 close = true; 307 } 308 } 309 } 310 311 if (direction) { 312 313 if (direction === "prev") { 314 //If there aren't any prior items move to last item in the list 315 _.currentFocus = _.currentFocus - 1 >= 0 ? _.currentFocus - 1 : _.currentLinks.length - 1; 316 } else { 317 //If there aren't any more items move to first item in the list 318 _.currentFocus = _.currentFocus + 1 < _.currentLinks.length ? _.currentFocus + 1 : 0; 319 } 320 next = _.currentLinks[_.currentFocus]; 321 322 } 323 324 //If there isn't anything next click the anchor 325 if (next) { 326 oldLink.attr("tabindex", "-1"); 327 _.currentLinks[_.currentFocus].attr("tabindex", "0").focus(); 328 } else if (close) { 329 //Same as ESCAPE - TBD should we actually close the whole menu and go to a previous item (ARIA Spec)? 330 _.$menu.find(".opened").last().find("[aria-haspopup]").first().trigger("click"); 331 } else if (open) { 332 //Only open if it isn't opened - escape is how to close a menu 333 //Also don't trigger click on a normal link - TBD should we really close the whole menu and go to the next item (ARIA Spec)? 334 if ( ! oldLink.closest("li").hasClass("opened") && _.currentLinks[_.currentFocus].hasClass("has-sub") ) { 335 _.currentLinks[_.currentFocus].trigger("click"); 336 } 337 } 338 } 339 break; 340 //ESCAPE 341 case 27: 342 e.preventDefault(); 343 _.$menu.find(".opened").last().find("[aria-haspopup]").first().trigger("click"); 344 break; 345 //SPACE BAR (ENTER ALREADY BY DEFAULT DOES THIS) 346 case 32: 347 e.preventDefault(); 348 _.currentLinks[_.currentFocus].trigger("click"); 349 break; 350 } 351 }; 352 353 ClickMenu.prototype.findCurrentLinks = function($parentLi, $currAnchor, skipFocus) { 354 var _ = this; 355 356 $.each(_.currentLinks, function() { 357 var $anchor = this;
358 //$anchor.attr("tabindex", "-1"); 359 }); 360 361 _.currentLinks = []; 362 _.currentFocus = 0; 363 364 if ( $parentLi && ! $parentLi.data("type") ) { 365 var actualKey = 0; 366 367 $parentLi.closest("[role=menu]").find("a, input, select, textarea, button").filter(":visible").each(function(key, val){ 368 //How do you find :hidden items that aren't actually hidden? Check the height of the parent - be careful of floating clearout issues 369 var $item = $(val); 370 //Looks like even with animation speed done correctly there can be a minor amount of pixels still transitioning in css 371 if ($item.closest("[role=menu]").height() > 10 && $item.closest("[role=menu]").width() > 10) { 372 _.currentLinks.push($item); 373 374 if ($currAnchor && $currAnchor.attr("id") && $currAnchor.attr("id") === $item.attr("id")) { 375 _.currentFocus = actualKey; 376 } 377 actualKey++; 378 } 379 }); 380 381 } else { 382 var $tabbables = _.$menuBar.find("a, input, select, textarea, button").filter(":visible"); 383 384 $tabbables.each(function(key, val){ 385 var $item = $(val); 386 if ( $item.closest("[role]:not(a)").is("[data-type]") ) { 387 _.currentLinks.push($item); 388 } 389 }); 390 //If a ParentLi is supplied e.g. from submenutoggle then get the eq otherwise get the first visible eq 391 _.currentFocus = $parentLi ? $parentLi.index() : 0; 392 } 393 394 if ( _.currentLinks[_.currentFocus] ) { 395 _.currentLinks[_.currentFocus].attr("tabindex", "0"); 396 397 if ( ! _.leavingMenu && ! skipFocus ) { 398 _.currentLinks[_.currentFocus].focus(); 399 } 400 } 401 }; 402 403 ClickMenu.prototype.resetMenus = function ($links) { 404 $links.each(function(){ 405 var $toggle = $(this), 406 $opened = $toggle.closest(".opened"), 407 labelId = $toggle.attr("id"), 408 $relatedSub = $("[aria-labelledby='" + labelId + "']"); 409 410 $toggle.attr("tabindex", "-1"); 411 $relatedSub.attr({"aria-hidden": true, "aria-expanded": false }); 412 $opened.removeClass("opened animating animated"); 413 }); 414 }; 415 416 ClickMenu.prototype.cleanUpEvents = function () { 417 var _ = this;
418 _.$menu.find("li a").off("click", _.subMenuToggle); 419 420 // Change into FOCUS with corresponding namespace function 421 _.$menu.off('keydown', _.keyHandler); 422 _.$menuBar.off("focusin", _.showMenu); 423 424 _.$html.off("touchstart click focusin", _.menuHandler); 425 _.$html.off("touchstart click focusin", _.menuToggleHandler); 426 }; 427 428 ClickMenu.prototype.destroy = function() { 429 var _ = this; 430 431 _.$menu.removeClass("cm-js-enabled cm-js-inFocus cm-js-active").removeAttr("tabindex"); 432 _.$menuBar.removeAttr("role"); 433 _.$menu.find("[role=presentation]").removeAttr("role").filter(".opened").removeClass("opened animating animated"); 434 _.$menu.find("[role=menuitem]").removeAttr("tabindex aria-haspopup role").removeClass("has-sub"); 435 _.$menu.find("[role=menu]").removeAttr("aria-expanded aria-hidden aria-labelledby role"); 436 _.cleanUpEvents(); 437 }; 438 439 ClickMenu.prototype.getClickMenu = function () { 440 return this; 441 }; 442 443 ClickMenu.prototype.showMenu = function(e) { 444 var _ = this; 445 446 //Need to make it check for hasClass on the current item rather than html and all items 447 if ( _.$menuBar.height() <= 10 && ! _.$menu.hasClass("cm-js-active") && ! _.$menu.hasClass("cm-animate-out") ) { 448 _.$menu.trigger("beforeMenuShow", [_]); 449 450 _.isActive = true; 451 _.isToggled = true; 452 _.$menu.addClass("cm-js-active"); 453 454 _.$menuToggle.addClass("active"); 455 _.$html.addClass(_.options.htmlClass); // ADD FOR INITIAL STYLING 456 457 _.findCurrentLinks(); 458 459 _.$html.off("touchstart click focusin", _.menuToggleHandler); 460 461 // ADD TOGGLE HANDLER AFTER ANIMATION TO PREVENT CLOSING MENUS FROM REMOVING THE HANDLER 462 setTimeout(function(){ 463 _.$menu.trigger("afterMenuShow", [_]); 464 _.$html.addClass(_.options.htmlClass).on("touchstart click focusin", _.menuToggleHandler); 465 }, _.options.animationSpeed); 466 } 467 468 }; 469 470 ClickMenu.prototype.hideMenu = function(e) { 471 var _ = this; 472 473 if ( _.$menu.hasClass("cm-js-active") && _.$html.hasClass(_.options.htmlClass) ) { 474 _.$menu.trigger("beforeMenuHide", [_]); 475 476 _.isActive = false; 477 _.isToggled = false; 478 _.$menu.removeClass("cm-js-active cm-js-inFocus"); 479 _.$menuToggle.removeClass("active"); 480 481 _.$html.removeClass(_.options.htmlClass).off("touchstart click focusin", _.menuToggleHandler); 482 _.$menu.addClass("cm-animate-out"); 483 484 setTimeout(function(){ 485 _.$html.removeClass(_.options.htmlClass); 486 _.$menu.removeClass("cm-animate-out").trigger("afterMenuHide", [_]); 487 }, _.options.animationSpeed); 488 } 489 }; 490 491 ClickMenu.prototype.menuToggle = function(e) { 492 var _ = this; 493 e.preventDefault(); 494 495 if ( e.type === "touchstart" || ! _.touchStart ) { 496 if (_.isActive) { 497 _.hideMenu(); 498 } else { 499 _.showMenu(); 500 } 501 } 502 503 _.touchStart = e.type === "touchstart" ? true : false; 504 505 }; 506 507 ClickMenu.prototype.subMenuToggle = function(e, params) { 508 var _ = this; 509 510 var $currAnchor = $(e.currentTarget), 511 $parentLi = $currAnchor.closest("li"), 512 $menuCol = $currAnchor.closest("[data-type]"), 513 menuType = $menuCol.data("type"), 514 $relatedMenu = $("[aria-labelledby=" + $currAnchor.attr("id") + "]"); 515 516 var subDefaults = { skipFocus : false }, 517 subOptions = $.extend({}, subDefaults, params); 518 519 520 _.$html.off("touchstart click focusin", _.menuHandler); 521 522 if ($parentLi.hasClass("opened")) { 523 524 _.$menu.trigger("beforeSubClose", [_, $currAnchor, $relatedMenu]); 525 526 if (_.options.singleClick) { 527 e.preventDefault(); 528 529 if (menuType === "sliding" && $parentLi.parents(".sub-menu").hasClass("sub-menu")) { 530 $parentLi.parents(".sub-menu").addClass("cm-js-inactive"); 531 } 532 533 $parentLi.removeClass("opened animating animated"); 534 535 if (_.$menu.find(".opened").length > 0 && _.options.isAutoClose){ 536 _.$html.on("touchstart click focusin", _.menuHandler); 537 } 538 539 $relatedMenu.attr({ "aria-expanded" : "false", "aria-hidden" : "true" }); 540 541 $relatedMenu.find("[aria-expanded=true]").each(function(){ 542 var $childMenu = $(this); 543 544 $childMenu.attr({ "aria-expanded" : "false", "aria-hidden" : "true" }).closest("[role=presentation]").removeClass("opened animating animated"); 545 }); 546 547 setTimeout(function(){ 548 549 //Update Current Links for keyboard 550 _.findCurrentLinks($parentLi, $currAnchor, subOptions.skipFocus); 551 552 _.$menu.trigger("afterSubClose", [_, $currAnchor, $relatedMenu]); 553 554 }, _.options.animationSpeed); 555 556 } 557 } else { 558 // Otherwise Open submenu and attach site click handler 559 // Also - close any other open menus and their children 560 e.preventDefault(); 561 562 _.$menu.trigger("beforeSubOpen", [_, $currAnchor, $relatedMenu]); 563 564 $parentLi.addClass("opened animating").siblings().removeClass("opened animating animated") 565 .find(".opened").removeClass("opened animating animated"); 566 567 //FOR SLIDING MENUS 568 $parentLi.siblings().find(".sub-menu").addClass("cm-js-inactive"); 569 570 if ( menuType === "sliding" && $parentLi.parents(".sub-menu").length > 0 ) { 571 $parentLi.parents(".sub-menu").removeClass("cm-js-inactive"); 572 } 573 //END FOR SLIDING MENU 574 575 $relatedMenu.attr({ "aria-expanded" : "true", "aria-hidden" : "false" }); 576 577 //Wait until timer is complete so the bindings and currentLink groupings don't overlap 578 setTimeout(function(){ 579 if ($parentLi.hasClass("animating")) { 580 $parentLi.removeClass("animating").addClass("animated"); 581 } 582 583 //Update Current Links for keyboard 584 _.findCurrentLinks($relatedMenu, $relatedMenu.find("a").first(), subOptions.skipFocus); 585 586 // ADD TOGGLE HANDLER AFTER ANIMATION TO PREVENT CLOSING MENUS FROM REMOVING THE HANDLER 587 if ( _.options.isAutoClose ) { // Only add if (default) menus set to auto close 588 _.$html.on("touchstart click focusin", _.menuHandler); 589 } 590 591 _.$menu.trigger("afterSubOpen", [_, $currAnchor, $relatedMenu]); 592 593 }, _.options.animationSpeed); 594 } 595 }; 596 597 ClickMenu.prototype.menuToggleHandler = function(e) { 598 var _ = this; 599 600 if ( ! $.contains(_.menu, e.target) && ! _.$menu.is( $(e.target) ) && _.isToggled ) { 601 _.isToggled = false; 602 _.touchStart = false; 603 604 if ( _.$menuToggle.length > 0 ) { 605 _.$menuToggle.trigger("click"); 606 } else { 607 _.hideMenu(); 608 } 609 610 _.$html.removeClass(_.options.htmlClass).off("touchstart click focusin", _.menuToggleHandler); 611 } 612 }; 613 614 ClickMenu.prototype.menuHandler = function(e) { 615 var _ = this; 616 617 if ( ! $.contains(_.menu, e.target) && ! _.$menu.is($(e.target)) ) { 618 //Make sure not to leave any tabindex=0 on submenu links by making sure the toggle knows we are leaving the menu 619 _.leavingMenu = true; 620 621 _.resetMenus( _.$menu.find(".opened > .has-sub, .opened > .expander-wrap > .has-sub") ); 622 _.findCurrentLinks(); 623 624 _.$html.off("touchstart click focusin", _.menuHandler); 625 626 setTimeout(function(){ 627 //We now know we have left the menu and are done triggering sub menus 628 _.leavingMenu = false; 629 }, _.options.animationSpeed); 630 } 631 }; 632 633 $.fn.clickMenu = function() { 634 var _ = this, 635 opt = arguments[0], 636 args = Array.prototype.slice.call(arguments, 1), 637 l = _.length, 638 i, 639 ret; 640 641 for (i = 0; i < l; i++) { 642 if (typeof opt == 'object' || typeof opt == 'undefined') { 643 _[i].clickMenu = new ClickMenu(_[i], opt); 644 } else { 645 ret = _[i].clickMenu[opt].apply(_[i].clickMenu, args); 646 } 647 648 if (typeof ret != 'undefined') return ret; 649 } 650 651 return _; 652 }; 653 654}));
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.