/**
// <source lang="javascript">
* Gadget-LinkComplete.js
// Auto complete for links in the editbox GPL, (c) 2006, [[en:User:Zocky]]
* Funzione di autocompletamento dei wikilink, si attiva con Tab o Ctrl+Spazio.
// type [[foo and press ctrl+space
* Riscritto da zero a partire da:
// should work in most browsers
* http://it.wikipedia.org/w/index.php?title=MediaWiki:Gadget-LinkComplete.js&oldid=51953861
* che a sua volta lo importava da:
* http://en.wikipedia.org/wiki/User:Zocky/LinkComplete.js
*
* @author [[Utente:Rotpunkt]]
*/
/*global mediaWiki, jQuery */
( function ( mw, $ ) {
//Preso da [[:en:User:Zocky/LinkComplete.js]] e adattato.
'use strict';
// Classe per la funzione di autocompletamento
if (typeof window.__LINKCOMPLETE_LOADED == 'undefined'){ //guard against multiple inclusions
function AutoComplete( pos, text, el ) {
window.__LINKCOMPLETE_LOADED = true;
var position = pos,
initialText = text,
element = el,
pages = null,
currPage = 0,
currContinue = null,
prevContinue = null,
currText = text;
// Ritorna la lista delle pagine che iniziano con prefix ( in JSON )
//init
function getPages( prefix, pcontinue, pageHandler ) {
function linkCompleteInit()
$.ajax( {
{
url: mw.util.wikiScript( 'api' ),
if (document.getElementById('wpTextbox1'))
data: {
{
action: 'query',
eventAddListener(document.getElementById('wpTextbox1'),'keydown',linkCompleteKeyHandler);
list: 'allpages',
eventAddListener(document.getElementById('wpTextbox1'),'keyup',linkCompleteKeyIgnorer1);
apprefix: prefix,
eventAddListener(document.getElementById('wpTextbox1'),'keypress',linkCompleteKeyIgnorer2);
apcontinue: pcontinue,
linkCompleteRegExp = window['linkCompleteTriggers'] || [ /\[\[([^\[\]\|\n]*?)$/ ];
aplimit: '50',
}
apfilterredir: 'nonredirects',
}
format: 'json',
rawcontinue: ''
},
async: false,
dataType: 'json'
} )
.done( function ( data ) {
if ( data.query && data.query.allpages.length > 0 ) {
pageHandler( data.query.allpages, data['query-continue'] ?
data['query-continue'].allpages.apcontinue : null );
}
} );
}
// Inserisce il nome della pagina nell'area di modifica
// a bunch of globals [[a
function dump() {
var linkCompleteStatus='idle';
// preserva il case del primo carattere
var linkCompleteFind='';
if ( initialText.length > 0 ) {
var linkCompleteMatches=[];
pages[currPage].title = initialText.charAt( 0 ) + pages[currPage].title.substring( 1 );
var linkCompleteNextPage;
}
var linkCompleteNextMatch=0;
$( element ).textSelection( 'encapsulateSelection',
var linkCompleteStart=0;
{ pre: pages[currPage].title, selectionStart: position,
var linkCompleteTarget=null;
selectionEnd: position + currText.length, replace: true } );
var linkCompleteRegExp=[];
currText = pages[currPage].title;
// aggiorna currPage
if ( currPage >= pages.length - 1 ) {
if ( currContinue ) {
pages = null;
} else if ( prevContinue ) {
prevContinue = null;
pages = null;
} else {
currPage = 0;
}
} else {
currPage += 1;
}
}
AutoComplete.prototype.getCurrText = function () {
// helpers
return currText;
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);
}
AutoComplete.prototype.complete = function () {
function linkCompleteInsertMatch()
// eventualmente ottiene la lista di pagine
{
if ( !pages ) {
if (linkCompleteNextMatch<linkCompleteMatches.length)
getPages( initialText, currContinue, function ( retPages, pcontinue ) {
{
pages = retPages;
linkCompleteInsert(linkCompleteMatches[linkCompleteNextMatch]);
prevContinue = currContinue;
linkCompleteNextMatch++;
currContinue = pcontinue;
return true;
currPage = 0;
}
} );
else
}
{
if ( pages ) {
return false;
dump();
}
}
}
};
}
$( function linkCompleteGetMatches(from) {
// previene con Firefox l'azione di default del tasto Tab
{
var tabDefault = true, ac;
linkCompleteStatus='waiting';
mwQueryPhp(linkCompleteLoaded,"allpages","apcontinue", from, "aplimit","50","apfilterredir","nonredirects","apnamespace",window.linkCompleteNamespace || 0);
linkCompleteInsert(linkCompleteFind+'...');
}
$( '#wpTextbox1, #wpUploadDescription' ).keydown( function ( event ) {
function linkCompleteReset()
var pos, text;
{
if ( ( !event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey && event.keyCode === 9 ) ||
linkCompleteStatus='idle';
( !event.altKey && !event.shiftKey && event.ctrlKey && !event.metaKey && event.keyCode === 32 ) ) {
linkCompleteInsert(linkCompleteFind);
tabDefault = true;
linkCompleteMatches=[];
pos = $( event.target ).textSelection( 'getCaretPosition' );
}
text = $( event.target ).val().replace( /\r\n/g, '\n' ).substring( 0, pos );
pos = text.lastIndexOf( '[[' ) + 2;
// main function
text = text.substring( pos );
if ( pos >= 2 && !/[\[\]\{\}\r\n\|]/.test( text ) ) {
function linkCompleteKeyIgnorer1(e)
tabDefault = false;
{
event.preventDefault();
keynum = eventKeyCode(e);
if ( !ac || text !== ac.getCurrText() ) {
if (keynum==9) eventStop(e);
ac = new AutoComplete( pos, text, event.target );
}
}
ac.complete();
function linkCompleteKeyIgnorer2(e)
}
{
}
keynum = e.charCode || e.keyCode;
} );
if (keynum==9) eventStop(e);
$( '#wpTextbox1, #wpUploadDescription' ).keypress( function ( event ) {
}
if ( !event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey && event.keyCode === 9 ) {
return tabDefault;
}
function linkCompleteKeyHandler(e)
} );
{
} );
keynum = eventKeyCode(e);
}( mediaWiki, jQuery ) );
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.apcontinue.substr(0,linkCompleteFind.length) == linkCompleteFind.capitalize()
? obj['query-continue'].allpages.apcontinue
: 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;
}
};
jQuery(document).ready(linkCompleteInit);
} //guard
//</source>
|