User:Yair rand/sandbox.js
Jump to navigation
Jump to search
Note – after saving, you may have to bypass your browser’s cache to see the changes.
- Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
- Konqueror and Chrome: click Reload or press F5;
- Opera: clear the cache in Tools → Preferences;
- Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.
- This script lacks a documentation subpage. Please create it.
- Useful links: root page • root page’s subpages • links • redirects • your own
(function ( $ ) {
// This is a (very) modified version of User:Atelaes/TabbedLanguages.js.
// Tabbed languages with tabs on the side.
// Tabs design by [[User:Jorm (WMF)]]
// Currently undergoing rewrite in order to eliminate delay.
// Remember to remove extra console.logs before deploying.
if (($.cookie('disable-tabbed-languages') !== null) || (location.search.indexOf("tabbedlanguages=off") !== -1))
return;
if (!((mw.config.get('wgNamespaceNumber') === 0) || (mw.config.get('wgPageName') === "Wiktionary:Sandbox")))
return;
var bodyContent = $(".mw-content-ltr")[0], // NOT #bodyContent
observerStyleSheet,
languageLinks, ttr,
languageButtons = [],
isIE9 = $.client.profile().name === "msie" && $.client.profile().versionNumber == 9,
caption,
bodyContentFragment,
complete = false;
// Setting up the tabs has not yet been started.
function makeTabsfromScratch() {
// Set up the variables...
window.tabbedLanguages = [];
window.languageContainers = [];
window.currentLanguageTab = 0;
window.languageHeaderEditButtons = [];
window.tabstable = newNode('table', {id: 'tabstable'},
newNode('tbody',
ttr = newNode('tr',
newNode('td', {'style': 'padding-top:0px;vertical-align:top;'},
newNode('table', {'style': 'margin-top: -2px;'},
languageLinks = newNode('tbody', {id: 'languageLinks'}))))));
window.loadremovecatbuttons = false;
bodyContentFragment = document.createDocumentFragment();
// If bodyContent is complete, do it all at once.
// Otherwise, only start working, but don't attempt the whole thing.
// Use catlinks+*, as gEBCN isn't always available.
var catlinks = document.getElementById( "catlinks" );
if( bodyContent && catlinks && catlinks.nextSibling ) {
allAtOnce();
} else {
createObserver();
}
}
function allAtOnce() {
console.log( "allAtOnce()");
var languageContainer, toc = document.getElementById( "toc" );
currentLanguageTab = 0;
while ( bodyContent.firstChild ) {
bodyContentFragment.appendChild( bodyContent.firstChild );
}
try {
for( var child = bodyContentFragment.firstChild; child && !isHeader( child ); ){
child = child.nextSibling;
}
for (
child = child && bodyContentFragment.insertBefore(tabstable, child).nextSibling;
child && child.className !== 'printfooter' && child.className !== 'catlinks';
child = child.nextSibling
) {
if ( isHeader( child ) ) {
var spans = child.getElementsByTagName('span'),
span = spans[ 0 ],
language = span && ( span.innerText || span.textContent );
if ( language ) {
newTab( tabbedLanguages.push(language) - 1, language );
processEditButton( spans[ 1 ] );
// should probably be set from a return value of above.
languageContainer = languageContainers[ languageContainers.length - 1 ];
bodyContentFragment.removeChild( child );
child = tabstable;
}
} else {
if ( child.nodeName !== "HR" ) {
languageContainer.insertBefore(child, languageContainer.lastChild);
} else {
bodyContentFragment.removeChild(child);
}
child = tabstable;
}
}
if( tabbedLanguages.length ) {
if( toc ) {
toc.parentNode.removeChild( toc );
}
sortCats();
bodyContent.appendChild( bodyContentFragment );
setUpHashChange()();
if( location.hash === '' ) {
console.log( "Replacing hash with current tab" );
location.replace( "#" + tabbedLanguages[ currentLanguageTab ] );
}
complete = true;
} else {
bodyContent.appendChild( bodyContentFragment );
}
} catch( e ) {
window.console && console.log( e );
bodyContent.appendChild( bodyContentFragment );
complete || setUpHashChange()();
}
}
// Set up a stylesheet that uses animations/keyframes to allow
// animationStart to see each time a new node loads onto the bodyContent.
function createObserver() {
// If .ready happens early (or animstart isn't supported), go ahead.
// The "false" replacement is only needed for testing purposes.
// When ready to deploy, remove false and uncomment isReady check.
if( false /* $.isReady */ ) {
return; // ??? How did we get $.isReady if bC or catlinks aren't loaded?
} else {
$( document ).ready( function () {
if( tabbedLanguages.length === 0 ) {
removeObserver();
allAtOnce();
}
});
}
// Check whether animations are even supported. If not, abort.
// Basically yoinked from Modernizr.
var supportsAnimations = false;
$.each(
"animationName WebkitAnimationName MozAnimationName OAnimationName msAnimationName".split(" "),
function(a, b){
// Do documentElements even always have .style? If not, this'll need fixing.
if( document.documentElement.style[ b ] !== undefined ) {
supportsAnimations = true;
return false;
}
}
);
if( supportsAnimations === false || !document.getElementsByClassName ) {
return;
}
var foundHeader = false,
toc, recentChild,
timer = false, // It's the setTimeout value, or false otherwise.
recentHeader = -1,
checkTab, tabFound = false,
// If anyone on this project even considers making a random element
// on a page have the class "visualClear"...
visualClear = document.getElementsByClassName( "visualClear" ),
languageContainer;
// TODO: Deal with the little jumping elements below the tabstable.
// ...How?
/*
"@/@-moz-/@-webkit-/@-ms-/@-o-/".split("/")
.join("keyframes nodeInserted{" +
"from{outline-color:#fff;}" +
"to{outline-color:#000;}" +
"}\n");
*/
observerStyleSheet = mw.util.addCSS(
"@keyframes nodeInserted{from{outline-color:#fff;}to{outline-color:#000;}}" +
"@-moz-keyframes nodeInserted{from{outline-color:#fff;}to{outline-color:#000;}}" +
"@-webkit-keyframes nodeInserted{from{outline-color:#fff;}to{outline-color:#000;}}" +
"@-ms-keyframes nodeInserted{from{outline-color:#fff;}to{outline-color:#000;}}" +
"@-o-keyframes nodeInserted{from{outline-color:#fff;}to{outline-color:#000;}}" +
".mw-content-ltr>*,.mw-content-ltr+*,.visualClear{" + /* "background:#FF6A6A;" + */
"animation-duration:0.01s;-o-animation-duration:0.01s;-ms-animation-duration:0.01s;" +
"-moz-animation-duration:0.01s;-webkit-animation-duration:0.01s;" +
"animation-name:nodeInserted;-o-animation-name:nodeInserted;-ms-animation-name:nodeInserted;" +
"-moz-animation-name:nodeInserted;-webkit-animation-name:nodeInserted;" +
"}"
);
document.addEventListener('animationstart', animFound, false);
document.addEventListener('MSAnimationStart', animFound, false);
document.addEventListener('webkitAnimationStart', animFound, false);
function animFound() {
if( timer === false ) {
timer = setTimeout( function() {
timer = false;
reactToObserver();
}, 1);
}
}
function reactToObserver() {
// TODO: Surround main areas in try{} so that if it breaks, at least
// the content gets dumped back into visibility.
console.log("reactToObserver()");
// First: What part are we up to?
if( !foundHeader ) {
// search for header or toc
if( !recentChild ) { // Just starting, apparently.
if( !bodyContent ) {
bodyContent = $(".mw-content-ltr")[0];
if( !bodyContent ) {
// Somehow ended up here before bC loaded.
// Probably a result of someone else's animation.
return;
}
}
// Check if we can do the whole thing in one go.
if( visualClear.length ) {
removeObserver();
allAtOnce();
return;
}
recentChild = bodyContent.firstChild;
if( !recentChild ) {
return; // Somehow got activated between bodyContent load
// and bodyContent's content's load.
}
}
for( ; !isHeader( recentChild ) && recentChild.nextSibling; ) {
recentChild = recentChild.nextSibling;
}
if( isHeader( recentChild ) ) { // should simplify check. Maybe !recentChild.nextSibling?
// We have our first header.
foundHeader = true;
console.log( "Found header" );
checkTab = setUpHashChange();
// Default to the first tab.
currentLanguageTab = 0;
toc = document.getElementById('toc');
if ( toc ) {
if ( toc.nextSibling ) {
// And we have a usable ToC. Makes things much easier.
// Analyze the ToC. We'll be using it to determine what
// the tabs are going to be.
$( ".toclevel-1 > a > .toctext" ).each( function() {
var language = $( this ).text();
tabbedLanguages.push( language );
});
// Build all the tabs.
$( tabbedLanguages ).each( newTab );
toc.parentNode.removeChild( toc );
// Afterwards, we'll check if the right section
// is already available.
} else {
// Potential panic situation: Evil formatting places
// ToC *after* the first header, so it's actually
// *partly* loaded at this point, with no nextSibling.
// (Alternatively, someone put it alone in a box.) CSS
// builds it up as a huge tabbing block, but we can't
// remove it here. Oy.
// "Solution":
// Temporarily hide the ToC until ready() fires, then
// remove it. I'm not removing it right away, as I have
// no idea what doom might occur if something like this
// is removed while stuff is being loaded into it.
toc.style.display = "none";
( function ( toc ) {
$( function() {
if( toc.parentNode ) {
toc.parentNode.removeChild( toc );
}
});
})( toc );
toc = undefined;
window.console && console.error( "TL notice: " +
"Malformed entry. ToC either appears after " +
"headers, or is placed in a box. Mind fixing " +
"it or alerting me? Thanks. -- YR" );
}
}
languageContainer = languageContainers[ 0 ];
// Edit buttons.
processEditButton(
recentChild.getElementsByTagName( "span" )[ 1 ]
);
// Either way, start displaying the tabs right.
bodyContent.insertBefore( tabstable, recentChild );
if( toc ) {
tabFound = checkTab();
}
}
}
if( foundHeader ) {
// Note that there may or may not be a ToC available...
// Should this be reworked so that the toc check is inside the loop?
if( recentChild.nextSibling ) {
// I hope I'm not going to regret leaving out a recentChild && condition here...
for( var lastChild = bodyContent.lastChild, nextChild; recentChild !== lastChild; ) {
nextChild = recentChild.nextSibling;
if( isHeader( recentChild ) ) {
var spans = recentChild.getElementsByTagName('span');
if( recentHeader >= 0 ) {
languageContainer.insertBefore( bodyContentFragment, languageContainer.lastChild );
}
recentHeader++;
var language = ( language = spans[0] ).innerText || language.textContent;
// Make sure it actually matches, when necessary.
if( toc && language !== tabbedLanguages[ recentHeader ]) {
// PANIC!!!
// Okay, maybe don't panic. TL has encountered
// a header that doesn't match the ToC's
// description of the page. Possibilities
// include an h1 on the page, a fake header
// around somewhere, or some other malformed
// kind of header. This really isn't supposed
// to happen ever.
// Response: Clear everything after this point,
// and from there act as though the ToC never
// existed.
if( recentHeader > 0 ) {
toggleLanguageTabs( tabbedLanguages[ 0 ] );
} else {
currentLanguageTab = 0;
}
while( tabbedLanguages.length > recentHeader ) {
tabbedLanguages.pop();
ttr.removeChild(
languageContainers.pop()
);
languageLinks.removeChild(
languageButtons.pop().parentNode
);
}
toc = undefined; // Never. Existed.
tabFound = false;
window.console && console.error( "TL notice: " +
"Malformed entry. ToC does not match " +
"headers. Possibly a misplaced H1, fake " +
"header, or header with incorrect " +
"contents. Mind fixing it or " +
"alerting me? Thanks. -- YR "
);
}
if( !toc ) {
tabbedLanguages.push( language );
newTab( recentHeader, language );
}
// Check to see if the target tab is found.
// TODO: Need a better system of knowing when to check:
// If it's found, stop checking.
// Whether or not we have a ToC, checking can be necessary.
// If we do have a ToC, but no hash, we don't check, right?
// Put another way:
// No hash? W/ ToC, don't check. W/o ToC, only check when new headers come in.
// Hash? Depends.
// W/ ToC: Technically, target could come in at any non-header element... ???
// W/o ToC: Could be whenever. Target header coming in is rather likely, in fact. Oy.
// Either way: If the target, whether header or random element, is found, stop looking.
// Does delaying the tab switch to a element target until full load matter? Not sure.
//
// Plan B: Regardless of ToC presence, only
// check for potential target elems
// at each new header, unless target is found.
if( recentHeader > 0 && tabFound === false ) {
tabFound = checkTab();
}
languageContainer = languageContainers[ recentHeader ];
if( recentHeader > 0 ) { // I have too many of these checks...
// Don't duplicate earlier pEB for first header.
processEditButton( spans[ 1 ] );
}
// All done. Clear.
bodyContent.removeChild( recentChild );
} else {
if( recentChild.nodeName === "HR" ) {
// Kill unnecessary bars.
bodyContent.removeChild( recentChild );
} else {
// Regular content. Prepare for dumping into the
// latest tab.
bodyContentFragment.appendChild( recentChild );
}
}
recentChild = nextChild;
}
}
// If we're all done, finish up.
// How to tell?
// Option one: Repeatedly check for nextSibling.
// - Won't work. bodyContent doesn't always have a nS at the end.
// - Currently in use only for dealing with the last elem. (Uses O2 as fallback.)
// Option two: Set up getElemsByClassName, and poll for length.
// - presumably visualClear. This would probably be pretty heavy.
// - Currently in use.
// Option three: Use $.ready.
// - Potentially introduces substantial delay...
// Option four: In the listener, check for classnames each time.
// - Every time there's a new node? Lots of processing.
// Option five: ...
if( bodyContent.nextSibling ) { // are we done? ...
// bodyContent.nextSibling doesn't always exist, but if it
// does, get a head start on the stuff that can be done already.
console.log( recentChild, recentChild.nextSibling, recentChild.parentNode );
bodyContentFragment.appendChild( bodyContent.lastChild );
}
// Dump collected elems into most recent languageContainer.
if( bodyContentFragment.firstChild ) { // Exact duplicate of above code. TODO: Fix.
languageContainer.insertBefore( bodyContentFragment, languageContainer.lastChild );
}
if( visualClear.length ) {
if( bodyContent.lastChild === recentChild ) {
// bC.nS didn't exist. Move the last one left now.
languageContainer.insertBefore( bodyContent.lastChild, languageContainer.lastChild );
}
removeObserver();
sortCats();
// complete = true; // Not actually used anywhere here...
if( tabFound !== true ) {
checkTab();
if( location.hash === '' ) {
location.replace( "#" + tabbedLanguages[currentLanguageTab] );
}
}
}
}
}
function removeObserver() {
document.removeEventListener('animationstart', animFound, false);
document.removeEventListener('MSAnimationStart', animFound, false);
document.removeEventListener('webkitAnimationStart', animFound, false);
if( observerStyleSheet ) {
observerStyleSheet.disabled = true;
}
if( timer !== false ) {
clearTimeout( timer );
}
}
}
function isHeader( elem ) {
return elem && elem.nodeName === "H2" && elem.getElementsByTagName( "span" ).length !== 0;
}
function newTab( index, language ) {
var active = index === currentLanguageTab;
var languageContainer = ttr.appendChild( newNode('td', {
'class': 'languageContainer',
'id': language + 'container'
}, active ? undefined : { 'style' : 'display:none;' } ));
languageContainers.push( languageContainer );
newCategoryBox( languageContainer, language );
// lB contains .(un)?selectedTab nodes
languageButtons.push(
languageLinks.appendChild( newNode('tr', newNode('td', {
'class': ( active ? '' : 'un' ) + 'selectedTab'
}, newNode('a', language, {
// Note: ' + language' makes this inconsistent with the ordinary links
// themselves, which have the language name encoded. Issue?
// Keep in mind that the parser itself actually corrects for this,
// changing #!Xóõ links to the proper #.C7.83X.C3.B3.C3.B5 links.
// Probably nothing to worry about.
'href': location.pathname + location.search + '#' + language
}), ' '))).firstChild
);
}
function newCategoryBox( container, name ) {
// Put a container in each for categories.
return container.appendChild( newNode('div', name + ' categories: ', newNode('ul'), {
'class': 'catlinks',
'id': 'catlinks'
}));
}
function processEditButton( button ) {
if( button ) {
// Yes, theoretically if you have some fake H2s the edit buttons will
// be misplaced. Yet another TODO...
var len = languageHeaderEditButtons.push( button );
if( len === 1 ) {
caption = document.createElement('caption');
tabstable.insertBefore( caption, tabstable.firstChild );
}
button.className += " editlangsection";
// use a argument or variable ( from .push? ) instead of .length?
if( len - 1 === currentLanguageTab ) {
caption.firstChild && caption.removeChild( caption.firstChild );
caption.appendChild( button );
}
}
}
// Sets up the hash toggle system.
// Returns the checkTab() function, which returns true if
// we found whatever it was.
function setUpHashChange() {
// Important Note: The decodeURI mess is a real mess.
// #.C7.83X.C3.B3.C3.B5 should go to tab "!Xóõ", with
// the id "!Xóõcontainer" (no encoding). Urgh.
// Also, "#Old_English" needs to go to decoded "Old English".
// Remember to .substr( 1 ) before passing here.
function decodeHash( hash ) {
return decodeURI(
hash
.replace(/\.(?=[0-9A-F]{2})/g, '%')
.replace(/_/g, ' ')
);
}
// Called by onhashchange.
function hashToggleLT() {
var destination = decodeHash( location.hash.substr(1) );
toggleLanguageTabs( destination );
tabbedLanguages[currentLanguageTab] !== destination && resetHash();
}
// For updating page positioning.
// Doesn't activate hashchange, at least in Chrome. Not sure about others.
function resetHash() {
location.replace( location.hash );
}
// Need to decide if language arg is encoded or decoded.
// Will work with either for the moment. Decoded works earlier.
// Currently passed as decoded by every function but itself.
// The hashes are encoded, but hashToggleLT decodes them.
// Toggles to a different language tab.
window.toggleLanguageTabs = function (language) {
// Find the destination language.
var destinationLanguageTab = $.inArray( language, tabbedLanguages );
if( destinationLanguageTab === -1 ) {
var decoded = decodeHash( language );
if( decoded !== language ) {
destinationLanguageTab = $.inArray( decoded, tabbedLanguages );
}
}
// Style the right toggle button, hide the old language section and show the new one.
// var languageButtons = $("#languageLinks .selectedTab, #languageLinks .unselectedTab");
if (destinationLanguageTab !== -1 ) {
if( destinationLanguageTab !== currentLanguageTab ) {
languageButtons[currentLanguageTab].className = 'unselectedTab';
languageContainers[currentLanguageTab].style.display = 'none';
currentLanguageTab = destinationLanguageTab;
languageButtons[destinationLanguageTab].className = 'selectedTab';
languageContainers[destinationLanguageTab].style.display = '';
if (caption) {
// extra checks shouldn't be necessary...
caption.firstChild && caption.removeChild(caption.firstChild);
languageHeaderEditButtons[currentLanguageTab] && caption.appendChild(languageHeaderEditButtons[currentLanguageTab]);
}
if (isIE9) {
for (var ols = languageContainers[currentLanguageTab].getElementsByTagName('ol'), i = 0; i < ols.length; i++) {
(function (i) {
setTimeout(function () {
ols[i].removeChild(ols[i].insertBefore(document.createElement('li'), ols[i].firstChild));
}, 0);
})(i);
}
}
}
} else {
// Does the hash match the id of a node in a tab?
language = encodeURI( language.replace(/\ /g, '_') );
// Yes, I just possibly undid the decoding from hashToggleLT.
// Worse, this might double-encode, breaking things.
// Or maybe not? I think everything might be decoded before being
// sent here?
// I'll deal with it later.
// Find the node, and go up the node tree until
// you hit .languageContainer, or nothing.
language = document.getElementById( language );
for( ; language && ( language = language.parentNode ) &&
language.className !== 'languageContainer'; )
;
// language = language && language.parentNode.parentNode;
if ( language /* && language.className === 'languageContainer' */ ) {
// If someone maliciously makes a languageContainer with a
// non-compliant ID, boom.
toggleLanguageTabs( language.id.split('container')[0] );
}
// Possible doom bug: Endless loop?
}
};
// This function gets returned as checkTab(), btw.
// For during or immediately after load: Check if we have a
// good "starting" tab. Return true if we have a definitive find.
function checkTab() {
// If there's a location hash, the window may have scrolled down before
// we got a chance to reorganize everything.
// If the destination was a subsection or sense id, switch to the right
// tab, and rescroll.
// If it was simply a language, switch to the appropriate tab, and
// scroll back up.
// If there's no hash at all, work off of the localStorage and TT prefs.
console.log( "checkTab" );
try {
if ( location.hash !== '' ) {
var hash = ( location.hash ).substr( 1 ); // does hash.substr always exist?
var destination = decodeHash( hash );
// 'k, this is still awful.
if( $.inArray( destination, tabbedLanguages ) !== -1 ) {
toggleLanguageTabs( destination );
window.scrollY && window.scroll(0, 0);
return true;
} else if ( document.getElementById( hash ) ) { // This was going
// to receive an area to search from an argument, but it turns
// out that elem.getElementById doesn't actually exist. Meh.
toggleLanguageTabs( destination );
resetHash(); // Scroll to the element. (Necessary since we
// this isn't running through hashToggleLT, which normally does
// it in these situations.)
return true;
}
}
// No hash. Work from localStorage and TT.
if ('localStorage' in window) {
var ind = $.inArray(localStorage.langTabPref, tabbedLanguages);
if ( ind !== -1 ) {
toggleLanguageTabs( tabbedLanguages[ ind ] );
} else if (tabbedLanguages[0] !== 'Translingual' && tabbedLanguages[0] !== 'English' && localStorage.TargetedTranslations) {
for (
var tt_ = localStorage.TargetedTranslations.split("|"), tt = tt_[0].split(";").concat(
$.grep(
tt_[1].replace(/[^;\/]+\//g, '').split(";"),
function (z) {
return z && z !== "Latin" && z !== "Hebrew" && z !== "Arabic";
}
)
).concat( tt_[1].replace(/\/[^;]+/g, '').split(";") ), i = 0;
i < tt.length;
i++
) {
if ($.inArray(tt[i], tabbedLanguages) !== -1) {
toggleLanguageTabs(tabbedLanguages[$.inArray(tt[i], tabbedLanguages)]);
break;
}
}
}
}
return false;
} catch ( e ) {
// This probably isn't all that unlikely to happen. Too complicated. :(
window.console && console.log( "TL error: checkTab broke.", e );
}
}
if ("onhashchange" in window && (document.documentMode === undefined || document.documentMode > 7)) {
window.onhashchange = hashToggleLT;
} else {
$( bodyContent ).on(
'click',
'a[href^="' + location.pathname + location.search + '#"], a[href^="#"]',
function () {
setTimeout( hashToggleLT, 10 );
}
);
}
if ('localStorage' in window) {
window.onunload = function () {
if (tabbedLanguages[currentLanguageTab]) {
localStorage.langTabPref = tabbedLanguages[currentLanguageTab];
}
};
}
// checkTab();
return checkTab;
}
function sortCats() {
var catDiv = document.getElementById('mw-normal-catlinks'), z,
currentCatDiv;
if (catDiv) {
var cats = catDiv.getElementsByTagName('li'),
catname,
langcurrent = 0,
catskip = 1;
do {
while (cats.length > 0) {
z = 0;
catname = cats[z].getElementsByTagName('a')[0].innerHTML;
if (catname.indexOf(tabbedLanguages[langcurrent + catskip]) === 0 &&
!/letter\snames$|script\scharacters$|mythology$/.test(catname)
) {
langcurrent += catskip;
catskip = 1;
}
while (z--+1) {
currentCatDiv = languageContainers[langcurrent].lastChild;
currentCatDiv.lastChild.appendChild(cats[0]);
}
}
if (langcurrent + 1 < languageContainers.length - catskip) {
while (currentCatDiv.lastChild.firstChild) {
catDiv.lastChild.appendChild(currentCatDiv.lastChild.firstChild);
}
catskip++;
} else {
break;
}
} while (true);
}
// place patrol link at the bottom of the page
var pl = currentCatDiv.previousSibling; // languageContainer.lastChild.previousSibling;
console.log( 555, pl, tabstable.parentNode, tabstable.parentNode.childNodes );
// Got it, the patrollink is sometimes the lagging last elem.
if( pl && pl.className === "patrollink" ) {
tabstable.parentNode.appendChild(pl);
}
/*
// category editing buttons
if (mw.config.get('wgAction') === "view" && !/&printable=yes|&diff=|&oldid=/.test(location.search)) {
for (z = 0; z < languageContainers.length; z++) {
// TODO: import
// addTabbedLanguageNewCatButton(z);
}
if ( window.loadremovecatbuttons === true ) {
$.get(
mw.config.get( 'wgScript' ),
{ 'title' : mw.config.get('wgPageName'), 'action' : 'raw' },
// Note that this isn't actually defined. I'm considering not
// actually importing the function, and just dumping this section.
addRemoveCatButtons
);
}
}
*/
// Remove old cat box, allow display of hidden cats box.
if (catDiv && !(catDiv.nextSibling && catDiv.nextSibling.className === "mw-hidden-catlinks mw-hidden-cats-user-shown")) {
catDiv.parentNode.parentNode.removeChild(catDiv.parentNode);
} else {
if (catDiv) {
catDiv.parentNode.removeChild(catDiv);
}
}
}
/**
* newNode imported from Mediawiki:Common.js.
*
* Create a new DOM node for the current document.
* Basic usage: var mySpan = newNode('span', "Hello World!")
* Supports attributes and event handlers*: var mySpan = newNode('span', {style:"color: red", focus: function(){alert(this)}, id:"hello"}, "World, Hello!")
* Also allows nesting to create trees: var myPar = newNode('p', newNode('b',{style:"color: blue"},"Hello"), mySpan)
*
* *event handlers, there are some issues with IE6 not registering event handlers on some nodes that are not yet attached to the DOM,
* it may be safer to add event handlers later manually.
**/
function newNode(tagname){
var node = document.createElement(tagname);
for (var i = 1; i < arguments.length; ++i){
if (typeof arguments[i] == 'string') { // text
node.appendChild(document.createTextNode(arguments[i]));
} else if (typeof arguments[i] == 'object') {
if (arguments[i].nodeName) { //If it is a DOM Node
node.appendChild(arguments[i]);
} else { // Attributes (hopefully)
for (var j in arguments[i]){
if (j == 'class') { //Classname different because...
node.className = arguments[i][j];
} else if (j == 'style') { //Style is special
node.style.cssText = arguments[i][j];
} else if (typeof arguments[i][j] == 'function') { //Basic event handlers
newNode.addEventHandler(node, j, arguments[i][j]);
} else {
node.setAttribute(j, arguments[i][j]); //Normal attributes
}
}
}
}
}
node.addEventHandler = function(eventName, handler) {
newNode.addEventHandler(this, eventName, handler);
};
return node;
}
newNode.addEventHandler = function(node, eventName, handler)
{
try{ node.addEventListener(eventName,handler,false); //W3C
}catch(e){try{ node.attachEvent('on'+eventName,handler,"Language"); //MSIE
}catch(e){ node['on'+eventName]=handler; }} //Legacy
};
function testStuff() {
var delay = 5000, f = document.createDocumentFragment();
var x = [
function () {
// $("#toc").remove();
var x = document.getElementById( "mw-content-text" );
while( x.nextSibling ) {
f.appendChild( x.nextSibling );
}
}, function () {
var y = $( ".mw-content-ltr" )[ 0 ];
var q = document.createDocumentFragment();
while( y.firstChild ) {
q.appendChild( y.firstChild );
}
function u( i, e ) {
setTimeout( function () {
y.appendChild( q.firstChild );
}, i / e * delay );
}
for( var i = 0, e = q.childNodes.length; i < e; i++ ) {
u( i, e ); // encapsulate
}
makeTabsfromScratch();
}, function () {
setTimeout( function(){
$(".mw-content-ltr").after( f );
}, 1000 );
console.log(9);
}
];
x[0]();
for( var i = 1; i < x.length; i++ ) {
setTimeout( x[ i ], (i-1) * delay + 50 );
}
}
//testStuff();
makeTabsfromScratch();
// This is officially deprecated as of MW1.22. Should be replaced by mw.hook,
// but the docs don't say what event, so...
$(mw).bind('LivePreviewDone', function () {
bodyContent = $(".mw-content-ltr")[0]; // reset
makeTabsfromScratch();
});
})( window.jQuery );