mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/DiscussionTools
synced 2024-11-14 19:35:38 +00:00
eb497b00c7
Allow using Ctrl+click to open the link in a new tab, or Alt+click to select the text, without annoying side effects. Change-Id: I3ab4c1ec3d5fc6c69e7f44489bbe63c536a64b91
76 lines
2.2 KiB
JavaScript
76 lines
2.2 KiB
JavaScript
const utils = require( './utils.js' );
|
|
|
|
function init( $pageContainer ) {
|
|
$pageContainer.find( '.ext-discussiontools-init-timestamplink' ).on( 'click', ( e ) => {
|
|
if ( !utils.isUnmodifiedLeftClick( e ) ) {
|
|
// Only handle unmodified left clicks
|
|
return;
|
|
}
|
|
// Try to percent-decode the URL, so that non-Latin characters don't look so ugly (T357021)
|
|
// Use currentTarget rather than target to avoid conflicts with userscripts that do their
|
|
// own timestamp-wrapping. (T368701)
|
|
let link = e.currentTarget.href;
|
|
try {
|
|
// decodeURI() may throw
|
|
const decodedLink = decodeURI( link );
|
|
// Check that the decoded URL is parsed to the same canonical URL
|
|
// new URL() may throw
|
|
if ( new URL( decodedLink ).toString() === link ) {
|
|
link = decodedLink;
|
|
}
|
|
} catch ( err ) {}
|
|
copyLink( link );
|
|
} ).attr( 'data-event-name', 'discussiontools.permalink-copied' );
|
|
}
|
|
|
|
function copyLink( link ) {
|
|
const $win = $( window );
|
|
const scrollTop = $win.scrollTop();
|
|
|
|
const $tmpInput = $( '<input>' )
|
|
.val( link )
|
|
.addClass( 'noime' )
|
|
.css( {
|
|
position: 'fixed',
|
|
top: 0
|
|
} )
|
|
.appendTo( 'body' )
|
|
.trigger( 'focus' );
|
|
$tmpInput[ 0 ].setSelectionRange( 0, link.length );
|
|
let copied;
|
|
try {
|
|
copied = document.execCommand( 'copy' );
|
|
} catch ( err ) {
|
|
copied = false;
|
|
}
|
|
if ( copied ) {
|
|
mw.notify( mw.msg( 'discussiontools-permalink-comment-copied' ) );
|
|
}
|
|
$tmpInput.remove();
|
|
|
|
// Restore scroll position, can be changed by setSelectionRange, or hash navigation
|
|
function afterNextScroll() {
|
|
// On desktop we can restore scroll immediately after the scroll
|
|
// event, preventing a scroll flicker.
|
|
$win.scrollTop( scrollTop );
|
|
// On mobile, we need to wait another execution cycle (setTimeout)
|
|
// before the scroll is rendered (and not requestAnimationFrame).
|
|
setTimeout( () => {
|
|
$win.scrollTop( scrollTop );
|
|
} );
|
|
}
|
|
// Restore scroll position when the scroll event fires.
|
|
// setTimeout does't reliably wait long enough for the native
|
|
// scroll to happen.
|
|
$win.one( 'scroll', afterNextScroll );
|
|
// If we happened to be in the exact correct position, 'scroll' won't fire,
|
|
// so clear the listener after a short delay
|
|
setTimeout( () => {
|
|
$win.off( 'scroll', afterNextScroll );
|
|
}, 1000 );
|
|
}
|
|
|
|
module.exports = {
|
|
init: init
|
|
};
|