directory

  • How to implement a clipping using JavaScript
    • It’s not perfect, so let’s optimize it
    • Think about a problem
  • Rewrite and optimize with React and typescript
    • How do I use Copyme
  • The original reference

Write it up front

  • There is a simple requirement, users need to quickly copy some relevant information, and then carry on the next information to fill in. There needs to be a clipboard on the front end to facilitate user experience. Use React and typescript to rewrite and optimize react and typescript
  • The general design is as follows, with multiple messages, and then users can click the copy icon on the right for quick copy.

How to implement a clipboard using JavaScript

  • Specifically divided into five steps

    • 1. Create onetextarea, put the required text intextarea
    • 2,textareaElement insertbodyIn the.
    • 3, use,HTMLInputElement.select()Method to choosetextareaText content in
    • 4, the use ofdocument.execCommand('copy')copytextareaThe text content in the clipboard
    • 5, frombodydeletetextareaThe element
  • code

const copyToClipboard = str= > {
  const el = document.createElement('textarea');
  el.value = str;
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
};
Copy the code

Necessary API reference

  • Developer.mozilla.org/zh-CN/docs/…

It’s not perfect, so let’s optimize it

  • This method does not work everywhere, and pages sometimes flicker and shake due to textarea inserts and removers
  • Let’s use CSS to optimize our Textarea style and hide the textarea display.
const copyToClipboard = str= > {
  const el = document.createElement('textarea');
  el.value = str;
  el.setAttribute('readonly'.' ');
  el.style.position = 'absolute';
  el.style.left = '-9999px';
  
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
};
Copy the code

Think about a problem

  • Our users may have already selected text from existing HTML before using our clipboard, so we need to use a little more judgment here to avoid missing text from the user’s selection.
  • DocumentOrShadowRoot.getSelection(), Selection.rangeCount, Selection.getRangeAt(), Selection.removeAllRanges() and Selection.addRange()These methods store the text content selected by the user and solve the problem of range selection
const copyToClipboard = str= > {
  const el = document.createElement('textarea');  // Create a <textarea> element
  el.value = str;                                 // Set its value to the string that you want copied
  el.setAttribute('readonly'.' ');                // Make it readonly to be tamper-proof
  el.style.position = 'absolute';                 
  el.style.left = '-9999px';                      // Move outside the screen to make it invisible
  document.body.appendChild(el);                  // Append the <textarea> element to the HTML document
  const selected =            
    document.getSelection().rangeCount > 0        // Check if there is any content selected previously
      ? document.getSelection().getRangeAt(0)     // Store selection if found
      : false;                                    // Mark as false to know no selection existed before
  el.select();                                    // Select the <textarea> content
  document.execCommand('copy');                   // Copy - only works as a result of a user action (e.g. click events)
  document.body.removeChild(el);                  // Remove the <textarea> element
  if (selected) {                                 // If a selection existed before copying
    document.getSelection().removeAllRanges();    // Unselect everything on the HTML document
    document.getSelection().addRange(selected);   // Restore the original selection}};Copy the code

Rewrite and optimize with React and typescript

  • Learned the above article, combined with the requirements of the product to rewrite the relevant code.
  • Train of thought
    • 1. First create a targetNode and set the absolute layout to hide our element
    • Document.getselection () has been replaced by window.getSelection()
    • Create a result tag to check whether clipping works properly. If not, return false
    • Delete the targetNode
function createNode(text) {
    const node = document.createElement('div');

    node.innerText = text;
    node.style.cssText = 'position:absolute; top: 0; left: 0; height:0; width:0; pointer-events: none; ';

    document.body.appendChild(node);

    return node;
}

export default function copyMe(text) {
    const targetNode = createNode(text);
    const range = document.createRange();
    
    const selection = window.getSelection()! ;const selected = selection.rangeCount > 0       
      ? selection.getRangeAt(0)    
      : false;  

    targetNode.focus(); // focus on the text we need
    range.selectNodeContents(targetNode); 
    
    if(selected){
        selection.removeAllRanges();
        selection.addRange(range);
    }

    let result; 

    try {
        result = document.execCommand('copy');
    } catch (e) {
        result = false;
    }

    document.body.removeChild(targetNode);

    return result;
}
Copy the code

How do I use Copyme

import React, { Fragment } from 'react';
import copyMe from 'utils/copyMe'; interface ItemProps { value? : string | number; }const Item: React.FC<ItemProps> = props= > {
    const { value } = props;

    const copyme = (a)= > {
       alert(copyMe(value) ? 'Copied! ' : 'Failed! ');
    };

    return (
        <Fragment>
            {value && (
                <div>
                    {value}
                    <textarea  value={value} readOnly></textarea>
                    <span onClick={copyme}></span>
                </div>
            )}
        </Fragment>
    );
};

export default Item;
Copy the code

Necessary API reference

  • window/getSelection
  • Selection/getRangeAt
  • Range/selectNodeContents

The original reference

  • Hackernoon.com/copying-tex…