Jump to content

User:Anomie/ajaxpreview.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Anomie (talk | contribs) at 12:10, 8 July 2009 (Add pst=1 so subst and ~~~~ work). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/* If you want to use this script, simply add the following line to your monobook.js:
 
importScript('User:Anomie/ajaxpreview.js'); // Linkback: [[User:Anomie/ajaxpreview.js]]
 
* (Please keep the comment so I can see how many people use this).
*/

importScript('User:Anomie/util.js');

var AJAXPreview={
    node:null,
    txt:null,
    timer:null,
    idx:0,

    spinner:function(){
        switch(AJAXPreview.idx++){
          case 0:
            AJAXPreview.node.innerHTML='<center style="font-size:50pt">|</center>';
            break;
          case 1:
            AJAXPreview.node.innerHTML='<center style="font-size:50pt">/</center>';
            break;
          case 2:
            AJAXPreview.node.innerHTML='<center style="font-size:50pt">–</center>';
            break;
          case 3:
            AJAXPreview.node.innerHTML='<center style="font-size:50pt">\\</center>';
            AJAXPreview.idx=0;
            break;
        }
        AJAXPreview.node.style.display='block';
    },

    callback:function(r){
        if(AJAXPreview.timer) window.clearInterval(AJAXPreview.timer);
        AJAXPreview.timer=null;
        if(!r.parse || !r.parse.text || !r.parse.text['*']){
            AJAXPreview.node.innerHTML='<div style="border:1px solid #f00;background-color:#fcc;color:#f00;text-align:center">Bad response</div>';
            throw new Error('Bad response');
        }
        AJAXPreview.node.innerHTML=r.parse.text['*']+'<br />';
        AJAXPreview.node.style.display='block';

        // Set a timeout to allow the browser a chance to parse the innerHTML
        if(window.LinkClassifier) window.setTimeout(function(){ LinkClassifier.classifyChildren(AJAXPreview.node); }, 250);
        if(window.UserHighlighter) window.setTimeout(function(){ UserHighlighter.Highlight(AJAXPreview.node); }, 250);
    },

    doPreview:function(ev){
        if(!ev) ev=window.event;
        var txt='__NOEDITSECTION__\n'+AJAXPreview.getTextContent();
        var refs=AJAXPreview.getRefs(txt);
        var need=[];
        var groups='\x7b\x7b-\x7d\x7d';
        for(var g in refs){
            groups+='\n=='+(g?'Group '+g:'References')+'==\n\x7b\x7breflist|2|group='+g+'\x7d\x7d';
            for(var n in refs[g]){
                if(refs[g][n]===null) need.push([g,n]);
            }
        }
        if(need.length>0){
            var wikitext=rawpage(wgPageName);
            if(wikitext){
                txt+='\n\x3cdiv style="display:none"\x3e';
                refs=AJAXPreview.getRefs(wikitext);
                for(var i=need.length-1; i>=0; i--){
                    var x=refs[need[i][0]][need[i][1]];
                    if(!x) continue;
                    if(x.type=='tag'){
                        txt+='\x7b\x7b#tag:ref|'+x+'|name='+need[i][1]+'|group='+need[i][0]+'\x7d\x7d';
                    } else {
                        txt+='\x3cref name="'+need[i][1]+'" group="'+need[i][0]+'"\x3e'+x+'\x3c/ref\x3e';
                    }
                }
                txt+='\x3c/div\x3e';
            }
        }
        txt+=groups;

        var x=document.getElementById('wikiDiff');
        if(x) x.parentNode.removeChild(x);
        if(AJAXPreview.timer) window.clearInterval(AJAXPreview.timer);
        AJAXPreview.timer=window.setInterval(AJAXPreview.spinner, 250);
        if(!api({action:'parse',pst:1,text:txt,title:wgPageName,prop:'text'}, AJAXPreview.callback, true))
            return true;

        this.blur();
        window.scrollTo(0,0);
        if(ev.preventDefault) ev.preventDefault();
        if(ev.stopPropagation) ev.stopPropagation();
        ev.returnValue=false;
        ev.cancelBubble=true;
        return false;
    },

    getRefs:function(txt){
        var m,g,n,s;

        // First, pull out regular <refs>. We can do this with a regex.
        var refs={};
        txt.replace(/<ref((?:\s+\S+=(?:"[^\x22]*"|'[^\x27]*'|\S*?))*)\s*(?:\/>|>(.*?)<\/ref>)/ig, function(x,p,t){
            g=p.match(/\sgroup="([^\x22]*)"/i);
            if(!g) g=p.match(/\sgroup='([^\x27]*)'/i);
            if(!g) g=p.match(/\sgroup=(\S*)/i);
            g=g?g[1]:'';
            if(typeof(refs[g])=='undefined') refs[g]={};
            n=p.match(/\sname="([^\x22]*)"/i);
            if(!n) n=p.match(/\sname='([^\x27]*)'/i);
            if(!n) n=p.match(/\sname=(\S*)/i);
            if(!n) return;
            n=n[1];
            if(typeof(refs[g][n])=='undefined') refs[g][n]=null;
            if(refs[g][n]===null && typeof(t)!='undefined' && t!=='' && t!==null){
                refs[g][n]=t;
                refs[g][n].type='ref'
            }
        });

        // Second, if it looks like there are #tag refs, parse them too
        if(/\x7b\x7b\s*#tag\s*:\s*ref/.test(txt)){
            var d=[], i=0;
            while(i<txt.length){
                x=d.length?d[d.length-1]:null;
                if(txt.substr(i,3)=='\x7b\x7b\x7b'){
                    d.push({start:i,pstart:i+3,elen:3,end:'\x7d\x7d\x7d',params:[]});
                    i+=3;
                } else if(txt.substr(i,2)=='\x7b\x7b'){
                    d.push({start:i,pstart:i+2,elen:2,end:'\x7d\x7d',params:[]});
                    i+=2;
                } else if(x && txt.substr(i,x.elen)==x.end){
                    x.params.push(txt.substring(x.pstart,i));
                    i+=x.elen;
                    if(x.elen==2 && x.params[0].replace(/\s+/g,'').toLowerCase()=='#tag:ref'){
                        g=''; n=null;
                        for(var j=x.params.length-1; j>=2; j--){
                            m=x.params[j].match(/^\s*group=(.*?)\s*$/i);
                            if(m) g=m[1];
                            m=x.params[j].match(/^\s*name=(.*?)\s*$/i);
                            if(m) n=m[1];
                        }
                        if(typeof(refs[g])=='undefined') refs[g]={};
                        if(n!==null){
                            if(typeof(refs[g][n])=='undefined') refs[g][n]=null;
                            if(refs[g][n]===null && x.params[1]!==''){
                                refs[g][n]=x.params[1];
                                refs[g][n].type='tag'
                            }
                        }
                    }
                    d.pop();
                } else if(x && txt.substr(i,1)=='|'){
                    x.params.push(txt.substring(x.pstart,i));
                    x.pstart=++i;
                } else {
                    i++;
                }
            }
        }

        return refs;
    },
 
    onLoad:function(){
        if(wgAction!='edit' && wgAction!='submit') return;

        var editForm=document.getElementById('editform');
        if(!editForm) return;
        var sectionField = editForm.elements['wpSection'];
        var isSection=(sectionField && sectionField.value!="");

        AJAXPreview.node=document.getElementById('wikiPreview');
        if(!AJAXPreview.node) return;
        AJAXPreview.txt=editForm.elements["wpTextbox1"];
        if(!AJAXPreview.txt) return;

        var p=editForm.elements["wpPreview"];
        var b=document.createElement('INPUT');
        b.type='button';
        b.value='Ajax Preview'+(isSection?' w/Refs':'');
        b.tabIndex=p.tabIndex;
        b.onclick=AJAXPreview.doPreview;
        p.parentNode.insertBefore(b,p);
        p.parentNode.insertBefore(document.createTextNode(' '),p);
        p.value='Preview';
    },

    getTextContent:function(){
        return AJAXPreview.txt.value;
    }
};

if(doneOnloadHook) AJAXPreview.onLoad(); //if imported dynamically
else addOnloadHook(AJAXPreview.onLoad);