Weitere Optionen
KKeine Bearbeitungszusammenfassung |
KKeine Bearbeitungszusammenfassung |
||
| Zeile 4: | Zeile 4: | ||
HotCat V2.2b | HotCat V2.2b | ||
Ajax-based simple Category manager. Allows adding/removing/changing categories on a page view. | |||
Supports multiple category changes, as well as redirect and disambiguation resolution. Also | |||
plugs into the upload form. Search engines to use for the suggestion list are configurable, and | |||
can be selected interactively. | |||
Authors: | |||
V0.0: July 2007 - 2010-05-26: original version by [[User:Magnus Manske]], with lots of | |||
additions by many editors, notably [[User:Dschwen]], [[User:TheDJ]], [[User:Superm401]], | |||
and [[User:Lupo]]. No explicit license, assumed multi-licensed GFDL and CC-BY-SA-3.0 per | |||
normal wiki submissions. | |||
V2.0: April-May 2010: [[User:Lupo]]. Complete rewrite reusing only a little code from V0.0. | |||
V2.1: May 2010: [[User:Merlissimo]] (added features: namespace case insensitive, subcategory | |||
engine, category template mapping for removing; developed at de-Wikipedia.) | |||
V2.2: May 2010: [[User:Lupo]] (porting additions from de-WP to the Commons, auto-localization | |||
of template namespace name, cleanup, various other improvements. New features: | |||
highlighting of changed categories, enabling/disabling save button, search engine name | |||
localization, parent category engine). | |||
License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0) | |||
Choose whichever license of these you like best :-) | |||
*/ | */ | ||
// Globals: | |||
// (inline script on the page): | |||
// wgNamespaceNumber, wgCanonicalSpecialPageName, wgNamespaceIds (optional), wgFormattedNamespaces (optional) | |||
// wgScript, wgServer, wgArticlePath, wgScriptPath, wgAction, wgPageName, wgTitle, wgUserName, wgIsArticle, | |||
// wgArticleId | |||
// ajax.js | |||
// sajax_init_object | |||
// wikibits.js | |||
// addOnloadHook, window.ie6_bugs, importScript | |||
if (typeof (HotCat) == 'undefined') { // Guard against double inclusions | if (typeof (HotCat) == 'undefined') { // Guard against double inclusions | ||
| Zeile 10: | Zeile 41: | ||
// Configuration stuff. | // Configuration stuff. | ||
var HotCat = { | var HotCat = { | ||
// Localize these messages to the main language of your wiki. | |||
messages : | messages : | ||
{ cat_removed : 'Entferne [[Kategorie:$1]]' | { cat_removed : 'Entferne [[Kategorie:$1]]' | ||
| Zeile 17: | Zeile 49: | ||
,cat_notFound : 'Kategorie "$1" konnte nicht gefunden werden' | ,cat_notFound : 'Kategorie "$1" konnte nicht gefunden werden' | ||
,cat_exists : 'Kategorie "$1" bereits enthalten; nicht ergänzt' | ,cat_exists : 'Kategorie "$1" bereits enthalten; nicht ergänzt' | ||
,cat_resolved : ' (Weiterleitung [[Kategorie:$1]] aufgelöst)' //wird nicht benötigt | ,cat_resolved : ' (Weiterleitung [[Kategorie:$1]] aufgelöst)' //wird nicht für dewiki benötigt | ||
,uncat_removed: 'entferne {{uncategorized}}' //wird nicht benötigt | ,uncat_removed: 'entferne {{uncategorized}}' //wird nicht für dewiki benötigt | ||
,prefix : '[[ | ,prefix : '[[WP:HC|HC]]: ' | ||
// Some text to prefix to the edit summary. | // Some text to prefix to the edit summary. | ||
,using : '' | ,using : '' | ||
| Zeile 39: | Zeile 71: | ||
// see localization hook below. | // see localization hook below. | ||
} | } | ||
,category_regexp : '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Ii][Ee]' | |||
// 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 | |||
// Wikipedia, use '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Ii][Ee]', or at the | |||
// Chinese Wikipedia, use '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|分类|分類'. Note that namespaces are case- | |||
// insensitive! | |||
,category_canonical : 'Kategorie' | ,category_canonical : 'Kategorie' | ||
// 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 | ||
| Zeile 48: | Zeile 86: | ||
// 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 : null | ||
// 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 86: | Zeile 124: | ||
,existsYes : 'http://upload.wikimedia.org/wikipedia/commons/thumb/b/be/P_yes.svg/20px-P_yes.svg.png' | ,existsYes : 'http://upload.wikimedia.org/wikipedia/commons/thumb/b/be/P_yes.svg/20px-P_yes.svg.png' | ||
,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. | |||
,template_regexp : '[Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]|[Vv][Oo][Rr][Ll][Aa][Gg][Ee]' | |||
// 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]'. | |||
,template_categories : { | |||
'Begriffsklärung': '[Bb]egriffsklärung' | |||
, 'Geographische Lage gewünscht': '[Ll]agewunsch|[Cc]oordinate' | |||
, 'Wikipedia:Überarbeiten': '[Üü]berarbeiten' | |||
, 'Wikipedia:Quellen fehlen': '(?:[Bb]elege|[Qq]uelle)[_ ]fehlen' | |||
, 'Wikipedia:Lückenhaft': '[Ll]ückenhaft' | |||
, 'Wikipedia:Neutralität': '[Nn]eutralität|[Pp]OV|[Nn]POV' | |||
, 'Wikipedia:NurListe': '(?:Nur[_ ]?)?Liste' | |||
, 'Wikipedia:Unverständlich': '[Aa]llgemeinverständlichkeit|[Uu]nverständlich' | |||
, 'Wikipedia:Defekte Weblinks': '[Dd]efekter[_ ]Weblink[_ ]Bot' | |||
, 'Wikipedia:Widerspruch': '[Ww]iderspruch' | |||
} | |||
// 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 91: | Zeile 145: | ||
// If you don't have this at your wiki, or don't want this, set it to an empty object {}. | // If you don't have this at your wiki, or don't want this, set it to an empty object {}. | ||
,engine_names : { | ,engine_names : { | ||
searchindex : ' | searchindex : 'Indexsuche' | ||
,pagelist : ' | ,pagelist : 'Seitenliste' | ||
,combined : ' | ,combined : 'Kombinierte Suche' | ||
,subcat : ' | ,subcat : 'Unterkategorien' | ||
,parentcat : ' | ,parentcat : 'Überkategorien' | ||
} | } | ||
// Names for the search engines | |||
,capitalizePageNames : true | |||
// Set to false if your wiki has case-sensitive page names. MediaWiki has two modes: either the first letter | |||
// of a page is automatically capitalized ("first-letter"; Category:aa == Category:Aa), or it isn't | |||
// ("case-sensitive"; Category:aa != Category:Aa). It doesn't currently have a fully case-insensitive mode | |||
// (which would mean Category:aa == Category:Aa == Category:AA == Category:aA) | |||
// HotCat tries to set this corretcly automatically using an API query. It's still a good idea to manually | |||
// configure it correctly; either directly here if you copied HotCat, or in the local configuration file | |||
// MediaWiki:Gadget-HotCat.js/local_defaults if you hotlink to the Commons-version, to ensure it is set even | |||
// if that API query should fail for some strange reason. | |||
// Stuff changeable by users: | // Stuff changeable by users: | ||
,bg_changed : '#F8CCB0' | ,bg_changed : '#F8CCB0' | ||
| Zeile 217: | Zeile 279: | ||
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 238: | Zeile 305: | ||
var initial = cat_name.substr (0, 1); | var initial = cat_name.substr (0, 1); | ||
cat_regex = new RegExp ('\\[\\[\\s*(' + HotCat.category_regexp + ')\\s*:\\s*' | cat_regex = new RegExp ('\\[\\[\\s*(' + HotCat.category_regexp + ')\\s*:\\s*' | ||
+ (initial == '\\' | + (initial == '\\' || !HotCat.capitalizePageNames | ||
? initial | ? initial | ||
: '[' + initial.toUpperCase() + initial.toLowerCase() + ']') | : '[' + initial.toUpperCase() + initial.toLowerCase() + ']') | ||
| Zeile 330: | Zeile 397: | ||
} else { | } else { | ||
if (wikitext.length > 0 && wikitext.substr (wikitext.length - 1, 1) != '\n') | if (wikitext.length > 0 && wikitext.substr (wikitext.length - 1, 1) != '\n') | ||
wikitext += '\n'; | |||
if (wikitext.length > 0 && wikitext.substr (wikitext.length - 2, 1) != '\n') | |||
wikitext += '\n'; | wikitext += '\n'; | ||
wikitext += newcatstring; | wikitext += newcatstring; | ||
| Zeile 358: | Zeile 427: | ||
var toAdd = param ('hotcat_newcat'); | var toAdd = param ('hotcat_newcat'); | ||
if (toAdd) { | if (toAdd) { | ||
toAdd = | toAdd = toAdd.replace (/_/g, ' ').replace (/^\s+|\s+$/g, ""); | ||
if (toAdd.length == 0) toAdd = null; | if (toAdd.length == 0) { | ||
toAdd = null; | |||
} else if (HotCat.capitalizePageNames) { | |||
toAdd = capitalize (toAdd); | |||
} | |||
} | } | ||
if (toRemove) { | if (toRemove) { | ||
toRemove = | toRemove = toRemove.replace (/_/g, ' ').replace (/^\s+|\s+$/g, ""); | ||
if (toRemove.length == 0) toRemove = null; | if (toRemove.length == 0) { | ||
toRemove = null; | |||
} else if (HotCat.capitalizePageNames) { | |||
toRemove = capitalize (toRemove); | |||
} | |||
} | } | ||
if (toAdd || toRemove) { | if (toAdd || toRemove) { | ||
| Zeile 432: | Zeile 509: | ||
var is_rtl = false; | var is_rtl = false; | ||
var serverTime = null; | |||
function setMultiInput () { | function setMultiInput () { | ||
| Zeile 515: | Zeile 593: | ||
var uri = wgServer + wgScriptPath | var uri = wgServer + wgScriptPath | ||
+ '/api.php?format=json&action=query&titles=' + encodeURIComponent (wgPageName) | + '/api.php?format=json&action=query&titles=' + encodeURIComponent (wgPageName) | ||
+ '&prop=info%7Crevisions&inprop=watched&rvprop=content%7Ctimestamp'; | + '&prop=info%7Crevisions&inprop=watched&rvprop=content%7Ctimestamp&meta=siteinfo'; | ||
request.open ('GET', uri, false); // Yes, synchronous | request.open ('GET', uri, false); // Yes, synchronous | ||
request.send (null); | request.send (null); | ||
| Zeile 632: | Zeile 710: | ||
} | } | ||
commitForm.wpTextbox1.value = result.text; | commitForm.wpTextbox1.value = result.text; | ||
commitForm.wpStarttime.value = currentTimestamp (); | commitForm.wpStarttime.value = serverTime || currentTimestamp (); | ||
commitForm.wpEdittime.value = pageTime || commitForm.wpStarttime.value; | commitForm.wpEdittime.value = pageTime || commitForm.wpStarttime.value; | ||
commitForm.submit(); | commitForm.submit(); | ||
| Zeile 771: | Zeile 849: | ||
} | } | ||
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.244: | Zeile 1.334: | ||
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.265: | Zeile 1.355: | ||
var key = null; | var key = null; | ||
if (value.length > 1) key = value[1]; | if (value.length > 1) key = value[1]; | ||
var v = | var v = value[0].replace(/_/g, ' ').replace(/^\s+|\s+$/g, ""); | ||
if (HotCat.capitalizePageNames) v = capitalize (v); | |||
this.lastInput = v; | this.lastInput = v; | ||
if (v.length == 0) { | if (v.length == 0) { | ||
| Zeile 1.322: | Zeile 1.413: | ||
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.480: | Zeile 1.571: | ||
var re = new RegExp ('^(' + HotCat.category_regexp + '):'); | var re = new RegExp ('^(' + HotCat.category_regexp + '):'); | ||
if (re.test (v)) v = v.substring (v.indexOf (':') + 1); | if (re.test (v)) v = v.substring (v.indexOf (':') + 1); | ||
v = capitalize (v); | if (HotCat.capitalizePageNames) v = capitalize (v); | ||
// Only update the input field if there is a difference. IE8 appears to reset the selection | // Only update the input field if there is a difference. IE8 appears to reset the selection | ||
// and place the cursor at the front upon reset, which makes our autocompletetion become a | // and place the cursor at the front upon reset, which makes our autocompletetion become a | ||
| Zeile 1.602: | Zeile 1.693: | ||
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.610: | Zeile 1.707: | ||
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.637: | Zeile 1.739: | ||
} | } | ||
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.148: | Zeile 2.245: | ||
function setPage (json) { | function setPage (json) { | ||
if ( | if (json && json.query) { | ||
if (json.query.pages) { | |||
for (var p in json.query.pages) { | |||
var page = json.query.pages[p]; | |||
if (!page.revisions || page.revisions.length == 0) break; | |||
pageText = page.revisions[0]['*']; | |||
pageTime = page.revisions[0].timestamp.replace (/\D/g, ""); | |||
pageWatched = typeof (page.watched) == 'string'; | |||
break; | |||
} | |||
} | |||
// Siteinfo | |||
if (json.query.general) { | |||
HotCat.capitalizePageNames = (json.query.general['case'] == 'first-letter'); | |||
if (json.query.general.time) serverTime = json.query.general.time.replace (/\D/g, ""); | |||
} | |||
} | } | ||
} | } | ||
| Zeile 2.168: | Zeile 2.273: | ||
} else { | } else { | ||
var url = wgServer + wgScriptPath + '/api.php?format=json&callback=HotCat.start&action=query&titles=' | var url = wgServer + wgScriptPath + '/api.php?format=json&callback=HotCat.start&action=query&titles=' | ||
+ encodeURIComponent (wgPageName) + '&prop=info%7Crevisions&rvprop=content%7Ctimestamp'; | + encodeURIComponent (wgPageName) + '&prop=info%7Crevisions&rvprop=content%7Ctimestamp&meta=siteinfo'; | ||
var s = make ('script'); | var s = make ('script'); | ||
s.src = url; | s.src = url; | ||
| Zeile 2.252: | Zeile 2.357: | ||
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; | ||