MediaWiki:Gadget-TabbedLanguages.js

Chú ý: Sau khi lưu trang này, phải xóa bộ nhớ đệm (cache) của trình duyệt để những thay đổi hiện ra

  • Firefox / Safari: Nhấn giữ phím Shift trong khi nhấn Tải lại (Reload), hoặc nhấn tổ hợp Ctrl-F5 hay Ctrl-R (⌘R trên Mac)
  • Google Chrome: Nhấn tổ hợp Ctrl-Shift-R (⇧⌘R trên Mac)
  • Internet Explorer / Edge: Nhấn giữ phím Ctrl trong khi nhấn Làm tươi (Refresh), hoặc nhấn tổ hợp Ctrl-F5
  • Opera: Nhấn tổ hợp Ctrl-F5.
/**
 * Bố trí lại các mục từ để phân chia theo ngôn ngữ.
 * 
 * Phỏng theo [[:en:MediaWiki:Gadget-TabbedLanguages.js]].
 */

mw.loader.using(["mediawiki.util", "oojs-ui-core", "oojs-ui-widgets"], function () {

/**
 * Thoát các ký tự đặc biệt trong ID để tương thích với bộ lựa chọn jQuery.
 */
function queryEscapeId(str) {
	return str.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" );
}

/**
 * Mã hóa chuỗi được cho vào theo kiểu tên neo cũ của MediaWiki.
 */
function anchorEncode(str) {
	return encodeURIComponent(str.replace(/ /g, "_")).replace(/%/g, ".");
}

/**
 * Giải mã chuỗi được cho vào để tương thích với phần neo của URL.
 */
function anchorDecode(str) {
	return decodeURIComponent(str.replace(/\./g, "%")).replace(/ /g, "_");
}

/**
 * Bố trí chỉ mục.
 */
var index;

/**
 * Viết lại các liên kết trong thẻ được cho vào để chỉ đến một neo ngôn ngữ
 * trong mục từ.
 */
function prefillAnchors(panel) {
	var entry = panel.$element.find(".lang-entry");
	if (entry.data("anchors-prefilled") === true) return;
	entry.data("anchors-prefilled", true);
	
	var id = entry.data("title");
	var articlePrefix = location.protocol + mw.config.get("wgServer") +
		mw.config.get("wgArticlePath").replace("$1", "");
	// TODO: Quốc tế hóa danh sách đề mục để cho những người dùng giao diện
	// trong ngôn ngữ khác cũng được có tính năng này.
	var linkListHeaderTexts = [
		"Từ đồng âm", "Từ tương tự", "Đồng nghĩa", "Trái nghĩa", "Từ dẫn xuất",
		"Từ liên hệ",
	];
	var linkListHeaders = entry.find(":header").filter(function (idx, header) {
		return linkListHeaderTexts.indexOf($(header).find(".mw-headline").text()) !== -1;
	});
	linkListHeaders.nextUntil(":header", "ul, ol, dl, .NavFrame")
		.find("a:not(.new)").prop("href", function (idx, old) {
		if (old.indexOf(articlePrefix) !== 0 || old.indexOf("#") !== -1) return old;
		return old + "#" + id;
	});
}

/**
 * Chuyển qua thẻ ứng với ID được cho vào.
 * 
 * @param {string} id mã ngôn ngữ ISO hoặc tên ngôn ngữ
 * @returns đối tượng jQuery chứa mục từ của thẻ
 */
function showTabNamed(id) {
	if (!id) return;
	
	if (id.indexOf("%") !== -1) id = anchorDecode(id);
	var panel = index.getTabPanel("lang-entry-" + id);
	if (!panel) {
		var entry = $("#" + queryEscapeId(id)).parents(".lang-entry");
		id = entry && entry.data("iso");
		panel = id && index.getTabPanel("lang-entry-" + id);
	}
	if (!panel) return;
	
	index.setTabPanel("lang-entry-" + id);
	updateHashFromTab();
	prefillAnchors(panel);
	return panel;
}

/**
 * Chuyển qua thẻ ứng với neo trong URL.
 */
function updateTabFromHash() {
	showTabNamed(location.hash.substr(1));
}

/**
 * Cập nhật tên neo trong URL theo thẻ hiện tại.
 */
function updateHashFromTab() {
	var panel = index.getCurrentTabPanel();
	var title = panel.$element.find(".lang-entry").data("title");
	if (title && location.hash.substr(1) !== title) {
		location.replace("#" + title);
	}
}

/**
 * Ghi nhớ thẻ trong cookie.
 */
function rememberRequest(iso) {
	$.cookie("lastRequestedTabId", iso);
}

/**
 * Tạm tắt các thẻ để phù hợp với giấy in.
 */
function beforePrint() {
	$("#entry-tabs .oo-ui-panelLayout.oo-ui-element-hidden")
		.addClass("oo-ui-element-unhidden-while-printing")
		.removeClass("oo-ui-element-hidden");
	$(".mw-headline .lang").closest("h2").show();
	$("#toc").show();
}

/**
 * Khôi phục các thẻ sau khi in.
 */
function afterPrint() {
	$("#toc").hide();
	$(".mw-headline .lang").closest("h2").hide();
	$("#entry-tabs .oo-ui-panelLayout.oo-ui-element-unhidden-while-printing")
		.addClass("oo-ui-element-hidden")
		.removeClass("oo-ui-element-unhidden-while-printing");
}

/**
 * Bố trí lại mục từ.
 */
function tabbify() {
	if ($(".mw-headline .lang").length === 0) return;
	
	// Ẩn mục lục.
	$("#toc").hide();
	
	// Cho mỗi đề mục ngôn ngữ…
	var panels = [];
    $(".mw-headline .lang").each(function (headingIdx, langSpan) {
    	var heading = $(langSpan).closest("h2");
    	var headline = $(langSpan).parent();
    	var anchor = $(headline).prev();
    	
    	// Bọc đề mục và cả phần vào một thẻ <article>. Chuyển id từ đầu đề tới
    	// <article>.
    	var id = $(langSpan).data("iso");
    	var entry = $(mw.html.element("article", {
    		"class": "lang-entry",
    		"data-iso": id,
    		"data-title": anchorDecode(anchor.prop("id"))
    	}));
    	entry = heading.nextUntil("h2").addBack().wrapAll(entry).parent();
    	
    	var name = headline.text().replace(/^Tiếng |^Ngôn ngữ /, "");
    	
    	heading.hide();
    	
    	// Đưa những thể loại thuộc về ngôn ngữ này vào phần này.
    	var catItems = [];
    	$("#mw-normal-catlinks li").each(function (catIdx, catItem) {
    		var catName = $(catItem).text();
    		if (catName.toLowerCase().indexOf(headline.text().toLowerCase()) !== -1) {
    			catItems.push(catItem);
    		}
    	});
    	if (catItems.length) {
    		var catBox = $(mw.html.element("div", {
    			"class": "catlinks",
    		}));
    		entry.append(catBox);
    		catBox.append(mw.html.element("div", {
    			"class": "mw-normal-catlinks",
    		}));
    		catBox = catBox.find(".mw-normal-catlinks");
    		catBox.append($("#mw-normal-catlinks > a").text() + ":");
    		catBox.append($("<ul>").append(catItems));
    	}
    	
    	panels.push({
    		id: id,
			label: name,
			expanded: false,
			framed: true,
			scrollable: true,
			$content: entry
		});
    });
	$(".lang-entry").wrapAll(mw.html.element("div", {
    	id: "entry-tabs",
    	style: "clear: both;",
    }));
    
    // Xây dựng các thẻ.
	index = new OO.ui.IndexLayout({
		expanded: false
	});
	index.addTabPanels(panels.map(function (panel) {
		return new OO.ui.TabPanelLayout("lang-entry-" + panel.id, panel);
	}));
	$("#entry-tabs").append(index.$element);
	
	// Đồng bộ hóa phần neo của URL với thẻ hiện tại.
	$(window).on("hashchange", updateTabFromHash);
	index.on("set", function (panel) {
		rememberRequest(panel.$element.find(".lang-entry").data("iso"));
		updateHashFromTab();
	});
	
	// Chọn thẻ đầu tiên.
	if (location.hash.length) updateTabFromHash();
	else {
		showTabNamed($.cookie("lastRequestedTabId")) || showTabNamed(panels[0].id);
		if (window.scrollY) window.scroll(0, 0);
	}
	
	// Hiển thị nội dung của mọi thẻ trước khi in.
	$(window).on("beforeprint", beforePrint).on("afterprint", afterPrint);
}

if ((mw.config.get("wgNamespaceNumber") === 0 ||
	 mw.config.get("wgPageName") === "Wiktionary:Chỗ_thử") &&
	["view", "submit"].indexOf(mw.config.get("wgAction")) !== -1 &&
	$.cookie("disable-tabbed-languages") === null &&
	mw.util.getParamValue("tabbedlanguages") !== "off" &&
	mw.util.getParamValue("printable") !== "yes") {
	mw.hook("wikipage.content").add(tabbify);
}

});