|
|
Line 1: |
Line 1: |
− | // <pre><nowiki>
| + | alert('hello'); |
− | // Auto complete for links in the editbox GPL, (c) 2006, [[en:User:Zocky]]
| |
− | // type [[foo and press ctrl+space
| |
− | // should work in most browsers
| |
− | | |
− | // hook
| |
− | addOnloadHook(linkCompleteInit);
| |
− | | |
− | //init
| |
− | function linkCompleteInit()
| |
− | {
| |
− | if ($('#wpTextbox1'))
| |
− | {
| |
− | eventAddListener($('#wpTextbox1'),'keydown',linkCompleteKeyHandler);
| |
− | eventAddListener($('#wpTextbox1'),'keyup',linkCompleteKeyIgnorer1);
| |
− | eventAddListener($('#wpTextbox1'),'keypress',linkCompleteKeyIgnorer2);
| |
− | linkCompleteRegExp = window['linkCompleteTriggers'] || [ /\[\[([^\[\]\|\n]*?)$/ ];
| |
− | }
| |
− | }
| |
− | | |
− | // a bunch of globals [[a
| |
− | var linkCompleteStatus='idle';
| |
− | var linkCompleteFind='';
| |
− | var linkCompleteMatches=[];
| |
− | var linkCompleteNextPage;
| |
− | var linkCompleteNextMatch=0;
| |
− | var linkCompleteStart=0;
| |
− | var linkCompleteTarget=null;
| |
− | var linkCompleteRegExp=[];
| |
− | | |
− | // helpers
| |
− | function linkCompleteInsert(s)
| |
− | {
| |
− | var top=linkCompleteTarget.scrollTop;
| |
− | linkCompleteTarget.value = linkCompleteTarget.value.substr(0,linkCompleteStart)
| |
− | + s
| |
− | + linkCompleteTarget.value.substr(selectionGetStart(linkCompleteTarget));
| |
− | linkCompleteTarget.scrollTop=top;
| |
− | selectionSet(linkCompleteTarget, linkCompleteStart+s.length,linkCompleteStart+s.length);
| |
− | }
| |
− | | |
− | function linkCompleteInsertMatch()
| |
− | {
| |
− | if (linkCompleteNextMatch<linkCompleteMatches.length)
| |
− | {
| |
− | linkCompleteInsert(linkCompleteMatches[linkCompleteNextMatch]);
| |
− | linkCompleteNextMatch++;
| |
− | return true;
| |
− | }
| |
− | else
| |
− | {
| |
− | return false;
| |
− | }
| |
− | }
| |
− | | |
− | function linkCompleteGetMatches(from)
| |
− | {
| |
− | linkCompleteStatus='waiting';
| |
− | mwQueryPhp(linkCompleteLoaded,"allpages","apfrom", from, "aplimit","50","apfilterredir","nonredirects","apnamespace",window.linkCompleteNamespace || 0);
| |
− | linkCompleteInsert(linkCompleteFind+'...');
| |
− | }
| |
− | | |
− | function linkCompleteReset()
| |
− | {
| |
− | linkCompleteStatus='idle';
| |
− | linkCompleteInsert(linkCompleteFind);
| |
− | linkCompleteMatches=[];
| |
− | }
| |
− | | |
− | // main function
| |
− | | |
− | function linkCompleteKeyIgnorer1(e)
| |
− | {
| |
− | keynum = eventKeyCode(e);
| |
− | if (keynum==9) eventStop(e);
| |
− | }
| |
− | | |
− | function linkCompleteKeyIgnorer2(e)
| |
− | {
| |
− | keynum = e.charCode || e.keyCode;
| |
− | if (keynum==9) eventStop(e);
| |
− | }
| |
− | | |
− | | |
− | function linkCompleteKeyHandler(e)
| |
− | {
| |
− | keynum = eventKeyCode(e);
| |
− | target=eventTarget(e);
| |
− | | |
− | if ((keynum==9 || e.ctrlKey && keynum==32) && selectionGetStart(target)==selectionGetEnd(target))
| |
− | {
| |
− | if (target!=linkCompleteTarget)
| |
− | {
| |
− | linkCompleteTarget=target;
| |
− | linkCompleteStatus='idle';
| |
− | }
| |
− |
| |
− | switch(linkCompleteStatus)
| |
− | {
| |
− | case 'idle':
| |
− | var find;
| |
− | for (var i in linkCompleteRegExp)
| |
− | {
| |
− | find = (target.value.substr(0,selectionGetStart(target)).match(linkCompleteRegExp[i]) || [])[1];
| |
− | if (find) break;
| |
− | }
| |
− | if (find)
| |
− | {
| |
− | linkCompleteMatches=[];
| |
− | linkCompleteNextMatch=0;
| |
− | linkCompleteFind=find;
| |
− | linkCompleteStart=selectionGetStart(target)-find.length;
| |
− | linkCompleteGetMatches(find.capitalize());
| |
− | }
| |
− | break;
| |
− | case 'waiting':
| |
− | break;
| |
− | case 'loaded':
| |
− | if(linkCompleteNextMatch<linkCompleteMatches.length)
| |
− | {
| |
− | linkCompleteInsertMatch() || linkCompleteReset();
| |
− | }
| |
− | else
| |
− | {
| |
− | if (linkCompleteNextPage)
| |
− | {
| |
− | linkCompleteGetMatches(linkCompleteNextPage);
| |
− | }
| |
− | else
| |
− | {
| |
− | linkCompleteNextMatch=0;
| |
− | linkCompleteInsertMatch() || linkCompleteReset();
| |
− | }
| |
− | }
| |
− | }
| |
− | eventStop(e);
| |
− | }
| |
− | else
| |
− | {
| |
− | linkCompleteStatus == 'waiting' && linkCompleteReset();
| |
− | linkCompleteStatus = 'idle';
| |
− | }
| |
− | }
| |
− | | |
− | // JSON callback
| |
− | function linkCompleteLoaded(obj)
| |
− | {
| |
− | if (obj)
| |
− | {
| |
− | | |
− | | |
− | if (linkCompleteStatus=='waiting')
| |
− | {
| |
− | for (var i in obj.query.allpages)
| |
− | {
| |
− | page=obj.query.allpages[i];
| |
− | if
| |
− | (
| |
− | page.title
| |
− | && (page.ns && page.title.replace(/^.*?:/,'').substr(0,linkCompleteFind.length) == linkCompleteFind.capitalize())
| |
− | || page.title.substr(0,linkCompleteFind.length) == linkCompleteFind.capitalize()
| |
− | )
| |
− | {
| |
− | linkCompleteMatches[linkCompleteMatches.length]
| |
− | = page.ns ? page.title : linkCompleteFind + page.title.substr(linkCompleteFind.length);
| |
− | }
| |
− | }
| |
− | | |
− | linkCompleteNextPage
| |
− | = obj['query-continue']
| |
− | ? obj['query-continue'].allpages.apfrom.substr(0,linkCompleteFind.length) == linkCompleteFind.capitalize()
| |
− | ? obj['query-continue'].allpages.apfrom
| |
− | : false : false;
| |
− | | |
− | linkCompleteInsertMatch() && (linkCompleteStatus='loaded') || linkCompleteReset();
| |
− | }
| |
− | }
| |
− | else
| |
− | {
| |
− | linkCompleteReset();
| |
− | }
| |
− | }
| |
− | | |
− | | |
− | // query.php wrapper
| |
− | function mwQueryPhp (cb,what)
| |
− | {
| |
− | var x = window.XMLHttpRequest ? new XMLHttpRequest()
| |
− | : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP")
| |
− | : false;
| |
− | | |
− | if (mwQueryPhp.arguments.length>1 && x)
| |
− | {
| |
− | var url= wgScriptPath +"/api.php?format=json&action=query&list="+what;
| |
− | for (var i=2; i < mwQueryPhp.arguments.length; i+=2 )
| |
− | {
| |
− | url=url+"&"+escape(mwQueryPhp.arguments[i]) + "=" + escape(mwQueryPhp.arguments[i+1]);
| |
− | }
| |
− | | |
− | x.onreadystatechange=function() {
| |
− | if (x.readyState==4)
| |
− | return x.status==200
| |
− | ? cb(x.responseText.parseJSON())
| |
− | : cb(false);
| |
− | };
| |
− | x.open("GET",url,true);
| |
− | x.setRequestHeader('Accept','text/*');
| |
− | x.send(null);
| |
− | return true;
| |
− | }
| |
− | else return false;
| |
− | }
| |
− | | |
− | | |
− | | |
− | // cross-browser event functions
| |
− | | |
− | function eventAddListener (element,event,handler)
| |
− | {
| |
− | if (element.addEventListener)
| |
− | element.addEventListener(event,handler,false)
| |
− | else
| |
− | element.attachEvent('on'+event,handler);
| |
− | }
| |
− | | |
− | function eventRemoveListener (element, event, handler)
| |
− | {
| |
− | if (element.removeEventListener)
| |
− | element.removeEventListener(event,handler,false)
| |
− | else
| |
− | element.detachEvent('on'+event,handler);
| |
− | }
| |
− | | |
− | function eventStop(event)
| |
− | {
| |
− | if (event.preventDefault)
| |
− | {
| |
− | event.preventDefault();
| |
− | event.stopPropagation();
| |
− | }
| |
− | else
| |
− | {
| |
− | event.returnValue = false;
| |
− | event.cancelBubble = true;
| |
− | }
| |
− | }
| |
− | | |
− | function eventTarget(event)
| |
− | {
| |
− | return event.target || event.srcElement;
| |
− | }
| |
− | | |
− | function eventKeyCode(event)
| |
− | {
| |
− | return event.preventDefault ? event.which : event.keyCode ;
| |
− | }
| |
− | | |
− | | |
− | //from http://www.json.org/json.js
| |
− | String.prototype.parseJSON = function () {
| |
− | try {
| |
− | return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
| |
− | this.replace(/"(\\.|[^"\\])*"/g, ''))) &&
| |
− | eval('(' + this + ')');
| |
− | } catch (e) {
| |
− | return false;
| |
− | }
| |
− | };
| |
− | | |
− | //"foo".capitalize() -> "Foo"
| |
− | String.prototype.capitalize = function () { return this.substring(0,1).toUpperCase()+this.substring(1)};
| |
− | | |
− | function selectionSet(input, start, end) {
| |
− | if (input.setSelectionRange)
| |
− | {
| |
− | input.setSelectionRange(start,end)
| |
− | input.selectionEnd=end;
| |
− | }
| |
− | else
| |
− | {
| |
− | var range = input.createTextRange();
| |
− | range.collapse(true);
| |
− | range.moveStart("character", start);
| |
− | range.moveEnd("character", end - start);
| |
− | range.select();
| |
− | }
| |
− | };
| |
− | | |
− | function selectionGetStart(input)
| |
− | {
| |
− | if (input.setSelectionRange)
| |
− | {
| |
− | return input.selectionStart;
| |
− | }
| |
− | else
| |
− | {
| |
− | var range = document.selection.createRange();
| |
− | var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
| |
− | if (!isCollapsed)range.collapse(true);
| |
− | var b = range.getBookmark();
| |
− | return b.charCodeAt(2) - 2;
| |
− | }
| |
− | };
| |
− | | |
− | function selectionGetEnd(input) {
| |
− | if (input.setSelectionRange)
| |
− | {
| |
− | return input.selectionEnd;
| |
− | }
| |
− | else
| |
− | {
| |
− | var range = document.selection.createRange();
| |
− | var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
| |
− | if (!isCollapsed)range.collapse(false);
| |
− | var b = range.getBookmark();
| |
− | return b.charCodeAt(2) - 2;
| |
− | }
| |
− | };
| |
− | | |
− | //<nowiki></pre>
| |