PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.0
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.0
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
profile-builder / form-builder / blocks / src / components / DisableBlockClipboard.js

DisableBlockClipboard.js in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 4.0.0, at form-builder/blocks/src/components/DisableBlockClipboard.js

97 lines 3.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Block copy/cut/paste on PB form CPTs (native clipboard events, not the
3 * keyboard-shortcuts store). Pasting a field block would duplicate `meta-name`.
4 *
5 * Capture-phase on the canvas iframe doc; editable text targets are left alone.
6 * Re-attach when the iframe mounts or reloads.
7 */
8
9 import { registerPlugin } from '@wordpress/plugins';
10 import { useSelect } from '@wordpress/data';
11 import { useEffect } from '@wordpress/element';
12
13 const PB_CPTS = [ 'wppb-rf-cpt', 'wppb-epf-cpt' ];
14 const CLIP_EVENTS = [ 'copy', 'cut', 'paste' ];
15 const ATTACHED_FLAG = 'wppbFbClipboardGuard';
16
17 // Non-text inputs: block-level clipboard from these should still be blocked.
18 const NON_TEXT_INPUT_TYPES = [
19 'checkbox', 'radio', 'button', 'submit', 'reset', 'file', 'range', 'color', 'image',
20 ];
21
22 /** True when the target is editable text — leave native clipboard alone. */
23 function isEditableTextTarget( target ) {
24 if ( ! target || typeof target.closest !== 'function' ) return false;
25 if ( target.closest( '[contenteditable="true"], [contenteditable=""]' ) ) return true;
26 const field = target.closest( 'input, textarea' );
27 if ( ! field ) return false;
28 if ( field.tagName === 'TEXTAREA' ) return true;
29 const type = ( field.getAttribute( 'type' ) || 'text' ).toLowerCase();
30 return ! NON_TEXT_INPUT_TYPES.includes( type );
31 }
32
33 function clipboardHandler( event ) {
34 if ( isEditableTextTarget( event.target ) ) return;
35 event.stopImmediatePropagation();
36 event.preventDefault();
37 }
38
39 function attachTo( doc ) {
40 if ( ! doc || ! doc.documentElement ) return;
41 if ( doc.documentElement.dataset[ ATTACHED_FLAG ] === '1' ) return;
42 doc.documentElement.dataset[ ATTACHED_FLAG ] = '1';
43 // Doc + window so we win regardless of where Gutenberg attaches.
44 const targets = doc.defaultView ? [ doc, doc.defaultView ] : [ doc ];
45 for ( const t of targets ) {
46 for ( const type of CLIP_EVENTS ) {
47 t.addEventListener( type, clipboardHandler, true );
48 }
49 }
50 }
51
52 /** Canvas iframe doc, or main document as non-iframe fallback. */
53 function findCanvasDoc() {
54 const iframe = document.querySelector( 'iframe[name="editor-canvas"]' );
55 if ( iframe && iframe.contentDocument ) return iframe.contentDocument;
56 if ( document.querySelector( '.editor-styles-wrapper' ) ) return document;
57 return null;
58 }
59
60 const DisableBlockClipboard = () => {
61 const isOurPostType = useSelect(
62 ( select ) => PB_CPTS.includes( select( 'core/editor' ).getCurrentPostType() ),
63 []
64 );
65
66 useEffect( () => {
67 if ( ! isOurPostType ) return undefined;
68
69 let frame = null;
70 const scheduleAttach = () => {
71 if ( frame ) return;
72 frame = requestAnimationFrame( () => {
73 frame = null;
74 attachTo( findCanvasDoc() );
75 } );
76 };
77
78 attachTo( findCanvasDoc() );
79
80 const observer = new MutationObserver( scheduleAttach );
81 observer.observe( document.body, { childList: true, subtree: true } );
82
83 const iframe = document.querySelector( 'iframe[name="editor-canvas"]' );
84 if ( iframe ) iframe.addEventListener( 'load', scheduleAttach );
85
86 return () => {
87 observer.disconnect();
88 if ( frame ) cancelAnimationFrame( frame );
89 if ( iframe ) iframe.removeEventListener( 'load', scheduleAttach );
90 };
91 }, [ isOurPostType ] );
92
93 return null;
94 };
95
96 registerPlugin( 'wppb-fb-disable-block-clipboard', { render: DisableBlockClipboard } );
97