MediaWiki:Gadget/RegexMenuFramework.js

From OpenWetWare
Jump to: navigation, search
/*************
*** Regex menu framework 1.2
*** by [[m:user:Pathoschild]]
*** documentation: http://meta.wikimedia.org/wiki/User:Pathoschild/Script:Regex_menu_framework
*************/

if(wgAction=='edit' || wgAction=='submit') {
    /****************
    *** config tools
    ****************/
    // function
    function regexTool(name,functionname) {
        var newline = document.createElement('li');
    
        var newlink = document.createElement('a');
        newlink.setAttribute('href','javascript:'+functionname);
        newlink.setAttribute('title',name);
        newlink.setAttribute('class','sidebar-link');
        newlink.appendChild(document.createTextNode(name));
            
        newline.appendChild(newlink);
        toollist.appendChild(newline);
    }

    /****************
    *** framework tools
    ****************/
    /* search only */
    function regsearch(search) {
        return editbox.value.match(search);
    }
    
    /* search & replace */
    function regex(search,replace,repeat) {
        /* define how many times to perform */
        if(!repeat || repeat<0) {
            var repeat = 1;
        }
            /* perform */
        for(var i=0; i<repeat; i++) {
            editbox.value = editbox.value.replace(search,replace);
        }
    }

    /* change reason */
    function setreason(reason,mode) {
        // append mode
        if(mode=='append' && editreason.value.match(/[^\s]/)) {
            editreason.value = editreason.value+', '+reason;
        }
        // default mode
        else {
            editreason.value = reason;
        }
    }

    /* set edit options */
    function setoptions(minor,watch) {    
        // minor edit?
        if(minor=='true') {
            document.getElementById('wpMinoredit').checked = true;
        }
        else if(minor=='false') {
            document.getElementById('wpMinoredit').checked = false;
        }
        
        // watch page?
        if(watch=='true') {
            document.getElementById('wpWatchthis').checked = true;
        }
        else if(watch=='false') {
            document.getElementById('wpWatchthis').checked = false;
        }
    }

    /* automatically perform an action */
    function doaction(action) {
        if(action=='preview') {
            document.getElementById('wpPreview').click();
        }
        else if(action=='diff') {
            document.getElementById('wpDiff').click();
        }
        else if(action=='save') {
            document.getElementById('wpSave').click();
        }
    }

    /****************
    *** Custom regex form tool
    ****************/
    /* create form */
    function custom() {
        /* if already open */
        if(document.getElementById('regexform')) {
            /* display reset warning, unless it's already displayed */
            if(!document.getElementById('resetwarning')) {
                /* ask the user whether he wants to reset the form or cancel */
                // create elements
                resetwarning = document.createElement('div');
                resetwarning.setAttribute('id','resetwarning');
                
                var resetlink = document.createElement('a');
                resetlink.setAttribute('href','javascript:customremove(); custom();');
                resetlink.setAttribute('title','Reset form');
                resetlink.appendChild(document.createTextNode('reset form'));
    
                var cancellink = document.createElement('a');
                cancellink.setAttribute('href','javascript:function customreset() { regexform.removeChild(resetwarning); }; customreset();');
                cancellink.setAttribute('title','Cancel new launch');
                cancellink.appendChild(document.createTextNode('cancel new launch'));
    
                // put message together
                resetwarning.appendChild(document.createTextNode('You are launching the Custom regex tool, but it is already open. Please select an action: '));
                resetwarning.appendChild(resetlink);
                resetwarning.appendChild(document.createTextNode(' or '));
                resetwarning.appendChild(cancellink);
    
                // output
                regexform.insertBefore(resetwarning,regexform.firstChild);
            }
        }
        else {    
            /* container */
            regexform = document.createElement('div');
            regexform.setAttribute('id','regexform');
            editbox.parentNode.insertBefore(regexform,editbox.parentNode.firstChild);
    
            /* header */
            var formheader = document.createElement('h3');
            formheader.appendChild(document.createTextNode('Custom regex form'));
            regexform.appendChild(formheader);
    
            /* instructions */
            var newlink = document.createElement('a');
            newlink.setAttribute('href','javascript:function opennew(url) { window.open(url); }; opennew("http://www.regular-expressions.info/javascript.html");');
            newlink.setAttribute('title','JavaScript regex tutorial');
            newlink.setAttribute('class','external text');
            newlink.appendChild(document.createTextNode('tutorial'));
    
            var newtext = document.createElement('p');
            newtext.appendChild(document.createTextNode('This form allows you to dynamically run any number of regular expression patterns. Enter a search pattern in the search box, in the form "search pattern" or "/search pattern/modifiers" (see '));
            newtext.appendChild(newlink);
            newtext.appendChild(document.createTextNode('), and a replacement text in the replacement box (reference groups use "$1" through "$9").'));
            regexform.appendChild(newtext);

            /* mini tutorial */
            var newtext = document.createElement('p');
            newtext.appendChild(document.createTextNode('Available modifiers (can be combined, like /foo/mig):'));
            regexform.appendChild(newtext);

            var newtext = document.createElement('ul');
            var newitem = document.createElement('li');
            newitem.appendChild(document.createTextNode('multiline (/foo/m): pattern matches per-line, instead of treating the whole document as one line.'));
            regexform.appendChild(newtext);
            newtext.appendChild(newitem);

            var newitem = document.createElement('li');
            newitem.appendChild(document.createTextNode('global (/foo/g): replace all matches, not just the first one.'));
            newtext.appendChild(newitem);

            var newitem = document.createElement('li');
            newitem.appendChild(document.createTextNode('case-insensitive (/foo/i): pattern ignores case, so "/foo/i" matches both "foo" and "FOO".'));
            newtext.appendChild(newitem);
            
            /* form tag */
            var formform = document.createElement('form');
            formform.setAttribute('id','regexformform');
            regexform.appendChild(formform);
    
            // place marker for input boxes
            inputlist = document.createElement('ol');
            formform.appendChild(inputlist);
    
            /* options */
            // list format
            var formoptions = document.createElement('ul');
            formform.appendChild(formoptions);
            
            // go! link
            var container = document.createElement('li');
            var newlink = document.createElement('a');
            newlink.setAttribute('href','javascript:customgo();');
            newlink.setAttribute('title','Perform the above patterns');
            newlink.appendChild(document.createTextNode('Perform the above patterns'));
            newlink.setAttribute('style','font-weight:bold;');
            container.appendChild(newlink);
            formoptions.appendChild(container);
    
            // add new boxes link
            var container = document.createElement('li');
            var newlink = document.createElement('a');
            newlink.setAttribute('href','javascript:customaddnew();');
            newlink.setAttribute('title','Add new search & replace boxes');
            newlink.appendChild(document.createTextNode('Add search & replace boxes'));
            container.appendChild(newlink);
            formoptions.appendChild(container);
    
            // remove form
            var container = document.createElement('li');
            var newlink = document.createElement('a');
            newlink.setAttribute('href','javascript:customremove();');
            newlink.setAttribute('title','Remove this form');
            newlink.appendChild(document.createTextNode('Remove this form'));
            newlink.setAttribute('style','color:red;');
            container.appendChild(newlink);
            formoptions.appendChild(container);
    
            // add first pair of input boxes
            customaddnew();
        }
    }
    
    /* add a new pair of input boxes */
    function customaddnew() {
        /* count for later processing */
        if("patterncount" in window) {
            patterncount++;
        }
        else {
            patterncount = 0;
        }

        /* add new list item */
        var container = document.createElement('li');
        inputlist.appendChild(container);

        /* create search */
        var newinput = document.createElement('textarea');
        newinput.setAttribute('class','formsearch');
        newinput.setAttribute('tabindex',patterncount+100);
        newlabel = document.createElement('label');
        newlabel.setAttribute('for','formsearch');
        newlabel.appendChild(document.createTextNode('Search #'+(patterncount+1)));

        container.appendChild(newlabel);
        container.appendChild(newinput);
        
        /* force newline */
        container.appendChild(document.createElement('br'));

        /* create replace */
        var newinput = document.createElement('textarea');
        newinput.setAttribute('class','formreplace');
        newinput.setAttribute('tabindex',patterncount+101);
        newlabel = document.createElement('label');
        newlabel.setAttribute('for','formreplace');
        newlabel.appendChild(document.createTextNode('Replace #'+(patterncount+1)));
        
        container.appendChild(newlabel);
        container.appendChild(newinput);
    }

    /* run patterns */
    function customgo() {
        /* get search and replace arrays */
        var arrpatterns = regexform.getElementsByTagName('textarea');
        arrsearch = new Array();
        arrreplace = new Array();
        var searchcount = -1;
        var replacecount = -1;

        for(i=0; i<arrpatterns.length; i++) {
            /* search boxes */
            if(arrpatterns[i].getAttribute('class') == 'formsearch') {
                searchcount++;
                arrsearch[searchcount] = arrpatterns[i].value;
            }
            /* replace boxes */
            else if (arrpatterns[i].getAttribute('class') == 'formreplace') {
                replacecount++;
                arrreplace[replacecount] = arrpatterns[i].value;
            }
        }

        /* perform patterns */
        for(var i=0; i<arrsearch.length; i++) {
            /* convert input to regex */
            // without delimiters
            if(!arrsearch[i].match(/^\s*\/[\s\S]*\/[a-z]*\s*$/i)) {
                arrsearch[i] = new RegExp(arrsearch[i]);
            }
            // with delimiters
            else {
                // break into parts
                var regpattern = arrsearch[i].replace(/^\s*\/([\s\S]*)\/[a-z]*\s*$/i,'$1');
                var regmodifiers = arrsearch[i].replace(/^\s*\/[\s\S]*\/([a-z]*)\s*$/,'$1');

                // filter invalid flags
                regmodifiers = regmodifiers.replace(/[^gim]/ig,'');

                // convert into array
                arrsearch[i] = new RegExp(regpattern, regmodifiers);
            }

            /* perform */
            editbox.value = editbox.value.replace(arrsearch[i],arrreplace[i]);
        }
    }

    /* remove form */
    function customremove() {
        regexform.parentNode.removeChild(regexform);
        patterncount = -1;
    }

    /****************
    *** create menu
    ****************/
    function rfmenu(rfmconfig) {
        /* CSS */
        document.write('<style type="text/css">'
            + '#p-regex li { list-style:none !important; }'
            + '#p-regex a { color:gray !important; }'
            + '#regexform { margin:1em; padding:0.5em; border:2px solid blue; }'
            + '#regexform ol { list-style:none; border:1px solid #CCC; padding:0.5em; }'
            + '#resetwarning { border:1px solid red; padding:3px; }'
            + '</style>');


        /* create toolbar */
        /* get elements */
        // note: these must be global.
        editbox = document.getElementById('wpTextbox1');
        editreason = document.getElementById('wpSummary');
        sidebar = document.getElementById('p-navigation').parentNode;

        /* create menu */
        var container = document.createElement('div');
        container.setAttribute('class','portlet');
        container.setAttribute('id','p-regex');
        sidebar.appendChild(container);
                        
        var header = document.createElement('h5');
        header.appendChild(document.createTextNode('Scripts'));
        container.appendChild(header);
                        
        var toolbox = document.createElement('div');
        toolbox.setAttribute('class','p-body');
        container.appendChild(toolbox);
                        
        toollist = document.createElement('ul');
        toolbox.appendChild(toollist);
        

        /* load user-defined sidebar links */
        if(self['gadget_rmflinks']) { gadget_rmflinks(); }
        if(self['rmflinks']) { rmflinks(); }
    }

    /* load script */
    addOnloadHook(rfmenu);
}