Friday, 16 October 2020

Function to copy rendered table randomly stops working, a page refresh fixes the issue

I can't seem to figure out why this function stops working. Refreshing the page fixes the issue. What it does is take a table by ID, strip the classes and does some optimization on the styles. The users are copying and pasting a generated table into their emails.

Can you spot why it's occasionally failing? I don't see any errors in the console when it happens, and I can seem to figure out why it works fine most of the time.

A page refresh fixes the issue.

(this function is called onPress by a button in React. It has worked for over a year just fine but has seemed to have stopped working in the last week sporadically and I can't find any package updates that may have effected it)

function copyByElementId(element: HTMLElement | null) {
    if (!element) return false;

    // Clone the node so we don't interrupt the view
    let el = element.cloneNode(true) as HTMLTableElement;
    el.className = ""; // Remove classes from parent Div

    if (comparedScenarios.length > 1) {
      // Delete last row if the arrows are present
      el.deleteRow(el.children[0].children.length - 1);
    }

    // Add default fonts to the table
    el.style.fontSize = "inherit";
    el.style.fontFamily = "San Francisco, Helvetica, Arial, sans-serif";

    // This works for clients other than Outlook grrr...
    el.style.borderCollapse = "collapse";
    el.style.borderSpacing = "16px 4px";
    el.style.border = "0";

    let rows = el.children[0].children; // Rows in the table

    // Add padding to the left side of each cell other than the 1st column
    for (let i = 0; i < rows.length; i++) {
      let cells = rows[i].children;
      rows[i].className = ""; // Remove classes from rows
      for (let i = 0; i < cells.length; i++) {
        cells[i].className = ""; // Remove classes from cells
        // Only the 2nd column and after
        let cell = cells[i] as HTMLTableCellElement; // TD element
        cell.style.border = "0";
        if (i > 0) {
          cell.style.paddingTop = "0";
          cell.style.paddingRight = "0";
          cell.style.paddingBottom = "0";
          cell.style.paddingLeft = "20px";
        }
      }
    }

    // Create our hidden div element
    let hiddenDiv = document.createElement("div");
    hiddenDiv.style.position = "absolute";
    hiddenDiv.style.left = "-9999px";
    hiddenDiv.style.backgroundColor = "";

    // Render the table of the hidden div
    hiddenDiv.appendChild(el);

    // Check and see if the user had a text selection range
    let currentRange;
    let documentSelection = document.getSelection();
    if (documentSelection?.rangeCount && documentSelection?.rangeCount > 0) {
      // The user has a text selection range, store it
      currentRange = document.getSelection()?.getRangeAt(0);
      // Remove the current selection
      window.getSelection()?.removeAllRanges();
    }

    // Append the div to the body
    document.body.appendChild(hiddenDiv);
    // Create a selection range
    let CopyRange = document.createRange();
    // Set the copy range to be the hidden div
    CopyRange.selectNode(hiddenDiv);
    // Add the copy range
    window.getSelection()?.addRange(CopyRange);

    //since not all browsers support this, use a try block
    try {
      //copy the text
      document.execCommand("copy");
    } catch (err) {
      window.alert("Your browser doesn't support copy and paste! Error:" + err);
    }
    //remove the selection range (Chrome throws a warning if we don't.)
    window.getSelection()?.removeAllRanges();
    //remove the hidden div
    document.body.removeChild(hiddenDiv);

    //return the old selection range
    if (currentRange) {
      window.getSelection()?.addRange(currentRange);
    }
    runButtonStates();
  }


from Function to copy rendered table randomly stops working, a page refresh fixes the issue

No comments:

Post a Comment