Commits

Roger Haase committed 65b22a8

rework edit on doublclick; remove broken textarea autoscroll javascript

Comments (0)

Files changed (6)

MoinMoin/static/js/common.js

 };
 
 
-// ===========================================================================
-// The following functions are part of scroll edit textarea on double-click
-//
-// This code is public domain (or primarily public domain).
-// Do whatever you want with it.  In particular, you may release it under
-// GPL 2.0 or incorporate it into projects that use GPL 2.0.
-// -- Radomir Dopieralski and Roger D. Haase
-
-// Debugging helpers
-//  save debugging state in cookie - presence of a cookie means debugging mode is on
-cookiePath = '/';
-function autoScrollSetCookie (){
-    document.cookie = 'autoscrolldebug=on; path=' + cookiePath + '; ';
-}
-function autoScrollDeleteCookie (){
-    var cookie_date = new Date ( );  // current date & time
-    cookie_date.setTime ( cookie_date.getTime() - 1 );
-    document.cookie = 'autoscrolldebug=; expires=' + cookie_date.toGMTString() + '; path=' + cookiePath + '; ';
-}
-function autoScrollGetCookie (){
-    var results = document.cookie.match ( '(^|;) ?' + "autoscrolldebug" + '=([^;]*)(;|$)' );
-    if ( results ) {
-        return ( unescape ( results[2] ) );
-    } else {
-        return null;
-    }
-}
-// turn on debugging mode by previewing, saving or reading a page with "auto scroll debug on" within an h1 header
-// = My Page auto scroll debug on =
-// once set on,debug mode says on for current session or until turned off with
-// = My Page auto scroll debug off =
-autoScrollDebugOn = 0;
-// this function executed on page load
-function turnDebugOnOrOff () {
-    // set global variable for use by cookie functions
-    cookiePath = document.getElementsByName('edit_on_doubleclick')[0].content;
-    var hOnes = document.getElementsByTagName('H1');
-    for (var i = 0; i < hOnes.length; ++i) {
-        var header = hOnes[i].textContent || hOnes[i].innerText;
-        if (header.match ('auto scroll debug on')) {
-            autoScrollSetCookie ();
-        }
-        if (header.match ('auto scroll debug off')) {
-            autoScrollDeleteCookie ();
-        }
-    }
-    if (autoScrollGetCookie ()) {
-        autoScrollDebugOn = 1;
-    } else {
-        autoScrollDebugOn = 0;
-    }
-}
-
-// functions used for testing - mouseover tooltip with tagName and scroll line number
-function doMouseOver(e) {
-    var targ = getNode(e);
-    targ.title = 'tagName='+targ.tagName+'  line='+targ.scrollLine;
-}
-function doMouseOut(e) {
-    var targ = getNode(e);
-    targ.removeAttribute('title');
-}
-// add leading zeros to hours, minutes, seconds, milliseconds
-function leadingZeros (nbr,count) {
-    var strNbr = nbr + '';
-    while (strNbr.length < count) {
-        strNbr = "0" + strNbr;
-    }
-    return strNbr;
-}
-// format hours, minutes, seconds, and ms
-function formatTime (t) {
-    var sHours = leadingZeros (t.getHours(), 2);
-    var sMinutes = leadingZeros (t.getMinutes (), 2);
-    var sSeconds = leadingZeros (t.getSeconds (), 2);
-    var sMilliseconds = leadingZeros (t.getMilliseconds (), 3);
-    return sHours + ':' + sMinutes + ':' + sSeconds + ':' + sMilliseconds;
-}
-
-// this variable is available as easy way to display trace info
-autoDebugTrace = '';
-function showStartStopTimes (startTime) {
-    // display a message with start and end times at top of page
-    var endTime = new Date();
-    var tStart ='auto scroll debug on -- Initialization start H:M:S:ms=' + formatTime (startTime);
-    var tEnd = '  end H:M:S:ms=' + formatTime (endTime);
-    var timingMsg = document.createElement ('P');
-    timingMsg.innerHTML = tStart + tEnd;
-    timingMsg.style. color = "red";
-    var contentDiv;
-    if (document.getElementById ('preview')) {
-        contentDiv = document.getElementById ('preview');
-    } else {
-        contentDiv = document.getElementById ('content');
-    }
-    contentDiv.insertBefore (timingMsg, contentDiv.firstChild);
-    // display trace info is there is any
-    if (autoDebugTrace) {
-        alert(autoDebugTrace);
-    }
-}
-// end of debugging helpers
-
-// this scrolls the textarea after a doubleclick - jumpLine is scroll-to line
-function scrollTextarea(jumpLine) {
-    var txtBox = document.getElementById('editor-textarea');
-    scroll(0,0);
-    if (txtBox) {
-        // Calculate the cursor position - IE supports innerText, not textContent
-        var textLines = txtBox.textContent || txtBox.innerText;
-        textLines = textLines.match(/(.*\n)/g);
-        var scrolledText = '';
-        for (var i = 0; i < textLines.length && i < jumpLine; ++i) {
-            scrolledText += textLines[i];
-        }
-        txtBox.focus();
-        if (txtBox.setSelectionRange) {
-            // Standard-compliant browsers
-            // Move the cursor
-            txtBox.setSelectionRange(scrolledText.length, scrolledText.length);
-            // Calculate how far to scroll, by putting the text that is to be
-            // above the fold in a DIV, and checking the DIV's height.
-            var scrollPre = document.createElement('pre');
-            txtBox.parentNode.appendChild(scrollPre);
-            var style = window.getComputedStyle(txtBox, '');
-            scrollPre.style.lineHeight = style.lineHeight;
-            scrollPre.style.fontFamily = style.fontFamily;
-            scrollPre.style.fontSize = style.fontSize;
-            scrollPre.style.padding = 0;
-            scrollPre.style.letterSpacing = style.letterSpacing;
-            // Different browsers call this value differently:
-            try { scrollPre.style.whiteSpace = "-moz-pre-wrap"; } catch(e) {}
-            try { scrollPre.style.whiteSpace = "-o-pre-wrap"; } catch(e) {}
-            try { scrollPre.style.whiteSpace = "-pre-wrap"; } catch(e) {}
-            try { scrollPre.style.whiteSpace = "pre-wrap"; } catch(e) {}
-            scrollPre.textContent = scrolledText;
-            txtBox.scrollTop = scrollPre.scrollHeight-100;
-            scrollPre.parentNode.removeChild(scrollPre);
-        } else if (txtBox.createTextRange) {
-            // Microsoft Internet Explorer
-            // We don't need to scroll, it will do it automatically, just move
-            // the cursor.
-            var range = txtBox.createTextRange();
-            range.collapse(true);
-            range.moveEnd('character', scrolledText.length);
-            range.moveStart('character', scrolledText.length);
-            range.select();
-            txtBox.__column = 1;
+// Enter edit mode when user doubleclicks within the page body.  Executed once on page load.
+function editOnDoubleClick() {
+    var modifyButton;
+    // is edit on doubleclick available for this user and item?
+    if (document.getElementById('moin-edit-on-doubleclick')) {
+        modifyButton = jQuery('.moin-modify-button')[0];
+        if (modifyButton) {
+            // add a doubleclick action to the body tag
+            jQuery('body').dblclick(function () {
+                document.location = modifyButton.href;
+            });
         }
     }
 }
+jQuery(document).ready(editOnDoubleClick);
 
-// stop event bubbling
-function stopBubbling(e) {
-    if (e.stopPropagation) {
-        e.stopPropagation();
-    }
-    e.cancelBubble = true;
-}
-
-// stop bubbling and return event node
-function getNode(e) {
-    // window.event and e.srcElement are IE
-    var e = e || window.event;
-    var targ = e.target || e.srcElement;
-    if (targ.nodeType == 3) {
-        // workaround safari
-        targ = targ.parentNode;
-    }
-    stopBubbling(e);
-    return targ;
-}
-
-// add action=edit and scrollLine to document.location
-function doActionEdit(e) {
-    var targ = getNode(e);
-    // MoinMoin counts starting with 1, scrollTextarea starts with 0
-    document.location.search = '?action=edit&line='+(targ.scrollLine-1);
-}
-
-// scroll textarea on this page
-function doTextareaScroll(e) {
-    var targ = getNode(e);
-    scrollTextarea(targ.scrollLine-1);
-}
-
-// This is the function that registers double clicks.
-// isPreview is true if the current page is an edit draft preview
-function setCallback(node, line, isPreview) {
-    if (node.scrollLine) {
-        // this node already processed
-        return;
-    } else {
-        node.scrollLine = line;
-        if(window.addEventListener){
-            if (isPreview) {
-                node.addEventListener('dblclick',doTextareaScroll,false);
-            } else {
-                node.addEventListener('dblclick',doActionEdit,false);
-            }
-            if (autoScrollDebugOn) {
-                node.addEventListener('mouseover', doMouseOver,false);
-                node.addEventListener('mouseout',doMouseOut,false);
-            }
-        } else {
-            // IE
-            if (isPreview) {
-                node.attachEvent('ondblclick',doTextareaScroll);
-            } else {
-                node.attachEvent('ondblclick',doActionEdit);
-            }
-            if (autoScrollDebugOn) {
-                node.attachEvent('onmouseover', doMouseOver,false);
-                node.attachEvent('onmouseout',doMouseOut,false);
-            }
-        }
-    }
-}
-
-// walk part of DOM and add doubleclick function to all nodes with tagNames
-function walkDom (someNode, lineNbr, isPreview, nextId, topId) {
-
-    //~ // handle special cases of paragraph on line after <<TOC>> and ---- (horizontal rule)
-    //~ //   But this effects paragraphs on multiple lines: doubleclick goes to paragraph bottom rather than top.
-    //~ //   Seems best to live with TOC and HR problem and wait for Moin2.
-    //~ var next1, next2, next3;
-    //~ var nextNbr = 'line-' + (lineNbr-0+1);
-    //~ if (someNode.parentNode.tagName == 'P' && someNode.parentNode.scrollLine) {
-        //~ next1 = someNode.nextSibling;
-        //~ if (next1 && next1.tagName != 'SPAN') {
-            //~ next2 = next1.nextSibling;
-        //~ }
-        //~ if (next2 && next2.id == nextNbr) {
-            //~ alert('Correcting scrollLine='+lineNbr);
-            //~ someNode.parentNode.scrollLine = lineNbr;
-            //~ return;
-        //~ }
-    //~ }
-
-    var doChild = true;
-    while (!(someNode.id == nextId) && !(someNode.id == topId)) {
-        // add children, add siblings, add parent
-        if (doChild && someNode.firstChild) {
-            someNode = someNode.firstChild;
-        } else {
-            doChild = true;
-            if (someNode.nextSibling) {
-                someNode = someNode.nextSibling;
-            } else {
-                if (someNode.parentNode.nextSibling) {
-                someNode = someNode.parentNode.nextSibling;
-                } else {
-                    doChild = false;
-                    someNode = someNode.parentNode.parentNode;
-                }
-            }
-        }
-        if (doChild && someNode.tagName && !(someNode.id == nextId) && !(someNode.id == topId)) {
-            setCallback(someNode, lineNbr, isPreview);
-        }
-    }
-}
-
-// run during page load when user may edit current page OR is viewing draft preview
-function setSpanTags(isPreview) {
-    // find all the SPAN tags with an ID beginning with "line-"
-    var spanTags = document.getElementsByTagName('span');
-    var marks = [];
-    for (var i = 0; i < spanTags.length; ++i) {
-        if (spanTags[i].id && spanTags[i].id.substring(0, 5) == 'line-') {
-            marks.push(spanTags[i]);
-        }
-    }
-    var top = document.getElementById('content');
-    var bottom = document.getElementById('bottom');
-    // add expected stopping point to end of array for convenience
-    if (bottom) {
-        marks.push(bottom);
-    } else {
-        if (autoScrollDebugOn) {
-            alert("auto scroll debug 1: document.getElementById('bottom') failed");
-        }
-    }
-    var skipTo = -1;
-    // loop through span tags and apply double-click events to appropriate node(s)
-    for (i = 0; i < marks.length-1; ++i) {
-        var mark = marks[i];
-        // skip span tags generated by embedded parsers
-        if (i > skipTo) {
-            // split the ID into parts: looks line "line-22" or "line-22-1"
-            var lineParts = mark.id.split('-');
-            var line = lineParts[1];
-            if (lineParts.length == 3) {
-                // have found output from embedded parser
-                // find next span id that looks like "line-n" and the "line-n-n" just before it
-                var j = i - 0;
-                while (lineParts.length == 3) {
-                    j++;
-                    lineParts = marks[j].id.split('-');
-                }
-                // determine how many lines, starting line number, and add double-click events
-                var nbrParsedLines = j - i;
-                var parsedLineNbr = lineParts[1] - nbrParsedLines - 1;
-                for (var k = 0; k < nbrParsedLines; ++k) {
-                    if (marks[i+k] && marks[i+k+1] && marks[i+k+1].id) {
-                        walkDom (marks[i+k], parsedLineNbr+k, isPreview, marks[i+k+1].id, top.id);
-                    } else {
-                        if (autoScrollDebugOn) {
-                            alert('auto scroll debug 2: skipping walkDom, i=' + i + ' k=' + k + ' marks[i].id=' + marks[i].id);
-                        }
-                    }
-                }
-                // done with embedded parser lines, tell main loop to skip these
-                skipTo = j - 1;
-            } else {
-                // walk part of DOM and apply doubleclick function to every node with a tagname
-                if (marks[i+1] && marks[i+1].id) {
-                    walkDom (mark, line, isPreview, marks[i+1].id, top.id);
-                } else {
-                    if (autoScrollDebugOn) {
-                        alert('auto scroll debug 3: skipping walkDom, i=' + i + ' marks[i].id=' + marks[i].id);
-                    }
-                }
-            }
-        }
-    }
-    if (autoScrollDebugOn)  {
-        for (i = 0; i < marks.length-1; ++i) {
-            marks[i].innerHTML = ' ' + marks[i].id + ' ';
-            marks[i].style. color = "red";
-        }
-    }
-}
-
-// test to see if this user has selected or defaulted to edit_on_doubleclick AND
-// whether we are viewing a page, editing a page, or previewing an edit draft
-function scrollTextareaInit() {
-    // look for meta tag -- is edit_on_doubleclick present?
-    if (!document.getElementsByName('edit_on_doubleclick').length) {
-        return;
-    }
-    turnDebugOnOrOff ();
-    // are we viewing a page - both gui and text editors will have button named button_save
-    if (!document.getElementsByName('button_save').length) {
-        setSpanTags(0);
-        return;
-    }
-    // we are in editor -- is there a line number specified in URL?
-    var lineMatch = document.location.search.match(/line=(\d*)/);
-    if (lineMatch) {
-        scrollTextarea(lineMatch[1]);
-        return;
-    }
-    if (document.getElementById('preview')) {
-        // is an editor preview
-        setSpanTags(1);
-    }
-}
-
-// Now to resolve the problem of how to best execute scrollTextareaInit
-// -- We want to run as soon as DOM is loaded, perhaps many seconds before last big image is loaded
-// -- If we wait for body.onload, the user may see and doubleclick on text before we are ready
-// -- If every browser supported DOMContentLoaded, we could do:
-//         document.addEventListener("DOMContentLoaded", scrollTextareaInit, false);
-// -- If we had jQuery, we could do:
-//         jQuery(scrollTextareaInit);
-// -- Another possibility is to add a bit of script near the end of the mypage.HTML, hoping the DOM is ready
-//         '<script type="text/javascript" language="javascript">scrollTextareaInit()</script>'
-// -- Our choice is to speed up most current browsers and do slow but sure for the rest:
-
-// run scrollTextareaInit one time;  this function will be called twice for almost all browsers,
-scrollTextareaInitComplete = 0;
-function runScrollTextareaInitOnce() {
-    // uncomment next line to test - most browsers will display this alert twice
-    //~ alert('scrollTextareaInitComplete=' + scrollTextareaInitComplete);
-    if (scrollTextareaInitComplete) {
-        return;
-    }
-    scrollTextareaInitComplete = 1;
-    var startTime = new Date();
-    scrollTextareaInit();
-    if (autoScrollDebugOn && document.getElementById('content')) {
-        showStartStopTimes(startTime);
-    }
-}
-
-// speed up most browsers -- run my function As Soon As Possible
-function runASAP(func) {
-    if (document.addEventListener) {
-        // Firefox 3.6, Chrome 4.0.249.89, Safari for Windows 4.04, Opera 10.5beta, and maybe older versions
-        // schedule func to be run when DOM complete
-        document.addEventListener("DOMContentLoaded", func, false);
-    } else {
-        // trick discovered by Diego Perini to test for IE DOM complete
-        if (document.documentElement.doScroll && window == window.top) {
-            try {
-                document.documentElement.doScroll("left");
-                // DOM is complete; run func now
-                func();
-            } catch(e) {
-                // wait and try again
-                setTimeout(arguments.callee, 1);
-            }
-        }
-    }
-}
-
-
-runASAP(runScrollTextareaInitOnce);
-// ensure init will be run by obsolete browsers
-addLoadEvent(runScrollTextareaInitOnce);
 
 // ===========================================================================
 // The following functions are part of jQuery code

MoinMoin/templates/itemviews.html

                 </li>
             {%- endif %}
 
+            {%- if endpoint == 'frontend.modify_item' and user.may.write(item_name) %}
+                <li>
+                    <a class="moin-modify-button" href="{{ url_for(endpoint, item_name=item_name) }}" title="{{ title }}" rel="nofollow">{{ label }}</a>
+                </li>
+            {%- endif %}
+
             {%- if endpoint in [
-                'frontend.modify_item', 'frontend.rename_item', 'frontend.delete_item',
+                'frontend.rename_item', 'frontend.delete_item',
             ] and user.may.write(item_name) %}
                 <li>
                     <a href="{{ url_for(endpoint, item_name=item_name) }}" title="{{ title }}" rel="nofollow">{{ label }}</a>

MoinMoin/templates/show.html

 
 {% block options_for_javascript %}
 {%- if item_name and user.edit_on_doubleclick and user.may.write(item_name) -%}
-    <br id="moin-edit_on_doubleclick" />
+    <br id="moin-edit-on-doubleclick" />
 {%- endif %}
 {%- if user.show_comments -%}
     <br id="moin-show-comments" />

MoinMoin/themes/foobar/templates/itemviews.html

                 </li>
             {%- endif %}
 
+            {%- if endpoint == 'frontend.modify_item' and user.may.write(item_name) %}
+                <li>
+                    <a class="moin-modify-button" href="{{ url_for(endpoint, item_name=item_name) }}" title="{{ title }}" rel="nofollow">{{ label }}</a>
+                </li>
+            {%- endif %}
+
             {%- if endpoint in [
-                'frontend.modify_item', 'frontend.rename_item', 'frontend.delete_item',
+                'frontend.rename_item', 'frontend.delete_item',
             ] and user.may.write(item_name) %}
                 <li>
                     <a href="{{ url_for(endpoint, item_name=item_name) }}" title="{{ title }}" rel="nofollow">{{ label }}</a>

MoinMoin/themes/foobar/templates/local.html

                         </li>
                     {%- endif %}
 
+                    {%- if endpoint == 'frontend.modify_item' and user.may.write(item_name) %}
+                        <li>
+                            <a class="moin-modify-button" href="{{ url_for(endpoint, item_name=item_name) }}" title="{{ title }}" rel="nofollow">{{ label }}</a>
+                        </li>
+                    {%- endif %}
+
                     {%- if endpoint in [
-                        'frontend.modify_item', 'frontend.rename_item', 'frontend.delete_item',
+                        'frontend.rename_item', 'frontend.delete_item',
                     ] and user.may.write(item_name) %}
                         <li>
                             <a href="{{ url_for(endpoint, item_name=item_name) }}" title="{{ title }}" rel="nofollow">{{ label }}</a>

MoinMoin/themes/foobar/templates/show.html

     {% endblock %}
 {% endblock %}
 
+{% block options_for_javascript %}
+{%- if item_name and user.edit_on_doubleclick and user.may.write(item_name) -%}
+    <br id="moin-edit-on-doubleclick" />
+{%- endif %}
+{%- if user.show_comments -%}
+    <br id="moin-show-comments" />
+{%- endif %}
+{% endblock %}