Misplaced Pages

User:Enterprisey/copy-section-link.js

Article snapshot taken from[REDACTED] with creative commons attribution-sharealike license. Give it a read and then ask your questions in the chat. We can research this topic together.
< User:Enterprisey
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Enterprisey/copy-section-link.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Misplaced Pages:Bypass your cache.
// Fixed version of ]
// <nowiki>
$.when(
    $.ready,
    mw.loader.using(  )
).then( function () {
	/*
	 * The convoluted function is needed, because there are different HTML
	 * layouts for "headings" in different skins.
	 * In Vector 2022, layout of ==Second level== versus ===Third level===
	 * headings is different even for a _single_ skin.
	 *
	 * The HTML layout is either
	 *    <div><h*></h*><edit section link /></div>
	 * or
	 *    <h*><edit section link /></h*>
	 *
	 * For details, see:
	 *   - https://www.mediawiki.org/search/?title=Heading_HTML_changes&oldid=6538029
	 */
	// Returns a plain HTMLElement
	function findEditSectionForHeader(header) {
		// in Vector, the bracketed  section link is a direct child element/node
		const maybeVectorEditSection = header.querySelector('.mw-editsection');
		if (maybeVectorEditSection) {
			return maybeVectorEditSection;
		}
		// in other skins, the bracketed  section link is a sibling of <h2> <h3> etc
		if (header.parentElement.classList.contains('mw-heading')) {
			const maybeEditSection = header.parentElement.querySelector('.mw-editsection');
			if (maybeEditSection) {
				return maybeEditSection;
			}
		}
		return null;
	}
	/*
	 * The search for all section headings starts with
	 * finding all <h*> tags, which aren't for the table of contents.
	 * From the <h*> tags, we find the " section links".
	 */
	const allHeaders = $("#mw-content-text .mw-parser-output").find(":header").filter(':not(#mw-toc-heading)');

    allHeaders.each( function(i, header) {
        var popup = null;
        var editSection = findEditSectionForHeader(header);
        let target;
        if (editSection === null) {
        	target = $(header);
        	console.warn('', 'edit section link not found:', target);
        } else {
        	target = $(editSection);
        }
        target.after($( "<a>", { "class": "copy-section-link-pilcrow" } )
                .text( "ΒΆ" )
                .click( function () {
                    if( popup === null ) {
                        const hash = header.id ? header.id : header.querySelector('.mw-headline')?.id;
                        var oldid = mw.util.getParamValue( "oldid" );
                        var popupContent;
                        function makeContent( pageName, id ) {
                            var wikitext = (pageName + "#" + hash).replace( /_/g, " " );
                            if( !window.copySectionLinkNoSquareBrackets ) {
                               wikitext = ']';
                            }
                            return $( '<p>', { "class": "copy-section-link-content" } ).append(
                                $( "<code>", { "id": "copy-section-wikilink" + id } ).text( wikitext ),
                                $( "<button>" )
                                    .text( "Copy" )
                                    .css( { "padding": "0.5em", "cursor": "pointer", "margin-left": "0.5em" } )
                                    .click( function () {
                                        var textField = $( this ).prev();
                                        try {
                                            navigator.clipboard.writeText( textField.text() );
                                        } catch( e ) {
                                            textField.select();
                                            document.execCommand( "copy" );
                                        }
                                    } ),
                                $( "<br>" ),
                                $( "<a>" )
                                	.attr( "href", mw.util.getUrl( pageName ) + "#" + encodeURIComponent( hash ) )
                                	.text( "external" )
                            );
                        }

                        var generalCss = { 'font-size': '0.9rem', 'font-family': 'sans-serif' };

                        var index;
                        if( oldid ) {
                            popupContent = makeContent( "Special:Permalink/" + oldid );
                            popupContent.css( generalCss );
                            popupContent.css( { 'padding-top': '0.5em', 'font-weight': 'normal' } );
                        } else {
                            var normalPanel = new OO.ui.TabPanelLayout( 'normal', {
                                label: 'Link',
                                $content: makeContent( mw.config.get( 'wgPageName' ), 'normal' )
                            } );
                            var permalinkPanel = new OO.ui.TabPanelLayout( 'permalink', {
                                label: 'Permalink',
                                $content: makeContent( 'Special:Permalink/' + mw.config.get( 'wgCurRevisionId' ), 'permalink' )
                            } );
                            index = new OO.ui.IndexLayout();
                            index.addTabPanels(  );
                            popupContent = index.$element;
                        }
                        popup = new OO.ui.PopupWidget( {
                            $content: popupContent,
                            $floatableContainer: $( this ),
                            padded: true,
                            width: 400,
                            height: 190,
                            align: 'forwards',
                        } );
                        $( this ).after( popup.$element );
                        if( index ) {
                            index.$menu.find( 'span.oo-ui-labelElement-label' ).css( generalCss );
                            index.$content.css( generalCss );
                        }

                        popup.toggle( true );
                    } else {
                        popup.toggle();
                    }
                } ) );
    } );
    mw.util.addCSS( ".mw-heading .copy-section-link-pilcrow" +
                        "{ display: none; margin-left: 1em; }" +
                    ".mw-heading:hover .copy-section-link-pilcrow" +
                        "{ display: inline; }" +
                    ".mw-heading .copy-section-link-pilcrow + .oo-ui-widget" +
                        "{ font-weight: normal; }" );
} );
// </nowiki>
User:Enterprisey/copy-section-link.js Add topic