1/* 2 * jQuery clueTip plugin 3 * Version 0.9.8 (05/22/2008) 4 * @requires jQuery v1.1.4+ 5 * @requires Dimensions plugin (for jQuery versions < 1.2.5) 6 * 7 * Dual licensed under the MIT and GPL licenses: 8 * http://www.opensource.org/licenses/mit-license.php 9 * http://www.gnu.org/licenses/gpl.html 10 * 11 */ 12;(function($) { 13/* 14 * @name clueTip 15 * @type jQuery 16 * @cat Plugins/tooltip 17 * @return jQuery 18 * @author Karl Swedberg 19 * 20 * @credit Inspired by Cody Lindley's jTip (http://www.codylindley.com) 21 * @credit Thanks to the following people for their many and varied contributions: 22 Shelane Enos, Glen Lipka, Hector Santos, Torben Schreiter, Dan G. Switzer, Jörn Zaefferer 23 * @credit Thanks to Jonathan Chaffer, as always, for help with the hard parts. :-) 24 */ 25 26 /** 27 * 28 * Displays a highly customizable tooltip when the user hovers (default) or clicks (optional) the matched element. 29 * By default, the clueTip plugin loads a page indicated by the "rel" attribute via ajax and displays its contents. 30 * If a "title" attribute is specified, its value is used as the clueTip's heading. 31 * The attribute to be used for both the body and the heading of the clueTip is user-configurable. 32 * Optionally, the clueTip's body can display content from an element on the same page. 33 * * Just indicate the element's id (e.g. "#some-id") in the rel attribute. 34 * Optionally, the clueTip's body can display content from the title attribute, when a delimiter is indicated. 35 * * The string before the first instance of the delimiter is set as the clueTip's heading. 36 * * All subsequent strings are wrapped in separate DIVs and placed in the clueTip's body. 37 * The clueTip plugin allows for many, many more options. Pleasee see the examples and the option descriptions below... 38 * 39 * 40 * @example $('#tip).cluetip(); 41 * @desc This is the most basic clueTip. It displays a 275px-wide clueTip on mouseover of the element with an ID of "tip." On mouseout of the element, the clueTip is hidden. 42 * 43 * 44 * @example $('a.clue').cluetip({ 45 * hoverClass: 'highlight', 46 * sticky: true, 47 * closePosition: 'bottom', 48 * closeText: '<img src="cross.png" alt="close" />', 49 * truncate: 60, 50 * ajaxSettings: { 51 * type: 'POST' 52 * } 53 * }); 54 * @desc Displays a clueTip on mouseover of all <a> elements with class="clue". The hovered element gets a class of "highlight" added to it (so that it can be styled appropriately. This is esp. useful for non-anchor elements.). The clueTip is "sticky," which means that it will not be hidden until the user either clicks on its "close" text/graphic or displays another clueTip. The "close" text/graphic is set to diplay at the bottom of the clueTip (default is top) and display an image rather than the default "Close" text. Moreover, the body of the clueTip is truncated to the first 60 characters, which are followed by an ellipsis (...). Finally, the clueTip retrieves the content using POST rather than the $.ajax method's default "GET." 55 * 56 * More examples can be found at http://plugins.learningjquery.com/cluetip/demo/ 57 * 58 * Full list of options/settings can be found at the bottom of this file and at http://plugins.learningjquery.com/cluetip/ 59 */ 60 61 var $cluetip, $cluetipInner, $cluetipOuter, $cluetipTitle, $cluetipArrows, $dropShadow, imgCount; 62 $.fn.cluetip = function(js, options) { 63 if (typeof js == 'object') { 64 options = js; 65 js = null; 66 } 67 return this.each(function(index) { 68 var $this = $(this); 69 70 // support metadata plugin (v1.0 and 2.0) 71 var opts = $.extend(false, {}, $.fn.cluetip.defaults, options || {}, $.metadata ? $this.metadata() : $.meta ? $this.data() : {}); 72 73 // start out with no contents (for ajax activation) 74 var cluetipContents = false; 75 var cluezIndex = parseInt(opts.cluezIndex, 10)-1; 76 var isActive = false, closeOnDelay =0; 77 78 // create the cluetip divs 79 if (!$('#cluetip').length) { 80 $cluetipInner = $('<div id="cluetip-inner"></div>'); 81 $cluetipTitle = $('<h3 id="cluetip-title"></h3>'); 82 $cluetipOuter = $('<div id="cluetip-outer"></div>').append($cluetipInner).prepend($cluetipTitle); 83 $cluetip = $('<div id="cluetip"></div>').css({zIndex: opts.cluezIndex}) 84 .append($cluetipOuter).append('<div id="cluetip-extra"></div>')[insertionType](insertionElement).hide(); 85 $('<div id="cluetip-waitimage"></div>').css({position: 'absolute', zIndex: cluezIndex-1}) 86 .insertBefore('#cluetip').hide(); 87 $cluetip.css({position: 'absolute', zIndex: cluezIndex}); 88 $cluetipOuter.css({position: 'relative', zIndex: cluezIndex+1}); 89 $cluetipArrows = $('<div id="cluetip-arrows" class="cluetip-arrows"></div>').css({zIndex: cluezIndex+1}).appendTo('#cluetip'); 90 } 91 var dropShadowSteps = (opts.dropShadow) ? +opts.dropShadowSteps : 0; 92 if (!$dropShadow) { 93 $dropShadow = $([]); 94 for (var i=0; i < dropShadowSteps; i++) { 95 $dropShadow = $dropShadow.add($('<div></div>').css({zIndex: cluezIndex-i-1, opacity:.1, top: 1+i, left: 1+i})); 96 }; 97 $dropShadow.css({position: 'absolute', backgroundColor: '#000'}) 98 .prependTo($cluetip); 99 } 100 var tipAttribute = $this.attr(opts.attribute), ctClass = opts.cluetipClass; 101 if (!tipAttribute && !opts.splitTitle && !js) return true; 102 // if hideLocal is set to true, on DOM ready hide the local content that will be displayed in the clueTip 103 if (opts.local && opts.hideLocal) { $(tipAttribute + ':first').hide(); } 104 if (opts.topOffset == null) { 105 var ele_offset_top = $(this).offset(); 106 ele_offset_top = ele_offset_top.top; 107 var tOffset = parseInt(ele_offset_top, 10) 108 } else { 109 var tOffset = parseInt(opts.topOffset, 10) 110 } 111 if (opts.leftOffset == null) { 112 var ele_offset_left = $(this).offset(); 113 ele_offset_left = ele_offset_left.left;
114 var lOffset = parseInt(ele_offset_left, 10) 115 } else { 116 var lOffset = parseInt(opts.leftOffset, 10); 117 } 118 119 // vertical measurement variables 120 var tipHeight, wHeight; 121 var defHeight = isNaN(parseInt(opts.height, 10)) ? 'auto' : (/\D/g).test(opts.height) ? opts.height : opts.height + 'px'; 122 var sTop, linkTop, posY, tipY, mouseY, baseline; 123 // horizontal measurement variables 124 var tipInnerWidth = isNaN(parseInt(opts.width, 10)) ? 275 : parseInt(opts.width, 10); 125 var tipWidth = tipInnerWidth + (parseInt($cluetip.css('paddingLeft'))||0) + (parseInt($cluetip.css('paddingRight'))||0) + dropShadowSteps; 126 var linkWidth = this.offsetWidth; 127 var linkLeft, posX, tipX, mouseX, winWidth; 128 129 // parse the title 130 var tipParts; 131 var tipTitle = (opts.attribute != 'title') ? $this.attr(opts.titleAttribute) : ''; 132 if (opts.splitTitle) { 133 if(tipTitle == undefined) {tipTitle = '';} 134 tipParts = tipTitle.split(opts.splitTitle); 135 tipTitle = tipParts.shift(); 136 } 137 var localContent; 138 139/*************************************** 140* ACTIVATION 141****************************************/ 142 143//activate clueTip 144 var activate = function(event) { 145 if (!opts.onActivate($this)) { 146 return false; 147 } 148 isActive = true; 149 $cluetip.removeClass().css({width: tipInnerWidth}); 150 if (tipAttribute == $this.attr('href')) { 151 $this.css('cursor', opts.cursor); 152 } 153 $this.attr('title',''); 154 if (opts.hoverClass) { 155 $this.addClass(opts.hoverClass); 156 } 157 linkTop = posY = $this.offset().top; 158 linkLeft = $this.offset().left; 159 mouseX = event.pageX; 160 mouseY = event.pageY; 161 if ($this[0].tagName.toLowerCase() != 'area') { 162 sTop = $(document).scrollTop(); 163 winWidth = $(window).width(); 164 } 165// position clueTip horizontally 166 if (opts.positionBy == 'fixed') { 167 posX = linkWidth + linkLeft + lOffset; 168 $cluetip.css({left: posX}); 169 } else { 170 posX = (linkWidth > linkLeft && linkLeft > tipWidth) 171 || linkLeft + linkWidth + tipWidth + lOffset > winWidth 172 ? linkLeft - tipWidth - lOffset 173 : linkWidth + linkLeft + lOffset; 174 if ($this[0].tagName.toLowerCase() == 'area' || opts.positionBy == 'mouse' || linkWidth + tipWidth > winWidth) { // position by mouse 175 if (mouseX + 20 + tipWidth > winWidth) { 176 $cluetip.addClass(' cluetip-' + ctClass); 177 posX = (mouseX - tipWidth - lOffset) >= 0 ? mouseX - tipWidth - lOffset - parseInt($cluetip.css('marginLeft'),10) + parseInt($cluetipInner.css('marginRight'),10) : mouseX - (tipWidth/2); 178 } else { 179 posX = mouseX + lOffset; 180 } 181 } 182 var pY = posX < 0 ? event.pageY + tOffset : event.pageY; 183 $cluetip.css({left: (posX > 0 && opts.positionBy != 'bottomTop') ? posX : (mouseX + (tipWidth/2) > winWidth) ? winWidth/2 - tipWidth/2 : Math.max(mouseX - (tipWidth/2),0)}); 184 } 185 wHeight = $(window).height(); 186 187/*************************************** 188* load a string from cluetip method's first argument 189***************************************/ 190 if (js) { 191 $cluetipInner.html(js); 192 cluetipShow(pY); 193 } 194/*************************************** 195* load the title attribute only (or user-selected attribute). 196* clueTip title is the string before the first delimiter 197* subsequent delimiters place clueTip body text on separate lines 198***************************************/ 199 200 else if (tipParts) { 201 var tpl = tipParts.length; 202 for (var i=0; i < tpl; i++){ 203 if (i == 0) { 204 $cluetipInner.html(tipParts[i]); 205 } else { 206 $cluetipInner.append('<div class="split-body">' + tipParts[i] + '</div>'); 207 } 208 }; 209 cluetipShow(pY); 210 } 211/*************************************** 212* load external file via ajax 213***************************************/ 214 215 else if (!opts.local && tipAttribute.indexOf('#') != 0) { 216 if (cluetipContents && opts.ajaxCache) { 217 $cluetipInner.html(cluetipContents); 218 cluetipShow(pY); 219 } 220 else { 221 var ajaxSettings = opts.ajaxSettings; 222 ajaxSettings.url = tipAttribute; 223 ajaxSettings.beforeSend = function() { 224 $cluetipOuter.children().empty(); 225 if (opts.waitImage) { 226 $('#cluetip-waitimage') 227 .css({top: mouseY+20, left: mouseX+20}) 228 .show(); 229 } 230 }; 231 ajaxSettings.error = function() { 232 if (isActive) { 233 $cluetipInner.html('<i>sorry, the contents could not be loaded</i>'); 234 } 235 }; 236 ajaxSettings.success = function(data) { 237 cluetipContents = opts.ajaxProcess(data); 238 if (isActive) { 239 $cluetipInner.html(cluetipContents); 240 } 241 }; 242 ajaxSettings.complete = function() { 243 imgCount = $('#cluetip-inner img').length; 244 if (imgCount && !$.browser.opera) { 245 $('#cluetip-inner img').load(function() { 246 imgCount--; 247 if (imgCount<1) { 248 $('#cluetip-waitimage').hide(); 249 if (isActive) cluetipShow(pY); 250 } 251 }); 252 } else { 253 $('#cluetip-waitimage').hide(); 254 if (isActive) cluetipShow(pY); 255 } 256 }; 257 $.ajax(ajaxSettings); 258 } 259 260/*************************************** 261* load an element from the same page 262***************************************/ 263 } else if (opts.local){ 264 var $localContent = $(tipAttribute + ':first');
265 var localCluetip = $.fn.wrapInner && !opts.noWrapInner ? $localContent.wrapInner('<div></div>').children().clone(true) : $localContent.html(); 266 $.fn.wrapInner && !opts.noWrapInner ? $cluetipInner.empty().append(localCluetip) : $cluetipInner.html(localCluetip); 267 cluetipShow(pY); 268 } 269 }; 270 271// get dimensions and options for cluetip and prepare it to be shown 272 var cluetipShow = function(bpY) { 273 $cluetip.addClass('cluetip-' + ctClass); 274 275 if (opts.truncate) { 276 var $truncloaded = $cluetipInner.text().slice(0,opts.truncate) + '...'; 277 $cluetipInner.html($truncloaded); 278 } 279 function doNothing() {}; //empty function 280 tipTitle ? $cluetipTitle.show().html(tipTitle) : (opts.showTitle) ? $cluetipTitle.show().html(' ') : $cluetipTitle.hide(); 281 if (opts.sticky) { 282 var $closeLink = $('<div id="cluetip-close"><a href="#">' + opts.closeText + '</a></div>'); 283 (opts.closePosition == 'bottom') ? $closeLink.appendTo($cluetipInner) : (opts.closePosition == 'title') ? $closeLink.prependTo($cluetipTitle) : $closeLink.prependTo($cluetipInner); 284 $closeLink.click(function() { 285 cluetipClose(); 286 return false; 287 }); 288 if (opts.mouseOutClose) { 289 if ($.fn.hoverIntent && opts.hoverIntent) { 290 $cluetip.hoverIntent({ 291 over: doNothing, 292 timeout: opts.hoverIntent.timeout, 293 out: function() { $closeLink.trigger('click'); } 294 }); 295 } else { 296 $cluetip.hover(doNothing, 297 function() {$closeLink.trigger('click'); }); 298 } 299 } else { 300 $cluetip.unbind('mouseout'); 301 } 302 } 303// now that content is loaded, finish the positioning 304 var direction = ''; 305 $cluetipOuter.css({overflow: defHeight == 'auto' ? 'visible' : 'auto', height: defHeight}); 306 tipHeight = defHeight == 'auto' ? Math.max($cluetip.outerHeight(),$cluetip.height()) : parseInt(defHeight,10); 307 tipY = posY; 308 baseline = sTop + wHeight; 309 if (opts.positionBy == 'fixed') { 310 tipY = posY - opts.dropShadowSteps + tOffset; 311 } else if ( (posX < mouseX && Math.max(posX, 0) + tipWidth > mouseX) || opts.positionBy == 'bottomTop') { 312 if (posY + tipHeight + tOffset > baseline && mouseY - sTop > tipHeight + tOffset) { 313 tipY = mouseY - tipHeight - tOffset; 314 direction = 'top'; 315 } else { 316 tipY = mouseY + tOffset; 317 direction = 'bottom'; 318 } 319 } else if ( posY + tipHeight + tOffset > baseline ) { 320 tipY = (tipHeight >= wHeight) ? sTop : baseline - tipHeight - tOffset; 321 } else if ($this.css('display') == 'block' || $this[0].tagName.toLowerCase() == 'area' || opts.positionBy == "mouse") { 322 tipY = bpY - tOffset; 323 } else { 324 tipY = posY - opts.dropShadowSteps; 325 } 326 if (direction == '') { 327 posX < linkLeft ? direction = 'left' : direction = 'right'; 328 } 329 $cluetip.css({top: tipY + 'px'}).removeClass().addClass('clue-' + direction + '-' + ctClass).addClass(' cluetip-' + ctClass); 330 if (opts.arrows) { // set up arrow positioning to align with element 331 var bgY = (posY - tipY - opts.dropShadowSteps); 332 $cluetipArrows.css({top: (/(left|right)/.test(direction) && posX >=0 && bgY > 0) ? (bgY - 15) + 'px' : /(left|right)/.test(direction) ? 0 : ''}).show(); 333 } else { 334 $cluetipArrows.hide(); 335 } 336 337// (first hide, then) ***SHOW THE CLUETIP*** 338 $dropShadow.hide(); 339 $cluetip.hide()[opts.fx.open](opts.fx.open != 'show' && opts.fx.openSpeed); 340 if (opts.dropShadow) $dropShadow.css({height: tipHeight, width: tipInnerWidth}).show(); 341 if ($.fn.bgiframe) { $cluetip.bgiframe(); } 342 // trigger the optional onShow function 343 if (opts.delayedClose > 0) { 344 closeOnDelay = setTimeout(cluetipClose, opts.delayedClose); 345 } 346 opts.onShow($cluetip, $cluetipInner); 347 348 }; 349 350/*************************************** 351 =INACTIVATION 352-------------------------------------- */ 353 var inactivate = function() { 354 isActive = false;
355 $('#cluetip-waitimage').hide(); 356 if (!opts.sticky || (/click|toggle/).test(opts.activation) ) { 357 cluetipClose(); 358clearTimeout(closeOnDelay); 359 }; 360 if (opts.hoverClass) { 361 $this.removeClass(opts.hoverClass); 362 } 363 $('.cluetip-clicked').removeClass('cluetip-clicked'); 364 }; 365// close cluetip and reset some things 366 var cluetipClose = function() { 367 $cluetipOuter 368 .parent().hide().removeClass().end() 369 .children().empty(); 370 if (tipTitle) { 371 $this.attr(opts.titleAttribute, tipTitle); 372 } 373 $this.css('cursor',''); 374 if (opts.arrows) $cluetipArrows.css({top: ''}); 375 }; 376 377/*************************************** 378 =BIND EVENTS 379-------------------------------------- */ 380 // activate by click 381 if ( (/click|toggle/).test(opts.activation) ) { 382 $this.click(function(event) { 383 if ($cluetip.is(':hidden') || !$this.is('.cluetip-clicked')) { 384 activate(event); 385 $('.cluetip-clicked').removeClass('cluetip-clicked'); 386 $this.addClass('cluetip-clicked'); 387 388 } else { 389 inactivate(event); 390 391 } 392 this.blur(); 393 return false; 394 }); 395 // activate by focus; inactivate by blur 396 } else if (opts.activation == 'focus') { 397 $this.focus(function(event) { 398 activate(event); 399 }); 400 $this.blur(function(event) { 401 inactivate(event); 402 }); 403 // activate by hover 404 // clicking is returned false if cluetip url is same as href url 405 } else { 406 $this.click(function() { 407 if ($this.attr('href') && $this.attr('href') == tipAttribute && !opts.clickThrough) { 408 return false; 409 } 410 }); 411 //set up mouse tracking 412 var mouseTracks = function(evt) { 413 if (opts.tracking == true) { 414 var trackX = posX - evt.pageX; 415 var trackY = tipY ? tipY - evt.pageY : posY - evt.pageY; 416 $this.mousemove(function(evt) { 417 $cluetip.css({left: evt.pageX + trackX, top: evt.pageY + trackY }); 418 }); 419 } 420 }; 421 if ($.fn.hoverIntent && opts.hoverIntent) { 422 $this.mouseover(function() {$this.attr('title',''); }) 423 .hoverIntent({ 424 sensitivity: opts.hoverIntent.sensitivity, 425 interval: opts.hoverIntent.interval, 426 over: function(event) { 427 activate(event); 428 mouseTracks(event); 429 }, 430 timeout: opts.hoverIntent.timeout, 431 out: function(event) {inactivate(event); $this.unbind('mousemove');} 432 }); 433 } else { 434 $this.hover(function(event) { 435 activate(event); 436 mouseTracks(event); 437 }, function(event) { 438 inactivate(event); 439 $this.unbind('mousemove'); 440 }); 441 } 442 } 443 }); 444 }; 445 446/* 447 * options for clueTip 448 * 449 * each one can be explicitly overridden by changing its value. 450 * for example: $.fn.cluetip.defaults.width = 200; 451 * would change the default width for all clueTips to 200. 452 * 453 * each one can also be overridden by passing an options map to the cluetip method. 454 * for example: $('a.example').cluetip({width: 200}); 455 * would change the default width to 200 for clueTips invoked by a link with class of "example" 456 * 457 */ 458 459 $.fn.cluetip.defaults = { // set up default options 460 width: 275, // The width of the clueTip 461 height: 200, // The height of the clueTip 462 cluezIndex: 999, // Sets the z-index style property of the clueTip 463 positionBy: 'auto', // Sets the type of positioning: 'auto', 'mouse','bottomTop', 'fixed' 464 topOffset: 15, // Number of px to offset clueTip from top of invoking element 465 leftOffset: 15, // Number of px to offset clueTip from left of invoking element 466 local: false, // Whether to use content from the same page for the clueTip's body 467 hideLocal: true, // If local option is set to true, this determines whether local content 468 // to be shown in clueTip should be hidden at its original location 469 attribute: 'rel', // the attribute to be used for fetching the clueTip's body content 470 titleAttribute: 'title', // the attribute to be used for fetching the clueTip's title 471 splitTitle: '', // A character used to split the title attribute into the clueTip title and divs 472 // within the clueTip body. more info below [6] 473 noWrapInner: false, 474 showTitle: true, // show title bar of the clueTip, even if title attribute not set 475 cluetipClass: 'default',// class added to outermost clueTip div in the form of 'cluetip-' + clueTipClass. 476 hoverClass: '', // class applied to the invoking element onmouseover and removed onmouseout 477 waitImage: true, // whether to show a "loading" img, which is set in jquery.cluetip.css 478 cursor: 'help', 479 arrows: false, // if true, displays arrow on appropriate side of clueTip 480 dropShadow: true, // set to false if you don't want the drop-shadow effect on the clueTip 481 dropShadowSteps: 6, // adjusts the size of the drop shadow 482 sticky: false, // keep visible until manually closed 483 mouseOutClose: false, // close when clueTip is moused out 484 activation: 'hover', // set to 'click' to force user to click to show clueTip 485 // set to 'focus' to show on focus of a form element and hide on blur 486 clickThrough: false, // if true, and activation is not 'click', then clicking on link will take user to the link's href, 487 // even if href and tipAttribute are equal 488 tracking: false, // if true, clueTip will track mouse movement (experimental) 489 delayedClose: 0, // close clueTip on a timed delay (experimental) 490 closePosition: 'top', // location of close text for sticky cluetips; can be 'top' or 'bottom' or 'title'
491 closeText: 'Close', // text (or HTML) to to be clicked to close sticky clueTips 492 truncate: 0, // number of characters to truncate clueTip's contents. if 0, no truncation occurs 493 494 // effect and speed for opening clueTips 495 fx: { 496 open: 'show', // can be 'show' or 'slideDown' or 'fadeIn' 497 openSpeed: '' 498 }, 499 500 // settings for when hoverIntent plugin is used 501 hoverIntent: { 502 sensitivity: 3, 503 interval: 50, 504 timeout: 0 505 }, 506 507 // function to run just before clueTip is shown. 508 onActivate: function(e) {return true;}, 509 510 // function to run just after clueTip is shown. 511 onShow: function(ct, c){}, 512 513 // whether to cache results of ajax request to avoid unnecessary hits to server 514 ajaxCache: true, 515 516 // process data retrieved via xhr before it's displayed 517 ajaxProcess: function(data) { 518 data = data.replace(/<s(cript|tyle)(.|\s)*?\/s(cript|tyle)>/g, '').replace(/<(link|title)(.|\s)*?\/(link|title)>/g,''); 519 return data; 520 }, 521 522 // can pass in standard $.ajax() parameters, not including error, complete, success, and url 523 ajaxSettings: { 524 dataType: 'html' 525 }, 526 debug: false 527 }; 528 529 530/* 531 * Global defaults for clueTips. Apply to all calls to the clueTip plugin. 532 * 533 * @example $.cluetip.setup({ 534 * insertionType: 'prependTo', 535 * insertionElement: '#container' 536 * }); 537 * 538 * @property 539 * @name $.cluetip.setup 540 * @type Map 541 * @cat Plugins/tooltip 542 * @option String insertionType: Default is 'appendTo'. Determines the method to be used for inserting the clueTip into the DOM. Permitted values are 'appendTo', 'prependTo', 'insertBefore', and 'insertAfter' 543 * @option String insertionElement: Default is 'body'. Determines which element in the DOM the plugin will reference when inserting the clueTip. 544 * 545 */ 546 547 var insertionType = 'appendTo', insertionElement = 'body'; 548 $.cluetip = {}; 549 $.cluetip.setup = function(options) { 550 if (options && options.insertionType && (options.insertionType).match(/appendTo|prependTo|insertBefore|insertAfter/)) { 551 insertionType = options.insertionType; 552 } 553 if (options && options.insertionElement) { 554 insertionElement = options.insertionElement; 555 } 556 }; 557 558})(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.