מדיה ויקי:Gadget-autocomplete.js: הבדלים בין גרסאות בדף
Abhishek.it (שיחה | תרומות) החלפת הדף בתוכן "mw.loader.load('//he.wikipedia.org/w/load.php?modules=ext.gadget.autocomplete');" תגיות: החלפה שוחזרה |
Abhishek.it (שיחה | תרומות) אין תקציר עריכה תגית: שוחזרה |
||
(גרסת ביניים אחת של אותו משתמש אינה מוצגת) | |||
שורה 1: | שורה 1: | ||
mw.loader. | /* | ||
Autocomplete for links and templates | |||
Written by [[משתמש:ערן]] | |||
*/ | |||
mw.loader.using(['jquery.ui', 'jquery.textSelection'], function() { | |||
$.fn.autoCompleteWikiText = function(options) { | |||
var mode = "none", | |||
templateDataCache = {}, | |||
ctrl = $(this), | |||
settings = $.extend(true, { | |||
positionMy: $('body').is('.rtl') ? "left top" : "right top", | |||
positionAt: $('body').is('.rtl') ? "left bottom" : "right bottom", | |||
positionOf: ctrl, | |||
positionOffset: "0", | |||
filterResponse: function(a) { | |||
return a; | |||
}, | |||
menuCSS: { | |||
width: 'auto', | |||
maxHeight: '30em', | |||
'overflow-y': 'auto' | |||
}, | |||
itemCSS: { | |||
right: 'inherit' | |||
}, | |||
onselected: function(item) { | |||
var pos = ctrl.textSelection('getCaretPosition') - 1, | |||
txt = ctrl.val(), | |||
open, close, caretBackwards; | |||
switch (mode) { | |||
case "none": | |||
return; | |||
case "templateValue": | |||
open = "|"; | |||
close = ""; | |||
caretBackwards = 0; | |||
break; | |||
case "templateParams": | |||
open = "|"; | |||
close = "="; | |||
caretBackwards = 0; | |||
break; | |||
case "template": | |||
item = item.substr(mw.config.get('wgFormattedNamespaces')[10].length + 1); | |||
caretBackwards = 2; | |||
open = "{{"; | |||
close = "|}}"; | |||
break; | |||
case "link": | |||
open = "[["; | |||
close = "]]"; | |||
caretBackwards = 0; | |||
if (item[item.length - 1] == ')') item += '|'; | |||
break; | |||
} | |||
var lastbegin = txt.lastIndexOf(open, pos); | |||
if (txt[lastbegin + 2] == ':') | |||
item = ':' + item; | |||
var newTxt = txt.substr(0, lastbegin) + open + item + close + txt.substr(pos + 1); | |||
var orgScroll = ctrl.scrollTop(); | |||
ctrl.val(newTxt); | |||
ctrl.textSelection('setSelection', { | |||
start: lastbegin + (open + item + close).length - caretBackwards | |||
}); | |||
ctrl.scrollTop(orgScroll); | |||
} | |||
}, options); | |||
function findLinks(res) { | |||
var pos = ctrl.textSelection('getCaretPosition') - 1; | |||
var txt = ctrl.val(); | |||
var lastbegin = txt.lastIndexOf("[[", pos); | |||
var lastend = txt.lastIndexOf("]]", pos); | |||
var isLink = lastbegin > lastend; | |||
if (isLink) { | |||
mode = 'link'; | |||
fillLinksList(res, txt.substr(lastbegin + 2, pos - lastbegin)); | |||
} else { | |||
lastbegin = txt.lastIndexOf("{{", pos); | |||
lastend = txt.lastIndexOf("}}", pos); | |||
var isTemplate = lastbegin > lastend; | |||
if (isTemplate) { | |||
var prefixName = mw.config.get('wgFormattedNamespaces')[10] + ':' + txt.substr(lastbegin + 2, pos - lastbegin - 1); | |||
mode = (prefixName.indexOf('|') > -1) ? 'templateParams' : 'template'; | |||
fillLinksList(res, prefixName); | |||
} else { | |||
mode = "none"; | |||
res([]); | |||
} | |||
} | |||
} | |||
function resolveTemplate(templateName) { | |||
var dfd = new jQuery.Deferred(); | |||
if (!templateName) return dfd.reject().promise(); | |||
if (templateDataCache[templateName]) return dfd.resolve(templateDataCache[templateName]).promise(); | |||
var api = new mw.Api(); | |||
api.get({ | |||
action: 'templatedata', | |||
titles: templateName, | |||
redirects: 1 | |||
}).done(function(data) { | |||
if (!data.pages) return dfd.reject(); | |||
for (var pageid in data.pages) { | |||
templateDataCache[templateName] = data.pages[pageid]; | |||
dfd.resolve(templateDataCache[templateName]); | |||
} | |||
if (!templateDataCache[templateName]) dfd.reject(); | |||
}); | |||
return dfd.promise(); | |||
} | |||
function resolveApi(queryType, queryValue) { | |||
var dfd = new jQuery.Deferred(), | |||
api = new mw.Api(); | |||
switch (queryType) { | |||
case 'users': | |||
api.get({ | |||
action: 'query', | |||
list: 'allusers', | |||
auactiveusers: 1, | |||
auprefix: queryValue | |||
}).done(function(data) { | |||
if (data && data.query && data.query.allusers) dfd.resolve($.map(data.query.allusers, function(e) { | |||
return e.name; | |||
})); | |||
else dfd.reject(); | |||
}); | |||
break; | |||
case 'pages': | |||
api.get({ | |||
action: 'opensearch', | |||
search: queryValue | |||
}).done(function(data) { | |||
if (data[1]) dfd.resolve(settings.filterResponse(data[1])); | |||
else dfd.reject(); | |||
}); | |||
break; | |||
default: | |||
throw 'unexpected queryType'; | |||
} | |||
return dfd.promise(); | |||
} | |||
function fillLinksList(res, txt) { | |||
txt = $.trim(txt); | |||
if (txt.length <= 1 || (mode != 'templateParams' && txt.indexOf('|') > -1) || (txt.indexOf('#') > -1 && mw.config.get('wgNamespaceNumber') === 0)) res([]); | |||
else if (mode === 'templateParams') { | |||
var templateMatch = /(.+?)\|(?:.*\|)?([^=]+$)/.exec(txt); | |||
var templateParamMatch = /(.+?)\|(?:.*\|)?([^=]+=[^=]+$)/.exec(txt); | |||
$.when(resolveTemplate((templateMatch && templateMatch[1]) || (templateParamMatch && templateParamMatch[1]))).done(function(td) { | |||
var curTemplateData = td, | |||
suggestions = [], | |||
curParamIndex = txt.split('|').length - 1; | |||
if (templateParamMatch && !templateMatch) { | |||
var paramNameVal = templateParamMatch[2].split('='); | |||
if (paramNameVal[0] in curTemplateData.params && 'suggestedvalues' in curTemplateData.params[paramNameVal[0]]) { | |||
mode = 'templateValue'; | |||
var suggestedValues = curTemplateData.params[paramNameVal[0]].suggestedvalues; | |||
for (var i = 0; i < suggestedValues.length; i++) { | |||
var suggestedVal = suggestedValues[i]; | |||
if (suggestedVal.indexOf(paramNameVal[1]) === 0) { | |||
suggestions.push(paramNameVal[0] + '=' + suggestedVal); | |||
} | |||
} | |||
} | |||
} else { | |||
for (var paramName in curTemplateData.params) { | |||
if (paramName == curParamIndex) { | |||
var paramValue = templateMatch[2]; | |||
var dfd; | |||
switch (curTemplateData.params[paramName].type) { | |||
case 'wiki-page-name': | |||
dfd = $.when(resolveApi('pages', paramValue)); | |||
mode = 'templateValue'; | |||
break; | |||
case 'wiki-file-name': | |||
dfd = $.when(resolveApi('pages', 'File:' + paramValue)); | |||
mode = 'templateValue'; | |||
break; | |||
case 'wiki-template-name': | |||
dfd = $.when(resolveApi('pages', 'Template:' + paramValue)); | |||
mode = 'templateValue'; | |||
break; | |||
case 'wiki-user-name': | |||
dfd = $.when(resolveApi('users', paramValue)); | |||
mode = 'templateValue'; | |||
break; | |||
case 'string': | |||
if ('suggestedvalues' in curTemplateData.params[paramName]) { | |||
mode = 'templateValue'; | |||
var suggestedValues = curTemplateData.params[paramName].suggestedvalues; | |||
for (var i = 0; i < suggestedValues.length; i++) { | |||
var suggestedVal = suggestedValues[i]; | |||
if (suggestedVal.indexOf(paramValue) === 0) { | |||
suggestions.push(suggestedVal); | |||
} | |||
} | |||
return res(suggestions); | |||
} else | |||
return res([]); | |||
default: | |||
return res([]); | |||
} | |||
return dfd.done(res).fail(function() { | |||
res([]); | |||
}); | |||
} | |||
if (paramName === '1' || txt.indexOf(paramName) > -1) continue; | |||
suggestions.push(paramName); | |||
} | |||
} | |||
res(suggestions); | |||
}).fail(res); | |||
} else if (txt.indexOf('#') > -1) { | |||
var pageTitle = txt.substr(0, txt.indexOf('#')); | |||
var sectionPrefix = txt.substr(txt.indexOf('#') + 1); | |||
var api = new mw.Api(); | |||
api.get({ | |||
action: 'parse', | |||
page: pageTitle, | |||
prop: 'sections' | |||
}).done(function(data) { | |||
if (data && data.parse && data.parse.sections) res($(data.parse.sections).map(function() { | |||
return this.line.indexOf(sectionPrefix) == 0 ? (pageTitle + '#' + this.line.replace(/[|\[\]\{\}]/g, escape)) : null; | |||
})); | |||
}); | |||
} else { | |||
$.when(resolveApi('pages', txt)).done(res).fail(function() { | |||
res([]); | |||
}); | |||
} | |||
} | |||
ctrl.autocomplete({ | |||
source: function(request, response) { | |||
if (fixArrowsBug(this)) | |||
response([]); | |||
else | |||
findLinks(response); | |||
}, | |||
focus: function() { | |||
return false; | |||
}, | |||
select: function(e, ui) { | |||
settings.onselected(ui.item.value); | |||
return false; | |||
}, | |||
open: function() { | |||
$(".ui-autocomplete") | |||
.css(settings.menuCSS) | |||
.position({ | |||
my: settings.positionMy, | |||
at: settings.positionAt, | |||
of: settings.positionOf, | |||
offset: settings.positionOffset, | |||
collision: 'none fit' | |||
}) | |||
.find('li').css(settings.itemCSS); | |||
} | |||
}); | |||
var fixed, stfu, escapes = 0; | |||
function fixArrowsBug(self) { | |||
if (fixed) return false; | |||
fixed = true; | |||
ctrl.on("click.autocomplete", function(e) | |||
::contentReference[oaicite:12]{index=12} |