(Created page with "/* 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...") Tags: mobile edit mobile web edit |
No edit summary Tags: mobile edit mobile web edit |
||
Line 1: | Line 1: | ||
/* If you want to use this script, simply add the following line to your monobook.js: | /* If you want to use this script, simply add the following line to your monobook.js: | ||
importScript('User: | importScript('User:Wwepro126/ajaxpreview.js'); // Linkback: [[User:Wwepro126/ajaxpreview.js]] | ||
* (Please keep the comment so I can see how many people use this). | * (Please keep the comment so I can see how many people use this). |
Latest revision as of 16:09, 2 May 2019
/* If you want to use this script, simply add the following line to your monobook.js: importScript('User:Wwepro126/ajaxpreview.js'); // Linkback: [[User:Wwepro126/ajaxpreview.js]] * (Please keep the comment so I can see how many people use this). */ 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 window.setTimeout(function(){ mw.hook( 'wikipage.content' ).fire( $( AJAXPreview.node ) ); for(var i=AJAXPreview.$OnLoadHooks.length-1; i>=0; i--) AJAXPreview.$OnLoadHooks[i].call(window, AJAXPreview.node); }, 250); }, doError:function(xhr,textStatus,errorThrown){ if(AJAXPreview.timer) window.clearInterval(AJAXPreview.timer); AJAXPreview.timer=null; while(AJAXPreview.node.firstChild) AJAXPreview.node.removeChild(AJAXPreview.node.firstChild); var d=document.createElement('DIV'); d.style.border='1px solid #f00'; d.style.backgroundColor='#fcc'; d.style.color='#f00'; d.style.textAlign='center'; d.appendChild(document.createTextNode('AJAX Error: '+textStatus+' '+errorThrown)); AJAXPreview.node.appendChild(d); AJAXPreview.node.style.display='block'; throw new Error('AJAX error: '+textStatus+' '+errorThrown); }, doPreview:function(ev){ if(!ev) ev=window.event; var txt='__NOEDITSECTION__\n'+AJAXPreview.getTextContent(); var refs=AJAXPreview.getRefs(txt); var need=[]; var groups={}; for(var g in refs){ groups[g]=''; for(var n in refs[g]){ if(refs[g][n].text===null) need.push([g,n]); } } var doPreview2=function(wikitext,sts,xhr){ if(wikitext){ 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'){ groups[need[i][0]]+='\x7b\x7b#tag:ref|'+x.text+'|name='+need[i][1]+'|group='+need[i][0]+'\x7d\x7d'; } else { groups[need[i][0]]+='\x3cref name="'+need[i][1]+'" group="'+need[i][0]+'"\x3e'+x.text+'\x3c/ref\x3e'; } } } txt+='\n\n\x7b\x7b-\x7d\x7d\n----\n'; for(var g in groups){ txt+='\n;'+(g?'Group '+g:'References')+'\n\x7b\x7breflist|2|group='+g+'|refs='+groups[g]+'\x7d\x7d'; } jQuery.ajax({ url:mw.util.wikiScript('api'), dataType:'json', type:'POST', data:{ format:'json', action:'parse', pst:1, text:txt, title:mw.config.get('wgPageName'), prop:'text' }, success:AJAXPreview.callback, error:AJAXPreview.doError }); }; mw.loader.using('mediawiki.util', function(){ if(need.length>0){ jQuery.ajax({ url:mw.util.wikiScript('index'), dataType:'text', type:'GET', data:{ action:'raw', title:mw.config.get('wgPageName') }, success:doPreview2, error:AJAXPreview.doError }); } else { doPreview2(null,null,null); } }); 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); this.blur(); window.scrollTo(0,0); if(ev){ // OOUI may not have an event here if(ev.preventDefault) ev.preventDefault(); if(ev.stopPropagation) ev.stopPropagation(); ev.returnValue=false; ev.cancelBubble=true; } return false; }, getRefs:function(txt){ var g; var refs={}; // The new "list-defined references" have to be handled specially, // which means we have to manage to pull them out of the wikitext. Fun. // First, do the XML-style tags. txt=txt.replace(/<references((?:\s+[^>]*[^\/>])?)(?:\/>|>((?:.|[\r\n])*?)(<\/references>|$))/ig, function(x,p,t,c){ p=p.replace(/\s+$/g,''); 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]:''; refs=AJAXPreview.getRefs2(t,g,refs); return ''; }); // Next, to reflist and #tag:references txt=AJAXPreview.process_templates(txt,function(n,p,o){ var c=null, g=''; if(n=='Reflist'){ for(var j=0; j<p.length; j++){ var m=p[j].match(/^\s*refs\s*=\s*((?:.|[\r\n])*?)\s*$/); if(m) c=m[1]; var m=p[j].match(/^\s*group\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/); if(m) g=m[2]; } if(c===null) c=''; } else if(/^#tag:\s*references$/i.test(n)){ c=p.length ? p.shift() : ''; for(var j=0; j<p.length; j++){ var m=p[j].match(/^\s*group\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/); if(m) g=m[2]; } } else { return null; } refs=AJAXPreview.getRefs2(c,g,refs); return ''; }); return AJAXPreview.getRefs2(txt,'',refs); }, getRefs2:function(txt,defgroup,refs){ var g,n; // First, pull out regular <refs>. We can do this with a regex. txt.replace(/<ref((?:\s+\S+=(?:"[^\x22]*"|'[^\x27]*'|\S*?))*)\s*(?:\/>|>((?:.|[\r\n])*?)<\/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]:defgroup; 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 null; n=n[1]; if(typeof(refs[g][n])=='undefined') refs[g][n]={text:null,type:'?'}; if(refs[g][n].text===null && typeof(t)!='undefined' && t!=='' && t!==null){ refs[g][n].text=t; refs[g][n].type='ref' } return null; }); // Second, if it looks like there are #tag refs, parse them too AJAXPreview.process_templates(txt,function(nm,p,o){ if(!/^#tag:\s*ref$/i.test(nm)) return null; g=defgroup; n=null; for(var j=p.length-1; j>=1; j--){ var m=p[j].match(/^\s*group\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/); if(m) g=m[2]; var m=p[j].match(/^\s*name\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/); if(m) n=m[2]; } if(typeof(refs[g])=='undefined') refs[g]={}; if(n!==null){ if(typeof(refs[g][n])=='undefined') refs[g][n]={text:null,type:'?'}; if(refs[g][n].text===null && p[0]!==''){ refs[g][n].text=p[0]; refs[g][n].type='tag' } } return null; }); return refs; }, process_templates:function(txt,cb,data){ var stack=[], i=0; while(i<txt.length){ var x=stack.length?stack[stack.length-1]:null; var xb=null; for(var j=0; j<stack.length; j++){ if(stack[j].char=='\x5b') xb=stack[j]; } if(txt.substr(i,2)=='\x7b\x7b'){ var ct; for(ct=2; txt.substr(i+ct,1)=='\x7b'; ct++); stack.push({char:'\x7b',start:i,count:ct,pstart:i+ct,params:[]}); i+=ct; } else if(txt.substr(i,2)=='\x5b\x5b'){ var ct; for(ct=2; txt.substr(i+ct,1)=='\x5b'; ct++); stack.push({char:'\x5b',start:i,count:ct,pstart:i+ct,params:[]}); i+=ct; } else if(x && x.char=='\x7b' && txt.substr(i,2)=='\x7d\x7d'){ var ct; for(ct=2; txt.substr(i+ct,1)=='\x7d'; ct++); if(ct>x.count) ct=x.count; i+=ct; x.params.push(txt.substring(x.pstart,i-ct)); // First, parse out variables while(ct>=3){ x.count-=3; ct-=3; var s=x.start-x.count; x.params=[txt.substring(s,i-x.count)]; } // Any left is templates while(ct>=2){ x.count-=2; ct-=2; var s=x.start+x.count; var orig=txt.substring(s,i-ct); var name=x.params.shift(); var oname=name; name=name.replace(/_/g,' '); name=name.replace(/^\s+|\s+$/g,''); name=name.replace(/ +/g,' '); name=name.replace(/^Template\s*:\s*/ig,''); name=name.substr(0,1).toUpperCase()+name.substr(1); var ret=cb(name, x.params, orig, data, oname); if(ret===null){ x.params=[orig]; } else { ret=""+ret; var d=(ret=='' && (s==0 || txt.substr(s-1,1)=='\n') && txt.substr(i-ct,1)=='\n')?1:0; txt=txt.substr(0,s)+ret+txt.substr(i-ct+d); i=s+ret.length+ct; x.params=[ret]; } } if(x.count<2){ stack.pop(); } else { // The one we just completed might not be the end of the // param, so reset the param array and pstart x.params=[]; x.pstart=x.start+x.count; } } else if(xb && txt.substr(i,2)=='\x5d\x5d'){ // Drop any pending templates, they're not really templates while(stack[stack.length-1]!=xb) stack.pop(); var ct; for(ct=2; txt.substr(i+ct,1)=='\x5d'; ct++); if(ct>xb.count) ct=xb.count; i+=ct; xb.count-=ct; if(xb.count<2){ stack.pop(); } else { // The one we just completed might not be the end of the // param, so reset the param array and pstart xb.params=[]; xb.pstart=xb.start+xb.count; } } else if(x && txt.substr(i,1)=='|'){ x.params.push(txt.substring(x.pstart,i)); x.pstart=++i; } else { i++; } } return txt; }, onLoad:function(){ var action=mw.config.get('wgAction'); if(action!='edit' && action!='submit') return; var editForm=document.getElementById('editform'); if(!editForm) return; var sectionField = editForm.elements['wpSection']; var isSection=(sectionField && sectionField.value!=""); var p=editForm.elements["wpPreview"]; if(!p) return; AJAXPreview.node=document.getElementById('wikiPreview'); if(!AJAXPreview.node) return; AJAXPreview.txt=editForm.elements["wpTextbox1"]; if(!AJAXPreview.txt) return; mw.loader.using( [ 'oojs-ui-core' ] ).done( function () { var b = new OO.ui.ButtonWidget( { label: 'Ajax Preview'+(isSection?' w/Refs':''), tabIndex: p.tabIndex } ); b.on( 'click', AJAXPreview.doPreview ); $( p ).before( b.$element, ' ' ); } ); p.value='Preview'; // Hooks for standard functions if(typeof(window.createCollapseButtons) == 'function') AJAXPreview.AddOnLoadHook(createCollapseButtons); if(typeof(window.createNavigationBarToggleButton) == 'function') AJAXPreview.AddOnLoadHook(createNavigationBarToggleButton); }, getTextContent:function(){ return AJAXPreview.txt.value; }, // Add callback functions here. AddOnLoadHook:function(f){ AJAXPreview.$OnLoadHooks.push(f); }, $OnLoadHooks:[] }; $(document).ready(AJAXPreview.onLoad);