User:Isaacl/script/copy-comment-link-to-clipboard.js

(function{

let fShowCopyCommentLinkTriggers = false;

function copyLinkToClipboard(event) {   	let link = event.target.dataset.link2clipboardCommentLink; navigator.clipboard.writeText(link).then( => {    		showLinkCopiedNotification;    	}); }

function htmlEncode(text) {   	return text.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;'); }

function addCopyCommentLinkTrigger(commentIdElem, label, description) {		let labelText = ''; if (label != null) labelText = label; let descriptionText = ''; if (description != null) {		  descriptionText = description.concat(' '); }		descriptionText = descriptionText.concat('link');

let id = commentIdElem.getAttribute("id"); let linkElem = document.createElement("span"); linkElem.dataset.link2clipboardTrigger = ''; linkElem.style.textDecorationLine = 'underline'; linkElem.style.textDecorationStyle = 'dotted';

let link = mw.config.get('wgPageName'); link = link.replaceAll('_', ' '); link = link.concat('#', id.replaceAll('_', ' ')); linkElem.dataset.link2clipboardCommentLink = link;

let triggerText = ""; triggerText = triggerText.concat("<", labelText, "/> "); linkElem.appendChild(document.createTextNode(triggerText));

let popupContent = ' '.concat(htmlEncode(link), ' '); let popupWidget = new OO.ui.PopupWidget({       	$content: $(popupContent),        	$floatableContainer: $(linkElem),        	classes: [ 'link2clipboardPopup' ],        	head:true,        	padded:true        }); OO.ui.getTeleportTarget.append(popupWidget.$element[0]);

let titleText = ""; titleText = titleText.concat('Copy ', descriptionText, ' to clipboard'); linkElem.title = titleText; linkElem.addEventListener('click', function(event) {			popupWidget.toggle(true);			copyLinkToClipboard(event);		});

let parent = commentIdElem.parentNode; let insertBeforeElem = commentIdElem; if (parent.tagName == 'A' && parent.href != "") {       	insertBeforeElem = parent; parent = parent.parentNode; }		parent.insertBefore(linkElem, insertBeforeElem); }	function showCommentLinks {		let commentStartSpans = document.querySelectorAll("span[data-mw-comment-start]"); for (let commentStartElem of commentStartSpans) {			if (commentStartElem.hasAttribute("id")) {				addCopyCommentLinkTrigger(commentStartElem); }		}		// Legacy structure for headlines: span element inside a heading element let headlineIdSpans = document.getElementsByClassName('mw-headline'); for (let headlineIdElem of headlineIdSpans) {			if (headlineIdElem.hasAttribute("id")) {				addCopyCommentLinkTrigger(headlineIdElem, "h", "heading"); }		}		// Parsoid structure for headlines: div element wrapping heading element. let headingNameList = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ]; for (let headingName of headingNameList) {			let selector = "div.mw-heading ".concat(headingName.concat("[id]")); let headingElements = document.querySelectorAll(selector); for (let headingElem of headingElements) {				addCopyCommentLinkTrigger(headingElem, "h", "heading"); }		}	}	function hideCommentLinks {		let linkElems = document.querySelectorAll("span[data-link2clipboard-trigger]"); for (let linkElem of linkElems) {			linkElem.remove; }		let popupElems = document.querySelectorAll('.link2clipboardPopup'); for (let popupElem of popupElems) {			popupElem.remove; }	}

function showLinkCopiedNotification {   	mw.loader.using(['mediawiki.notification']).then(  => {    		mw.notification.notify("Copied link to clipboard.");    	});

}

function showEnabledNotification {   	mw.loader.using(['mediawiki.notification']).then(  => {			mw.notification.notify("Enabled copying links to clipboard.");		}); }

function showDisabledNotification {   	mw.loader.using(['mediawiki.notification']).then(  => {			mw.notification.notify("Disabled copying links to clipboard.");		}); }

function clickEventListener(event) {   	event.preventDefault; event.stopPropagation; hideCommentLinks; if (fShowCopyCommentLinkTriggers) {   		showDisabledNotification; }   	else {			showCommentLinks; showEnabledNotification; }		fShowCopyCommentLinkTriggers = !fShowCopyCommentLinkTriggers; return false; }

let portletItemDropDownMenuConfig = [ { portletName: 'p-personal', id: 'link2clipboard-PortletItem-personal' }, { portletName: 'p-personal-sticky-header', id: 'link2clipboard-PortletItem-personal-sticky-header' }, ];	let portletItemSidebarConfig = [ { portletName: 'p-tb', id: 'link2clipboard-PortletItem-tb' }, ];

let skinsWithDropDownMenu = [ 'vector2022', 'timeless', 'minerva' ]; let portletItemConfig = portletItemSidebarConfig;

// TODO: mw.config.skin is returning undefined, and not the skin name //console.log("Using skin: ", mw.config.skin); //if (skinsWithDropDownMenu.includes(mw.config.skin)) //	portletItemConfig = portletItemDropDownMenuConfig;

let portletItemText = "Toggle link2clipboard";

function addPortletLinkEventHandler(item, options) {		for (let portletItemInfo of portletItemConfig) {	   	if (options.id == portletItemInfo.id) {	   		mw.loader.using('oojs-ui-core').done( function {					item.addEventListener('click', clickEventListener);	    		}); }		}	}

function initializePortletItem {		mw.hook('util.addPortletLink').add(addPortletLinkEventHandler); mw.loader.using( [ 'mediawiki.util' ] ).then( function {			for (let portletItemInfo of portletItemConfig)			{				let portletItem = document.getElementById(portletItemInfo.id);				if (portletItem == null)				{					mw.util.addPortletLink(portletItemInfo.portletName, '#', portletItemText, portletItemInfo.id);				}			}		} ); return; }

initializePortletItem; });