MediaWiki:Gadget-zhDialMap.js

// Chinese dialectal maps, part of gadget zhDialMap // designed by User:Suzukaze-c, originally posted at User:Suzukaze-c/zhDialMap.js // discussion: Module talk:User:Suzukaze-c/zh-dial-map

// ideas: // * group locations in the popup by lect

'use strict';

mw.loader.load('oojs-ui-core');

var classes = { dotHover: 'zh-dial-map__dot--hover', dotSuperHover: 'zh-dial-map__dot--superHover', legendRowHover: 'zh-dial-map__legend-row--hover', };

var groupZH = { 'Mandarin': '官話', 'Northeastern Mandarin': '東北官話', 'Jilu Mandarin': '冀魯官話', 'Jiaoliao Mandarin': '膠遼官話', 'Central Plains Mandarin': '中原官話', 'Lanyin Mandarin': '蘭銀官話', 'Southwestern Mandarin': '西南官話', 'Jianghuai Mandarin': '江淮官話', 'Cantonese': '粵語', 'Hakka': '客家話', 'Huizhou': '徽語', 'Gan': '贛語', 'Jin': '晉語', 'Jiuxing Yumin': '九姓漁民方言', 'Northern Min': '閩北語', 'Eastern Min': '閩東語', 'Southern Min': '閩南語', 'Puxian Min': '莆仙閩語', 'Zhongshan Min': '中山閩語', 'Central Min': '閩中語', 'Shaojiang Min': '邵將閩語', 'Southern Pinghua': '桂南平話', 'Northern Pinghua': '桂北平話', 'Shehua': '畬話', 'Waxiang': '瓦鄉話', 'Wu': '吳語', 'Xiang': '湘語', 'Xiangnan Tuhua': '湘南土話', 'Yuebei Tuhua': '粵北土話', };

function zh(data) { var element; if (data.type == 'lang') { element = $(' '); } else if (data.type == 'link') { element = $('').attr('href', '/wiki/' + data.word + '#Chinese'); }	element.addClass('Hani').attr('lang', 'zh').text(data.alt ? data.alt : data.word); if (data.red) element.addClass('new');

return element; }

function updateGroupSelection { var groupSelectionStyle = $("style.zh-dial-map__groupSelectionStyle"); var groupInputChecked = $("input.zh-dial-map__groupItem:checked"); var checkedGroups = [];

for (var i = 0; i < groupInputChecked.length; i++) { checkedGroups.push($(groupInputChecked[i]).attr('data-group')); }

if (checkedGroups.length === 0) { groupSelectionStyle.text(''); } else { var checkedGroupsNotSelector = ''; for (var i = 0; i < checkedGroups.length; i++) { checkedGroupsNotSelector += ':not([data-group="' + checkedGroups[i] + '"])' }

groupSelectionStyle.text('.zh-dial-map__dot' + checkedGroupsNotSelector + ' { display: none; }'); } }

function main { var dots; var redLinks = {}; // Record which pages don't exist (for the "other terms" popup links) var wordLocations = {}; // Initialize object that will contain locations for each dialectal word. Cache instead of regenerating all the time var otherTerms = []; var activePopup; var popups = [];

var mapImg = $('.zh-dial-map__map img');

// take original pixel dimensions from the image // and give them to the image and the container holding the image $('.zh-dial-map__map, .zh-dial-map__map img') .css('width', mapImg.attr('width') + 'em') .css('height', mapImg.attr('height') + 'em') ;

// change image source to svg // and remove dimension attributes mapImg .removeAttr('width') .removeAttr('height')

.attr('src', function(index, attr) {			return attr.replace('1200px', '2400px');		}) .removeAttr('srcset') /*		.attr('src', function(index, attr) {			return attr.replace('thumb/', '').replace(/(svg).+/, '$1')		}) .removeAttr('srcset') */	;

var inputContainer = $(' '); inputContainer .addClass('zh-dial-map__inputContainer') .prependTo('.zh-dial-map__container') ;

var zoomContainer = $(' '); var zoomController = $(' '); zoomContainer .addClass('zh-dial-map__zoomContainer') .appendTo('.zh-dial-map__inputContainer') ;	zoomController .addClass('zh-dial-map__zoomController') .attr('type', 'range') .attr('min', 0.1) .attr('max', 4) .attr('step', 0.1) .val(1) // default zoom at 100% .on("change", function {			//console.log($(this).val);			$('.zh-dial-map__map').css("font-size", $(this).val + "px");		}) .appendTo('.zh-dial-map__zoomContainer') ;

var groupSelectionContainer = $(' '); var groupSelectionStyle = $(" "); groupSelectionContainer .addClass('zh-dial-map__groupSelectionContainer') .appendTo('.zh-dial-map__inputContainer') ;	groupSelectionStyle .addClass('zh-dial-map__groupSelectionStyle') .appendTo('head') ;	for (var group in groupZH) { var groupItem = $(' '); var groupLabel = $(' '); var id = 'zh-dial-map__groupItem--' + group.replace(' ', '-'); groupItem .attr('type', 'checkbox') .addClass('zh-dial-map__groupItem') .attr('id', id) .attr('name', 'zh-dial-map__groupItem') .attr('data-group', group) .on("change", updateGroupSelection) .appendTo('.zh-dial-map__groupSelectionContainer') ;		groupLabel .attr('for', id) .text(group) .appendTo('.zh-dial-map__groupSelectionContainer') ;	}

$('.zh-dial-map__legend-row').on("touchstart mouseenter",		function {			var word = $(this).data('word'); // Get the dialectal word for the active legend row			var isOther = (word == 'other'); // Is our row the "other terms" row?

if (isOther) { dots = $('.zh-dial-map__dot-other'); // Get all grey dots } else { dots = $('.zh-dial-map__dot[data-word=' + word + ']'); // Get every dot corresponding to our word }

$(this).addClass(classes.legendRowHover); // Add hovered class to the legend row dots.addClass(classes.dotHover); // Add hovered class to every corresponding dot

if (! wordLocations[word]) { wordLocations[word] = [];

dots.each(					function(index) {						var location = [$(this).data('location-en'), $(this).data('location-zh'), $(this).data('group')]; // Get location of dot						wordLocations[word].push(location);

if (isOther) { var otherWord = $(this).data('word'); // For "other terms", collect the terms too otherTerms.push(otherWord);

if (! redLinks[otherWord]) redLinks[otherWord] = $(this).parent.hasClass('new'); //console.log(otherWord, redLinks[otherWord]); }					}				);				//console.log(word, wordLocations[word]);				//if (isOther) { console.log(otherTerms) };			}

if (! popups[word]) { var locationsList = $('').addClass('zh-dial-map__legend-row-locations'); // Popup contents

$.each(wordLocations[word], function(index, value) { // Do stuff related to each location recorded for this word					if (isOther) word = otherTerms[index];

var locationEn = value[0], locationZh = value[1], group = value[2]; var listItem = $('');

listItem.append(zh({type: 'lang', word: locationZh + groupZH[group]})).append(' (' + locationEn + ' ' + group + ')'); // FIXME: this feels really hacky if (isOther) listItem.append(': ').append(zh({type: 'link', word: otherTerms[index], red: redLinks[word]})); // FIXME: this too

var locationDot = $('[data-location-zh=' + locationZh + '][data-word=' + word + ']'); // Find the dot for this word at this location //console.log('[data-location-zh=' + locationZh + '][data-word=' + word + ']', locationDot); listItem.hover(						function {							locationDot.addClass(classes.dotSuperHover);						},						function {							locationDot.removeClass(classes.dotSuperHover);						}					);

listItem.appendTo(locationsList); });

popups[word] = new OO.ui.PopupWidget({					$content: locationsList,					$container: $('.zh-dial-map__container'),				});

$(this).append(popups[word].$element); // Add cool popup to DOM }

popups[word].toggle(true); // Make the popup visible activePopup = popups[word]; }	);

$('.zh-dial-map__legend-row').on("touchend mouseleave",		function {			$(this).removeClass(classes.legendRowHover); // Remove hovered class from legend row			dots.removeClass(classes.dotHover); // Remove hovered class from every dot that corresponds to that word			activePopup.toggle(false); // Hide popup		}	); }

if ($('.zh-dial-map__map').length) { main; }