1 2/** 3 * Finds verse references and highlights them 4 * 5 * @author John Dyer (http://j.hn/) 6 */ 7 8docs.plugins.push({ 9 10 init: function(docManager) { 11 12 // insert style 13 $('<style id="verse-popup-style">.tagged-reference { cursor: pointer; color: #779; }</style>').appendTo($(document.body)); 14 15 // create popup 16 var versePopup = docs.createModal('Verses', 'Verses'); 17 versePopup.content.css({'max-height': '150px', 'overflow': 'auto'}); 18 19 // setup events to add media icons 20 docManager.addEventListener('load', function(e) { 21 findVerses(e.chapter); 22 }); 23 24 function findVerses(chapter) { 25 26 bibly.ignoreClassName = 'cf'; 27 bibly.handleLinks = function(node, reference) { 28 29 //node.style.fontWeight = 'bold'; 30 //node.style.color = '#0ff'; 31 node.className = 'tagged-reference'; 32 33 $(node).on('mouseover', function() { 34 35 // measure position 36 var 37 node = $(this), 38 nodePos = node.offset(), 39 nodeWidth = node.width(), 40 nodeHeight = node.height(), 41 popupWidth = versePopup.window.outerWidth(true), 42 popupHeight = versePopup.window.outerHeight(true), 43 windowWidth = $(window).width(), 44 windowHeight = $(window).height(), 45 // default to below and to the right 46 top = (nodePos.top + nodeHeight + nodeHeight > windowHeight) ? nodePos.top - popupHeight - 5 : nodePos.top + nodeHeight + 4, 47 left = (nodePos.left + popupWidth > windowWidth) ? windowWidth - popupWidth : nodePos.left; 48 49 50 versePopup.title.html(reference.toString()); 51 versePopup.show(); 52 versePopup.window.css({top: top, left: left}); 53 54 var chapterUrl = 'content/bibles/' + docManager.documents[0].selector.val() + '/' + reference.osisBookID + '.' + reference.chapter1 + '.html'; 55 56 versePopup.content.html('Loading...'); 57 58 // TODO: get verse text! 59 $.ajax({
60 url: chapterUrl, 61 dataType: 'html', 62 success: function(data) { 63 var verseClasses = [], 64 startVerse = reference.verse1 > 0 ? reference.verse1 : 1, 65 endVerse = reference.verse2 > 0 ? Math.min(reference.verse1+3,reference.verse2) : reference.verse1; 66 67 for (var i=startVerse; i<=endVerse; i++) { 68 verseClasses.push('.' + reference.osisBookID + '_' + reference.chapter1 + '_' + i); 69 } 70 71 versePopup.content.empty(); 72 73 var verses = $(data).find( verseClasses.join(',') ) 74 .find('span.note, span.cf') 75 .remove() 76 .end(); 77 78 verses.appendTo(versePopup.content); 79 80 }, error: function() { 81 82 console.log('error', chapterUrl); 83 } 84 }); 85 86 87 }).on('mouseout', function() { 88 89 versePopup.hide(); 90 91 }).on('click', function() { 92 93 var firstDoc = docManager.documents[0]; 94 95 firstDoc.input.val( reference.toString() ); 96 firstDoc.navigateToUserInput(); 97 }); 98 99 100 } 101 102 //console.log('scan', chapter[0]); 103 104 bibly.scanForReferences(chapter[0]); 105 106 } 107 } 108}); 109 110 111bible.genNames = function() { 112 var names = [], 113 i = 0, 114 il = bible.DEFAULT_BIBLE.length; 115 for (; i<il; i++) { 116 117 var osisName = bible.DEFAULT_BIBLE[i]; 118 119 names.push( bible.BOOK_DATA[osisName].names['eng'].join('|') ); 120 } 121 122 return names.join('|'); 123}; 124 125 126// adapted from old scripturizer.js code 127 128(function() { 129 130 /* Scripture API methods */ 131 var 132 callbackIndex = 100000, 133 jsonpCache = {}, 134 jsonp = function(url, callback){ 135 136 var jsonpName = 'callback' + (callbackIndex++), 137 script = doc.createElement("script"); 138 139 win[jsonpName] = function(d) { 140 callback(d); 141 } 142 jsonpCache[url] = jsonpName; 143 144 url += (url.indexOf("?") > -1 ? '&' : '?') + 'callback=' + jsonpName; 145 //url += '&' + new Date().getTime().toString(); // prevent caching 146 147 script.setAttribute("src",url); 148 script.setAttribute("type","text/javascript"); 149 body.appendChild(script); 150 151 }, 152 getBibleText = function(refString, callback) { 153 var v = getPopupVersion(), 154 max = bibly.maxVerses, 155 reference = new bible.Reference(refString); 156 157 // check that it's only 4 verses 158 if (reference.verse1 > 0 && reference.verse2 > 0 && reference.verse2 - reference.verse1 > (max-1)) { 159 reference.verse2 = reference.verse1 + (max-1); 160 } else if (reference.verse1 <= 0 && reference.verse2 <= 0) { 161 reference.verse1 = 1; 162 reference.verse2 = max; 163 reference.chapter2 = -1; 164 } 165 166 switch (v) { 167 default: 168 case 'NET': 169 jsonp('http://labs.bible.org/api/?passage=' + encodeURIComponent(reference.toString()) + '&type=json', callback); 170 break; 171 case 'KJV': 172 case 'LEB': 173 jsonp('http://api.biblia.com/v1/bible/content/' + v + '.html.json?style=oneVersePerLine&key=' + bibly.bibliaApiKey + '&passage=' + encodeURIComponent(reference.toString()), callback); 174 break; 175 case 'ESV': 176 jsonp('http://www.esvapi.org/crossref/ref.php?reference=' + encodeURIComponent(reference.toString()), callback); 177 break; 178 } 179 }, 180 handleBibleText = function(d) { 181 var 182 v = getPopupVersion(), 183 p = bibly.popup, 184 max = bibly.maxVerses, 185 text = '', 186 className = v + '-version', 187 i,il; 188 189 switch (v) { 190 default: 191 case 'NET': 192 for (i=0,il=d.length; i<il && i<max; i++) { 193 text += '<span class="bibly_verse_number">' + d[i].verse + '</span>' + d[i].text + ' '; 194 } 195 break; 196 case 'KJV': 197 case 'LEB': 198 className += ' biblia'; 199 text = d.text; 200 break; 201 case 'ESV': 202 text = d.content; 203 break; 204 } 205 206 p.content.innerHTML = '<div class="' + className + '">
206' + text + '</div>'; 207 }; 208 209 /* handler for when a verse node is found */ 210 var 211 createBiblyLinks = function(newNode, reference) { 212 newNode.setAttribute('href', reference.toShortUrl() + (bibly.linkVersion != '' ? '.' + bibly.linkVersion : '')); 213 newNode.setAttribute('title', 'Read ' + reference.toString()); 214 newNode.setAttribute('rel', reference.toString()); 215 newNode.setAttribute('class', bibly.className); 216 if (bibly.newWindow) { 217 newNode.setAttribute('target', '_blank') 218 } 219 220 if (bibly.enablePopups) { 221 addEvent(newNode,'mouseover', handleLinkMouseOver); 222 addEvent(newNode,'mouseout', handleLinkMouseOut); 223 } 224 225 }, 226 227 checkPosTimeout, 228 handleLinkMouseOver = function(e) { 229 if (!e) e = win.event; 230 231 clearPositionTimer(); 232 233 var target = (e.target) ? e.target : e.srcElement, 234 p = bibly.popup, 235 pos = getPosition(target), 236 x = y = 0, 237 v = getPopupVersion(); 238 referenceText = target.getAttribute('rel'), 239 viewport = getWindowSize(), 240 scrollPos = getScroll(); 241 242 p.outer.style.display = 'block'; 243 p.header.innerHTML = referenceText + ' (' + v + ')'; 244 p.content.innerHTML = 'Loading...<br/><br/><br/>'; 245 p.footer.innerHTML = getFooter(v); 246 247 248 function positionPopup() { 249 x = pos.left - (p.outer.offsetWidth/2) + (target.offsetWidth/2); 250 y = pos.top - p.outer.clientHeight; // for the arrow 251 252 if (x < 0) { 253 x = 0; 254 } else if (x + p.outer.clientWidth > viewport.width) { 255 x = viewport.width - p.outer.clientWidth - 20; 256 } 257 258 if (y < 0 || (y < scrollPos.y) ){ // above the screen 259 y = pos.top + target.offsetHeight + 10; 260 p.arrowtop.style.display = 'block'; 261 p.arrowtop_border.style.display = 'block'; 262 p.arrowbot.style.display = 'none'; 263 p.arrowbot_border.style.display = 'none'; 264 265 } else { 266 y = y-10; 267 p.arrowtop.style.display = 'none'; 268 p.arrowtop_border.style.display = 'none'; 269 p.arrowbot.style.display = 'block'; 270 p.arrowbot_border.style.display = 'block'; 271 } 272 273 p.outer.style.top = y + 'px'; 274 p.outer.style.left = x + 'px'; 275 } 276 positionPopup(); 277 278 279 getBibleText(referenceText, function(d) { 280 // handle the various JSON outputs 281 handleBibleText(d); 282 283 // reposition the popup 284 //y = pos.top - p.outer.clientHeight - 10; // border 285 //p.outer.style.top = y + 'px'; 286 positionPopup(); 287 }); 288 }, 289 handleLinkMouseOut = function(e) { 290 startPositionTimer(); 291 }, 292 293 handlePopupMouseOver = function(e) { 294 clearPositionTimer(); 295 }, 296 handlePopupMouseOut = function(e) { 297 startPositionTimer(); 298 }, 299 300 /* Timer on/off */ 301 startPositionTimer = function () { 302 checkPosTimeout = setTimeout(hidePopup, 500); 303 }, 304 clearPositionTimer = function() { 305 clearTimeout(checkPosTimeout); 306 delete checkPosTimeout; 307 }, 308 hidePopup = function() { 309 var p = bibly.popup; 310 p.outer.style.display = 'none'; 311 }, 312 313 getPosition = function(node) { 314 var curleft = curtop = curtopscroll = curleftscroll = 0; 315 if (node.offsetParent) { 316 do { 317 curleft += node.offsetLeft; 318 curtop += node.offsetTop; 319 curleftscroll += node.offsetParent ? node.offsetParent.scrollLeft : 0; 320 curtopscroll += node.offsetParent ? node.offsetParent.scrollTop : 0; 321 } while (node = node.offsetParent); 322 } 323 324 return {left:curleft,top:curtop,leftScroll:curleftscroll,topScroll:curtopscroll}; 325 }, 326 getWindowSize= function() { 327 var width = 0, 328 height = 0; 329 if( typeof( win.innerWidth ) == 'number' ) { 330 // Non-IE 331 width = win.innerWidth; 332 height = win.innerHeight; 333 } else if( doc.documentElement && ( doc.documentElement.clientWidth || doc.documentElement.clientHeight ) ) { 334 //IE 6+ in 'standards compliant mode' 335 width = doc.documentElement.clientWidth; 336 height = doc.documentElement.clientHeight; 337 } else if( body && ( body.clientWidth || body.clientHeight ) ) { 338 //IE 4 compatible 339 width = body.clientWidth; 340 height = body.clientHeight; 341 } 342 343 return {width:width, height: height}; 344 }, 345 getScroll = function () { 346 var scrOfX = 0, 347 scrOfY = 0; 348 if( body && ( body.scrollLeft || body.scrollTop ) ) { 349 //DOM compliant 350 scrOfY = body.scrollTop; 351 scrOfX = body.scrollLeft; 352 } else if( doc.documentElement && ( doc.documentElement.scrollLeft || doc.documentElement.scrollTop ) ) { 353 //IE6 standards compliant mode 354 scrOfY = doc.documentElement.scrollTop; 355 scrOfX = doc.documentElement.scrollLeft; 356 } else if( typeof( win.pageYOffset ) == 'number' ) { 357 //Netscape compliant 358 scrOfY = win.pageYOffset; 359 scrOfX = win.pageXOffset; 360 } 361 362 return {x: scrOfX, y:scrOfY }; 363 }; 364 365 366 /* core bibly functions */ 367 var bibly = { 368 version: '0.9.2', 369 maxNodes: 500, 370 className: 'bibly_reference', 371 enablePopups: true, 372 popupVersion: 'ESV', 373 linkVersion: '', 374 bibliaApiKey: '436e02d01081d28a78a45d65f66f4416', 375 autoStart: true, 376 startNodeId: '', 377 maxVerses: 4, 378 newWindow: false, 379 ignoreClassName: 'bibly_ignore', 380 ignoreTags: ['h1','h2','h3','h4'], 381 newTagName: 'A', 382 handleLinks: createBiblyLinks 383 }, 384 win = window, 385 doc = document, 386 body = null, 387 defaultPopupVersion = 'ESV', 388 allowedPopupVersions = ['NET','ESV','KJV','LEB','DARBY'], 389 bok = bible.genNames(), 390 391 392 393 // 1 OR 1:1 OR 1:1-2, 100, but not 1000 394 ver = '(' + // 395 '(1?\\d{1,2})' + // 1 396 '([\.:]\\s?(\\d+))?' + // :2 397 ')' + 398 '(' + 399 '\\s?[-Ð&]\\s?(\\d+)' + // -3 400 '([\.:]\\s?(\\d+))?' + // :4 401 ')?', 402 403 // NOT 1. Only 1:1 OR 1:1-2 404 ver2 = '(1?\\d{1,2})' // 1## 405 + '[\.:]\\s?(\\d+)' 406 + '(\\s?[-Ð&]\\s?(\\d+))?', // this is needed so verses after semi-colons require a :. Problem John 3:16;
406 2 Cor 3:3 <-- the 2 will be a verse) 407 408 regexPattern = '\\b('+bok+')\.?\\s+' // book name with period and/or spaces afterward 409 + '(' + ver // verse pattern (1 OR 1:1 OR 1:1-2) 410 + '(' 411 + '(\\s?,(\\s+)?'+ver+')|' // , VERSE 412 + '(\\s?;(\\s+)?'+ver2+')' // ; CHAPTER:Verse 413 + ')*' // infinite reoccurance 414 + ')\\b', 415 416 referenceRegex = new RegExp(regexPattern, 'mi'), 417 verseRegex = new RegExp(ver, 'mi'), 418 alwaysSkipTags = ['a','script','style','textarea'], 419 lastReference = null, 420 textHandler = function(node) { 421 var match = referenceRegex.exec(node.data), 422 val, 423 referenceNode, 424 afterReferenceNode, 425 newLink; 426 427 // reset this 428 lastReference = null; 429 430 if (match) { 431 val = match[0]; 432 // see https://developer.mozilla.org/en/DOM/text.splitText 433 // split into three parts [node=before][referenceNode][afterReferenceNode] 434 referenceNode = node.splitText(match.index); 435 afterReferenceNode = referenceNode.splitText(val.length); 436 437 // send the matched text down the 438 newLink = createLinksFromNode(node, referenceNode); 439 440 return newLink; 441 } else { 442 return node; 443 } 444 }, 445 createLinksFromNode = function(node, referenceNode) { 446 if (referenceNode.nodeValue == null) 447 return referenceNode; 448 449 // split up match by ; and , characters and make a unique link for each 450 var 451 newLink, 452 commaIndex = referenceNode.nodeValue.indexOf(','), 453 semiColonIndex = referenceNode.nodeValue.indexOf(';'), 454 separatorIndex = (commaIndex > 0 && semiColonIndex > 0) ? Math.min(commaIndex, semiColonIndex) : Math.max(commaIndex, semiColonIndex), 455 separator, 456 remainder, 457 reference, 458 startRemainder; 459 460 // if there is a separator ,; then split up into three parts [node][separator][after] 461 if (separatorIndex > 0) { 462 separator = referenceNode.splitText(separatorIndex); 463 464 startRemainder = 1; 465 while(startRemainder < separator.nodeValue.length && separator.nodeValue.substring(startRemainder,startRemainder+1) == ' ') 466 startRemainder++; 467 468 remainder = separator.splitText(startRemainder); 469 } 470 471 // test if the text matches a real reference 472 refText = referenceNode.nodeValue; 473 reference = parseRefText(refText); 474 if (typeof reference != 'undefined' && reference.isValid()) { 475 476 // replace the referenceNode TEXT with an anchor node to bib.ly 477 newNode = node.ownerDocument.createElement(bibly.newTagName); 478 node.parentNode.replaceChild(newNode, referenceNode); 479 480 // this can be overridden for other systems 481 bibly.handleLinks(newNode, reference); 482 483 newNode.appendChild(referenceNode); 484 485 // if there was a separator, now parse the stuff after it 486 if (remainder) { 487 newNode = createLinksFromNode(node, remainder); 488 } 489 490 return newNode; 491 } else { 492 // for false matches, return it unchanged 493 return referenceNode; 494 } 495 }, 496 parseRefText = function(refText) { 497 498 var 499 text = refText, 500 reference = new bible.Reference(text), 501 match = null, 502 p1, p2, p3, p4; 503 504 if (reference != null && typeof reference.isValid != 'undefined' && reference.isValid()) { 505 506 lastReference = reference; 507 return reference; 508 509 } else if (lastReference != null) { 510 511 // single verse match (3) 512 match = verseRegex.exec(refText); 513 if (match) { 514 515// "1" ["1", "1", "1", u, u, u, u, u, u] 516// "1:2" ["1:2", "1:2", "1", ":2", "2", u, u, u, u] 517// "1-2" ["1-2", "1", "1", u, u, "-2", "2", u, u] 518// "1:2-3" ["1:2-3", "1:2", "1", ":2", "2", "-3", "3", u, u] 519// "1:2-3:4" ["1:2-3:4", "1:2", "1", ":2", "2", "-3:4", "3", ":4", "4"] 520 521 p1 = parseInt(match[2],10); 522 p2 = parseInt(match[4],10); 523 p3 = parseInt(match[6],10); 524 p4 = parseInt(match[8],10); 525 526 if (isNaN(p2)) { 527 p2 = 0; 528 } 529 if (isNaN(p3)) { 530 p3 = 0; 531 } 532 if (isNaN(p4)) { 533 p4 = 0; 534 } 535 536 // single verse (1) 537 if (p1 > 0 && p2 == 0 && p3 == 0 && p4 == 0) { 538 539 lastReference.verse1 = p1; 540 lastReference.chapter2 = -1; 541 lastReference.verse2 = -1; 542 543 // 1:2 544 } else if (p1 > 0 && p2 > 0 && p3 == 0 && p4 == 0) { 545 546 lastReference.chapter1 = p1; 547 lastReference.verse1 = p2; 548 lastReference.chapter2 = -1; 549 lastReference.verse2 = -1; 550 551 // 1-2 552 } else if (p1 > 0 && p2 == 0 && p3 > 0 && p4 == 0) { 553 554 lastReference.verse1 = p1; 555 lastReference.chapter2 = -1; 556 lastReference.verse2 = p3; 557 558 // 1:2-3 559 } else if (p1 > 0 && p2 > 0 && p3 > 0 && p4 == 0) { 560 561 lastReference.chapter1 = p1; 562 lastReference.verse1 = p2; 563 lastReference.chapter2 = -1; 564 lastReference.verse2 = p3; 565 566 567 // 1:2-3:4 568 } else if (p1 > 0 && p2 > 0 && p3 > 0 && p4 > 0) { 569 570 lastReference.chapter1 = p1; 571 lastReference.verse1 = p2; 572 lastReference.chapter2 = p3; 573 lastReference.verse2 = p4; 574 } 575 576 577 return lastReference; 578 } 579 580 // failure 581 return { 582 refText: refText, 583 toShortUrl: function() { 584 return 'http://bib.ly/' + refText.replace(/\s/ig,'').replace(/:/ig,'.').replace(/Ð/ig,'-'); 585 }, 586 toString: function() { 587 return refText + " = Can't parse it"; 588 } 589 }; 590 } else { 591 return undefined; 592 } 593 }, 594 595 getFooter = function(version) { 596 switch (version) { 597 case 'NET': 598 return '<a href="http://bible.org/">NET Bible¨ copyright ©1996-2006 by Biblical Studies Press, LLC</a>'; 599 case 'ESV':
600 return 'English Standard Version. Copyright ©2001 by <a href="http://www.crosswaybibles.org">Crossway Bibles</a>'; 601 case 'LEB': 602 case 'KJV': 603 return version + ' powered by <a href="http://biblia.com/">Biblia</a> web services from <a href="http://www.logos.com/">Logos Bible Software</a>'; 604 default: 605 return ''; 606 } 607 }, 608 609 getPopupVersion = function() { 610 var v = bibly.popupVersion.toUpperCase(), 611 indexOf=-1, 612 i=0, 613 il=allowedPopupVersions.length; 614 615 // old IEs don't have Array.indexOf 616 for (; i < il; i++) { 617 if (allowedPopupVersions[i].toUpperCase() === v) { 618 indexOf = i; 619 break; 620 } 621 } 622 623 return (indexOf > -1) ? v : defaultPopupVersion; 624 }, 625 626 scanForReferences = function(node) { 627 // build doc 628 traverseDOM(node.childNodes[0], 1, textHandler); 629 }, 630 traverseDOM = function(node, depth, textHandler) { 631 var count = 0, 632 //skipRegex = /^(a|script|style|textarea)$/i, 633 skipRegex = new RegExp('^(' + alwaysSkipTags.concat(bibly.ignoreTags).join('|') + ')$', 'i'); 634 635 636 while (node && depth > 0) { 637 count++; 638 if (count >= bibly.maxNodes) { 639 setTimeout(function() { traverseDOM(node, depth, textHandler); }, 50); 640 return; 641 } 642 643 switch (node.nodeType) { 644 case 1: // ELEMENT_NODE 645 if (!skipRegex.test(node.tagName.toLowerCase()) && node.childNodes.length > 0 && (bibly.ignoreClassName == '' || node.className.toString().indexOf(bibly.ignoreClassName) == -1)) { 646 node = node.childNodes[0]; 647 depth ++; 648 continue; 649 } 650 break; 651 case 3: // TEXT_NODE 652 case 4: // CDATA_SECTION_NODE 653 node = textHandler(node); 654 break; 655 } 656 657 if (node.nextSibling) { 658 node = node.nextSibling; 659 } else { 660 while (depth > 0) { 661 node = node.parentNode; 662 depth --; 663 if (node.nextSibling) { 664 node = node.nextSibling; 665 break; 666 } 667 } 668 } 669 } 670 }, 671 addEvent = function(obj,name,fxn) { 672 if (obj.attachEvent) { 673 obj.attachEvent('on' + name, fxn); 674 } else if (obj.addEventListener) { 675 obj.addEventListener(name, fxn, false); 676 } else { 677 var __ = obj['on' + name]; 678 obj['on' + name] = function() { 679 fxn(); 680 __(); 681 }; 682 } 683 }, 684 isStarted = false, 685 extend = function() { 686 // borrowed from ender 687 var options, name, src, copy, 688 target = arguments[0] || {}, 689 i = 1, 690 length = arguments.length; 691 692 // Handle case when target is a string or something (possible in deep copy) 693 if ( typeof target !== "object" && typeof target !== "function" ) { 694 target = {}; 695 } 696 697 for ( ; i < length; i++ ) { 698 // Only deal with non-null/undefined values 699 if ( (options = arguments[ i ]) != null ) { 700 // Extend the base object 701 for ( name in options ) { 702 src = target[ name ]; 703 copy = options[ name ]; 704 705 // Prevent never-ending loop 706 if ( target === copy ) { 707 continue; 708 } 709 710 if ( copy !== undefined ) { 711 target[ name ] = copy; 712 } 713 } 714 } 715 } 716 717 // Return the modified object 718 return target; 719 }, 720 startBibly = function() { 721 722 if (isStarted) 723 return; 724 isStarted = true; 725 726 doc = document; 727 body = doc.body; 728 729 // create popup 730 var p = bibly.popup = { 731 outer: doc.createElement('div') 732 }, 733 parts = ['header','content','footer','arrowtop_border','arrowtop','arrowbot_border','arrowbot'], 734 i, 735 il, 736 div, 737 name, 738 node = null; 739 740 p.outer.className = 'bibly_popup_outer'; 741 // build all the parts 742 for (i=0,il=parts.length; i<il; i++) { 743 name = parts[i]; 744 div = doc.createElement('div'); 745 div.className = 'bibly_popup_' + name; 746 p.outer.appendChild(div); 747 p[name] = div; 748 } 749 750 body.appendChild(p.outer); 751 752 addEvent(p.outer,'mouseover',handlePopupMouseOver); 753 addEvent(p.outer,'mouseout',handlePopupMouseOut); 754 755 if (bibly.autoStart) { 756 if (bibly.startNodeId != '') { 757 node = doc.getElementById(bibly.startNodeId); 758 } 759 760 if (node == null) { 761 node = body; 762 } 763 764 scanForReferences(node); 765 } 766 }; 767 768 // super cheater version of DOMoade 769 // do whatever happens first 770 addEvent(doc,'DOMContentLoaded',startBibly); 771 addEvent(win,'load',startBibly); 772 773 if (typeof window.bibly != 'undefined') 774 bibly = extend(bibly, window.bibly); 775 776 // export 777 bibly.startBibly = startBibly; 778 bibly.scanForReferences = scanForReferences; 779 win.bibly = bibly; 780})();
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.