User:SunAfterRain/js/CollapsibleToggle.js

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
警告:User:SunAfterRain/js下的所有script幾乎都是本人隨興撰寫的,不保證可用性。如要使用,請確保您的瀏覽器支援ES6、async & await等語法糖,並接受本人突然改變任何內容以至於用法改變或是毀損無法使用。任何問題請至:User talk:SunAfterRain
/**
 * CollapsibleToggle.js
 * 早期的 NavFrame 替代產品,使用後可以如同 NavFrame 點 Head 展開或關閉
 * 使用方式:
 * <syntaxhighlight lang="html">
<div class="mw-collapsible" style="..."><!-- 以前的 NavFrame -->
<div class="skin-invert collapsible-title" style="..."><!-- 以前的 NavHead -->
<div style="...">標題</div>
<div class="collapsible-toggle-place" style="..."><span class="mw-collapsible-toggle-placeholder"><!-- 会被替换 --></span></div>
</div>
<div class="mw-collapsible-content" style="..."><!-- 以前的 NavContent -->
</div>
</div>
</syntaxhighlight>
 * <syntaxhighlight lang="wikitext">
{| class="mw-collapsible" style="..."
|-
! class="skin-invert collapsible-title" style="..." | 標題
|-
| style="..." | ... <!-- mw-collapsible-content -->
|}
</syntaxhighlight>
 * 
 * 註1:.collapsible-title 也可以放在 mw-collapsible 的直接父元素,不過請注意嵌套多個摺疊模板的問題
 *      亦即可以達成點父元素展開所有子摺疊模板
 * 註2:建議搭配[[User:SunAfterRain/js/CollapsibleToggle.css]]一起使用
 * 註3:在 .collapsible-toggle-place 加上 .gadget-collapsible-toggle-hide-toggle
 *      可以在套用 CollapsibleToggle 後隱藏 toggle(沒有安裝 css 則無效)
 * 
 * @author [[User:SunAfterRain]]
 */
/* _addText: {{User:SunAfterRain/js}} */
// <nowiki>
$(() => {
	const HEAD_KEY = 'CollapsibleToggle.head';
	const DATA_KEY = 'CollapsibleToggle.data';

	const CLASS_SELECTOR = '.collapsible-title';
	const IGNORE_TRIGGER_SELECTOR = 'a, button, .mw-collapsible-toggle, .collapsible-toggle-ignore';
	
	function collapsibleGetHead($collapsible) {
		let $element;
		if ($collapsible.is('table')) {
			// If the table has a caption, collapse to the caption
			// as opposed to the first row
			const $caption = $collapsible.find( '> caption' );
			if ($caption.length) {
				$element = $caption;
			} else {
				const $tr = $collapsible.find('tr').first();
				if ($tr.is(CLASS_SELECTOR)) {
					return $tr;
				}
				$element = $tr.find('th, td');
			}
		} else if ($collapsible.is('ul') || $collapsible.is('ol')) {
			// The toggle-link will be in the first list-item
			$element = $collapsible.find( 'li' ).first();
		} else {
			$element = $collapsible.children();
		}
		return $element.filter(CLASS_SELECTOR);
	}

	function initCollapsibleToggle(element) {
		const $element = $(element);
		let $head = collapsibleGetHead($element);
		if (!$head.length) {
			$head = $element.parent(CLASS_SELECTOR);
		}
		const mwCollapsibleData = $element.data('mwCollapsible');
		if (
			!$element.hasClass('mw-collapsible')
			|| ($element.attr('id') || '').startsWith('mw-customcollapsible-')
			|| $element.hasClass('gadget-collapsible-toggle-optout')
			|| !$element.data('mwMadeCollapsible')
			|| !mwCollapsibleData
			|| !$head.length
			|| !!$element.data(DATA_KEY)
		) {
			return;
		}

		$element.addClass('gadget-collapsible-toggle');
		$head
			.on('mousedown', (e) => {
				// https://commons.wikimedia.org/wiki/MediaWiki:Gadget-CollapsibleTemplates.js?oldid=458731733#L47
				const $target = $(e.target);
				if ($target.is(IGNORE_TRIGGER_SELECTOR) || $target.parents(IGNORE_TRIGGER_SELECTOR).length) {
					return true;
				}
				mwCollapsibleData.toggle();
				return false;
			});

		$head.data(HEAD_KEY, true);
		$element.data(DATA_KEY, {
			mwCollapsibleData
		});
	}

	function initCollapsibleToggleWrapper($frame) {
		for (const frame of $frame.get()) {
			initCollapsibleToggle(frame);
		}
	}

	if (typeof $.fn.makeCollapsible === 'function') {
		initCollapsibleToggleWrapper($('.mw-collapsible'));
	}

	mw.hook('wikipage.collapsibleContent').add(initCollapsibleToggleWrapper);
	mw.hook('ext.gadget.CollapsibleToggle').add(initCollapsibleToggleWrapper);
});
// </nowiki>