Attachment 'common.js'

Download

   1 //
   2 // MoinMoin commonly used JavaScript functions
   3 //
   4 
   5 // We keep here the state of the search box
   6 searchIsDisabled = false;
   7 
   8 function searchChange(e) {
   9     // Update search buttons status according to search box content.
  10     // Ignore empty or whitespace search term.
  11     var value = e.value.replace(/\s+/, '');
  12     if (value == '' || searchIsDisabled) { 
  13         searchSetDisabled(true);
  14     } else {
  15         searchSetDisabled(false);
  16     }
  17 }
  18 
  19 function searchSetDisabled(flag) {
  20     // Enable or disable search
  21     document.getElementById('fullsearch').disabled = flag;
  22     document.getElementById('titlesearch').disabled = flag;
  23 }
  24 
  25 function searchFocus(e) {
  26     // Update search input content on focus
  27     if (e.value == search_hint) {
  28         e.value = '';
  29         e.className = '';
  30         searchIsDisabled = false;
  31     }
  32 }
  33 
  34 function searchBlur(e) {
  35     // Update search input content on blur
  36     if (e.value == '') {
  37         e.value = search_hint;
  38         e.className = 'disabled';
  39         searchIsDisabled = true;
  40     }
  41 }
  42 
  43 function actionsMenuInit(title) {
  44     // Initialize action menu
  45     for (i = 0; i < document.forms.length; i++) {
  46         var form = document.forms[i];
  47         if (form.className == 'actionsmenu') {
  48             // Check if this form needs update
  49             var div = form.getElementsByTagName('div')[0];
  50             var label = div.getElementsByTagName('label')[0];
  51             if (label) {
  52                 // This is the first time: remove label and do buton.
  53                 div.removeChild(label);
  54                 var dobutton = div.getElementsByTagName('input')[0];
  55                 div.removeChild(dobutton);
  56                 // and add menu title
  57                 var select = div.getElementsByTagName('select')[0];
  58                 var item = document.createElement('option');
  59                 item.appendChild(document.createTextNode(title));
  60                 item.value = 'show';
  61                 select.insertBefore(item, select.options[0]);
  62                 select.selectedIndex = 0;
  63             }
  64         }
  65     }
  66 }
  67 
  68 // use this instead of assigning to window.onload directly:
  69 function addLoadEvent(func) {
  70     // alert("addLoadEvent " + func)
  71     var oldonload = window.onload;
  72     if (typeof window.onload != 'function') {
  73         window.onload = func;
  74     } else {
  75         window.onload = function() {
  76             oldonload();
  77             func();
  78         }
  79     }
  80 }
  81 
  82 // copy from fckeditor browser check code (fckeditor.js:298, function : FCKeditor_IsCompatibleBrowser)
  83 function can_use_gui_editor() {
  84     var sAgent = navigator.userAgent.toLowerCase() ;
  85 
  86     // Internet Explorer 5.5+
  87     if ( /*@cc_on!@*/false && sAgent.indexOf("mac") == -1 )
  88     {
  89         var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;
  90         return ( sBrowserVersion >= 5.5 ) ;
  91     }
  92 
  93     // Gecko (Opera 9 tries to behave like Gecko at this point).
  94     if ( navigator.product == "Gecko" && navigator.productSub >= 20030210 && !( typeof(opera) == 'object' && opera.postError ) )
  95         return true ;
  96 
  97     // Opera 9.50+
  98     if ( window.opera && window.opera.version && parseFloat( window.opera.version() ) >= 9.5 )
  99         return true ;
 100 
 101 /*
 102   // disable safari : until fck devteam fix http://dev.fckeditor.net/ticket/2333
 103   
 104     // Adobe AIR
 105     // Checked before Safari because AIR have the WebKit rich text editor
 106     // features from Safari 3.0.4, but the version reported is 420.
 107     if ( sAgent.indexOf( ' adobeair/' ) != -1 )
 108         return ( sAgent.match( / adobeair\/(\d+)/ )[1] >= 1 ) ; // Build must be at least v1
 109 
 110     // Safari 3+
 111     if ( sAgent.indexOf( ' applewebkit/' ) != -1 )
 112         return ( sAgent.match( / applewebkit\/(\d+)/ )[1] >= 522 ) ;    // Build must be at least 522 (v3)
 113 */
 114     return false ;
 115 
 116 }
 117 
 118 
 119 function update_edit_links() {
 120     // Update editlink according if if the browser is compatible
 121     if (can_use_gui_editor() == false){
 122         //alert("update_edit_links: can't use gui editor");
 123         return;
 124     }
 125     var editlinks = document.getElementsByName("editlink");
 126     for (i = 0; i < editlinks.length; i++) {
 127         var link = editlinks[i];
 128         href = link.href.replace('editor=textonly','editor=guipossible');
 129         link.href = href;
 130         //alert("update_edit_links: modified to guipossible");
 131     }
 132 }
 133 
 134 
 135 function add_gui_editor_links() {
 136     // Add gui editor link after the text editor link
 137     
 138     // If the variable is not set or browser is not compatible, exit
 139     try {gui_editor_link_href}
 140     catch (e) {
 141         //alert("add_gui_editor_links: gui_editor_link_href not here");
 142         return
 143     }
 144     if (can_use_gui_editor() == false){
 145         //alert("add_gui_editor_links: can't use gui_editor");
 146         return;
 147     }
 148     var all = document.getElementsByName('texteditlink');
 149     for (i = 0; i < all.length; i++) {
 150         var textEditorLink = all[i];
 151         // Create a list item with a link
 152         var guiEditorLink = document.createElement('a');
 153         guiEditorLink.href = gui_editor_link_href;
 154         var text = document.createTextNode(gui_editor_link_text);
 155         guiEditorLink.appendChild(text);
 156         var listItem = document.createElement('li')
 157         listItem.appendChild(guiEditorLink);
 158         // Insert in the editbar
 159         var editbar = textEditorLink.parentNode.parentNode
 160         var nextListItem = textEditorLink.parentNode.nextSibling;
 161         editbar.insertBefore(listItem, nextListItem);
 162         //alert("add_gui_editor_links: added gui editor link");
 163     }
 164 }
 165  
 166 
 167 function show_switch2gui() {
 168     // Show switch to gui editor link if the browser is compatible
 169     if (can_use_gui_editor() == false) return;
 170     
 171     var switch2gui = document.getElementById('switch2gui')
 172     if (switch2gui) {
 173         switch2gui.style.display = 'inline';
 174     }
 175 }
 176 
 177 // for long documents with many comments this is expensive to calculate,
 178 // thus we keep it here:
 179 comments = null;
 180 
 181 function toggleComments() {
 182     // Toggle visibility of every tag with class "comment"
 183     for (i = 0; i < comments.length; i++){
 184         el = comments[i];
 185         if ( el.style.display != 'none' ) {
 186             el.style.display = 'none';
 187         } else {
 188             el.style.display = '';
 189         }
 190     }
 191 }
 192 
 193 function show_toggleComments() {
 194     // Show edit bar item for toggling inline comments on/off only if inline comments exist on the page
 195     comments = getElementsByClassName('comment', null, document);
 196     if (comments.length > 0) {
 197         var buttons = getElementsByClassName('toggleCommentsButton', null, document);
 198         for (i = 0; i < buttons.length; i++){
 199             el = buttons[i];
 200             el.style.display = '';
 201         }
 202     }
 203 }
 204 
 205 
 206 function load() {
 207     // Do not name this "onload", it does not work with IE :-)
 208     // TODO: create separate onload for each type of view and set the
 209     // correct function name in the html. 
 210     // e.g <body onlod='editor_onload()'>
 211 
 212     // login focus
 213     if (document.forms['loginform']) {
 214         document.forms['loginform'].elements['name'].focus();
 215     }
 216     
 217     // Page view stuff
 218     update_edit_links();
 219     add_gui_editor_links();
 220     
 221     // Editor stuff
 222     show_switch2gui();
 223 
 224     // Enable menu item "ToggleComments" if inline comments exist
 225     show_toggleComments();
 226  
 227     // data browser widget
 228     dbw_hide_buttons();
 229 }
 230 
 231 
 232 function before_unload(evt) {
 233     // TODO: Better to set this in the editor html, as it does not make
 234     // sense elsehwere.
 235     // confirmleaving is available when editing
 236     try {return confirmleaving();}
 237     catch (e) {}
 238 }
 239 
 240 // Initialize after loading the page
 241 addLoadEvent(load)
 242 
 243 // Catch before unloading the page
 244 window.onbeforeunload = before_unload
 245 
 246 function dbw_update_search(dbw_id)
 247 {
 248     var table = document.getElementById(dbw_id+'table');
 249     var cell;
 250     var shown;
 251     var i
 252     var cols = table.rows[0].cells.length;
 253     var filter = new Array();
 254     var dofilter = new Array();
 255     var form = document.forms[dbw_id+'form'];
 256 
 257     for (i = 0; i < cols; i++) {
 258         dofilter[i] = false;
 259         if (form[dbw_id+'filter'+i]) {
 260             dofilter[i] = true;
 261             filter[i] = form[dbw_id+'filter'+i].value;
 262             if (filter[i] == '[all]')
 263                 dofilter[i] = false;
 264             if (filter[i] == '[empty]')
 265                 filter[i] = '';
 266         }
 267     }
 268 
 269     for (i = 1; i < table.rows.length; i++) {
 270         var show = true;
 271         for (col = 0; col < cols; col++) {
 272             if (!dofilter[col])
 273                 continue;
 274 
 275             cell = table.rows[i].cells[col];
 276 
 277             if (filter[col] == '[notempty]') {
 278                 if (cell.abbr == '') {
 279                     show = false;
 280                     break;
 281                 }
 282             } else if (filter[col] != cell.abbr) {
 283                 show = false;
 284                 break;
 285             }
 286         }
 287         if (show)
 288             table.rows[i].style.display = '';
 289         else
 290             table.rows[i].style.display = 'none';
 291     }
 292 }
 293 
 294 function dbw_hide_buttons() {
 295     var form;
 296     var elem;
 297     var name;
 298 
 299     for (var fidx = 0; fidx < document.forms.length; fidx++) {
 300         form = document.forms[fidx];
 301         for (var eidx = 0; eidx < form.elements.length; eidx++) {
 302             elem = form.elements[eidx];
 303             name = elem.name;
 304             if (name) {
 305                 if (name.indexOf('dbw.') >= 0 && name.substr(-7) == '.submit')
 306                     elem.style.display = 'none';
 307             }
 308         }
 309     }
 310 }
 311 
 312 /*  getElementsByClassName
 313     Developed by Robert Nyman, http://www.robertnyman.com
 314     Code/licensing: http://code.google.com/p/getelementsbyclassname/ (MIT license)
 315     Version: 1.0.1
 316 */  
 317 var getElementsByClassName = function (className, tag, elm){
 318     if (document.getElementsByClassName) {
 319         getElementsByClassName = function (className, tag, elm) {
 320             elm = elm || document;
 321             var elements = elm.getElementsByClassName(className),
 322                 nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
 323                 returnElements = [],
 324                 current;
 325             for(var i=0, il=elements.length; i<il; i+=1){
 326                 current = elements[i];
 327                 if(!nodeName || nodeName.test(current.nodeName)) {
 328                     returnElements.push(current);
 329                 }
 330             }
 331             return returnElements;
 332         };
 333     }
 334     else if (document.evaluate) {
 335         getElementsByClassName = function (className, tag, elm) {
 336             tag = tag || "*";
 337             elm = elm || document;
 338             var classes = className.split(" "),
 339                 classesToCheck = "",
 340                 xhtmlNamespace = "http://www.w3.org/1999/xhtml",
 341                 namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
 342                 returnElements = [],
 343                 elements,
 344                 node;
 345             for(var j=0, jl=classes.length; j<jl; j+=1){
 346                 classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
 347             }
 348             try {
 349                 elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
 350             }
 351             catch (e) {
 352                 elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
 353             }
 354             while ((node = elements.iterateNext())) {
 355                 returnElements.push(node);
 356             }
 357             return returnElements;
 358         };
 359     }
 360     else {
 361         getElementsByClassName = function (className, tag, elm) {
 362             tag = tag || "*";
 363             elm = elm || document;
 364             var classes = className.split(" "),
 365                 classesToCheck = [],
 366                 elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
 367                 current,
 368                 returnElements = [],
 369                 match;
 370             for(var k=0, kl=classes.length; k<kl; k+=1){
 371                 classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
 372             }
 373             for(var l=0, ll=elements.length; l<ll; l+=1){
 374                 current = elements[l];
 375                 match = false;
 376                 for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
 377                     match = classesToCheck[m].test(current.className);
 378                     if (!match) {
 379                         break;
 380                     }
 381                 }
 382                 if (match) {
 383                     returnElements.push(current);
 384                 }
 385             }
 386             return returnElements;
 387         };
 388     }
 389     return getElementsByClassName(className, tag, elm);
 390 };
 391 
 392 
 393 // ===========================================================================
 394 // The following functions are part of scroll edit textarea on double-click
 395 //
 396 // This code is public domain (or primarily public domain).
 397 // Do whatever you want with it.  In particular, you may release it under
 398 // GPL 2.0 or incorporate it into projects that use GPL 2.0.
 399 // -- Radomir Dopieralski and Roger D. Haase
 400 
 401 // Debugging helpers
 402 //  save debugging state in cookie - presence of a cookie means debugging mode is on
 403 cookiePath = '/';
 404 function autoScrollSetCookie (){
 405     document.cookie = 'autoscrolldebug=on; path=' + cookiePath + '; ';
 406 }
 407 function autoScrollDeleteCookie (){
 408     var cookie_date = new Date ( );  // current date & time
 409     cookie_date.setTime ( cookie_date.getTime() - 1 );
 410     document.cookie = 'autoscrolldebug=; expires=' + cookie_date.toGMTString() + '; path=' + cookiePath + '; ';
 411 }
 412 function autoScrollGetCookie (){
 413     var results = document.cookie.match ( '(^|;) ?' + "autoscrolldebug" + '=([^;]*)(;|$)' );
 414     if ( results ) {
 415         return ( unescape ( results[2] ) );
 416     } else {
 417         return null;
 418     }
 419 }
 420 // turn on debugging mode by previewing, saving or reading a page with "auto scroll debug on" within an h1 header
 421 // = My Page auto scroll debug on =
 422 // once set on,debug mode says on for current session or until turned off with
 423 // = My Page auto scroll debug off =
 424 autoScrollDebugOn = 0;
 425 // this function executed on page load
 426 function turnDebugOnOrOff () {
 427     // set global variable for use by cookie functions
 428     cookiePath = document.getElementsByName('edit_on_doubleclick')[0].content;
 429     var hOnes = document.getElementsByTagName('H1');
 430     for (var i = 0; i < hOnes.length; ++i) {
 431         var header = hOnes[i].textContent || hOnes[i].innerText;
 432         if (header.match ('auto scroll debug on')) {
 433             autoScrollSetCookie ();
 434         }
 435         if (header.match ('auto scroll debug off')) {
 436             autoScrollDeleteCookie ();
 437         }
 438     }
 439     if (autoScrollGetCookie ()) {
 440         autoScrollDebugOn = 1;
 441     } else {
 442         autoScrollDebugOn = 0;
 443     }
 444 }
 445 
 446 // functions used for testing - mouseover tooltip with tagName and scroll line number
 447 function doMouseOver(e) {
 448     var targ = getNode(e);
 449     targ.title = 'tagName='+targ.tagName+'  line='+targ.scrollLine;
 450 }
 451 function doMouseOut(e) {
 452     var targ = getNode(e);
 453     targ.removeAttribute('title');
 454 }
 455 // add leading zeros to hours, minutes, seconds, milliseconds
 456 function leadingZeros (nbr,count) { 
 457     var strNbr = nbr + '';
 458     while (strNbr.length < count) {
 459         strNbr = "0" + strNbr; 
 460     }
 461     return strNbr;
 462 }
 463 // format hours, minutes, seconds, and ms
 464 function formatTime (t) {
 465     var sHours = leadingZeros (t.getHours(), 2);
 466     var sMinutes = leadingZeros (t.getMinutes (), 2);
 467     var sSeconds = leadingZeros (t.getSeconds (), 2);
 468     var sMilliseconds = leadingZeros (t.getMilliseconds (), 3);
 469     return sHours + ':' + sMinutes + ':' + sSeconds + ':' + sMilliseconds;
 470 }
 471 
 472 // this variable is available as easy way to display trace info
 473 autoDebugTrace = '';
 474 function showStartStopTimes (startTime) {
 475     // display a message with start and end times at top of page
 476     var endTime = new Date();
 477     var tStart ='auto scroll debug on -- Initialization start H:M:S:ms=' + formatTime (startTime);
 478     var tEnd = '  end H:M:S:ms=' + formatTime (endTime);
 479     var timingMsg = document.createElement ('P');
 480     timingMsg.innerHTML = tStart + tEnd;
 481     timingMsg.style. color = "red";
 482     var contentDiv;
 483     if (document.getElementById ('preview')) {
 484         contentDiv = document.getElementById ('preview');
 485     } else {
 486         contentDiv = document.getElementById ('content');
 487     }
 488     contentDiv.insertBefore (timingMsg, contentDiv.firstChild);
 489     // display trace info is there is any
 490     if (autoDebugTrace) {
 491         alert(autoDebugTrace);
 492     }
 493 }
 494 // end of debugging helpers
 495 
 496 // this scrolls the textarea after a doubleclick - jumpLine is scroll-to line
 497 function scrollTextarea(jumpLine) {
 498     var txtBox = document.getElementById('editor-textarea');
 499     scroll(0,0); 
 500     if (txtBox) {
 501         // Calculate the cursor position - IE supports innerText, not textContent
 502         var textLines = txtBox.textContent || txtBox.innerText;
 503         textLines = textLines.match(/(.*(\r\n|\r|\n))/g);
 504         var scrolledText = '';
 505         for (var i = 0; i < textLines.length && i < jumpLine; ++i) {
 506             scrolledText += textLines[i];
 507         }
 508         txtBox.focus();
 509         if (txtBox.setSelectionRange) {
 510             // Standard-compliant browsers
 511             // Move the cursor
 512             txtBox.setSelectionRange(scrolledText.length, scrolledText.length);
 513             // Calculate how far to scroll, by putting the text that is to be
 514             // above the fold in a DIV, and checking the DIV's height.
 515             var scrollPre = document.createElement('pre');
 516             txtBox.parentNode.appendChild(scrollPre);
 517             var style = window.getComputedStyle(txtBox, '');
 518             scrollPre.style.lineHeight = style.lineHeight;
 519             scrollPre.style.fontFamily = style.fontFamily;
 520             scrollPre.style.fontSize = style.fontSize;
 521             scrollPre.style.padding = 0;
 522             scrollPre.style.letterSpacing = style.letterSpacing;
 523             // Different browsers call this value differently:
 524             try { scrollPre.style.whiteSpace = "-moz-pre-wrap"; } catch(e) {}
 525             try { scrollPre.style.whiteSpace = "-o-pre-wrap"; } catch(e) {}
 526             try { scrollPre.style.whiteSpace = "-pre-wrap"; } catch(e) {}
 527             try { scrollPre.style.whiteSpace = "pre-wrap"; } catch(e) {}
 528             scrollPre.textContent = scrolledText;
 529             txtBox.scrollTop = scrollPre.scrollHeight-100;
 530             scrollPre.parentNode.removeChild(scrollPre);
 531         } else if (txtBox.createTextRange) {
 532             // Microsoft Internet Explorer
 533             // We don't need to scroll, it will do it automatically, just move
 534             // the cursor.
 535             var range = txtBox.createTextRange();
 536             range.collapse(true);
 537             range.moveEnd('character', scrolledText.length);
 538             range.moveStart('character', scrolledText.length);
 539             range.select();
 540             txtBox.__column = 1;
 541         }
 542     } 
 543 }
 544 
 545 // stop event bubbling
 546 function stopBubbling(e) {
 547     if (e.stopPropagation) {
 548         e.stopPropagation(); 
 549     }
 550     e.cancelBubble = true;
 551 }
 552 
 553 // stop bubbling and return event node 
 554 function getNode(e) {
 555     // window.event and e.srcElement are IE
 556     var e = e || window.event;
 557     var targ = e.target || e.srcElement;
 558     if (targ.nodeType == 3) {
 559         // workaround safari
 560         targ = targ.parentNode;
 561     }
 562     stopBubbling(e);
 563     return targ;
 564 }
 565 
 566 // add action=edit and scrollLine to document.location
 567 function doActionEdit(e) {
 568     var targ = getNode(e);
 569     // MoinMoin counts starting with 1, scrollTextarea starts with 0
 570     document.location.search = '?action=edit&line='+(targ.scrollLine-1);
 571 }
 572 
 573 // scroll textarea on this page
 574 function doTextareaScroll(e) {
 575     var targ = getNode(e);
 576     scrollTextarea(targ.scrollLine-1);
 577 }
 578 
 579 // This is the function that registers double clicks.
 580 // isPreview is true if the current page is an edit draft preview
 581 function setCallback(node, line, isPreview) {
 582     if (node.scrollLine) {
 583         // this node already processed
 584         return;
 585     } else {
 586         node.scrollLine = line;
 587         if(window.addEventListener){ 
 588             if (isPreview) {
 589                 node.addEventListener('dblclick',doTextareaScroll,false);
 590             } else {
 591                 node.addEventListener('dblclick',doActionEdit,false);
 592             }
 593             if (autoScrollDebugOn) {
 594                 node.addEventListener('mouseover', doMouseOver,false); 
 595                 node.addEventListener('mouseout',doMouseOut,false); 
 596             }
 597         } else {
 598             // IE
 599             if (isPreview) {
 600                 node.attachEvent('ondblclick',doTextareaScroll);
 601             } else {
 602                 node.attachEvent('ondblclick',doActionEdit);
 603             }
 604             if (autoScrollDebugOn) {
 605                 node.attachEvent('onmouseover', doMouseOver,false); 
 606                 node.attachEvent('onmouseout',doMouseOut,false);
 607             }
 608         }
 609     }
 610 }
 611 
 612 // walk part of DOM and add doubleclick function to all nodes with tagNames
 613 function walkDom (someNode, lineNbr, isPreview, nextId, topId) {
 614 
 615     //~ // handle special cases of paragraph on line after <<TOC>> and ---- (horizontal rule)
 616     //~ //   But this effects paragraphs on multiple lines: doubleclick goes to paragraph bottom rather than top.
 617     //~ //   Seems best to live with TOC and HR problem and wait for Moin2.
 618     //~ var next1, next2, next3;
 619     //~ var nextNbr = 'line-' + (lineNbr-0+1);
 620     //~ if (someNode.parentNode.tagName == 'P' && someNode.parentNode.scrollLine) {
 621         //~ next1 = someNode.nextSibling;
 622         //~ if (next1 && next1.tagName != 'SPAN') {
 623             //~ next2 = next1.nextSibling;
 624         //~ }
 625         //~ if (next2 && next2.id == nextNbr) {
 626             //~ alert('Correcting scrollLine='+lineNbr);
 627             //~ someNode.parentNode.scrollLine = lineNbr;
 628             //~ return;
 629         //~ }
 630     //~ }
 631     
 632     var ie8LoopCounter = 0;
 633     var doChild = true;
 634     while (!(someNode.id == nextId) && !(someNode.id == topId)) {
 635         // workaround IE8 bug:  http://moinmo.in/MoinMoinBugs/FormInsideTableCausesIE8ScriptLoop
 636         ie8LoopCounter += 1;
 637         if (ie8LoopCounter > 10000) {
 638             return;
 639         }
 640         
 641         // add children, add siblings, add parent
 642         if (doChild && someNode.firstChild) {
 643             someNode = someNode.firstChild;
 644         } else {
 645             doChild = true;
 646             if (someNode.nextSibling) {
 647                 someNode = someNode.nextSibling;
 648             } else {
 649                 if (someNode.parentNode.nextSibling) {
 650                 someNode = someNode.parentNode.nextSibling;
 651                 } else {
 652                     doChild = false;
 653                     someNode = someNode.parentNode.parentNode;
 654                 }
 655             }
 656         }
 657         if (doChild && someNode.tagName && !(someNode.id == nextId) && !(someNode.id == topId)) {
 658             setCallback(someNode, lineNbr, isPreview);
 659         }
 660     }
 661 }
 662 
 663 // run during page load when user may edit current page OR is viewing draft preview
 664 function setSpanTags(isPreview) {
 665     var startTime = new Date();
 666     // find all the SPAN tags with an ID beginning with "line-"
 667     var spanTags = document.getElementsByTagName('span');
 668     var marks = [];
 669     for (var i = 0; i < spanTags.length; ++i) {
 670         if (spanTags[i].id && spanTags[i].id.substring(0, 5) == 'line-') {
 671             marks.push(spanTags[i]);
 672         }
 673     }
 674     var top = document.getElementById('content');
 675     var bottom = document.getElementById('bottom');
 676     // add expected stopping point to end of array for convenience
 677     if (bottom) {
 678         marks.push(bottom); 
 679     } else {
 680         if (autoScrollDebugOn) {
 681             alert("auto scroll debug 1: document.getElementById('bottom') failed");
 682         }
 683     }
 684     var skipTo = -1; 
 685     // loop through span tags and apply double-click events to appropriate node(s) 
 686     for (i = 0; i < marks.length-1; ++i) {
 687         var mark = marks[i];
 688         // skip span tags generated by embedded parsers
 689         if (i > skipTo) {
 690             // split the ID into parts: looks like "line-22" or "line-22-1"
 691             var lineParts = mark.id.split('-');
 692             var line = lineParts[1];
 693             if (lineParts.length == 3) {
 694                 // have found output from embedded parser
 695                 // find next span id that looks like "line-n" and the "line-n-n" just before it
 696                 var j = i - 0;
 697                 while (lineParts.length == 3) {
 698                     j++;
 699                     lineParts = marks[j].id.split('-');
 700                 }
 701                 // determine how many lines, starting line number, and add double-click events
 702                 var nbrParsedLines = j - i;
 703                 var parsedLineNbr = lineParts[1] - nbrParsedLines - 1;
 704                 for (var k = 0; k < nbrParsedLines; ++k) { 
 705                     if (marks[i+k] && marks[i+k+1] && marks[i+k+1].id) {
 706                         walkDom (marks[i+k], parsedLineNbr+k, isPreview, marks[i+k+1].id, top.id);
 707                     } else {
 708                         if (autoScrollDebugOn) {
 709                             alert('auto scroll debug 2: skipping walkDom, i=' + i + ' k=' + k + ' marks[i].id=' + marks[i].id);
 710                         }
 711                     }
 712                 }
 713                 // done with embedded parser lines, tell main loop to skip these
 714                 skipTo = j - 1; 
 715             } else {
 716                 // walk part of DOM and apply doubleclick function to every node with a tagname
 717                 if (marks[i+1] && marks[i+1].id) {
 718                     walkDom (mark, line, isPreview, marks[i+1].id, top.id);
 719                 } else {
 720                     if (autoScrollDebugOn) {
 721                         alert('auto scroll debug 3: skipping walkDom, i=' + i + ' marks[i].id=' + marks[i].id);
 722                     }
 723                 }
 724             }
 725         }
 726     }
 727     if (autoScrollDebugOn && document.getElementById('content'))  {
 728         for (i = 0; i < marks.length-1; ++i) {
 729             marks[i].innerHTML = ' ' + marks[i].id + ' ';
 730             marks[i].style. color = "red";
 731         }
 732         showStartStopTimes(startTime);
 733     }
 734 }
 735 
 736 // test to see if this user has selected or defaulted to edit_on_doubleclick AND
 737 // whether we are viewing a page, editing a page, or previewing an edit draft 
 738 function scrollTextareaInit() {
 739     // look for meta tag -- is edit_on_doubleclick present?
 740     if (!document.getElementsByName('edit_on_doubleclick').length) {
 741         return;
 742     }
 743     turnDebugOnOrOff ();
 744     // are we viewing a page - both gui and text editors will have button named button_save
 745     if (!document.getElementsByName('button_save').length) {
 746         setSpanTags(0);
 747         return;
 748     }
 749     // we are in editor -- is there a line number specified in URL?
 750     var lineMatch = document.location.search.match(/line=(\d*)/);
 751     if (lineMatch) {
 752         scrollTextarea(lineMatch[1]);
 753         return;
 754     } 
 755     if (document.getElementById('preview')) {
 756         // is an editor preview
 757         setSpanTags(1);
 758     }
 759 }
 760 
 761 // The DOM ready check for Internet Explorer
 762 function ieScrollCheck() {
 763 	try {
 764 		// If IE is used, use the trick by Diego Perini
 765 		document.documentElement.doScroll("left");
 766 	} catch( error ) {
 767 		setTimeout( ieScrollCheck, 1 );
 768 		return;
 769 	}
 770     scrollTextareaInit();
 771 }
 772 
 773 // run auto scroll init As Soon As Possible -- prior to onload for modern browsers
 774 function runASAP() {
 775     if (document.addEventListener) { 
 776         // Firefox 3.6, Chrome 4.0.249.89, Safari for Windows 4.04, Opera 10.5beta, and maybe older versions
 777         // schedule func to be run when DOM complete, usually before last image loaded
 778         document.addEventListener("DOMContentLoaded", scrollTextareaInit, false);
 779     } else {
 780         if (document.documentElement.doScroll && window == window.top) {
 781             // IE 5-8 and not using frames
 782             ieScrollCheck();
 783         } else {
 784             addLoadEvent(scrollTextareaInit);
 785         }
 786     }
 787 }
 788 // auto scroll initialization starts here
 789 runASAP();

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2010-11-02 21:38:54, 73.2 KB) [[attachment:IE8Loop.png]]
  • [get | view] (2010-11-03 04:48:10, 27.4 KB) [[attachment:common.js]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.