User:84user/monobook.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | The accompanying .css page for this skin is at User:84user/monobook.css. |
importScript('User:Dr pda/prosesize.js'); //[[User:Dr pda/prosesize.js]]
importScript('Wikipedia:WikiProject User scripts/Scripts/User tabs'); //
importScript('User:Anomie/ajaxpreview.js'); // Linkback: [[User:Anomie/ajaxpreview.js]]
importScript('User:Tra/userwatchlist.js'); //[[User:Tra/userwatchlist.js]]
// I copied the following from [[User:SharkD/Sandbox/wikibits 4]]
// remove the following line
// alert('This is sandbox version 133 of "wikibits.js". Delete this message.')
// MediaWiki JavaScript support functions
var clientPC = navigator.userAgent.toLowerCase(); // Get client info
var is_gecko = /gecko/.test(clientPC) && !/khtml|spoofer|netscape\/7\.0/.test(clientPC)
var webkit_match = clientPC.match(/applewebkit\/(\d+)/)
if (webkit_match) {
var is_safari = clientPC.indexOf('applewebkit') != -1 && clientPC.indexOf('spoofer') == -1
var is_safari_win = is_safari && clientPC.indexOf('windows') != -1
var webkit_version = parseInt(webkit_match[1])
}
var is_khtml = navigator.vendor == 'KDE' || (document.childNodes && !document.all && !navigator.taintEnabled)
// For accesskeys; note that FF3+ is included here!
var is_ff2 = /firefox\/[2-9]|minefield\/3/.test( clientPC )
// These aren't used here, but some custom scripts rely on them
var is_ff2_win = is_ff2 && clientPC.indexOf('windows') != -1
var is_ff2_x11 = is_ff2 && clientPC.indexOf('x11') != -1
if (clientPC.indexOf('opera') != -1) {
var is_opera = true
var is_opera_preseven = window.opera && !document.childNodes
var is_opera_seven = window.opera && document.childNodes
var is_opera_95 = /opera\/(9.[5-9]|[1-9][0-9])/.test(clientPC)
}
// Global external objects used by this script.
/*extern ta, stylepath, skin */
// add any onload functions in this hook (please don't hard-code any events in the xhtml source)
var doneOnloadHook
if (!window.onloadFuncts)
var onloadFuncts = []
function addOnloadHook(hookFunct) {
// Allows add-on scripts to add onload functions
if (!doneOnloadHook)
onloadFuncts[onloadFuncts.length] = hookFunct
else
hookFunct(); // bug in MSIE script loading
}
function hookEvent(hookName, hookFunct) {
if (window.addEventListener)
window.addEventListener(hookName, hookFunct, false)
else if (window.attachEvent)
window.attachEvent("on" + hookName, hookFunct)
}
function importScript(page) {
return importScriptURI(wgScript + '?action=raw&ctype=text/javascript&title=' + encodeURIComponent(page.replace(/ /g,'_')))
}
var loadedScripts = {}; // included-scripts tracker
function importScriptURI(url) {
if (loadedScripts[url])
return null
loadedScripts[url] = true
var s = document.createElement('script')
s.setAttribute('src',url)
s.setAttribute('type','text/javascript')
document.getElementsByTagName('head')[0].appendChild(s)
return s
}
function importStylesheet(page) {
return importStylesheetURI(wgScript + '?action=raw&ctype=text/css&title=' + encodeURIComponent(page.replace(/ /g,'_')))
}
function importStylesheetURI(url) {
return document.createStyleSheet ? document.createStyleSheet(url) : appendCSS('@import "' + url + '";')
}
function appendCSS(text) {
var s = document.createElement('style')
s.type = 'text/css'
s.rel = 'stylesheet'
if (s.styleSheet) //IE
s.styleSheet.cssText = text
else //Safari sometimes borks on null
s.appendChild(document.createTextNode(text + ''))
document.getElementsByTagName('head')[0].appendChild(s)
return s
}
// special stylesheet links
if (typeof stylepath != 'undefined' && typeof skin != 'undefined') {
if (is_opera_preseven)
importStylesheetURI(stylepath + '/' + skin + '/Opera6Fixes.css')
else if (is_opera_seven && !is_opera_95)
importStylesheetURI(stylepath + '/' + skin + '/Opera7Fixes.css')
else if (is_khtml)
importStylesheetURI(stylepath + '/' + skin + '/KHTMLFixes.css')
}
if (wgBreakFrames) {
// Un-trap us from framesets
if (window.top != window)
window.top.location = window.location
}
// for enhanced RecentChanges
function toggleVisibility(_levelId, _otherId, _linkId) {
var thisLevel = document.getElementById(_levelId)
var otherLevel = document.getElementById(_otherId)
var linkLevel = document.getElementById(_linkId)
if (thisLevel.style.display == 'none') {
thisLevel.style.display = 'block'
otherLevel.style.display = 'none'
linkLevel.style.display = 'inline'
} else {
thisLevel.style.display = 'none'
otherLevel.style.display = 'inline'
linkLevel.style.display = 'none'
}
}
function showTocToggle() {
if (document.createTextNode) {
// Uses DOM calls to avoid document.write + XHTML issues
var linkHolder = document.getElementById('toctitle')
if (!linkHolder)
return
var outerSpan = document.createElement('span')
outerSpan.className = 'toctoggle'
var toggleLink = document.createElement('a')
toggleLink.id = 'togglelink'
toggleLink.className = 'internal'
toggleLink.href = 'javascript:toggleToc()'
toggleLink.appendChild(document.createTextNode(tocHideText))
outerSpan.appendChild(document.createTextNode('['))
outerSpan.appendChild(toggleLink)
outerSpan.appendChild(document.createTextNode(']'))
linkHolder.appendChild(document.createTextNode(' '))
linkHolder.appendChild(outerSpan)
var cookiePos = document.cookie.indexOf("hidetoc=")
if (cookiePos > -1 && document.cookie.charAt(cookiePos + 8) == 1)
toggleToc()
}
}
function changeText(el, newText) {
// Safari work around
if (el.innerText)
el.innerText = newText
else if (el.firstChild && el.firstChild.nodeValue)
el.firstChild.nodeValue = newText
}
function toggleToc() {
var toc = document.getElementById('toc').getElementsByTagName('ul')[0]
var toggleLink = document.getElementById('togglelink')
if (toc && toggleLink && toc.style.display == 'none') {
changeText(toggleLink, tocHideText)
toc.style.display = 'block'
document.cookie = "hidetoc=0"
} else {
changeText(toggleLink, tocShowText)
toc.style.display = 'none'
document.cookie = "hidetoc=1"
}
}
var mwEditButtons = []
var mwCustomEditButtons = []; // eg to add in MediaWiki:Common.js
function escapeQuotes(text) {
var re = new RegExp("'","g")
text = text.replace(re,"\\'")
re = new RegExp("\\n","g")
text = text.replace(re,"\\n")
return escapeQuotesHTML(text)
}
function escapeQuotesHTML(text) {
var re = new RegExp('&',"g")
text = text.replace(re,"&")
re = new RegExp('"',"g")
text = text.replace(re,""")
re = new RegExp('<',"g")
text = text.replace(re,"<")
re = new RegExp('>',"g")
text = text.replace(re,">")
return text
}
/**
* Set the accesskey prefix based on browser detection.
*/
var tooltipAccessKeyPrefix = 'alt-'
if (is_opera)
tooltipAccessKeyPrefix = 'shift-esc-'
else if (!is_safari_win && is_safari && webkit_version > 526)
tooltipAccessKeyPrefix = 'ctrl-alt-'
else if (!is_safari_win && (is_safari || clientPC.indexOf('mac') != -1 || clientPC.indexOf('konqueror') != -1 ))
tooltipAccessKeyPrefix = 'ctrl-'
else if (is_ff2)
tooltipAccessKeyPrefix = 'alt-shift-'
var tooltipAccessKeyRegexp = /\[(ctrl-)?(alt-)?(shift-)?(esc-)?(.)\]$/
/**
* Add the appropriate prefix to the accesskey shown in the tooltip.
* If the nodeList parameter is given, only those nodes are updated
* otherwise, all the nodes that will probably have accesskeys by
* default are updated.
*
* @param Array nodeList -- list of elements to update
*/
function updateTooltipAccessKeys( nodeList ) {
if (!nodeList) {
// skins without a "column-one" element don't seem to have links with accesskeys either
var columnOne = document.getElementById("column-one")
if (columnOne)
updateTooltipAccessKeys(columnOne.getElementsByTagName("a"))
// these are rare enough that no such optimization is needed
updateTooltipAccessKeys(document.getElementsByTagName("input"))
updateTooltipAccessKeys(document.getElementsByTagName("label"))
return
}
for (var i = 0, n = nodeList.length; i < n; i++) {
var element = nodeList[i]
var tip = element.getAttribute("title")
if (tip && tooltipAccessKeyRegexp.exec(tip)) {
tip = tip.replace(tooltipAccessKeyRegexp, "[" + tooltipAccessKeyPrefix + "$5]")
element.setAttribute("title", tip)
}
}
}
/**
* Add a link to one of the portlet menus on the page, including:
*
* p-cactions: Content actions (shown as tabs above the main content in Monobook)
* p-personal: Personal tools (shown at the top right of the page in Monobook)
* p-navigation: Navigation
* p-tb: Toolbox
*
* This function exists for the convenience of custom JS authors. All
* but the first three parameters are optional, though providing at
* least an id and a tooltip is recommended.
*
* By default the new link will be added to the end of the list. To
* add the link before a given existing item, pass the DOM node of
* that item (easily obtained with document.getElementById()) as the
* nextnode parameter; to add the link _after_ an existing item, pass
* the node's nextSibling instead.
*
* @param String portlet -- id of the target portlet ("p-cactions", "p-personal", "p-navigation" or "p-tb")
* @param String href -- link URL
* @param String text -- link text (will be automatically lowercased by CSS for p-cactions in Monobook)
* @param String id -- id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
* @param String tooltip -- text to show when hovering over the link, without accesskey suffix
* @param String accesskey -- accesskey to activate this link (one character, try to avoid conflicts)
* @param Node nextnode -- the DOM node before which the new item should be added, should be another item in the same list
*
* @return Node -- the DOM node of the new item (an LI element) or null
*/
function addPortletLink(portlet, href, text, id, tooltip, accesskey, nextnode) {
var node = document.getElementById(portlet)
if (!node) return null
node = node.getElementsByTagName("ul")[0]
if (!node) return null
var link = document.createElement("a")
link.appendChild(document.createTextNode(text))
link.href = href
var item = document.createElement("li")
item.appendChild(link)
if (id)
item.id = id
if (accesskey) {
link.setAttribute("accesskey", accesskey)
tooltip += " [" + accesskey + "]"
}
if (tooltip)
link.setAttribute("title", tooltip)
if (accesskey && tooltip)
updateTooltipAccessKeys(new Array(link))
if (nextnode && nextnode.parentNode == node)
node.insertBefore(item, nextnode)
else // IE compatibility (?)
node.appendChild(item)
return item
}
/**
* Set up accesskeys/tooltips from the deprecated ta array. If doId
* is specified, only set up for that id. Note that this function is
* deprecated and will not be supported indefinitely -- use
* updateTooltipAccessKey() instead.
*
* @param mixed doId string or null
*/
function akeytt(doId) {
// A lot of user scripts (and some of the code below) break if
// ta isn't defined, so we make sure it is. Explictly using
// window.ta avoids a "ta is not defined" error.
if (!window.ta) window.ta = []
// Make a local, possibly restricted, copy to avoid clobbering
// the original.
if (doId)
var ta = [doId]
else
var ta = window.ta
// Now deal with evil deprecated ta
var watchCheckboxExists = document.getElementById('wpWatchthis') ? true : false
for (var id in ta) {
var n = document.getElementById(id)
if (n) {
var a = null
var ak = ''
// Are we putting accesskey in it
if (ta[id][0].length > 0) {
// Is this object a object? If not assume it's the next child.
if (n.nodeName.toLowerCase() == "a")
a = n
else
a = n.childNodes[0]
// Don't add an accesskey for the watch tab if the watch
// checkbox is also available.
if (a && ((id != 'ca-watch' && id != 'ca-unwatch') || !watchCheckboxExists)) {
a.accessKey = ta[id][0]
ak = ' [' + tooltipAccessKeyPrefix + ta[id][0] + ']'
}
} else {
// We don't care what type the object is when assigning tooltip
a = n
ak = ''
}
if (a)
a.title = ta[id][1] + ak
}
}
}
var checkboxes
var lastCheckbox
function setupCheckboxShiftClick() {
checkboxes = []
lastCheckbox = null
var inputs = document.getElementsByTagName('input')
addCheckboxClickHandlers(inputs)
}
function addCheckboxClickHandlers(inputs, start) {
if (!start) start = 0
var finish = start + 250
if (finish > inputs.length)
finish = inputs.length
for (var i = start; i < finish; i++) {
var cb = inputs[i]
if (!cb.type || cb.type.toLowerCase() != 'checkbox')
continue
var end = checkboxes.length
checkboxes[end] = cb
cb.index = end
cb.onclick = checkboxClickHandler
}
if (finish < inputs.length) {
setTimeout(
function () {
addCheckboxClickHandlers(inputs, finish)
},
200
)
}
}
function checkboxClickHandler(e) {
if (typeof e == 'undefined')
e = window.event
if (!e.shiftKey || lastCheckbox === null) {
lastCheckbox = this.index
return true
}
var endState = this.checked
var start, finish
if (this.index < lastCheckbox) {
start = this.index + 1
finish = lastCheckbox
} else {
start = lastCheckbox
finish = this.index - 1
}
for (var i = start; i <= finish; ++i)
checkboxes[i].checked = endState
lastCheckbox = this.index
return true
}
function toggle_element_activation(ida, idb) {
if (!document.getElementById)
return
document.getElementById(ida).disabled = true
document.getElementById(idb).disabled = false
}
function toggle_element_check(ida, idb) {
if (!document.getElementById)
return
document.getElementById(ida).checked = true
document.getElementById(idb).checked = false
}
/*
Written by Jonathan Snook, http://www.snook.ca/jonathan
Add-ons by Robert Nyman, http://www.robertnyman.com
Author says "The credit comment is all it takes, no license. Go crazy with it!:-)"
From http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
*/
function getElementsByClassName(oElm, strTagName, oClassNames) {
var arrElements = (strTagName == "*" && oElm.all) ? oElm.all : oElm.getElementsByTagName(strTagName)
var arrReturnElements = []
var arrRegExpClassNames = []
if (typeof oClassNames == "object") {
for (var i = 0, n = oClassNames.length; i < n; i++) {
arrRegExpClassNames[arrRegExpClassNames.length] =
new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)")
}
} else {
arrRegExpClassNames[arrRegExpClassNames.length] =
new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)")
}
for (var j = 0, o = arrElements.length; j < o; j++) {
var oElement = arrElements[j]
var bMatchesAll = true
for (var k = 0, p = arrRegExpClassNames.length; k < p; k++) {
if (!arrRegExpClassNames[k].test(oElement.className)) {
bMatchesAll = false
break
}
}
if (bMatchesAll)
arrReturnElements[arrReturnElements.length] = oElement
}
return (arrReturnElements)
}
function redirectToFragment(fragment) {
var match = navigator.userAgent.match(/AppleWebKit\/(\d+)/)
if (match) {
var webKitVersion = parseInt(match[1])
if (webKitVersion < 420) {
// Released Safari w/ WebKit 418.9.1 messes up horribly
// Nightlies of 420+ are ok
return
}
}
if (is_gecko) {
// Mozilla needs to wait until after load, otherwise the window doesn't scroll
addOnloadHook(
function () {
if (window.location.hash == "")
window.location.hash = fragment
}
)
} else {
if (window.location.hash == "")
window.location.hash = fragment
}
}
/*
* Table sorting script based on one (c) 1997-2006 Stuart Langridge and Joost
* de Valk:
* http://www.joostdevalk.nl/code/sortable-table/
* http://www.kryogenix.org/code/browser/sorttable/
*
* @todo don't break on colspans/rowspans (bug 8028)
* @todo language-specific digit grouping/decimals (bug 8063)
* @todo support all accepted date formats (bug 8226)
*/
var ts_image_path = stylepath+"/common/images/"
var ts_image_up = "sort_up.gif"
var ts_image_down = "sort_down.gif"
var ts_image_none = "sort_none.gif"
var ts_europeandate = wgContentLanguage != "en"; // The non-American-inclined can change to "true"
var ts_alternate_row_colors = true; // the "even" and "odd" classes required by this table seem not to exist
var SORT_COLUMN_INDEX
function sortables_init() {
var idnum = 0
// Find all tables with class sortable and make them sortable
var tables = getElementsByClassName(document, "table", "sortable")
for (var ti = 0, n = tables.length; ti < n ; ti++) {
var thisTable = tables[ti]
if (!thisTable.id)
thisTable.setAttribute('id', 'sortable_table_id_' + idnum++)
ts_makeSortable(thisTable)
}
}
function ts_makeSortable(table) {
var newTableClass = (" " + table.className + " ").replace(" sortable ", " ")
if (!table.rows || table.rows.length < 3) // no sense in continuing if there are fewer than three rows
return
// set the firstRow after the last THEAD row
// note: the THEAD element is not currently supported on Wikipedia
// if (table.tHead && table.tHead.rows.length > 0)
// var firstRow = table.tHead.rows[table.tHead.rows.length - 1]
// else
var firstRow = table.rows[0]
// We have a first row: assume it's the header, and make its contents clickable links
for (var i = 0, n = firstRow.cells.length; i < n; i++) {
var cell = firstRow.cells[i]
var cellClass = " " + cell.className + " "
var cellType = cell.tagName.toLowerCase()
var newTable = document.createElement('table')
var newTbody = document.createElement('tbody')
var newRow = document.createElement('tr')
var newCell1 = document.createElement(cellType)
while (cell.hasChildNodes())
newCell1.appendChild(cell.removeChild(cell.firstChild))
cell.style.padding = '0px'
newTable.className = newTableClass
newTable.style.border = '0px'
newTable.style.margin = '0px'
newTable.style.width = '100%'
newCell1.className = cellClass
newCell1.style.border = '0px'
newRow.appendChild(newCell1)
if (cellClass.indexOf(" unsortable ") == -1) {
var newCell2 = document.createElement(cellType)
if (cellClass.indexOf(" sortreverse ") == -1)
newCell2.innerHTML = '<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;"><span class="sortarrow" sortdir="up"><img src="' + ts_image_path + ts_image_none + '" alt="Sort in ascending order."/></span></a>'
else
newCell2.innerHTML = '<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;"><span class="sortarrow" sortdir="down"><img src="' + ts_image_path + ts_image_none + '" alt="Sort in descending order."/></span></a>'
newCell2.className = cellClass
newCell2.style.border = '0px'
newCell2.style.width = '12px'
newRow.appendChild(newCell2)
}
newTbody.appendChild(newRow)
newTable.appendChild(newTbody)
cell.appendChild(newTable)
}
if (ts_alternate_row_colors)
ts_alternate(table)
}
function ts_getInnerText(el) {
if (typeof el == "string" || typeof el == "undefined") return el
if (el.textContent) return el.textContent; // not needed but it is faster
if (el.innerText) return el.innerText; // IE doesn't have textContent
var str = ""
var cs = el.childNodes
for (var i = 0, n = cs.length; i < n; i++) {
switch (cs[i].nodeType) {
case 1: //ELEMENT_NODE
str += ts_getInnerText(cs[i])
break
case 3: //TEXT_NODE
str += cs[i].nodeValue
break
}
}
return str
}
function ts_resortTable(lnk) {
var td = lnk.parentNode.parentNode.parentNode.parentNode.parentNode
var tr = td.parentNode
var table = tr.parentNode
while (table && !(table.tagName && table.tagName.toLowerCase() == 'table'))
table = table.parentNode
if (!table) return
// quit if there are fewer than 3 rows
if (table.rows.length < 3) return
// get the span and column
var span = lnk.getElementsByTagName('span')[0]
var column = td.cellIndex
// Skip the first row if that's where the headings are.
// Note: the THEAD element is not supported on Wikipedia. Uncomment the following line when support is added.
// var rowStart = (table.tHead && table.tHead.rows.length > 0 ? 0 : 1)
var rowStart = 1
// Remove leading and trailing spaces
var itm = ""
for (var i = rowStart, n = table.rows.length; i < n; i++) {
if (table.rows[i].cells.length > column) {
itm = ts_getInnerText(table.rows[i].cells[column])
itm = itm.replace(/^[\s\xa0]+/, "").replace(/[\s\xa0]+$/, "")
if (itm != "") break
}
}
// determine which sorting function to use
if (itm.match(/^[^\d]+$/)) // matches any string without digits
var sortfn = ts_sort_caseinsensitive
else if (itm.match(/^[\d\.\,]+\%?$/)) // matches: nn.nnn or nn,nnn or nn.nnn% or nn,nnn% or nn.nnn,nnn% or nn,nnn.nnn%
var sortfn = ts_sort_numeric
else if (itm.match(/^\d{1,2}[\/\.\-]\d{1,2}[\/\.\-](\d{2}|\d{4})$/)) // matches: D(D)-M(M)-YY(YY) or M(M)-D(D)-YY(YY)
var sortfn = ts_sort_date_1
else if (itm.match(/^([^\d\/\.\- ]+[\/\.\- ]\d{1,2}|\d{1,2}[\/\.\- ][^\d\/\.\- ]+),?[\/\.\- ](\d{2}|\d{4})$/)) // matches: D(D)-MONTHABV-YY(YY) or MONTHABV-D(D)-YY(YY) or MONTHABV D(D), YY(YY)
var sortfn = ts_sort_date_2
else if (itm.match(/^[\u00a3$\u20ac\u00a5]/)) // pound dollar euro yen
var sortfn = ts_sort_currency
// else if (itm.match(/^[\d\.\,]+\s*[\/\:]\s*[\d\.\,]+$/)) // matches: nnn/nnn or nnn:nnn
// var sortfn = ts_sort_fraction
else
var sortfn = ts_sort_caseinsensitive
var reverse = (span.getAttribute("sortdir") == "down")
var newRows = []
for (var j = rowStart, n = table.rows.length; j < n; j++) {
var row = table.rows[j]
var keyText = ts_getInnerText(row.cells[column])
var oldIndex = (reverse ? -j : j)
newRows[newRows.length] = [row, keyText, oldIndex]
}
newRows.sort(sortfn)
if (reverse) {
span.innerHTML = '<img src="' + ts_image_path + ts_image_down + '" alt="Sort in ascending order."/>'
span.setAttribute('sortdir','up')
newRows.reverse()
} else {
span.innerHTML = '<img src="' + ts_image_path + ts_image_up + '" alt="Sort in descending order."/>'
span.setAttribute('sortdir','down')
}
// append rows that already exist to the tbody, so it moves them rather than creating new ones
// don't do sortbottom rows
for (var i = 0, n = newRows.length; i < n; i++) {
if ((" " + newRows[i][0].className + " ").indexOf(" sortbottom ") == -1)
table.tBodies[0].appendChild(newRows[i][0])
}
// do sortbottom rows only
for (var i = 0, n = newRows.length; i < n; i++) {
if ((" " + newRows[i][0].className + " ").indexOf(" sortbottom ") != -1)
table.tBodies[0].appendChild(newRows[i][0])
}
// delete any other arrows that may be showing
var spans = getElementsByClassName(tr, "span", "sortarrow")
for (var i = 0, n = spans.length; i < n; i++) {
var thisSpan = spans[i]
if (thisSpan != span) {
var cellClass = " " + thisSpan.parentNode.parentNode.className + " "
if (cellClass.indexOf(" sortreverse ") == -1) {
thisSpan.setAttribute("sortdir", "up")
thisSpan.innerHTML = '<img src="' + ts_image_path + ts_image_none + '" alt="Sort in ascending order."/>'
} else {
thisSpan.setAttribute("sortdir", "down")
thisSpan.innerHTML = '<img src="' + ts_image_path + ts_image_none + '" alt="Sort in descending order."/>'
}
}
}
if (ts_alternate_row_colors)
ts_alternate(table);
}
function ts_dateToSortKey_1(date) {
// matches: D(D)-M(M)-YY(YY) or M(M)-D(D)-YY(YY)
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
date = date.replace(/[\/\.]/g, '-')
var dateLen = date.length
var firstIdx = date.indexOf('-')
var secndIdx = date.indexOf('-', firstIdx + 1)
var yearIdx = secndIdx + 1
var yearLen = dateLen - yearIdx
var secndLen = dateLen - yearLen - firstIdx - 2
var year = parseInt(date.substr(yearIdx, yearLen))
if (yearLen == 2)
year += year < 50 ? 2000 : 1900
if (ts_europeandate) {
var month = date.substr(firstIdx + 1, secndLen)
var day = date.substr(0, firstIdx)
} else {
var month = date.substr(0, firstIdx)
var day = date.substr(firstIdx + 1, secndLen)
}
month = parseInt(month)
day = parseInt(day)
if (month < 10) month = "0" + month
if (day < 10) day = "0" + day
return "".concat(year, month, day)
}
function ts_dateToSortKey_2(date) {
// matches: D(D)-MONTHABV-YY(YY) or MONTHABV-D(D)-YY(YY) or MONTHABV D(D), YY(YY)
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
// the following is valid only for the English language, and should ideally be set as a global variable in "common.js"
var monthStr = "janfebmaraprmayjunjulaugsepoctnovdec"
var monthLen = 3
var monthNam = date.match(/[^\d\/\.\- ]+/)[0]
var monthAbv = monthNam.substr(0, monthLen)
date = date.replace(/[^\d\/\.\- ]+/, monthAbv)
date = date.replace(/[\/\. ]/g, '-')
date = date.replace(/,/g, '')
var dateLen = date.length
var firstIdx = date.indexOf('-')
var secndIdx = date.indexOf('-', firstIdx + 1)
var yearIdx = secndIdx + 1
var yearLen = dateLen - yearIdx
var secndLen = dateLen - yearLen - firstIdx - 2
var year = parseInt(date.substr(yearIdx, yearLen))
if (yearLen == 2)
year += year < 50 ? 2000 : 1900
if (date.charCodeAt(0) < 58) {
var month = date.substr(firstIdx + 1, secndLen)
var day = date.substr(0, firstIdx)
} else {
var month = date.substr(0, firstIdx)
var day = date.substr(firstIdx + 1, secndLen)
}
month = monthStr.indexOf(month.toLowerCase()) / monthLen + 1
day = parseInt(day)
if (month < 10) month = "0" + month
if (day < 10) day = "0" + day
return "".concat(year, month, day)
}
function ts_parseFloat(num) {
if (!num) return 0
// if (ts_europeandate)
// num = parseFloat(num.replace(/\./g, "").replace(/,/g, "."))
// else
num = parseFloat(num.replace(/,/g, ""))
return (isNaN(num) ? 0 : num)
}
function ts_sort_date_1(a, b) {
var aa = ts_dateToSortKey_1(a[1])
var bb = ts_dateToSortKey_1(b[1])
return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2])
}
function ts_sort_date_2(a, b) {
var aa = ts_dateToSortKey_2(a[1])
var bb = ts_dateToSortKey_2(b[1])
return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2])
}
function ts_sort_currency(a, b) {
var aa = ts_parseFloat(a[1].replace(/[^0-9.]/g, ''))
var bb = ts_parseFloat(b[1].replace(/[^0-9.]/g, ''))
return (aa != bb ? aa - bb : a[2] - b[2])
}
function ts_sort_numeric(a, b) {
var aa = ts_parseFloat(a[1])
var bb = ts_parseFloat(b[1])
return (aa != bb ? aa - bb : a[2] - b[2])
}
function ts_sort_fraction(a, b) {
// colons also count as division operators in this case; may cause problems
a[1] = a[1].replace(/\s+/g, '')
b[1] = b[1].replace(/\s+/g, '')
var aa1 = a[1].match(/^[\d\.,]+[\/\:]/)[0].replace(/[\/\:]/, '')
var aa2 = a[1].match(/[\/\:][\d\.,]+$/)[0].replace(/[\/\:]/, '')
var bb1 = b[1].match(/^[\d\.,]+[\/\:]/)[0].replace(/[\/\:]/, '')
var bb2 = b[1].match(/[\/\:][\d\.,]+$/)[0].replace(/[\/\:]/, '')
if (ts_europeandate == true) {
aa1 = aa1.replace(/\./g, "")
aa2 = aa2.replace(/\./g, "")
bb1 = bb1.replace(/\./g, "")
bb2 = bb2.replace(/\./g, "")
} else {
aa1 = aa1.replace(/,/g, "")
aa2 = aa2.replace(/,/g, "")
bb1 = bb1.replace(/,/g, "")
bb2 = bb2.replace(/,/g, "")
}
var aa = parseFloat(aa1) / parseFloat(aa2)
var bb = parseFloat(bb1) / parseFloat(bb2)
return (aa != bb ? aa - bb : a[2] - b[2])
}
function ts_sort_caseinsensitive(a, b) {
var aa = a[1].toLowerCase()
var bb = b[1].toLowerCase()
return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2])
}
function ts_sort_default(a, b) {
return (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : a[2] - b[2])
}
function ts_alternate(table) {
// Take object table and get all its tbodies.
var tableBodies = table.getElementsByTagName("tbody")
// Loop through these tbodies
for (var i = 0, n = tableBodies.length; i < n; i++) {
// Take the tbody, and get all it's rows
var tableRows = tableBodies[i].getElementsByTagName("tr")
// Loop through these rows
// Start at 1 because we want to leave the heading row untouched
for (var j = 0, o = tableRows.length; j < o; j++) {
// Check if j is even, and apply classes for both possible results
var oldClasses = tableRows[j].className.split(" ")
var newClassName = ""
for (var k = 0, p = oldClasses.length; k < p; k++) {
var thisClass = oldClasses[k]
if (thisClass != "" && thisClass != "even" && thisClass != "odd")
newClassName += thisClass + " "
}
tableRows[j].className = newClassName + (j % 2 == 0 ? "even" : "odd")
}
}
}
/*
* End of table sorting code
*/
/**
* Add a cute little box at the top of the screen to inform the user of
* something, replacing any preexisting message.
*
* @param String -or- Dom Object message HTML to be put inside the right div
* @param String className Used in adding a class; should be different for each
* call to allow CSS/JS to hide different boxes. null = no class used.
* @return Boolean True on success, false on failure
*/
function jsMsg(message, className) {
if (!document.getElementById)
return false
// We special-case skin structures provided by the software. Skins that
// choose to abandon or significantly modify our formatting can just define
// an mw-js-message div to start with.
var messageDiv = document.getElementById('mw-js-message')
if (!messageDiv) {
messageDiv = document.createElement('div')
var contentDiv = document.getElementById('content')
var columnDiv = document.getElementById('column-content')
var articleDiv = document.getElementById('article')
if (contentDiv) {
// MonoBook, presumably
if (columnDiv)
contentDiv.insertBefore(messageDiv, contentDiv.firstChild)
// Non-Monobook but still recognizable (old-style)
else if (articleDiv)
articleDiv.insertBefore(messageDiv, articleDiv.firstChild)
else
return false
} else
return false
}
messageDiv.setAttribute('id', 'mw-js-message')
if (className)
messageDiv.setAttribute('class', 'mw-js-message-' + className)
if (typeof message === 'object') {
while (messageDiv.hasChildNodes()) // Remove old content
messageDiv.removeChild(messageDiv.firstChild)
messageDiv.appendChild(message); // Append new content
}
else
messageDiv.innerHTML = message
return true
}
/**
* Inject a cute little progress spinner after the specified element
*
* @param element Element to inject after
* @param id Identifier string (for use with removeSpinner(), below)
*/
function injectSpinner(element, id) {
var spinner = document.createElement("img")
spinner.id = "mw-spinner-" + id
spinner.src = stylepath + "/common/images/spinner.gif"
spinner.alt = spinner.title = "..."
if (element.nextSibling)
element.parentNode.insertBefore(spinner, element.nextSibling)
else
element.parentNode.appendChild(spinner)
}
/**
* Remove a progress spinner added with injectSpinner()
*
* @param id Identifier string
*/
function removeSpinner(id) {
var spinner = document.getElementById("mw-spinner-" + id)
if (spinner)
spinner.parentNode.removeChild(spinner)
}
function runOnloadHook() {
// don't run anything below this for non-dom browsers
if (doneOnloadHook || !(document.getElementById && document.getElementsByTagName))
return
// set this before running any hooks, since any errors below
// might cause the function to terminate prematurely
doneOnloadHook = true
updateTooltipAccessKeys(null)
akeytt(null)
setupCheckboxShiftClick()
sortables_init()
// Run any added-on functions
for (var i = 0, n = onloadFuncts.length; i < n; i++)
onloadFuncts[i]()
}
/**
* Add an event handler to an element
*
* @param Element element Element to add handler to
* @param String attach Event to attach to
* @param callable handler Event handler callback
*/
function addHandler(element, attach, handler) {
if (window.addEventListener)
element.addEventListener(attach, handler, false)
else if (window.attachEvent)
element.attachEvent('on' + attach, handler)
}
/**
* Add a click event handler to an element
*
* @param Element element Element to add handler to
* @param callable handler Event handler callback
*/
function addClickHandler(element, handler) {
addHandler(element, 'click', handler)
}
//note: all skins should call runOnloadHook() at the end of html output,
// so the below should be redundant. It's there just in case.
hookEvent("load", runOnloadHook)