মিডিয়াউইকি:Gadget-defaultVisibilityToggles.js

উইকিঅভিধান, মুক্ত অভিধান থেকে

লক্ষ্য করুন: প্রকাশ করার পর, পরিবর্তনগুলো দেখতে আপনাকে আপনার ব্রাউজারের ক্যাশে পরিষ্কার করার প্রয়োজন হতে পারে।

  • ফায়ারফক্স / সাফারি: পুনরায় লোড-এ ক্লিক করার সময় শিফট টিপে ধরে রাখুন, অথবা হয় Ctrl-F5 বা Ctrl-R টিপুন (ম্যাকে ⌘-R টিপুন)
  • গুগল ক্রোম: Ctrl-Shift-R (ম্যাকে ⌘-Shift-R) টিপুন
  • ইন্টারনেট এক্সপ্লোরার / এজ: Ctrl ধরে রাখা অবস্থায় Refresh-এ ক্লিক করুন, অথবা Ctrl-F5 টিপুন
  • অপেরা: Ctrl-F5 টিপুন।
"use strict";

/* jshint undef: true, esversion: 5 */
/* globals $, jQuery, mw, window */

(function defaultVisibilityTogglesIIFE() {
	"use strict";

	if (window.noDefaultVisibilityToggles) return;

	/* == NavBars == */
	var NavigationBarHide = "লুকান ▲";
	var NavigationBarShow = "দেখান ▼";

	// Check if an element has been activated with a toggle.
	// For convenience, this has the side effect of marking the element as having
	// a toggle, if it is not already marked.
	// Allows the functions to avoid toggleifying elements more than once, which
	// can lead to multiple "show" buttons, for instance.
	// The argument must be an Element, not a jQuery object.
	function checkAndSetToggleified(element) {
		if (element.isToggleified) {
			return true;
		}
		element.isToggleified = true;
	}

	function getToggleCategory(element, defaultCategory) {
		if ($(element).find("table").first().is(".translations")) return "translations";

		var heading = element;
		while (heading = heading.previousElementSibling) {
			// tagName is always uppercase:
			// https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName
			var num = heading.tagName.match(/H(\d)/);
			if (num) num = Number(num[1]);else continue;
			if (4 <= num && num <= 6) {
				if (heading.getElementsByTagName("span")[1]) heading = heading.getElementsByTagName("span")[0];
				var text = jQuery(heading).text().toLowerCase()
				// jQuery's .text() is inconsistent about whitespace:
				.replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ")
				// remove numbers added by the "Auto-number headings" pref:
				.replace(/^[1-9][0-9.]+ ?/, "");
				// Toggle category must be convertible to a valid CSS identifier so
				// that it can be used in an id selector in jQuery in
				// ToggleCategory.prototype.newSidebarToggle
				// in [[MediaWiki:Gadget-VisibilityToggles.js]].
				// Spaces must later be converted to hyphens or underscores.
				// Reference: https://drafts.csswg.org/selectors-4/#id-selectors
				if (/^[a-zA-Z0-9\s_-]+$/.test(text)) return text;else break;
			} else if (num) break;
		}

		return defaultCategory;
	}

	function createNavToggle(navFrame) {
		if (checkAndSetToggleified(navFrame)) {
			return;
		}

		var navHead, navContent;
		for (var i = 0, children = navFrame.childNodes; i < children.length; ++i) {
			var child = children[i];
			if (child.nodeName === "DIV") {
				var classList = child.classList;
				if (classList.contains("NavHead")) navHead = child;
				if (classList.contains("NavContent")) navContent = child;
			}
		}
		if (!(navHead && navContent)) return;

		// Step 1, don't react when a subitem is clicked.
		$(navHead).find("a").on("click", function (e) {
			e.stopPropagation();
		});

		// Step 2, toggle visibility when bar is clicked.
		// NOTE This function was chosen due to some funny behaviour in Safari.
		var $navToggle = $("<a>").attr("role", "button").attr("tabindex", "0");

		$("<span>").addClass("NavToggle").append($navToggle).prependTo(navHead);

		navHead.style.cursor = "pointer";
		var toggleCategory = $(navFrame).data("toggle-category") || getToggleCategory(navFrame, "other boxes");
		navHead.onclick = window.VisibilityToggles.register(toggleCategory, function show() {
			$navToggle.html(NavigationBarHide);
			if (navContent) navContent.style.display = "block";
		}, function hide() {
			$navToggle.html(NavigationBarShow);
			if (navContent) navContent.style.display = "none";
		});
	}

	/* ==Hidden Quotes== */
	function setupHiddenQuotes(li) {
		if (checkAndSetToggleified(li)) {
			return;
		}

		var HQToggle, liComp, dl;
		var HQShow = "উদ্ধৃতিসমূহ ▼";
		var HQHide = "উদ্ধৃতিসমূহ ▲";
		function show() {
			HQToggle.html(HQHide);
			$(li).children("ul").show();
		}
		function hide() {
			HQToggle.html(HQShow);
			$(li).children("ul").hide();
		}

		for (var k = 0; k < li.childNodes.length; k++) {
			// Look at each component of the definition.
			liComp = li.childNodes[k];
			if (liComp.nodeName.toLowerCase() === "dl" && !dl) {
				dl = liComp;
			}
			// If we find a ul or dl, we have quotes or example sentences, and thus need a button.
			if (/^(ul|UL)$/.test(liComp.nodeName)) {
				HQToggle = $("<a>").attr("role", "button").attr("tabindex", "0");
				$(dl || liComp).before($("<span>").addClass("HQToggle").append(HQToggle));
				HQToggle.on("click", window.VisibilityToggles.register("উদ্ধতি", show, hide));
				break;
			}
		}
	}

	/* == View Switching == */

	function viewSwitching(rootElement) {
		if (checkAndSetToggleified(rootElement)) {
			return;
		}

		var $rootElement = $(rootElement);
		var showButtonText = $rootElement.data("vs-showtext") || "অধিক ▼";
		var hideButtonText = $rootElement.data("vs-hidetext") || "ন্যূন ▲";

		var toSkip = $rootElement.find(".vsSwitcher").find("*");
		var elemsToHide = $rootElement.find(".vsHide").not(toSkip);
		var elemsToShow = $rootElement.find(".vsShow").not(toSkip);

		// Find the element to place the toggle button in.
		var toggleElement = $rootElement.find(".vsToggleElement").not(toSkip).first();

		// The toggleElement becomes clickable in its entirety, but
		// we need to prevent this if a contained link is clicked instead.
		toggleElement.children("a").on("click", function (e) {
			e.stopPropagation();
		});

		// Add the toggle button.
		var toggleButton = $("<a>").attr("role", "button").attr("tabindex", "0");

		$("<span>").addClass("NavToggle").append(toggleButton).prependTo(toggleElement);

		// Determine the visibility toggle category (for the links in the bar on the left).
		var toggleCategory = $rootElement.data("toggle-category");
		if (!toggleCategory) {
			var classNames = $rootElement.attr("class").split(/\s+/);

			for (var i = 0; i < classNames.length; ++i) {
				var className = classNames[i].split("-");

				if (className[0] == "vsToggleCategory") {
					toggleCategory = className[1];
				}
			}
		}

		if (!toggleCategory) toggleCategory = "others";

		// Register the visibility toggle.
		toggleElement.css("cursor", "pointer");
		toggleElement.on("click", window.VisibilityToggles.register(toggleCategory, function show() {
			toggleButton.html(hideButtonText);
			elemsToShow.hide();
			elemsToHide.show();
		}, function hide() {
			toggleButton.html(showButtonText);
			elemsToShow.show();
			elemsToHide.hide();
		}));
	}

	/* ==List switching== */
	// Number of rows of list items to show in the hidden state of a "list switcher" list.
	// Customize by adding
	// window.listSwitcherCount = <your preferred number of rows>;
	// to your common.js before loading this script.
	window.listSwitcherRowCount = window.listSwitcherRowCount || 3;

	function getListItemsToHide($listItems, columnCount, rowsInShowState) {
		var count = $listItems.length;
		var itemsPerColumn = Math.ceil(count / columnCount);

		var $elemsToHide = $();
		if (itemsPerColumn > rowsInShowState) {
			for (var i = 0; i < columnCount; ++i) {
				var columnStart = i * itemsPerColumn;
				$elemsToHide = $elemsToHide.add($listItems.slice(columnStart + rowsInShowState, columnStart + itemsPerColumn));
			}
		}

		return $elemsToHide;
	}

	function enableListSwitch(rootElement, rowsInShowState) {
		if (checkAndSetToggleified(rootElement)) {
			return;
		}

		var $rootElement = $(rootElement);
		// Number of columns must be set in data-term-list-column-count attribute
		// of the element with class term-list.
		var $termList = $rootElement.find(".term-list");

		// Find the element to place the toggle button in.
		var $toggleElement = $rootElement.find(".list-switcher-element");

		var columnCount = parseInt($termList.data("column-count"), 10);
		if (!(columnCount && columnCount > 0)) {
			$toggleElement.hide();
			return;
		}

		var $listItems = $rootElement.find("ul").first().find("li");
		var $toHide = getListItemsToHide($listItems, columnCount, rowsInShowState);

		// Don't do anything if there aren't any items to hide.
		if ($toHide.length === 0) {
			$toggleElement.hide();
			return;
		}

		$toggleElement.css("cursor", "pointer");

		// Add the toggle button.
		var $toggleButton = $("<a>").attr("role", "button").attr("tabindex", "0");

		var rootBackgroundColor = $termList.css("background-color"),
		    rootBackground = $termList.css("background");
		var $navToggle = $("<span>").addClass("NavToggle");
		if (rootBackgroundColor || rootBackground) $navToggle.css(rootBackgroundColor ? "background-color" : "background", rootBackgroundColor || rootBackground);

		// The $toggleElement becomes clickable in its entirety, but
		// we need to prevent this if a contained link is clicked instead.
		$toggleElement.children("a").on("click", function (e) {
			e.stopPropagation();
		});

		// Determine the visibility toggle category (for the links in the bar on the
		// left). It will either be the value of the "data-toggle-category"
		// attribute or will be based on the text of the closest preceding
		// fourth-to-sixth-level header.
		var toggleCategory = $rootElement.data("toggle-category") || getToggleCategory($rootElement[0], "other lists");

		// Determine the text for the $toggleButton.
		var showButtonText = $toggleElement.data("showtext") || "অধিক ▼";
		var hideButtonText = $toggleElement.data("hidetext") || "ন্যূন ▲";

		// Register the visibility toggle.
		$toggleElement.on("click", window.VisibilityToggles.register(toggleCategory, function show() {
			$toggleButton.html(hideButtonText);
			$toHide.show();
		}, function hide() {
			$toggleButton.html(showButtonText);
			$toHide.hide();
		}));

		// Add the toggle button to the DOM tree.
		$navToggle.append($toggleButton).prependTo($toggleElement);
		$toggleElement.show();
	}

	// based on [[User:Erutuon/scripts/semhide.js]], [[User:Jberkel/semhide.js]],
	// [[User:Ungoliant_MMDCCLXIV/synshide.js]]
	function setupNyms(index, dlTag) {
		// [[Wiktionary:Semantic relations]]
		var relationClasses = ['সমার্থক শব্দ', 'বিপরীত শব্দ', 'hypernym', 'hyponym', 'meronym', 'holonym', 'troponym', 'তুল্য শব্দ'];

		var relations = $(dlTag).find('dd > .nyms').get().filter(function (element) {
			return Array.prototype.some.call(element.classList, function (className) {
				if (relationClasses.indexOf(className) !== -1) {
					$(element).data('relationClass', className);
					return true;
				}
			});
		});

		function setupToggle(elements, category, visibleByDefault) {
			if (elements.length === 0) return null;
			var toggler = $('<a>');
			var text = elements.map(function (e) {
				return $(e).data('relationClass').replace('-', ' ') + ($(e).find('a').length > 1 ? 's' : '');
			}).join(', ');

			function show() {
				toggler.html(text + '&nbsp;▲');
				$(dlTag).show();
				$(elements).show();
			}
			function hide() {
				toggler.html(text + '&nbsp;▼');
				if ($(dlTag).children().length === elements.length) {
					$(dlTag).hide();
				} else {
					$(elements).hide();
				}
			}

			$(dlTag).before($('<span>').addClass('nyms-toggle').append(toggler).css('margin-left', '5px'));

			toggler.click(window.VisibilityToggles.register(category, show, hide, visibleByDefault));
		}

		var synonyms = relations.filter(function (e) {
			return ['synonym', 'antonym'].indexOf($(e).data('relationClass')) !== -1;
		});
		var other = relations.filter(function (e) {
			return synonyms.indexOf(e) === -1;
		});

		setupToggle(synonyms, 'synonyms', true /* show by default  */);
		setupToggle(other, 'semantic relations');
	}

	window.createNavToggle = createNavToggle;
	window.setupHiddenQuotes = setupHiddenQuotes;
	window.viewSwitching = viewSwitching;
	window.getToggleCategory = getToggleCategory;

	/* == Apply four functions defined above == */
	mw.hook('wikipage.content').add(function ($content) {
		// NavToggles
		$('.NavFrame', $content).each(function () {
			createNavToggle(this);
		});

		//quotes
		if (mw.config.get('wgNamespaceNumber') === 0) {
			// First, find all the ordered lists, i.e. all the series of definitions.
			$('ol > li', $content).each(function () {
				setupHiddenQuotes(this);
			});
		}

		//view switching
		$('.vsSwitcher', $content).each(function () {
			viewSwitching(this);
		});

		// list switching
		$(".list-switcher", $content).each(function () {
			enableListSwitch(this, window.listSwitcherRowCount);
		});

		// synonyms and such under definitions
		$(function () {
			// if (mw.config.get('wgNamespaceNumber') === 0) {
			$('dl:has(dd > .nyms)').each(setupNyms);
			// }
		});
	});

	jQuery(mw).on("LivePreviewDone", function (ev, sels) {
		var ols = jQuery(sels.join(",")).find("ol");
		for (var i = 0; i < ols.length; i++) {
			for (var j = 0; j < ols[i].childNodes.length; j++) {
				var li = ols[i].childNodes[j];
				if (li.nodeName.toUpperCase() == "LI") {
					setupHiddenQuotes(li);
				}
			}
		}
	});
})();