MediaWiki:Common.js

Материал из Игра-Говно точка com

(Различия между версиями)
Перейти к: навигация, поиск
м (Новая страница: «- Any JavaScript here will be loaded for all users on every page load.: // If the page name (wgPageName) contains "MediaWiki" and we're in normal view // mode, a…»)
м
Строка 1: Строка 1:
-
/* Any JavaScript here will be loaded for all users on every page load. */
+
// Documentation/Examples: [[RL/DM#jQuery.makeCollapsible]]
 +
// See also [[MediaWiki:JQuery-makeCollapsible.css]]
 +
/* http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/resources/jquery/jquery.makeCollapsible.js?revision=83309&view=markup */
-
// If the page name (wgPageName) contains "MediaWiki" and we're in normal view
+
/**
-
// mode, add "mainpage" class to the body element
+
* jQuery makeCollapsible
-
if ( /^MediaWiki(\/.+)?$/.test( wgPageName ) && wgAction == 'view' ) {
+
-
$(function() {
+
-
document.body.className += ' mainpage';
+
-
});
+
-
}
+
-
 
+
-
// switches for scripts
+
-
// TODO: migrate to JSConfig
+
-
// var load_extratabs = true;
+
-
var load_edittools = true;
+
-
 
+
-
// extra drop down menu on editing for adding special characters
+
-
importScript( 'MediaWiki:Edittools.js' );
+
-
 
+
-
// Editpage scripts
+
-
if( wgAction == 'edit' || wgAction == 'submit' ) {
+
-
importScript( 'MediaWiki:Editpage.js' );
+
-
}
+
-
 
+
-
/* End of extra pages */
+
-
 
+
-
/* Test if an element has a certain class **************************************
+
  *
  *
-
  * From English Wikipedia, 2008-09-15
+
  * This will enable collapsible-functionality on all passed elements.
-
  *
+
  * Will prevent binding twice to the same element.
-
* Description: Uses regular expressions and caching for better performance.
+
  * Initial state is expanded by default, this can be overriden by adding class
-
  * Maintainers: [[User:Mike Dillon]], [[User:R. Koot]], [[User:SG]]
+
  * "mw-collapsed" to the "mw-collapsible" element.
-
  */
+
* Elements made collapsible have class "mw-made-collapsible".
-
var hasClass = (function() {
+
* Except for tables and lists, the inner content is wrapped in "mw-collapsible-content".
-
var reCache = {};
+
-
return function( element, className ) {
+
-
return ( reCache[className] ? reCache[className] : ( reCache[className] = new RegExp( "(?:\\s|^)" + className + "(?:\\s|$)" ) ) ).test( element.className );
+
-
};
+
-
})();
+
-
 
+
-
mw.loader.load( 'http://www.mediawiki.org/w/index.php?title=MediaWiki:JQuery-makeCollapsible.js&action=raw&ctype=text/javascript&smaxage=21600&maxage=86400' );
+
-
 
+
-
/** Collapsible tables *********************************************************
+
  *
  *
-
* From English Wikipedia, 2008-09-15
+
  * @author Krinkle <krinklemail@gmail.com>
-
  * @deprecated: Do not use this in new constructions, use class="mw-collapsible" instead
+
  *
  *
-
  * Description: Allows tables to be collapsed, showing only the header.
+
  * Dual license:
-
  *               See [[Wikipedia:NavFrame]].
+
  * @license CC-BY 3.0 <http://creativecommons.org/licenses/by/3.0>
-
  * Maintainers: [[User:R. Koot]]
+
  * @license GPL2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
  */
  */
-
var autoCollapse = 2;
+
( function( $, mw ) {
-
var collapseCaption = 'hide';
+
-
var expandCaption = 'show';
+
-
function collapseTable( tableIndex ) {
+
$.fn.makeCollapsible = function() {
-
var Button = document.getElementById( 'collapseButton' + tableIndex );
+
-
var Table = document.getElementById( 'collapsibleTable' + tableIndex );
+
-
if ( !Table || !Button ) {
+
return this.each(function() {
-
return false;
+
mw.config.set( 'mw.log.prefix', 'jquery.makeCollapsible' );
-
}
+
-
var Rows = Table.rows;
+
// Define reused variables and functions
 +
var $that = $(this).addClass( 'mw-collapsible' ), // case: $( '#myAJAXelement' ).makeCollapsible()
 +
that = this,
 +
collapsetext = $(this).attr( 'data-collapsetext' ),
 +
expandtext = $(this).attr( 'data-expandtext' ),
 +
toggleElement = function( $collapsible, action, $defaultToggle, instantHide ) {
 +
// Validate parameters
 +
if ( !$collapsible.jquery ) { // $collapsible must be an instance of jQuery
 +
return;
 +
}
 +
if ( action != 'expand' && action != 'collapse' ) {
 +
// action must be string with 'expand' or 'collapse'
 +
return;
 +
}
 +
if ( typeof $defaultToggle !== 'undefined' && !($defaultToggle instanceof jQuery) ) {
 +
// is optional (may be undefined), but if passed it must be an instance of jQuery and nothing else
 +
return;
 +
}
 +
var $containers = null;
-
if ( Button.firstChild.data == collapseCaption ) {
+
if ( action == 'collapse' ) {
-
for ( var i = 1; i < Rows.length; i++ ) {
+
-
Rows[i].style.display = 'none';
+
-
}
+
-
Button.firstChild.data = expandCaption;
+
-
} else {
+
-
for ( var i = 1; i < Rows.length; i++ ) {
+
-
Rows[i].style.display = Rows[0].style.display;
+
-
}
+
-
Button.firstChild.data = collapseCaption;
+
-
}
+
-
}
+
-
function createCollapseButtons(){
+
// Collapse the element
-
var tableIndex = 0;
+
if ( $collapsible.is( 'table' ) ) {
-
var NavigationBoxes = new Object();
+
// Hide all table rows of this table
-
var Tables = document.getElementsByTagName( 'table' );
+
// Slide doens't work with tables, but fade does as of jQuery 1.1.3
 +
// http://stackoverflow.com/questions/467336#920480
 +
$containers = $collapsible.find( '>tbody>tr' );
 +
if ( typeof $defaultToggle !== 'undefined' && ($defaultToggle instanceof jQuery) ) {
 +
// Exclude tablerow containing togglelink
 +
$containers.not( $defaultToggle.closest( 'tr' ) ).stop(true, true).fadeOut();
 +
} else {
 +
if ( instantHide ) {
 +
$containers.hide();
 +
} else {
 +
$containers.stop( true, true ).fadeOut();
 +
}
 +
}
 +
 +
} else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
 +
$containers = $collapsible.find( '> li' );
 +
if ( $defaultToggle && $defaultToggle.jquery ) {
 +
// Exclude list-item containing togglelink
 +
$containers.not( $defaultToggle.parent() ).stop( true, true ).slideUp();
 +
} else {
 +
if ( instantHide ) {
 +
$containers.hide();
 +
} else {
 +
$containers.stop( true, true ).slideUp();
 +
}
 +
}
 +
 +
} else { // <div>, <p> etc.
 +
var $collapsibleContent = $collapsible.find( '> .mw-collapsible-content' );
 +
 +
// If a collapsible-content is defined, collapse it
 +
if ( $collapsibleContent.size() ) {
 +
if ( instantHide ) {
 +
$collapsibleContent.hide();
 +
} else {
 +
$collapsibleContent.slideUp();
 +
}
-
for ( var i = 0; i < Tables.length; i++ ) {
+
// Otherwise assume this is a customcollapse with a remote toggle
-
if ( hasClass( Tables[i], 'collapsible' ) ) {
+
// .. and there is no collapsible-content because the entire element should be toggled
-
/* only add button and increment count if there is a header row to work with */
+
} else {
-
var HeaderRow = Tables[i].getElementsByTagName( 'tr' )[0];
+
if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
-
if( !HeaderRow ) {
+
$collapsible.fadeOut();
-
continue;
+
} else {
-
}
+
$collapsible.slideUp();
-
var Header = HeaderRow.getElementsByTagName( 'th' )[0];
+
}
-
if( !Header ) {
+
}
-
continue;
+
}
-
}
+
-
NavigationBoxes[tableIndex] = Tables[i];
+
} else {
-
Tables[i].setAttribute( 'id', 'collapsibleTable' + tableIndex );
+
 +
// Expand the element
 +
if ( $collapsible.is( 'table' ) ) {
 +
$containers = $collapsible.find( '>tbody>tr' );
 +
if ( $defaultToggle && $defaultToggle.jquery ) {
 +
// Exclude tablerow containing togglelink
 +
$containers.not( $defaultToggle.parent().parent() ).stop(true, true).fadeIn();
 +
} else {
 +
$containers.stop(true, true).fadeIn();
 +
}
 +
 +
} else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
 +
$containers = $collapsible.find( '> li' );
 +
if ( $defaultToggle && $defaultToggle.jquery ) {
 +
// Exclude list-item containing togglelink
 +
$containers.not( $defaultToggle.parent() ).stop( true, true ).slideDown();
 +
} else {
 +
$containers.stop( true, true ).slideDown();
 +
}
 +
 +
} else { // <div>, <p> etc.
 +
var $collapsibleContent = $collapsible.find( '> .mw-collapsible-content' );
 +
 +
// If a collapsible-content is defined, collapse it
 +
if ( $collapsibleContent.size() ) {
 +
$collapsibleContent.slideDown();
-
var Button    = document.createElement( 'span' );
+
// Otherwise assume this is a customcollapse with a remote toggle
-
var ButtonLink = document.createElement( 'a' );
+
// .. and there is no collapsible-content because the entire element should be toggled
-
var ButtonText = document.createTextNode( collapseCaption );
+
} else {
 +
if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
 +
$collapsible.fadeIn();
 +
} else {
 +
$collapsible.slideDown();
 +
}
 +
}
 +
}
 +
}
 +
},
 +
// Toggles collapsible and togglelink class and updates text label
 +
toggleLinkDefault = function( that, e ) {
 +
var $that = $(that),
 +
$collapsible = $that.closest( '.mw-collapsible.mw-made-collapsible' ).toggleClass( 'mw-collapsed' );
 +
e.preventDefault();
 +
 +
// It's expanded right now
 +
if ( !$that.hasClass( 'mw-collapsible-toggle-collapsed' ) ) {
 +
// Change link to "Show"
 +
$that.removeClass( 'mw-collapsible-toggle-expanded' ).addClass( 'mw-collapsible-toggle-collapsed' );
 +
if ( $that.find( '> a' ).size() ) {
 +
$that.find( '> a' ).text( expandtext );
 +
} else {
 +
$that.text( expandtext );
 +
}
 +
// Collapse element
 +
toggleElement( $collapsible, 'collapse', $that );
-
Button.style.styleFloat = 'right';
+
// It's collapsed right now
-
Button.style.cssFloat = 'right';
+
} else {
-
Button.style.fontWeight = 'normal';
+
// Change link to "Hide"
-
Button.style.textAlign = 'right';
+
$that.removeClass( 'mw-collapsible-toggle-collapsed' ).addClass( 'mw-collapsible-toggle-expanded' );
-
Button.style.width = '6em';
+
if ( $that.find( '> a' ).size() ) {
 +
$that.find( '> a' ).text( collapsetext );
 +
} else {
 +
$that.text( collapsetext );
 +
}
 +
// Expand element
 +
toggleElement( $collapsible, 'expand', $that );
 +
}
 +
return;
 +
},
 +
// Toggles collapsible and togglelink class
 +
toggleLinkPremade = function( $that, e ) {
 +
var $collapsible = $that.eq(0).closest( '.mw-collapsible.mw-made-collapsible' ).toggleClass( 'mw-collapsed' );
 +
e.preventDefault();
 +
 +
// It's expanded right now
 +
if ( !$that.hasClass( 'mw-collapsible-toggle-collapsed' ) ) {
 +
// Change toggle to collapsed
 +
$that.removeClass( 'mw-collapsible-toggle-expanded' ).addClass( 'mw-collapsible-toggle-collapsed' );
 +
// Collapse element
 +
toggleElement( $collapsible, 'collapse', $that );
-
ButtonLink.style.color = Header.style.color;
+
// It's collapsed right now
-
ButtonLink.setAttribute( 'id', 'collapseButton' + tableIndex );
+
} else {
-
ButtonLink.setAttribute( 'href', "javascript:collapseTable(" + tableIndex + ");" );
+
// Change toggle to expanded
-
ButtonLink.appendChild( ButtonText );
+
$that.removeClass( 'mw-collapsible-toggle-collapsed' ).addClass( 'mw-collapsible-toggle-expanded' );
 +
// Expand element
 +
toggleElement( $collapsible, 'expand', $that );
 +
}
 +
return;
 +
},
 +
// Toggles customcollapsible
 +
toggleLinkCustom = function( $that, e, $collapsible ) {
 +
// For the initial state call of customtogglers there is no event passed
 +
if (e) {
 +
e.preventDefault();
 +
}
 +
// Get current state and toggle to the opposite
 +
var action = $collapsible.hasClass( 'mw-collapsed' ) ? 'expand' : 'collapse';
 +
$collapsible.toggleClass( 'mw-collapsed' );
 +
toggleElement( $collapsible, action, $that )
 +
 +
};
-
Button.appendChild( document.createTextNode( '[' ) );
+
// Use custom text or default ?
-
Button.appendChild( ButtonLink );
+
if( !collapsetext || collapsetext === '' ){
-
Button.appendChild( document.createTextNode( ']' ) );
+
collapsetext = mw.msg( 'collapsible-collapse', 'Collapse' );
-
 
+
-
Header.insertBefore( Button, Header.childNodes[0] );
+
-
tableIndex++;
+
}
}
-
    }
+
if ( !expandtext || expandtext === '' ){
-
 
+
expandtext = mw.msg( 'collapsible-expand', 'Expand' );
-
for ( var i = 0;  i < tableIndex; i++ ) {
+
-
if ( hasClass( NavigationBoxes[i], 'collapsed' ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[i], 'autocollapse' ) ) ) {
+
-
collapseTable( i );
+
}
}
-
}
 
-
}
 
-
addOnloadHook( createCollapseButtons );
+
// Create toggle link with a space around the brackets (&nbsp;[text]&nbsp;)
 +
var $toggleLink = $( '<a href="#"></a>' ).text( collapsetext ).wrap( '<span class="mw-collapsible-toggle"></span>' ).parent().prepend( '&nbsp;[' ).append( ']&nbsp;' ).bind( 'click.mw-collapse', function(e){
 +
toggleLinkDefault( this, e );
 +
} );
-
/** Dynamic Navigation Bars (experimental) *************************************
+
// Return if it has been enabled already.
-
*
+
if ( $that.hasClass( 'mw-made-collapsible' ) ) {
-
* From English Wikipedia, 2008-09-15
+
return;
-
*
+
} else {
-
*  Description: See [[Wikipedia:NavFrame]].
+
$that.addClass( 'mw-made-collapsible' );
-
*  Maintainers: UNMAINTAINED
+
-
*/
+
-
 
+
-
// set up the words in your language
+
-
var NavigationBarHide = '[' + collapseCaption + ']';
+
-
var NavigationBarShow = '[' + expandCaption + ']';
+
-
 
+
-
// shows and hides content and picture (if available) of navigation bars
+
-
// Parameters:
+
-
//    indexNavigationBar: the index of navigation bar to be toggled
+
-
function toggleNavigationBar( indexNavigationBar ) {
+
-
var NavToggle = document.getElementById( 'NavToggle' + indexNavigationBar );
+
-
var NavFrame = document.getElementById( 'NavFrame' + indexNavigationBar );
+
-
 
+
-
if( !NavFrame || !NavToggle ) {
+
-
return false;
+
-
}
+
-
 
+
-
// if shown now
+
-
if( NavToggle.firstChild.data == NavigationBarHide ) {
+
-
for( var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling ) {
+
-
if ( hasClass( NavChild, 'NavPic' ) ) {
+
-
NavChild.style.display = 'none';
+
-
}
+
-
if ( hasClass( NavChild, 'NavContent' ) ) {
+
-
NavChild.style.display = 'none';
+
-
}
+
}
}
-
NavToggle.firstChild.data = NavigationBarShow;
+
 +
// Check if this element has a custom position for the toggle link
 +
// (ie. outside the container or deeper inside the tree)
 +
// Then: Locate the custom toggle link(s) and bind them
 +
if ( $that.attr( 'id' ).indexOf( 'mw-customcollapsible-' ) === 0 ) {
-
// if hidden now
+
var thatId = $that.attr( 'id' ),
-
} else if( NavToggle.firstChild.data == NavigationBarShow ) {
+
$customTogglers = $( '.' + thatId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) );
-
for( var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling ) {
+
mw.log( 'Found custom collapsible: #' + thatId );
-
if( hasClass( NavChild, 'NavPic' ) ) {
+
-
NavChild.style.display = 'block';
+
// Double check that there is actually a customtoggle link
 +
if ( $customTogglers.size() ) {
 +
$customTogglers.bind( 'click.mw-collapse', function( e ) {
 +
toggleLinkCustom( $(this), e, $that );
 +
} );
 +
} else {
 +
mw.log( '#' + thatId + ': Missing toggler!' );
}
}
-
if( hasClass( NavChild, 'NavContent' ) ) {
+
-
NavChild.style.display = 'block';
+
// Initial state
 +
if ( $that.hasClass( 'mw-collapsed' ) ) {
 +
$that.removeClass( 'mw-collapsed' );
 +
toggleLinkCustom( $customTogglers, null, $that )
}
}
-
}
 
-
NavToggle.firstChild.data = NavigationBarHide;
 
-
}
 
-
}
 
-
// adds show/hide-button to navigation bars
+
// If this is not a custom case, do the default:
-
function createNavigationBarToggleButton() {
+
// Wrap the contents add the toggle link
-
var indexNavigationBar = 0;
+
} else {
-
// iterate over all < div >-elements
+
-
var divs = document.getElementsByTagName( 'div' );
+
-
for( var i = 0; NavFrame = divs[i]; i++ ) {
+
-
// if found a navigation bar
+
-
if( hasClass( NavFrame, 'NavFrame' ) ) {
+
-
indexNavigationBar++;
+
-
var NavToggle = document.createElement( 'a' );
+
-
NavToggle.className = 'NavToggle';
+
-
NavToggle.setAttribute( 'id', 'NavToggle' + indexNavigationBar );
+
-
NavToggle.setAttribute( 'href', 'javascript:toggleNavigationBar(' + indexNavigationBar + ');' );
+
-
var NavToggleText = document.createTextNode( NavigationBarHide );
+
// Elements are treated differently
-
for( var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling ) {
+
if ( $that.is( 'table' ) ) {
-
if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) {
+
// The toggle-link will be in one the the cells (td or th) of the first row
-
if( NavChild.style.display == 'none' ) {
+
var $firstRowCells = $( 'tr:first th, tr:first td', that ),
-
NavToggleText = document.createTextNode( NavigationBarShow );
+
$toggle = $firstRowCells.find( '> .mw-collapsible-toggle' );
-
break;
+
 +
// If theres no toggle link, add it to the last cell
 +
if ( !$toggle.size() ) {
 +
$firstRowCells.eq(-1).prepend( $toggleLink );
 +
} else {
 +
$toggleLink = $toggle.unbind( 'click.mw-collapse' ).bind( 'click.mw-collapse', function( e ){
 +
toggleLinkPremade( $toggle, e );
 +
} );
 +
}
 +
 +
} else if ( $that.is( 'ul' ) || $that.is( 'ol' ) ) {
 +
// The toggle-link will be in the first list-item
 +
var $firstItem = $( 'li:first', $that),
 +
$toggle = $firstItem.find( '> .mw-collapsible-toggle' );
 +
 +
// If theres no toggle link, add it
 +
if ( !$toggle.size() ) {
 +
// Make sure the numeral order doesn't get messed up, reset to 1 unless value-attribute is already used
 +
// WebKit return '' if no value, Mozilla returns '-1' is no value
 +
if ( $firstItem.attr( 'value' ) == '' || $firstItem.attr( 'value' ) == '-1' ) { // Will fail with ===
 +
$firstItem.attr( 'value', '1' );
}
}
 +
$that.prepend( $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent() );
 +
} else {
 +
$toggleLink = $toggle.unbind( 'click.mw-collapse' ).bind( 'click.mw-collapse', function( e ){
 +
toggleLinkPremade( $toggle, e );
 +
} );
}
}
-
}
+
-
 
+
} else { // <div>, <p> etc.
-
NavToggle.appendChild(NavToggleText);
+
// If a direct child .content-wrapper does not exists, create it
-
// Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
+
if ( !$that.find( '> .mw-collapsible-content' ).size() ) {
-
for( var j = 0; j < NavFrame.childNodes.length; j++) {
+
$that.wrapInner( '<div class="mw-collapsible-content"></div>' );
-
if( hasClass( NavFrame.childNodes[j], 'NavHead' ) ) {
+
}
-
NavFrame.childNodes[j].appendChild( NavToggle );
+
 +
// The toggle-link will be the first child of the element
 +
var $toggle = $that.find( '> .mw-collapsible-toggle' );
 +
 +
// If theres no toggle link, add it
 +
if ( !$toggle.size() ) {
 +
$that.prepend( $toggleLink );
 +
} else {
 +
$toggleLink = $toggle.unbind( 'click.mw-collapse' ).bind( 'click.mw-collapse', function( e ){
 +
toggleLinkPremade( $toggle, e );
 +
} );
}
}
}
}
-
NavFrame.setAttribute( 'id', 'NavFrame' + indexNavigationBar );
 
}
}
-
}
+
 
-
}
+
// Initial state (only for those that are not custom)
-
addOnloadHook( createNavigationBarToggleButton );
+
if ( $that.hasClass( 'mw-collapsed' ) && $that.attr( 'id' ).indexOf( 'mw-customcollapsible-' ) !== 0 ) {
 +
$that.removeClass( 'mw-collapsed' );
 +
// The collapsible element could have multiple togglers
 +
// To toggle the initial state only click one of them (ie. the first one, eq(0) )
 +
// Else it would go like: hide,show,hide,show for each toggle link.
 +
toggleElement( $that, 'collapse', $toggleLink.eq(0), /* instantHide = */ true );
 +
$toggleLink.eq(0).click();
 +
}
 +
} );
 +
};
 +
} )( jQuery, mediaWiki );
 +
 
 +
 
 +
 
 +
// Remove this file when it is deployed for real (and the import from Common.js)
 +
// The following four lines are not in the original module and are required since it is not deployed
 +
importStylesheet('MediaWiki:JQuery-makeCollapsible.css');mw.messages.set({"collapsible-collapse":"Collapse","collapsible-expand":"Expand"});
 +
$(document).ready(function(){
 +
$('.mw-collapsible').makeCollapsible();
 +
});

Версия 18:50, 1 апреля 2011

// Documentation/Examples: [[RL/DM#jQuery.makeCollapsible]]
// See also [[MediaWiki:JQuery-makeCollapsible.css]]
/* http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/resources/jquery/jquery.makeCollapsible.js?revision=83309&view=markup */

/**
 * jQuery makeCollapsible
 *
 * This will enable collapsible-functionality on all passed elements.
 * Will prevent binding twice to the same element.
 * Initial state is expanded by default, this can be overriden by adding class
 * "mw-collapsed" to the "mw-collapsible" element.
 * Elements made collapsible have class "mw-made-collapsible".
 * Except for tables and lists, the inner content is wrapped in "mw-collapsible-content".
 *
 * @author Krinkle <krinklemail@gmail.com>
 *
 * Dual license:
 * @license CC-BY 3.0 <http://creativecommons.org/licenses/by/3.0>
 * @license GPL2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
 */
( function( $, mw ) {

$.fn.makeCollapsible = function() {

	return this.each(function() {
		mw.config.set( 'mw.log.prefix', 'jquery.makeCollapsible' );

		// Define reused variables and functions
		var	$that = $(this).addClass( 'mw-collapsible' ), // case: $( '#myAJAXelement' ).makeCollapsible()
			that = this,
			collapsetext = $(this).attr( 'data-collapsetext' ),
			expandtext = $(this).attr( 'data-expandtext' ),
			toggleElement = function( $collapsible, action, $defaultToggle, instantHide ) {
				// Validate parameters
				if ( !$collapsible.jquery ) { // $collapsible must be an instance of jQuery
					return;
				}
				if ( action != 'expand' && action != 'collapse' ) {
					// action must be string with 'expand' or 'collapse'
					return;
				}
				if ( typeof $defaultToggle !== 'undefined' && !($defaultToggle instanceof jQuery) ) {
					// is optional (may be undefined), but if passed it must be an instance of jQuery and nothing else
					return;
				}
				var $containers = null;

				if ( action == 'collapse' ) {

					// Collapse the element
					if ( $collapsible.is( 'table' ) ) {
						// Hide all table rows of this table
						// Slide doens't work with tables, but fade does as of jQuery 1.1.3
						// http://stackoverflow.com/questions/467336#920480
						$containers = $collapsible.find( '>tbody>tr' );
						if ( typeof $defaultToggle !== 'undefined' && ($defaultToggle instanceof jQuery) ) { 
							// Exclude tablerow containing togglelink
							$containers.not( $defaultToggle.closest( 'tr' ) ).stop(true, true).fadeOut();
						} else {
							if ( instantHide ) {	
								$containers.hide();
							} else {
								$containers.stop( true, true ).fadeOut();
							}
						}
	
					} else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
						$containers = $collapsible.find( '> li' );
						if ( $defaultToggle && $defaultToggle.jquery ) {
							// Exclude list-item containing togglelink
							$containers.not( $defaultToggle.parent() ).stop( true, true ).slideUp();
						} else {
							if ( instantHide ) {
								$containers.hide();
							} else {
								$containers.stop( true, true ).slideUp();
							}
						}
	
					} else { // <div>, <p> etc.
						var $collapsibleContent = $collapsible.find( '> .mw-collapsible-content' );
						
						// If a collapsible-content is defined, collapse it
						if ( $collapsibleContent.size() ) {
							if ( instantHide ) {
								$collapsibleContent.hide();
							} else {
								$collapsibleContent.slideUp();
							}

						// Otherwise assume this is a customcollapse with a remote toggle
						// .. and there is no collapsible-content because the entire element should be toggled
						} else {
							if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
								$collapsible.fadeOut();
							} else {
								$collapsible.slideUp();
							}
						}
					}

				} else {
				
					// Expand the element
					if ( $collapsible.is( 'table' ) ) {
						$containers = $collapsible.find( '>tbody>tr' );
						if ( $defaultToggle && $defaultToggle.jquery ) {
							// Exclude tablerow containing togglelink
							$containers.not( $defaultToggle.parent().parent() ).stop(true, true).fadeIn();
						} else {
							$containers.stop(true, true).fadeIn();
						}
	
					} else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
						$containers = $collapsible.find( '> li' );
						if ( $defaultToggle && $defaultToggle.jquery ) {
							// Exclude list-item containing togglelink
							$containers.not( $defaultToggle.parent() ).stop( true, true ).slideDown();
						} else {
							$containers.stop( true, true ).slideDown();
						}
	
					} else { // <div>, <p> etc.
						var $collapsibleContent = $collapsible.find( '> .mw-collapsible-content' );
						
						// If a collapsible-content is defined, collapse it
						if ( $collapsibleContent.size() ) {
							$collapsibleContent.slideDown();

						// Otherwise assume this is a customcollapse with a remote toggle
						// .. and there is no collapsible-content because the entire element should be toggled
						} else {
							if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
								$collapsible.fadeIn();
							} else {
								$collapsible.slideDown();
							}
						}
					}
				}
			},
			// Toggles collapsible and togglelink class and updates text label
			toggleLinkDefault = function( that, e ) {
				var	$that = $(that),
					$collapsible = $that.closest( '.mw-collapsible.mw-made-collapsible' ).toggleClass( 'mw-collapsed' );
				e.preventDefault();
				
				// It's expanded right now
				if ( !$that.hasClass( 'mw-collapsible-toggle-collapsed' ) ) {
					// Change link to "Show"
					$that.removeClass( 'mw-collapsible-toggle-expanded' ).addClass( 'mw-collapsible-toggle-collapsed' );
					if ( $that.find( '> a' ).size() ) {
						$that.find( '> a' ).text( expandtext );
					} else {
						$that.text( expandtext );
					}
					// Collapse element
					toggleElement( $collapsible, 'collapse', $that );

				// It's collapsed right now
				} else {
					// Change link to "Hide"
					$that.removeClass( 'mw-collapsible-toggle-collapsed' ).addClass( 'mw-collapsible-toggle-expanded' );
					if ( $that.find( '> a' ).size() ) {
						$that.find( '> a' ).text( collapsetext );
					} else {
						$that.text( collapsetext );
					}
					// Expand element
					toggleElement( $collapsible, 'expand', $that );
				}
				return;
			},
			// Toggles collapsible and togglelink class
			toggleLinkPremade = function( $that, e ) {
				var	$collapsible = $that.eq(0).closest( '.mw-collapsible.mw-made-collapsible' ).toggleClass( 'mw-collapsed' );
				e.preventDefault();
				
				// It's expanded right now
				if ( !$that.hasClass( 'mw-collapsible-toggle-collapsed' ) ) {
					// Change toggle to collapsed
					$that.removeClass( 'mw-collapsible-toggle-expanded' ).addClass( 'mw-collapsible-toggle-collapsed' );
					// Collapse element
					toggleElement( $collapsible, 'collapse', $that );

				// It's collapsed right now
				} else {
					// Change toggle to expanded
					$that.removeClass( 'mw-collapsible-toggle-collapsed' ).addClass( 'mw-collapsible-toggle-expanded' );
					// Expand element
					toggleElement( $collapsible, 'expand', $that );
				}
				return;
			},
			// Toggles customcollapsible
			toggleLinkCustom = function( $that, e, $collapsible ) {
				// For the initial state call of customtogglers there is no event passed
				if (e) {
					e.preventDefault();
				}
				// Get current state and toggle to the opposite
				var action = $collapsible.hasClass( 'mw-collapsed' ) ? 'expand' : 'collapse';
				$collapsible.toggleClass( 'mw-collapsed' );
				toggleElement( $collapsible, action, $that )
				
			};

		// Use custom text or default ?
		if( !collapsetext || collapsetext === '' ){
			collapsetext = mw.msg( 'collapsible-collapse', 'Collapse' );
		}
		if ( !expandtext || expandtext === '' ){
			expandtext = mw.msg( 'collapsible-expand', 'Expand' );
		}

		// Create toggle link with a space around the brackets (&nbsp;[text]&nbsp;)
		var $toggleLink = $( '<a href="#"></a>' ).text( collapsetext ).wrap( '<span class="mw-collapsible-toggle"></span>' ).parent().prepend( '&nbsp;[' ).append( ']&nbsp;' ).bind( 'click.mw-collapse', function(e){
			toggleLinkDefault( this, e );
		} );

		// Return if it has been enabled already.
		if ( $that.hasClass( 'mw-made-collapsible' ) ) {
			return;
		} else {
			$that.addClass( 'mw-made-collapsible' );
		}
		
		// Check if this element has a custom position for the toggle link
		// (ie. outside the container or deeper inside the tree)
		// Then: Locate the custom toggle link(s) and bind them
		if ( $that.attr( 'id' ).indexOf( 'mw-customcollapsible-' ) === 0 ) {

			var thatId = $that.attr( 'id' ),
				$customTogglers = $( '.' + thatId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) );
			mw.log( 'Found custom collapsible: #' + thatId );
						
			// Double check that there is actually a customtoggle link
			if ( $customTogglers.size() ) {
				$customTogglers.bind( 'click.mw-collapse', function( e ) {
					toggleLinkCustom( $(this), e, $that );
				} );
			} else {
				mw.log( '#' + thatId + ': Missing toggler!' );
			}
			
			// Initial state
			if ( $that.hasClass( 'mw-collapsed' ) ) {
				$that.removeClass( 'mw-collapsed' );
				toggleLinkCustom( $customTogglers, null, $that )
			}

		// If this is not a custom case, do the default:
		// Wrap the contents add the toggle link 
		} else {

			// Elements are treated differently
			if ( $that.is( 'table' ) ) {
				// The toggle-link will be in one the the cells (td or th) of the first row
				var	$firstRowCells = $( 'tr:first th, tr:first td', that ),
					$toggle = $firstRowCells.find( '> .mw-collapsible-toggle' );
	
				// If theres no toggle link, add it to the last cell
				if ( !$toggle.size() ) {
					$firstRowCells.eq(-1).prepend( $toggleLink );
				} else {
					$toggleLink = $toggle.unbind( 'click.mw-collapse' ).bind( 'click.mw-collapse', function( e ){
						toggleLinkPremade( $toggle, e );
					} );
				}
				
			} else if ( $that.is( 'ul' ) || $that.is( 'ol' ) ) {
				// The toggle-link will be in the first list-item
				var	$firstItem = $( 'li:first', $that),
					$toggle = $firstItem.find( '> .mw-collapsible-toggle' );
	
				// If theres no toggle link, add it
				if ( !$toggle.size() ) {
					// Make sure the numeral order doesn't get messed up, reset to 1 unless value-attribute is already used
					// WebKit return '' if no value, Mozilla returns '-1' is no value
					if ( $firstItem.attr( 'value' ) == '' || $firstItem.attr( 'value' ) == '-1' ) { // Will fail with ===
						$firstItem.attr( 'value', '1' );
					}
					$that.prepend( $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent() );
				} else {
					$toggleLink = $toggle.unbind( 'click.mw-collapse' ).bind( 'click.mw-collapse', function( e ){
						toggleLinkPremade( $toggle, e );
					} );
				}
	
			} else { // <div>, <p> etc.
				// If a direct child .content-wrapper does not exists, create it
				if ( !$that.find( '> .mw-collapsible-content' ).size() ) {
					$that.wrapInner( '<div class="mw-collapsible-content"></div>' );
				}
	
				// The toggle-link will be the first child of the element
				var $toggle = $that.find( '> .mw-collapsible-toggle' );
	
				// If theres no toggle link, add it
				if ( !$toggle.size() ) {
					$that.prepend( $toggleLink );
				} else {
					$toggleLink = $toggle.unbind( 'click.mw-collapse' ).bind( 'click.mw-collapse', function( e ){
						toggleLinkPremade( $toggle, e );
					} );
				}
			}
		}

		// Initial state (only for those that are not custom)
		if ( $that.hasClass( 'mw-collapsed' ) && $that.attr( 'id' ).indexOf( 'mw-customcollapsible-' ) !== 0 ) {
			$that.removeClass( 'mw-collapsed' );
			// The collapsible element could have multiple togglers
			// To toggle the initial state only click one of them (ie. the first one, eq(0) )
			// Else it would go like: hide,show,hide,show for each toggle link.
			toggleElement( $that, 'collapse', $toggleLink.eq(0), /* instantHide = */ true );
			$toggleLink.eq(0).click();
		}
	} );
};
} )( jQuery, mediaWiki );



// Remove this file when it is deployed for real (and the import from Common.js)
// The following four lines are not in the original module and are required since it is not deployed
importStylesheet('MediaWiki:JQuery-makeCollapsible.css');mw.messages.set({"collapsible-collapse":"Collapse","collapsible-expand":"Expand"});
$(document).ready(function(){
 $('.mw-collapsible').makeCollapsible();
});
Личные инструменты