|
|
Line 10: |
Line 10: |
| if(!confirm(message)) return e.preventDefault(); | | if(!confirm(message)) return e.preventDefault(); |
| }); | | }); |
| mw.loader.implement("ext.gadget.autocomplete", function($, jQuery) {
| | $( function() { |
| mw.loader.using(['jquery.ui.widget', 'jquery.ui.autocomplete', 'jquery.textSelection'], function() {
| | 'use strict'; |
| $.fn.autoCompleteWikiText = function(options) {
| |
| var mode = "none";
| |
| var templateDataCache = {};
| |
| var ctrl = $(this);
| |
| var 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();
| |
| var 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 resolveTempalte(templateName) {
| | $( 'body' ).append( '<span id="to-top">▲ Go to top</span>' ); |
| var dfd = new jQuery.Deferred();
| | var $topButton = $( '#to-top' ); |
| if (!templateName) return dfd.reject().promise();
| |
| if (templateDataCache[templateName]) return dfd.resolve().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();
| |
| }
| |
| if (!templateDataCache[templateName]) dfd.reject();
| |
| });
| |
| return dfd.promise();
| |
| }
| |
|
| |
|
| function resolveApi(queryType, queryValue) {
| | $topButton.css( { |
| var dfd = new jQuery.Deferred();
| | 'color': '#000', |
| var api = new mw.Api();
| | 'position': 'fixed', |
| switch (queryType) {
| | 'bottom': '-30px', |
| case 'users':
| | 'left': '4px', |
| api.get({
| | 'cursor': 'pointer', |
| action: 'query',
| | 'transition': 'bottom 0.5s', |
| list: 'allusers',
| | '-webkit-transition': 'bottom 0.5s', |
| auactiveusers: 1,
| | 'user-select': 'none', |
| auprefix: queryValue
| | '-webkit-user-select': 'none', |
| }).done(function(data) {
| | '-moz-user-select': 'none', |
| if (data && data.query && data.query.allusers) dfd.resolve($.map(data.query.allusers, function(e) {
| | '-ms-user-select': 'none' |
| return e.name;
| | } ).click( function() { |
| }));
| | $( 'html, body' ).animate( { scrollTop: 0 }, 'slow' ); |
| 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) {
| | $( window ).scroll( function() { |
| txt = $.trim(txt);
| | if ( $( window ).scrollTop() > 100 ) { |
| if (txt.length <= 1 || (mode != 'templateParams' && txt.indexOf('|') > -1) || (txt.indexOf('#') > -1 && mw.config.get('wgNamespaceNumber') === 0)) res([]);
| | $topButton.css( 'bottom', '4px' ); |
| else if (mode === 'templateParams') {
| | } else { |
| var templateMatch = /(.+?)\|(?:.*\|)?([^=]+$)/.exec(txt);
| | $topButton.css( 'bottom', '-30px' ); |
| $.when(resolveTempalte(templateMatch && templateMatch[1])).done(function() {
| | } |
| var curTemplateData = templateDataCache[templateMatch[1]];
| | } ); |
| var suggestions = [];
| |
| var curParamIndex = txt.split('|').length - 1;
| |
| 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-user-name':
| |
| dfd = $.when(resolveApi('users', paramValue));
| |
| mode = 'templateValue';
| |
| break;
| |
| 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) : 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 = false;
| |
|
| |
|
| function fixArrowsBug(self) {
| | |
| if (fixed) return false;
| | } ); |
| fixed = true;
| |
| ctrl.off("keydown.autocomplete");
| |
| ctrl.off("keydown.autocomplete0");
| |
| ctrl.on("keydown.autocomplete", function(event) {
| |
| var keyCode = $.ui.keyCode;
| |
| switch (event.keyCode) {
| |
| case keyCode.PAGE_UP:
| |
| self._move("previousPage", event);
| |
| break;
| |
| case keyCode.PAGE_DOWN:
| |
| self._move("nextPage", event);
| |
| break;
| |
| case keyCode.UP:
| |
| if (!self.menu.element.is(":visible")) return;
| |
| self._move("previous", event);
| |
| event.preventDefault();
| |
| break;
| |
| case keyCode.DOWN:
| |
| if (!self.menu.element.is(":visible")) return;
| |
| self._move("next", event);
| |
| event.preventDefault();
| |
| break;
| |
| case keyCode.ENTER:
| |
| case keyCode.NUMPAD_ENTER:
| |
| if (self.menu.active) {
| |
| event.preventDefault();
| |
| }
| |
| case keyCode.TAB:
| |
| if (!self.menu.active) {
| |
| return;
| |
| }
| |
| self.menu.select(event);
| |
| break;
| |
| case keyCode.ESCAPE:
| |
| self.element.val(self.term);
| |
| self.close(event);
| |
| break;
| |
| case keyCode.LEFT:
| |
| case keyCode.RIGHT:
| |
| case keyCode.SHIFT:
| |
| case keyCode.
| |
| CONTROL:
| |
| case keyCode.ALT:
| |
| case keyCode.COMMAND:
| |
| case keyCode.COMMAND_RIGHT:
| |
| case keyCode.INSERT:
| |
| case keyCode.CAPS_LOCK:
| |
| case keyCode.END:
| |
| case keyCode.HOME:
| |
| break;
| |
| default:
| |
| clearTimeout(self.searching);
| |
| self.searching = setTimeout(function() {
| |
| self.search(null, event);
| |
| }, self.options.delay);
| |
| break;
| |
| }
| |
| });
| |
| return true;
| |
| }
| |
| }
| |
| });
| |
| if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) + 1) mw.loader.using(['jquery.ui.widget', 'jquery.ui.autocomplete', 'jquery.textSelection'], function() {
| |
| $("#wpTextbox1").autoCompleteWikiText({
| |
| positionAt: $('#wpTextbox1').prop('dir') == 'rtl' ? "left top" : "right top",
| |
| positionOf: '#editform',
| |
| positionOffset: "0 0",
| |
| menuCSS: {
| |
| background: '#E0EEF7',
| |
| opacity: 0.8
| |
| },
| |
| itemCSS: {
| |
| padding: 0,
| |
| margin: 0
| |
| }
| |
| });
| |
| });
| |
| }); | |