Weitere Optionen
KKeine Bearbeitungszusammenfassung |
KKeine Bearbeitungszusammenfassung |
||
| Zeile 2: | Zeile 2: | ||
/* | /* | ||
HotCat V2. | HotCat V2.2 | ||
Ajax-based simple Category manager. Allows adding/removing/changing categories on a page view. | Ajax-based simple Category manager. Allows adding/removing/changing categories on a page view. | ||
| Zeile 8: | Zeile 8: | ||
plugs into the upload form. Search engines to use for the suggestion list are configurable, and | plugs into the upload form. Search engines to use for the suggestion list are configurable, and | ||
can be selected interactively. | can be selected interactively. | ||
License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0) | License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0) | ||
| Zeile 41: | Zeile 28: | ||
// Configuration stuff. | // Configuration stuff. | ||
var HotCat = { | var HotCat = { | ||
isCommonsVersion : true | |||
// If you copy HotCat to your wiki, you should set this to false! | |||
// Localize these messages to the main language of your wiki. | // Localize these messages to the main language of your wiki. | ||
messages : | ,messages : | ||
{ cat_removed : ' | { cat_removed : 'removed [[Category:$1]]' | ||
,template_removed : ' | ,template_removed : 'removed {{[[Category:$1]]}}' | ||
,cat_added : ' | ,cat_added : 'added [[Category:$1]]' | ||
,cat_keychange: ' | ,cat_keychange: 'new key for [[Category:$1]]: ' | ||
,cat_notFound : ' | ,cat_notFound : 'Category "$1" not found' | ||
,cat_exists : ' | ,cat_exists : 'Category "$1" already exists; not added.' | ||
,cat_resolved : ' ( | ,cat_resolved : ' (redirect [[Category:$1]] resolved)' | ||
,uncat_removed: ' | ,uncat_removed: 'removed {{uncategorized}}' | ||
,prefix : | ,prefix : "" | ||
// Some text to prefix to the edit summary. | // Some text to prefix to the edit summary. | ||
,using : '' | ,using : ' using [[Help:Gadget-HotCat|HotCat]]' | ||
// Some text to append to the edit summary. Named 'using' for historical reasons. If you prefer | // Some text to append to the edit summary. Named 'using' for historical reasons. If you prefer | ||
// to have a marker at the front, use prefix and set this to the empty string. | // to have a marker at the front, use prefix and set this to the empty string. | ||
,multi_change : '$1 | ,multi_change : '$1 categories' | ||
// $1 is replaced by a number | // $1 is replaced by a number | ||
,commit : ' | ,commit : 'Save' | ||
// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | // Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | ||
// see localization hook below. | // see localization hook below. | ||
| Zeile 64: | Zeile 54: | ||
// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | // Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | ||
// see localization hook below. | // see localization hook below. | ||
,cancel : ' | ,cancel : 'Cancel' | ||
// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | // Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | ||
// see localization hook below. | // see localization hook below. | ||
,multi_error : ' | ,multi_error : 'Could not retrieve the page text from the server. Therefore, your category changes ' | ||
+'cannot be saved. We apologize for the inconvenience.' | |||
// Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | // Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage, | ||
// see localization hook below. | // see localization hook below. | ||
} | } | ||
,category_regexp : '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy | ,category_regexp : '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]' | ||
// Regular sub-expression matching all possible names for the category namespace. Is automatically localized | // Regular sub-expression matching all possible names for the category namespace. Is automatically localized | ||
// correctly if you're running MediaWiki 1.16 or later. Otherwise, set it appropriately, e.g. at the German | // correctly if you're running MediaWiki 1.16 or later. Otherwise, set it appropriately, e.g. at the German | ||
| Zeile 77: | Zeile 68: | ||
// Chinese Wikipedia, use '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|分类|分類'. Note that namespaces are case- | // Chinese Wikipedia, use '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|分类|分類'. Note that namespaces are case- | ||
// insensitive! | // insensitive! | ||
,category_canonical : ' | ,category_canonical : 'Category' | ||
// The standard category name on your wiki. Is automatically localized correctly if you're running | // The standard category name on your wiki. Is automatically localized correctly if you're running | ||
// MediaWiki 1.16 or later; otherwise, set it to the preferred category name (e.g., "Kategorie"). | // MediaWiki 1.16 or later; otherwise, set it to the preferred category name (e.g., "Kategorie"). | ||
,categories : ' | ,categories : 'Categories' | ||
// Plural of category_canonical | // Plural of category_canonical | ||
,disambig_category : | ,disambig_category : 'Disambiguation' | ||
// Any category in this category is deemed a disambiguation category; i.e., a category that should not contain | // Any category in this category is deemed a disambiguation category; i.e., a category that should not contain | ||
// any items, but that contains links to other categories where stuff should be categorized. If you don't have | // any items, but that contains links to other categories where stuff should be categorized. If you don't have | ||
// that concept on your wiki, set it to null. | // that concept on your wiki, set it to null. | ||
,redir_category : ' | ,redir_category : 'Category redirects' | ||
// Any category in this category is deemed a (soft) redirect to some other category defined by the first link | // Any category in this category is deemed a (soft) redirect to some other category defined by the first link | ||
// to another category. If your wiki doesn't have soft category redirects, set this to null. | // to another category. If your wiki doesn't have soft category redirects, set this to null. | ||
| Zeile 92: | Zeile 83: | ||
// The little modification links displayed after category names. | // The little modification links displayed after category names. | ||
,tooltips : { | ,tooltips : { | ||
change: ' | change: 'Modify' | ||
,remove: ' | ,remove: 'Remove' | ||
,add: ' | ,add: 'Add a new category' | ||
,restore: ' | ,restore: 'Undo changes' | ||
,undo: ' | ,undo: 'Undo changes' | ||
,down: ' | ,down: 'Open for modifying and display subcategories' | ||
,up: ' | ,up: 'Open for modifying and display parent categories' | ||
} | } | ||
// The tooltips for the above links | // The tooltips for the above links | ||
,addmulti : '<span>+<sup>+</sup></span>' | ,addmulti : '<span>+<sup>+</sup></span>' | ||
// The HTML content of the "enter multi-mode" link at the front. | // The HTML content of the "enter multi-mode" link at the front. | ||
,multi_tooltip : ' | ,multi_tooltip : 'Modify several categories' | ||
// Tooltip for the "enter multi-mode" link | // Tooltip for the "enter multi-mode" link | ||
,disable : | ,disable : | ||
| Zeile 119: | Zeile 110: | ||
); | ); | ||
} | } | ||
,uncat_regexp : | ,uncat_regexp : /\{\{\s*([Uu]ncat(egori[sz]ed( image)?)?|[Nn]ocat|[Nn]eedscategory)[^}]*\}\}\s*(<\!--.*?--\>)?/g | ||
// A regexp matching a templates used to mark uncategorized pages, if your wiki does have that. | // A regexp matching a templates used to mark uncategorized pages, if your wiki does have that. | ||
// If not, set it to null. | // If not, set it to null. | ||
| Zeile 125: | Zeile 116: | ||
,existsNo : 'http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/P_no.svg/20px-P_no.svg.png' | ,existsNo : 'http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/P_no.svg/20px-P_no.svg.png' | ||
// The images used for the little indication icon. Should not need changing. | // The images used for the little indication icon. Should not need changing. | ||
,template_regexp : '[Tt][Ee][Mm][Pp][Ll][Aa][Tt | ,template_regexp : '[Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]' | ||
// Regexp to recognize templates. Like "category" above; autolocalized for MW 1.16+, otherwise set manually here. | // Regexp to recognize templates. Like "category" above; autolocalized for MW 1.16+, otherwise set manually here. | ||
// On the German Wikipedia, you might use '[Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]|[Vv][Oo][Rr][Ll][Aa][Gg][Ee]'. | // On the German Wikipedia, you might use '[Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]|[Vv][Oo][Rr][Ll][Aa][Gg][Ee]'. | ||
,template_categories : { | ,template_categories : {} | ||
// a list of categories which can be removed by removing a template | // a list of categories which can be removed by removing a template | ||
// key: the category without namespace | // key: the category without namespace | ||
| Zeile 172: | Zeile 152: | ||
}; | }; | ||
if (HotCat.isCommonsVersion && wgServer.indexOf ('/commons') < 0) { | |||
// | // We're running in some other wiki, which hotlinks to the Commons version. The other wiki can put local settings | ||
// file | // in this file to override the Commons settings for all user languages. For instance, if on your wiki people do | ||
// | // not like automatic saving, you'd add in that file the line HotCat.no_autocommit = true; If you hotlink, you | ||
// | // *must* adapt HotCat.categories in this file to the local translation in wgContentLanguage of your wiki of the | ||
// HotCat. | // English plural "Categories", and you should provide translations in wgContentLanguage of your wiki of all messages, | ||
// tooltips, and of the engine names. | |||
// HotCat | importScript ('MediaWiki:Gadget-HotCat.js/local_defaults'); | ||
} | |||
if (wgUserLanguage != wgContentLanguage) importScript ('MediaWiki:Gadget-HotCat.js/' + wgUserLanguage); | |||
// Localization hook to localize HotCat messages, tooltips, and engine names for wgUserLanguage. | |||
// No further changes should be necessary here. | // No further changes should be necessary here. | ||
| Zeile 271: | Zeile 254: | ||
return str.substr(0, 1).toUpperCase() + str.substr (1); | return str.substr(0, 1).toUpperCase() + str.substr (1); | ||
} | } | ||
function wikiPagePath (pageName) { | |||
// Note: do not simply use encodeURI, it doesn't encode '&', which might break if wgArticlePath catually has the $1 in | |||
// a query parameter. | |||
return wgArticlePath.replace('$1', encodeURIComponent (pageName).replace(/%3A/g, ':').replace(/%2F/g, '/')); | |||
} | |||
// Text modification | // Text modification | ||
| Zeile 560: | Zeile 548: | ||
// it doesn't succeed), getting the page text. Perform the changes on the text, then construct | // it doesn't succeed), getting the page text. Perform the changes on the text, then construct | ||
// a form to submit all this as a diff. | // a form to submit all this as a diff. | ||
// Note: we have to do this even if we already got the page text. Other scripts may have already | // Note: we have to do this even if we already got the page text. Other scripts may have already | ||
// edited the text, and we don't necessarily get an edit conflict with ourself. Use case: open | // edited the text, and we don't necessarily get an edit conflict with ourself. Use case: open | ||
// a file page, add an image note through ImageAnnotator, then change the categories. If HotCat | // a file page, add an image note through ImageAnnotator, then change the categories. If HotCat | ||
| Zeile 574: | Zeile 562: | ||
if (request.status == 200 && request.responseText && request.responseText.charAt(0) == '{') { | if (request.status == 200 && request.responseText && request.responseText.charAt(0) == '{') { | ||
setPage (eval ('(' + request.responseText + ')')); | setPage (eval ('(' + request.responseText + ')')); | ||
} else { | |||
pageText = null; | |||
} | } | ||
} | } | ||
if (pageText === null) { | if (pageText === null) { | ||
| Zeile 825: | Zeile 813: | ||
} | } | ||
var cat_prefix = null; | |||
var noSuggestions = false; | var noSuggestions = false; | ||
var suggestionEngines = { | var suggestionEngines = { | ||
opensearch : | opensearch : | ||
{ uri : '/api.php?format=json&action=opensearch&namespace=14&limit=30&search=$1' // $1 = search term | { uri : '/api.php?format=json&action=opensearch&namespace=14&limit=30&search=Category:$1' // $1 = search term | ||
,handler : // Function to convert result of uri into an array of category names | ,handler : // Function to convert result of uri into an array of category names | ||
function (responseText, queryKey) { | function (responseText, queryKey) { | ||
if (responseText.charAt (0) != '[') return null; | if (responseText.charAt (0) != '[') return null; | ||
var queryResult = eval ('(' + responseText + ')'); | var queryResult = eval ('(' + responseText + ')'); | ||
if (queryResult != null && queryResult.length == 2 && queryResult[0].toLowerCase() == queryKey.toLowerCase()) { | if ( queryResult != null && queryResult.length == 2 | ||
&& queryResult[0].toLowerCase() == 'category:' + queryKey.toLowerCase() | |||
) | |||
{ | |||
var titles = queryResult[1]; | var titles = queryResult[1]; | ||
if (!cat_prefix) cat_prefix = new RegExp ('^(' + HotCat.category_regexp + ':)'); | |||
for (var i = 0; i < titles.length; i++) { | for (var i = 0; i < titles.length; i++) { | ||
titles[i] = titles[i].substring (titles[i].indexOf (':') + 1); // rm namespace | cat_prefix.lastIndex = 0; | ||
var m = cat_prefix.exec (titles[i]); | |||
if (m && m.length > 1) { | |||
titles[i] = titles[i].substring (titles[i].indexOf (':') + 1); // rm namespace | |||
} else { | |||
titles.splice (i, 1); // Nope, it's not a category after all. | |||
i--; | |||
} | |||
} | } | ||
return titles; | return titles; | ||
| Zeile 1.146: | Zeile 1.146: | ||
} | } | ||
// Do not use type 'submit'; we cannot detect modifier keys if we do | // Do not use type 'submit'; we cannot detect modifier keys if we do | ||
var OK = make ('input'); OK.type = 'button'; | var OK = make ('input'); OK.type = 'button'; | ||
OK.value = button_label ('wpOkUploadLbl', HotCat.messages.ok); | OK.value = button_label ('wpOkUploadLbl', HotCat.messages.ok); | ||
| Zeile 1.298: | Zeile 1.298: | ||
this.catLink.removeChild (this.catLink.firstChild); | this.catLink.removeChild (this.catLink.firstChild); | ||
this.catLink.appendChild (make (this.currentCategory, true)); | this.catLink.appendChild (make (this.currentCategory, true)); | ||
this.catLink.href = | this.catLink.href = wikiPagePath (HotCat.category_canonical + ':' + this.currentCategory); | ||
this.catLink.title = ""; | this.catLink.title = ""; | ||
this.catLink.className = this.currentExists ? "" : 'new'; | this.catLink.className = this.currentExists ? "" : 'new'; | ||
| Zeile 1.376: | Zeile 1.376: | ||
this.catLink.removeChild (this.catLink.firstChild); | this.catLink.removeChild (this.catLink.firstChild); | ||
this.catLink.appendChild (make (this.currentCategory, true)); | this.catLink.appendChild (make (this.currentCategory, true)); | ||
this.catLink.href = | this.catLink.href = wikiPagePath (HotCat.category_canonical + ':' + this.currentCategory); | ||
this.catLink.title = ""; | this.catLink.title = ""; | ||
this.catLink.className = this.currentExists ? "" : 'new'; | this.catLink.className = this.currentExists ? "" : 'new'; | ||
| Zeile 1.656: | Zeile 1.656: | ||
this.lastQuery = queryKey; | this.lastQuery = queryKey; | ||
// Get current input text | |||
var v = this.text.value.split('|'); | |||
var key = v.length > 1 ? '|' + v[1] : ""; | |||
v = capitalize (v[0]); | |||
if (titles) { | if (titles) { | ||
var vLow = v.toLowerCase (); | |||
titles.sort ( | titles.sort ( | ||
function (a, b) { | function (a, b) { | ||
| Zeile 1.664: | Zeile 1.670: | ||
var prefixMatchA = (a.indexOf (v) == 0 ? 1 : 0); | var prefixMatchA = (a.indexOf (v) == 0 ? 1 : 0); | ||
var prefixMatchB = (b.indexOf (v) == 0 ? 1 : 0); | var prefixMatchB = (b.indexOf (v) == 0 ? 1 : 0); | ||
if (prefixMatchA != prefixMatchB) return prefixMatchB - prefixMatchA; | |||
// Case-insensitive prefix match! | |||
var aLow = a.toLowerCase(), bLow = b.toLowerCase(); | |||
prefixMatchA = (aLow.indexOf (vLow) == 0 ? 1 : 0); | |||
prefixMatchB = (bLow.indexOf (vLow) == 0 ? 1 : 0); | |||
if (prefixMatchA != prefixMatchB) return prefixMatchB - prefixMatchA; | if (prefixMatchA != prefixMatchB) return prefixMatchB - prefixMatchA; | ||
if (a < b) return -1; | if (a < b) return -1; | ||
| Zeile 1.691: | Zeile 1.702: | ||
} | } | ||
var firstTitle = titles[0]; | var firstTitle = titles[0]; | ||
var completed = this.autoComplete (firstTitle, v, key, dontAutocomplete); | var completed = this.autoComplete (firstTitle, v, key, dontAutocomplete); | ||
| Zeile 2.306: | Zeile 2.312: | ||
var key = cat.length > 1 ? cat[1] : null; | var key = cat.length > 1 ? cat[1] : null; | ||
cat = cat[0]; | cat = cat[0]; | ||
var lk = make ('a'); lk.href = | var lk = make ('a'); lk.href = wikiPagePath (HotCat.category_canonical + ':' + cat); | ||
lk.appendChild (make (cat, true)); | lk.appendChild (make (cat, true)); | ||
lk.title = cat; | lk.title = cat; | ||