]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/skins/default/media/js/wmd/wmd.js
bring back the question mark button of the markdown editor (WMD) and make it point...
[osqa.git] / forum / skins / default / media / js / wmd / wmd.js
index b6d0e434173c6fc25717de009ce7aae3c3157e17..fd429a4b241445b9ea532bc22ca6bc5705e29c38 100644 (file)
@@ -17,7 +17,7 @@ function ajaxFileUpload(imageUrl)
       $.ajaxFileUpload
       (
         {
-            url:'/upload/',
+            url: scriptUrl+'upload/',
               secureuri:false,
               fileElementId:'file-upload',
               dataType: 'xml',
@@ -28,7 +28,7 @@ function ajaxFileUpload(imageUrl)
                   if(error != ''){
                     alert(error);
                   }else{
-                    imageUrl.attr('value', fileURL);
+                    imageUrl.attr('value', appUrl + fileURL);
                   }
 
               },
@@ -71,19 +71,7 @@ Attacklab.wmdBase = function(){
        global.isOpera          = /opera/.test(nav.userAgent.toLowerCase());
        global.isKonqueror      = /konqueror/.test(nav.userAgent.toLowerCase());
        
-       var toolbar_strong_label = $.i18n._('bold') + " <strong> Ctrl-B";
-    var toolbar_emphasis_label = $.i18n._('italic') + " <em> Ctrl-I";
-    var toolbar_hyperlink_label = $.i18n._('link') + " <a> Ctrl-L";
-    var toolbar_blockquote_label = $.i18n._('quote') + " <blockquote> Ctrl-.";
-    var toolbar_code_label = $.i18n._('preformatted text') + " <pre><code> Ctrl-K";
-    var toolbar_image_label = $.i18n._('image') + " <img> Ctrl-G";
-    var toolbar_numbered_label = $.i18n._('numbered list') + " <ol> Ctrl-O";
-    var toolbar_bulleted_label = $.i18n._('bulleted list') + " <ul> Ctrl-U";
-    var toolbar_heading_label = $.i18n._('heading') + " <h1>/<h2> Ctrl-H";
-    var toolbar_horizontal_label = $.i18n._('horizontal bar') + " <hr> Ctrl-R";
-    var toolbar_undo_label = $.i18n._('undo') + " Ctrl-Z";
-    var toolbar_redo_label = $.i18n._('redo') + " Ctrl-Y";
-
+       
        // -------------------------------------------------------------------
        //  YOUR CHANGES GO HERE
        //
@@ -93,14 +81,13 @@ Attacklab.wmdBase = function(){
        
        // The text that appears on the upper part of the dialog box when
        // entering links.
-       var imageDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter image url') + "</p>";
-       var linkDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter url') + "</p>";
+    var imageDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter image url') + "</p>";
+    var linkDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter url') + "</p>";
     var uploadImageHTML ="<div>" + $.i18n._('upload image') + "</div>" +
             "<input type=\"file\" name=\"file-upload\" id=\"file-upload\" size=\"26\" "+
             "onchange=\"return ajaxFileUpload($('#image-url'));\"/><br>" +
             "<img id=\"loading\" src=\"" + mediaUrl("media/images/indicator.gif") + "\" style=\"display:none;\"/>";
 
-    
        // The default text that appears in the dialog input box when entering
        // links.
        var imageDefaultText = "http://";
@@ -114,8 +101,8 @@ Attacklab.wmdBase = function(){
        var pastePollInterval = 100;
        
        // The link and title for the help button
-       var helpLink = "http://wmd-editor.com/";
-       var helpHoverTitle = "WMD website";
+       var helpLink = "http://daringfireball.net/projects/markdown/syntax";
+       var helpHoverTitle = "MarkDown Syntax";
        var helpTarget = "_blank";
        
        // -------------------------------------------------------------------
@@ -302,7 +289,7 @@ Attacklab.wmdBase = function(){
                                text = text.replace('http://https://', 'https://');
                                text = text.replace('http://ftp://', 'ftp://');
                                
-                               if (text.indexOf('http://') === -1 && text.indexOf('ftp://') === -1 && text.indexOf('https://') === -1 && text.indexOf('/') !== 0) {
+                               if (text.indexOf('http://') === -1 && text.indexOf('ftp://') === -1 && text.indexOf('https://') === -1) {
                                        text = 'http://' + text;
                                }
                        }
@@ -386,9 +373,7 @@ Attacklab.wmdBase = function(){
                        
                        // The input text box
                        input = doc.createElement("input");
-            if(type == 1){
-                input.id = "image-url";
-            }
+            input.id = "image-url";
                        input.type = "text";
                        input.value = defaultInputText;
                        style = input.style;
@@ -396,15 +381,13 @@ Attacklab.wmdBase = function(){
                        style.width = "80%";
                        style.marginLeft = style.marginRight = "auto";
                        form.appendChild(input);
-                       
-            // The upload file input
-            if(type == 1){
-                var upload = doc.createElement("div");
-                upload.innerHTML = uploadImageHTML;
-                upload.style.padding = "5px";
-                form.appendChild(upload);
-            }
 
+            // The upload file input
+            var upload = doc.createElement("div");
+            upload.innerHTML = uploadImageHTML;
+            upload.style.padding = "5px";
+            form.appendChild(upload);
+                       
                        // The ok button
                        var okButton = doc.createElement("input");
                        okButton.type = "button";
@@ -1002,7 +985,7 @@ Attacklab.wmdBase = function(){
                        var boldButton = document.createElement("li");
                        boldButton.className = "wmd-button";
                        boldButton.id = "wmd-bold-button";
-                       boldButton.title = toolbar_strong_label;
+                       boldButton.title = "Strong <strong> Ctrl+B";
                        boldButton.XShift = "0px";
                        boldButton.textOp = command.doBold;
                        setupButton(boldButton, true);
@@ -1011,7 +994,7 @@ Attacklab.wmdBase = function(){
                        var italicButton = document.createElement("li");
                        italicButton.className = "wmd-button";
                        italicButton.id = "wmd-italic-button";
-                       italicButton.title = toolbar_emphasis_label;
+                       italicButton.title = "Emphasis <em> Ctrl+I";
                        italicButton.XShift = "-20px";
                        italicButton.textOp = command.doItalic;
                        setupButton(italicButton, true);
@@ -1025,7 +1008,7 @@ Attacklab.wmdBase = function(){
                        var linkButton = document.createElement("li");
                        linkButton.className = "wmd-button";
                        linkButton.id = "wmd-link-button";
-                       linkButton.title = toolbar_hyperlink_label;
+                       linkButton.title = "Hyperlink <a> Ctrl+L";
                        linkButton.XShift = "-40px";
                        linkButton.textOp = function(chunk, postProcessing, useDefaultText){
                                return command.doLinkOrImage(chunk, postProcessing, false);
@@ -1036,7 +1019,7 @@ Attacklab.wmdBase = function(){
                        var quoteButton = document.createElement("li");
                        quoteButton.className = "wmd-button";
                        quoteButton.id = "wmd-quote-button";
-                       quoteButton.title = toolbar_blockquote_label;
+                       quoteButton.title = "Blockquote <blockquote> Ctrl+Q";
                        quoteButton.XShift = "-60px";
                        quoteButton.textOp = command.doBlockquote;
                        setupButton(quoteButton, true);
@@ -1045,7 +1028,7 @@ Attacklab.wmdBase = function(){
                        var codeButton = document.createElement("li");
                        codeButton.className = "wmd-button";
                        codeButton.id = "wmd-code-button";
-                       codeButton.title = toolbar_code_label;
+                       codeButton.title = "Code Sample <pre><code> Ctrl+K";
                        codeButton.XShift = "-80px";
                        codeButton.textOp = command.doCode;
                        setupButton(codeButton, true);
@@ -1054,7 +1037,7 @@ Attacklab.wmdBase = function(){
                        var imageButton = document.createElement("li");
                        imageButton.className = "wmd-button";
                        imageButton.id = "wmd-image-button";
-                       imageButton.title = toolbar_image_label;
+                       imageButton.title = "Image <img> Ctrl+G";
                        imageButton.XShift = "-100px";
                        imageButton.textOp = function(chunk, postProcessing, useDefaultText){
                                return command.doLinkOrImage(chunk, postProcessing, true);
@@ -1070,7 +1053,7 @@ Attacklab.wmdBase = function(){
                        var olistButton = document.createElement("li");
                        olistButton.className = "wmd-button";
                        olistButton.id = "wmd-olist-button";
-                       olistButton.title = toolbar_numbered_label;
+                       olistButton.title = "Numbered List <ol> Ctrl+O";
                        olistButton.XShift = "-120px";
                        olistButton.textOp = function(chunk, postProcessing, useDefaultText){
                                command.doList(chunk, postProcessing, true, useDefaultText);
@@ -1081,7 +1064,7 @@ Attacklab.wmdBase = function(){
                        var ulistButton = document.createElement("li");
                        ulistButton.className = "wmd-button";
                        ulistButton.id = "wmd-ulist-button";
-                       ulistButton.title = toolbar_bulleted_label;
+                       ulistButton.title = "Bulleted List <ul> Ctrl+U";
                        ulistButton.XShift = "-140px";
                        ulistButton.textOp = function(chunk, postProcessing, useDefaultText){
                                command.doList(chunk, postProcessing, false, useDefaultText);
@@ -1092,7 +1075,7 @@ Attacklab.wmdBase = function(){
                        var headingButton = document.createElement("li");
                        headingButton.className = "wmd-button";
                        headingButton.id = "wmd-heading-button";
-                       headingButton.title = toolbar_heading_label;
+                       headingButton.title = "Heading <h1>/<h2> Ctrl+H";
                        headingButton.XShift = "-160px";
                        headingButton.textOp = command.doHeading;
                        setupButton(headingButton, true);
@@ -1101,7 +1084,7 @@ Attacklab.wmdBase = function(){
                        var hrButton = document.createElement("li");
                        hrButton.className = "wmd-button";
                        hrButton.id = "wmd-hr-button";
-                       hrButton.title = toolbar_horizontal_label;
+                       hrButton.title = "Horizontal Rule <hr> Ctrl+R";
                        hrButton.XShift = "-180px";
                        hrButton.textOp = command.doHorizontalRule;
                        setupButton(hrButton, true);
@@ -1115,7 +1098,7 @@ Attacklab.wmdBase = function(){
                        var undoButton = document.createElement("li");
                        undoButton.className = "wmd-button";
                        undoButton.id = "wmd-undo-button";
-                       undoButton.title = toolbar_undo_label;
+                       undoButton.title = "Undo - Ctrl+Z";
                        undoButton.XShift = "-200px";
                        undoButton.execute = function(manager){
                                manager.undo();
@@ -1126,13 +1109,13 @@ Attacklab.wmdBase = function(){
                        var redoButton = document.createElement("li");
                        redoButton.className = "wmd-button";
                        redoButton.id = "wmd-redo-button";
-                       redoButton.title = toolbar_redo_label;
+                       redoButton.title = "Redo - Ctrl+Y";
                        if (/win/.test(nav.platform.toLowerCase())) {
-                               redoButton.title = toolbar_redo_label;
+                               redoButton.title = "Redo - Ctrl+Y";
                        }
                        else {
                                // mac and other non-Windows platforms
-                               redoButton.title = $.i18n._('redo') + " - Ctrl+Shift+Z";
+                               redoButton.title = "Redo - Ctrl+Shift+Z";
                        }
                        redoButton.XShift = "-220px";
                        redoButton.execute = function(manager){
@@ -1141,6 +1124,21 @@ Attacklab.wmdBase = function(){
                        setupButton(redoButton, true);
                        buttonRow.appendChild(redoButton); 
                        
+                       var helpButton = document.createElement("li");
+                       helpButton.className = "wmd-button";
+                       helpButton.id = "wmd-help-button";
+                       helpButton.XShift = "-240px";
+                       helpButton.isHelp = true;
+                       
+                       var helpAnchor = document.createElement("a");
+                       helpAnchor.href = helpLink;
+                       helpAnchor.target = helpTarget
+                       helpAnchor.title = helpHoverTitle;
+                       helpButton.appendChild(helpAnchor);
+                       
+                       setupButton(helpButton, true);
+                       buttonRow.appendChild(helpButton);
+                       
                        setUndoRedoButtonStates();
                }
                
@@ -1173,14 +1171,6 @@ Attacklab.wmdBase = function(){
                                        var keyCode = key.charCode || key.keyCode;
                                        var keyCodeStr = String.fromCharCode(keyCode).toLowerCase();
                                        
-                                       // Bugfix for messed up DEL and .
-                                       if (keyCode === 46) {
-                                               keyCodeStr = "";
-                                       }
-                                       if (keyCode === 190) {
-                                               keyCodeStr = ".";
-                                       }
-
                                        switch(keyCodeStr) {
                                                case "b":
                                                        doClick(document.getElementById("wmd-bold-button"));
@@ -1350,7 +1340,7 @@ Attacklab.wmdBase = function(){
                                this.text = inputArea.value;
                        }
                        
-               };
+               }
                
                // Sets the selected text in the input box after we've performed an
                // operation.
@@ -1565,6 +1555,10 @@ Attacklab.wmdBase = function(){
                
                var regexText;
                var replacementText;
+
+        if (navigator.userAgent.match(/Chrome/)) {
+            "X".match(/()./)
+        }
                
                this.selection = this.selection.replace(/(^\n*)/, "");
                this.startTag = this.startTag + re.$1;
@@ -1642,7 +1636,7 @@ Attacklab.wmdBase = function(){
        // insertText: If you just click the button without highlighting text, this gets inserted
        command.doBorI = function(chunk, nStars, insertText){
        
-               // Get rid of whitespace and fixup newlines.
+               // Get rid of whitespace and fix up newlines.
                chunk.trimWhitespace();
                chunk.selection = chunk.selection.replace(/\n{2,}/g, "\n");
                
@@ -1711,7 +1705,9 @@ Attacklab.wmdBase = function(){
                chunk.after = command.stripLinkDefs(chunk.after, defsToAdd);
                
                var defs = "";
-               var regex = /(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;
+               var regex = /(\[)((?:\[[^\]]*\]|[^\[\]])*)(\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;
+        
+        
                
                var addDefNumber = function(def){
                        refNumber++;
@@ -1719,11 +1715,16 @@ Attacklab.wmdBase = function(){
                        defs += "\n" + def;
                };
                
-               var getLink = function(wholeMatch, link, id, end){
-               
+        // note that
+        // a) the recursive call to getLink cannot go infinite, because by definition
+        //    of regex, inner is always a proper substring of wholeMatch, and
+        // b) more than one level of nesting is neither supported by the regex
+        //    nor making a lot of sense (the only use case for nesting is a linked image)
+        var getLink = function (wholeMatch, before, inner, afterInner, id, end) {
+            inner = inner.replace(regex, getLink);
                        if (defsToAdd[id]) {
                                addDefNumber(defsToAdd[id]);
-                               return link + refNumber + end;
+                return before + inner + afterInner + refNumber + end;
                                
                        }
                        return wholeMatch;
@@ -1799,8 +1800,7 @@ Attacklab.wmdBase = function(){
                        };
                        
                        if (isImage) {
-                // add fourth param to identify image window
-                               util.prompt(imageDialogText, imageDefaultText, makeLinkMarkdown, 1);
+                               util.prompt(imageDialogText, imageDefaultText, makeLinkMarkdown);
                        }
                        else {
                                util.prompt(linkDialogText, linkDefaultText, makeLinkMarkdown);
@@ -2107,19 +2107,74 @@ Attacklab.wmdBase = function(){
                chunk.selection = chunk.selection.replace(/^(\s|>)+$/ ,"");
                chunk.selection = chunk.selection || defaultText;
                
+        // The original code uses a regular expression to find out how much of the
+        // text *directly before* the selection already was a blockquote:
+        /*
                if(chunk.before){
                        chunk.before = chunk.before.replace(/\n?$/,"\n");
                }
+        chunk.before = chunk.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/,
+                       function (totalMatch) {
+                           chunk.startTag = totalMatch;
+                           return "";
+                       });
+        */
+        // This comes down to:
+        // Go backwards as many lines a possible, such that each line
+        //  a) starts with ">", or
+        //  b) is almost empty, except for whitespace, or
+        //  c) is preceeded by an unbroken chain of non-empty lines
+        //     leading up to a line that starts with ">" and at least one more character
+        // and in addition
+        //  d) at least one line fulfills a)
+        //
+        // Since this is essentially a backwards-moving regex, it's susceptible to
+        // catstrophic backtracking and can cause the browser to hang;
+        // see e.g. http://meta.stackoverflow.com/questions/9807.
+        //
+        // Hence we replaced this by a simple state machine that just goes through the
+        // lines and checks for a), b), and c).
+
+        var match = "";
+        var leftOver = "";
+        if (chunk.before) {
+            var lines = chunk.before.replace(/\n$/, "").split("\n");
+            var inChain = false;
+            for (var i in lines) {
+                var good = false;
+                line = lines[i];
+                inChain = inChain && line.length > 0; // c) any non-empty line continues the chain
+                if (/^>/.test(line)) {                // a)
+                    good = true;
+                    if (!inChain && line.length > 1)  // c) any line that starts with ">" and has at least one more character starts the chain
+                        inChain = true;
+                } else if (/^[ \t]*$/.test(line)) {   // b)
+                    good = true;
+                } else {
+                    good = inChain;                   // c) the line is not empty and does not start with ">", so it matches if and only if we're in the chain
+                }
+                if (good) {
+                    match += line + "\n";
+                } else {
+                    leftOver += match + line;
+                    match = "\n";
+                }
+            }
+            if (!/(^|\n)>/.test(match)) {             // d)
+                leftOver += match;
+                match = "";
+            }
+        }
+
+        chunk.startTag = match;
+        chunk.before = leftOver;
+
+        // end of change
+        
                if(chunk.after){
                        chunk.after = chunk.after.replace(/^\n?/,"\n");
                }
                
-               chunk.before = chunk.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/,
-                       function(totalMatch){
-                               chunk.startTag = totalMatch;
-                               return "";
-                       });
-                       
                chunk.after = chunk.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/,
                        function(totalMatch){
                                chunk.endTag = totalMatch;
@@ -2408,7 +2463,7 @@ Attacklab.wmdBase = function(){
 
 Attacklab.wmd_env = {};
 Attacklab.account_options = {};
-Attacklab.wmd_defaults = {version:1, output:"Markdown", lineLength:40, delayLoad:false};
+Attacklab.wmd_defaults = {version:1, output:"HTML", lineLength:40, delayLoad:false};
 
 if(!Attacklab.wmd)
 {