All files / ext.wikilambda.app/composables useClipboardManager.js

100% Statements 88/88
100% Branches 19/19
100% Functions 5/5
100% Lines 88/88

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 8917x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 39x 39x 39x 39x 39x 39x 39x 39x 3x 3x 3x 39x 39x 39x 39x 39x 39x 39x 39x 1x 1x 1x 39x 39x 39x 39x 39x 39x 39x 86x 86x 86x 86x 86x 85x 86x 82x 82x 4x 4x 86x 1x 1x 3x 3x 3x 3x 3x 3x 3x 86x 39x 39x 39x 39x 39x 39x 39x 39x 39x 32x 32x 39x 39x 39x 39x 17x  
/*!
 * WikiLambda Vue composable for managing clipboard operations across the app
 *
 * @module ext.wikilambda.app.composables.useClipboardManager
 * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt
 * @license MIT
 */
'use strict';
 
const { onMounted, onBeforeUnmount } = require( 'vue' );
const useClipboard = require( './useClipboard.js' );
 
/**
 * Composable that sets up global clipboard event listeners for specified CSS classes.
 * Automatically attaches/detaches listeners on mount/unmount.
 *
 * @param {Object} options - Configuration options
 * @param {Array<string>} options.classNames - Array of CSS class names to watch for copy events
 * @return {Object} Clipboard functionality
 */
module.exports = function useClipboardManager( { classNames = [] } = {} ) {
	const clipboard = useClipboard();
 
	/**
	 * Display "Copied!" message on the element
	 *
	 * @param {HTMLElement} element - The element to display the copied message on
	 */
	function displayCopiedMessage( element ) {
		element.setAttribute( 'data-copied', 'true' );
		element.innerText = clipboard.getCopiedText.value;
	}
 
	/**
	 * Clear the copied message and restore original text
	 *
	 * @param {HTMLElement} element - The element to clear the copied message for
	 * @param {string} value - The original value to restore
	 */
	function clearCopiedMessage( element, value ) {
		element.removeAttribute( 'data-copied' );
		element.innerText = value;
	}
 
	/**
	 * Handle click and keydown events for copy operations
	 *
	 * @param {Event} event - Click or keydown event
	 */
	function handleEvent( event ) {
		const element = event.target;
 
		// If already copied, or doesn't match target classes, do nothing
		if (
			element.hasAttribute( 'data-copied' ) ||
			!classNames.some( ( className ) => element.classList.contains( className ) )
		) {
			return;
		}
 
		// Check if Event is a KeyboardEvent and ignore non-Enter keys
		if ( event instanceof KeyboardEvent && event.key !== 'Enter' ) {
			return;
		}
 
		const value = element.textContent;
		clipboard.copyToClipboard(
			value,
			() => displayCopiedMessage( element ),
			() => clearCopiedMessage( element, value )
		);
	}
 
	// Set up event listeners on mount
	onMounted( () => {
		window.addEventListener( 'click', handleEvent );
		window.addEventListener( 'keydown', handleEvent );
	} );
 
	// Clean up event listeners on unmount
	onBeforeUnmount( () => {
		window.removeEventListener( 'click', handleEvent );
		window.removeEventListener( 'keydown', handleEvent );
	} );
 
	// Return clipboard functionality (optional - for components that need it)
	return clipboard;
};