MediaWiki:Common.js

提供:Noita Wiki
ナビゲーションに移動 検索に移動

他言語版: English


CSS and Javascript changes must comply with the wiki design rules.


Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
/* Any JavaScript here will be loaded for all users on every page load. */

$(function() {
	// MW content hooks
	// These will be run every time the MW parser adds content to a page, which occurs
	// on page load, as well as when reloading parts of the page for using the
	// "Preview content without reloading" in the editor.

	var matches = document.querySelectorAll("div.spoiler-content, div.spoiler-hidden a");
	var matchesplus = document.querySelectorAll("span.spoiler-content, span.spoiler-hidden a");
	// Erase all the hyperlinks when the page loads, includes inline spoilers
	var links = new Array(matches.length+matchesplus.length);
	// Labeling them for giving back them the links in the future
	var i = 0;
	for (var k1 = 0; k1 < matches.length ; k1 ++) {
		if (matches[k1]) {
			if (matches[k1].hasAttribute('href')) {
				matches[k1].setAttribute('idforlink', i);
				links[i] = matches[k1].getAttribute('href');
				matches[k1].removeAttribute('href');
				i = i + 1;
			}
		}
	}
	for (k1 = 0; k1 < matchesplus.length ; k1 ++) {
		if (matchesplus[k1]) {
			if (matchesplus[k1].hasAttribute('href')) {
				matchesplus[k1].setAttribute('idforlink', i);
				links[i] = matchesplus[k1].getAttribute('href');
				matchesplus[k1].removeAttribute('href');
				i = i + 1;
			}
		}
	}
	// Saves all the hyperlinks to the array
	
	// synopsis: Add/remove functions to handle spoiler toggles for [[Template:Spoiler]] / [[Template:Spoiler/start]]
	mw.hook('wikipage.content').add(function ($content) {
	    var excludedElements = ['VIDEO', 'A'];
	
	    $content.on('click', '.spoiler-toggle', function (event) {
	        var clickedElement = event.target;
	
	        if (excludedElements.includes(clickedElement.tagName)) {
	            return;
	        }
	
	        var spoiler = event.currentTarget;
	        var content = $(spoiler).find('.spoiler-content');
	
	        if (content) {
	            if (content.hasClass('spoiler-hidden')) {
	                content.removeClass('spoiler-hidden');
	
	                // Restore hyperlinks
	                content.find('p > a, a').each(function () {
	                    var idForLink = $(this).attr('idforlink');
	                    if (idForLink !== undefined) {
	                        $(this).attr('href', links[idForLink]);
	                    }
	                });
	            } else {
	                content.addClass('spoiler-hidden');
	
	                // Remove hyperlinks
	                content.find('p > a, a').removeAttr('href');
	            }
	        }
	});
	    $content.on('click', '.spoiler-content a', function (event) {
        	var content = $(this).closest('.spoiler-content');
	        if (content.hasClass('spoiler-hidden')) {
	            // Conditionally prevent default behavior based on your criteria
	            event.preventDefault();
	        if (content) {
	            if (content.hasClass('spoiler-hidden')) {
	                content.removeClass('spoiler-hidden');
	
	                // Restore hyperlinks
	                content.find('p > a, a').each(function () {
	                    var idForLink = $(this).attr('idforlink');
	                    if (idForLink !== undefined) {
	                        $(this).attr('href', links[idForLink]);
	                    }
	                });
	            } else {
	                content.addClass('spoiler-hidden');
	
	                // Remove hyperlinks
	                content.find('p > a, a').removeAttr('href');
	            }
	        }
	        }
	    });
	    $content.on('touchend', '.spoiler-toggle', function (event) {
	        if($(this).data('moved') == 0){
	        	var clickedElement = event.target;
	
	        if (excludedElements.includes(clickedElement.tagName)) {
	            return;
	        }
	
	        var spoiler = event.currentTarget;
	        var content = $(spoiler).find('.spoiler-content');
	
	        if (content) {
	            if (content.hasClass('spoiler-hidden')) {
	                content.removeClass('spoiler-hidden');
	
	                // Restore hyperlinks
	                content.find('p > a, a').each(function () {
	                    var idForLink = $(this).attr('idforlink');
	                    if (idForLink !== undefined) {
	                        $(this).attr('href', links[idForLink]);
	                    }
	                });
	            } else {
	                content.addClass('spoiler-hidden');
	
	                // Remove hyperlinks
	                content.find('p > a, a').removeAttr('href');
	            }
	        }
		}
	});
	    $content.on('touchend', '.spoiler-content a', function (event) {
	        if($(this).data('moved') == 0){
	        	var content = $(this).closest('.spoiler-content');
		        if (content.hasClass('spoiler-hidden')) {
			            // Conditionally prevent default behavior based on your criteria
			            event.preventDefault();
			        if (content) {
			            if (content.hasClass('spoiler-hidden')) {
			                content.removeClass('spoiler-hidden');
			
			                // Restore hyperlinks
			                content.find('p > a, a').each(function () {
			                    var idForLink = $(this).attr('idforlink');
			                    if (idForLink !== undefined) {
			                        $(this).attr('href', links[idForLink]);
			                    }
			                });
			            } else {
			                content.addClass('spoiler-hidden');
			
			                // Remove hyperlinks
			                content.find('p > a, a').removeAttr('href');
			            }
			        }
		        }
	        }
	    });
	});

	
	
	// synopsis: Functionality for [[Template:Hover gif]]
	mw.hook('wikipage.content').add(function($content) {
		$content.find(".hover-gif img").each(function(i, obj) {
		  var $canvas = $("<canvas width='" + $(obj).attr("width") + "' height='" + $(obj).attr("height") + "'></canvas>");
		  $(obj).parent().append($canvas);
		  var ctx = $canvas[0].getContext("2d");
		  var img = new Image();
		  img.onload = function() {
		    ctx.drawImage(img, 0, 0);
		  };
		  img.src = obj.src;
		});
	});
	
	// synopsis: show a random item from [[Template:Choose]]
	mw.hook('wikipage.content').add(function($content) {
		$content.find('.choose-random').each(function(i, obj) {
			var options = $(obj).children();
			var item = options[Math.floor(Math.random()*options.length)];
			item.classList.add('selected');
		});
	});
	
	// synopsis: attach an onclick handler to "listen" links for pronunciation templates
	// in order to have them play the related hidden audio clips
	mw.hook('wikipage.content').add(function($content) {
		var links = $content.find('.pronunciation a');
		links.click(function() {
		    var player = $(this).parent().find('audio').get(0);
		    if (player) {
		        player.currentTime = 0;
		        player.play();
		    }
		    
		    return false;
		});
	});
});

// synopsis: make the sidebar headers clickable to collapse the sidebar section
$(function(){
	$panel = $('#mw-panel');
	$("#mw-panel .portal").each(function(index, element){
		var $element = $(element);
		var $id = $element.attr("id");
		
		if (!$id) {
			return;
		}
		
		if (localStorage.getItem('sidebar_c_'+$id) === "y") {
			$element.addClass('collapsed').find('.body').slideUp(0);
			$element.find('.vector-menu-heading').addClass('noborder');
		}
	});
	
	$("#mw-panel .portal").on("click", "h3", function(event) {
		var $element = $(this).parent();
		var $id = $element.attr("id");
		
		if (!$id) {
			return;
		}
		
		event.stopPropagation();

		$element.toggleClass('collapsed');
		if ($element.hasClass('collapsed')) {
			localStorage.setItem('sidebar_c_'+$id, "y");
			$element.find('.body').slideUp('fast', function() {
				$element.find('.vector-menu-heading').addClass('noborder');
			});
		}
		else {
			localStorage.setItem('sidebar_c_'+$id, "n");
			$element.find('.body').slideDown('fast');
			$element.find('.vector-menu-heading').removeClass('noborder');
		}
	});
});


///* Tabs-Script-Start */
$(function() {
  /*  Tabs Script by Y&#x1F375
      Minimal example HTML:
      //  <.tabs-container>
      //    <.tabs-btn.tabs-id-1>ButtonText1</.tabs-btn.tabs-id-1>
      //    <.tabs-btn.tabs-id-2>ButtonText2</.tabs-btn.tabs-id-2>
      //    <.tabs-btn.tabs-tcmp>SpecialTabKeyForRowComparisonSupport</.tabs-btn.tabs-tcmp>
      //    <.tabs-group>
      //      <.tabs-tab.tabs-id-1><.tabs-v>prefix<.tabs-c>Content1</.tabs-c></.tabs-v></.tabs-tab.tabs-id-1>
      //      <.tabs-tab.tabs-id-2><.tabs-v><.tabs-c>Content2</.tabs-c>suffix</.tabs-v></.tabs-tab.tabs-id-2>
      //    </.tabs-group>
      //  </.tabs-container>
      Any DOM element can be used so long as the classes are set correctly. Tab nesting unsupported.
      None of the classes have to be direct children, all descendant are found by the script so
      long as they are within the corrent tags (meaning you can for example put all the `tabs.btn`
      elements inside a parent div to make it look neater, which you absolutely should do).
  */
  // Helper functions
  function isEmpty( any ){ return ( any==null || any=="" ); }
  function arrFilterTokenList( arr, list, filter ){
    if( !(Array.isArray(arr)) ) arr = [];
    list.forEach( function( item ){
      if( item.startsWith( filter ) && arr.indexOf(item) === -1 ) arr.push(item); });
    return arr; }
  function forQuerySelectorIn( parent, query, func ){
    var table = parent.querySelectorAll( query );
    if( isEmpty(table) ) return null; [].forEach.call( table, func ); return 1; }
  function classListAdr( list, classname, state ){
    if( state ) list.add(classname); else list.remove(classname); return state; }
  // Main function
  function ytabs_handler( ctn, btn, btnCls ){
    if( btn.target ) btn = btn.currentTarget; // btn should be element, check event just in case
    if( isEmpty(btn) || isEmpty(ctn) ) return;
    var bCL = btn.classList, cCL = ctn.classList;
    var cmpbtn = bCL.contains("tabs-tcmp"), cmpmode = cCL.contains("tabs-multi");
    if( cmpbtn && classListAdr( bCL, "tabs-active", (cmpmode = cCL.toggle("tabs-multi")) ) ) return;
    var btn_on = bCL.contains("tabs-active");
    if( cmpmode ){ classListAdr( bCL, "tabs-active", !(btn_on) ); }
    else{ var tmpCls = arrFilterTokenList( [], cCL, "tabs-id-" ); // 0 container tabs-id classes
      if( !(isEmpty(tmpCls)) ){ if( btn_on ) return;// btn already active in normal mode
        tmpCls.forEach( function( item ){ cCL.remove(item); });
      }
      forQuerySelectorIn( ctn, ".tabs-active", function( btn_on ){ // 0 all btn highlights
        classListAdr( btn_on.classList, "tabs-active", false );
        if( isEmpty(btnCls) && cmpbtn ){ // if no id (cmp btn), use first btn
          bCL = btn_on.classList; btnCls = arrFilterTokenList( [], bCL, "tabs-id-" ); }
      });
    }
    if( !(cmpmode) ) classListAdr( bCL, "tabs-active", true );
    btnCls.forEach( function( item ){ if( cmpmode ) cCL.toggle(item); else cCL.add(item); });
    var ctnCls = arrFilterTokenList( [], cCL, "tabs-id-" ); // gotta get the updated tabs
    forQuerySelectorIn( ctn, ".tabs-group", function( group ){
      var tabs_filled = 0;
      forQuerySelectorIn( group, ".tabs-tab", function( tab ){
        var tabCls = arrFilterTokenList( [], tab.classList, "tabs-id-" );
        tabCls.forEach( function( item_tab ) { //tabs have to come first
          var tab_show = 0;
          ctnCls.forEach( function( item_ctn ) { // if ctn has tab id, show
            if( item_ctn === item_tab ){ tab_show = 1; return; }
          });
          if( tab_show ){
            if( tab.innerHTML !== "" ) tabs_filled += 1;
            tab.style.display = "";
          }
          else {
            tab.style.display = "none";
          }
        });
      });
      group.style.display = ((tabs_filled == 0)?("none"):(""));
    });
  } // Create buttons, save some values as variables in the function
  forQuerySelectorIn( document, ".tabs-container", function( ctn ){
    var tabs_openFirst = null;
    var anchor_id = window.location.hash.substring(1);
    forQuerySelectorIn( ctn, ".tabs-btn", function( btn ){
      var btnCls = arrFilterTokenList( [], btn.classList, "tabs-id-" );
      btn.addEventListener( "click", function(){
        ytabs_handler( ctn, btn, btnCls );
      });
      if( anchor_id !== "" && anchor_id === btn.id )
        tabs_openFirst = function(){ ytabs_handler( ctn, btn, btnCls ); };
      if( isEmpty( tabs_openFirst ) )
        tabs_openFirst = function(){ ytabs_handler( ctn, btn, btnCls ); };
    });
    tabs_openFirst();
  });
});
///* Tabs-Script-End */