InvalidOperation is firing instead of ClipboardPasted on paste in chrome v 127

Posted by: dsudhir on 13 August 2024, 3:39 am EST

  • Posted 13 August 2024, 3:39 am EST

    We render only the viewport range of spread sheet initially and render the cells as and when the user scrolls.

    If the user tries to paste cell from excel that goes beyond the viewport, we handle it in ClipboardPasted event by rendering the additional cells.

    After the latest chrome update (v127.x) we are observing that ClipboardPasted isn’t triggered in the above mentioned scenario. InvalidOperation is triggered instead.

    PS: It worked fine before the chrome update. It works fine in other browsers like Firefox & MS Edge.

  • Posted 14 August 2024, 12:47 am EST - Updated 14 August 2024, 12:52 am EST

    Hi,

    From what I understand, when you’re pasting data from Excel into Spread, the “invalid operation” event is being triggered instead of the “clipboard pasted” event.

    I attempted to replicate the behavior on my end and found that the “invalid operation” event only occurs when trying to paste data that requires a larger range, which is the expected behavior. However, if you want to prevent the “invalid operation” event when pasting data that exceeds the available range, you can use the spread.options.allowExtendPasteRange = true option. This setting automatically extends the range to accommodate the pasted data. Refer to the attached gif “Steps.gif” and the designer link below.

    Designer link: https://developer.mescius.com/spreadjs/designer/index.html

    If there’s a difference in understanding, could you please provide more details? To assist you better, could you share a sample along with the steps to replicate the behavior you’ve observed? Alternatively, you can modify the existing samples provided below to demonstrate the issue. This will help me investigate the problem more thoroughly. Additionally, it would be helpful if you could provide a GIF or video illustrating the issue.

    Spread component: https://jscodemine.mescius.io/share/F_d7Q33JOkmS33zBip8vwA/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"]%2C"ActiveFile"%3A"%2Findex.html"}

    Designer component: https://jscodemine.mescius.io/share/Yw7CCu0nTUi-8GwonSGqKQ/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"]%2C"ActiveFile"%3A"%2Findex.html"}

    Regards,

    Priyam

  • Posted 17 August 2024, 3:44 am EST

    Please review the two video GIFs for comparison. As shown in “MS Edge.gif”, the functionality works correctly in MS Edge, similar to how it performed in Chrome v126.x. The other GIF (Chrome.gif) demonstrates the behavior in Chrome v127.x.

    Additionally, setting spread.options.allowExtendPasteRange = true; does not seem to resolve the issue.

    Please let me know if you need any further information.

  • Posted 17 August 2024, 3:47 am EST - Updated 17 August 2024, 3:49 am EST

    Chrome.gif didn’t get uploaded in the previous reply. Attaching the compressed version here.Chrome.rar

  • Posted 19 August 2024, 2:45 am EST - Updated 19 August 2024, 2:50 am EST

    Hi,

    This issue appears to be expected behavior in both Edge and Chrome browsers. When you copy and paste data, if there isn’t enough space to paste the data, an invalid operation event will be triggered. I tested this in both Edge and Chrome and observed the same result: if there isn’t enough range available for pasting, the invalid operation event is triggered; however, if there is sufficient range, the paste operation completes without any issues.

    To avoid this issue, ensure that you paste data where there is enough range available. Please refer to the attached GIF “Steps.gif” for more details.

    Gif:

    If you still encounter an invalid operation despite having enough range, please share a sample along with the steps to replicate the behavior you’ve observed. Alternatively, you can modify the existing samples provided below to demonstrate the issue. This will help me investigate the problem more thoroughly.

    Spread component: https://jscodemine.mescius.io/share/F_d7Q33JOkmS33zBip8vwA/?defaultOpen={“OpenedFileName”%3A[“%2Findex.html”]%2C"ActiveFile"%3A"%2Findex.html"}

    Designer component: https://jscodemine.mescius.io/share/Yw7CCu0nTUi-8GwonSGqKQ/?defaultOpen={“OpenedFileName”%3A[“%2Findex.html”]%2C"ActiveFile"%3A"%2Findex.html"}

    Regards,

    Priyam

  • Posted 19 August 2024, 8:56 am EST - Updated 19 August 2024, 11:41 am EST

    If you see the gifs I shared, InvalidOperations is not thrown in MS Edge and it works fine. This even works fine in chrome v 126.x. I also wanted to let you know that we are using spread js version 12.2.5. Has the older version anything to do with the issue?

  • Posted 20 August 2024, 5:31 am EST - Updated 20 August 2024, 5:37 am EST

    Hi,

    I tried to replicate the issue on my end using SpreadJS version 12.2.5 and Chrome version 127, but I was unable to reproduce the problem. Everything is working as expected on my side with SpreadJS version 12.2.5 in both Edge and Chrome. Please see the attached GIF (“Steps.gif”) and sample (“Sample.zip”) for reference.

    Gif:

    Sample: Sample.zip

    Tested Environment:

    OS: Windows 11 Pro (Version: 23H2)

    Chrome Version: 127.0.6533.120 (Official Build) (64-bit)

    Edge Version: 127.0.2651.105 (Official Build) (64-bit)

    Processor: 12th Gen Intel(R) Core™ i7-1270P

    RAM: 16 GB

    Could you please try testing with the latest version 17.1.3 using the provided sample? If the issue persists, could you share a small working sample to help replicate the behavior or modify the existing sample? This would greatly assist in thoroughly investigating the issue. Additionally, it would be helpful if you could provide a GIF or video illustrating the issue and could you share your tested environment details as well?

    Latest version sample: https://jscodemine.mescius.io/share/F_d7Q33JOkmS33zBip8vwA/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fapp.js"%2C"%2Fpackage.json"]%2C"ActiveFile"%3A"%2Fpackage.json"}

    Regards,

    Priyam

  • Posted 22 August 2024, 2:07 am EST

    Hi,

    You are right.

    Looks like I have got hold of the root cause. As I mentioned, we only render the viewport initially and as and when the user scrolls we leverage the topRowChange and leftColChange event to render the new viewport.

    In case of pasting from Excel, we are hooking the DOMNodeInserted event on the container div and registering paste event listener on the textarea that the spread control adds. Inside the paste callback, we figure out the new viewport range and render it. Now that DOMNodeInserted event is removed from chrome 127.x , we are encountering this issue.

    In order to solve this, I have tried to replace DOMNodeInserted with MutationObserver but that is causing InvalidOperations event to be called before the paste callback of the textarea. I wanted to check if there is a way to delay InvalidOperations or any other solution that you think will work. Here is the code of the DomNodeInserted event for your reference:

    var self = this,

    addPasteHandler = true;

    $(config.container)[0].addEventListener(‘DOMNodeInserted’, function (e) {

    if(!addPasteHandler){

    return;

    }

    var ta;

    // When we dont set any value to allowCopyPasteExcelStyle

    // div (gcSheetClipboard) is used, else text area is used by library.

    if(self.constants.isMacOS) {

    ta = $(‘div[gcuielement=“gcSheetClipboard”]’, this);

    }

    else {

    ta = $(‘textarea[gcuielement=“gcSheetClipboard”]’, this);

    }

            if (ta.length == 1) {
                ta[0].addEventListener("paste", function (event) {
                    var clipText = "",
                        cLen;
                    if (window.clipboardData && window.clipboardData.getData) { // IE
                        clipText = window.clipboardData.getData('Text');
                    } else if (event.clipboardData && event.clipboardData.getData) {
                        clipText = event.clipboardData.getData("text/plain");
                    }
                    console.log('clipText ', clipText);
                    cLen = clipText.length;
    
                    if (clipText[cLen - 1] == '\r' || clipText[cLen - 1] == '\n' || clipText[cLen - 1] == '\f') {
                        clipText = clipText.substring(0, cLen - 1);
                    }
                    
                    var clipRows = clipText.split(/[\n\f\r]/),
                        delim = "\t",
                        clipCols = clipRows[0].split(delim).length,
                        sheet = self.getActiveSheet(),
                        row = sheet.getActiveRowIndex(),
                        col = sheet.getActiveColumnIndex();
                    console.log('clipCols ', clipCols);
                    /*
                    * Making sure the destination rendered before the paste so we can avoid the read-only cells issue 
                    */
                   
                    var selections = self.getSelections();
                    var toRows = row + clipRows.length - 1;
                    var toCols = col + clipCols - 1;
    
                    if(selections && selections.length > 0) {
                        toRows = Math.max(toRows, row + selections[0].rowCount);
                        toCols = Math.max(toCols, col + selections[0].colCount);
                    }
                    console.log('toCols', toCols);
                    self.isPaintSuspended(true);
                    self.renderRange(sheet, self.getSheetDataBySheet(sheet), row, col,toRows, toCols);
                    self.isPaintSuspended(false);
                });
                addPasteHandler = false;
            }
        }, false);
    
  • Posted 23 August 2024, 8:22 am EST

    Hi,

    The DOMNodeInserted event is deprecated and has been replaced by the more efficient MutationObserver API, which offers a better way to monitor DOM changes. It seems you’re already using the MutationObserver API but are encountering an issue where an invalid operation is being triggered before the paste event you’ve attached.

    After reviewing your code snippet, it looks like your paste event is attached in the bubble phase. I suggest attaching the paste event in the capture mode instead. Please refer to the attached code snippet:

    ta[0].addEventListener("paste", function (event) {
        var clipText = "",
            cLen;
        if (window.clipboardData && window.clipboardData.getData) { // IE
            clipText = window.clipboardData.getData('Text');
        } else if (event.clipboardData && event.clipboardData.getData) {
            clipText = event.clipboardData.getData("text/plain");
        }
        console.log('clipText ', clipText);
        cLen = clipText.length;
    
        if (clipText[cLen - 1] == '\r' || clipText[cLen - 1] == '\n' || clipText[cLen - 1] == '\f') {
            clipText = clipText.substring(0, cLen - 1);
        }
    
        var clipRows = clipText.split(/[\n\f\r]/),
            delim = "\t",
            clipCols = clipRows[0].split(delim).length,
            sheet = self.getActiveSheet(),
            row = sheet.getActiveRowIndex(),
            col = sheet.getActiveColumnIndex();
        console.log('clipCols ', clipCols);
        
        /*
        * Ensuring the destination is rendered before pasting to avoid issues with read-only cells
        */
        
        var selections = self.getSelections();
        var toRows = row + clipRows.length - 1;
        var toCols = col + clipCols - 1;
    
        if (selections && selections.length > 0) {
            toRows = Math.max(toRows, row + selections[0].rowCount);
            toCols = Math.max(toCols, col + selections[0].colCount);
        }
        console.log('toCols', toCols);
        self.isPaintSuspended(true);
        self.renderRange(sheet, self.getSheetDataBySheet(sheet), row, col, toRows, toCols);
        self.isPaintSuspended(false);
    }, true); // Set the third argument to true for capture mode

    If you continue to experience issues, could you please provide more details about your exact use case? I’m having some difficulty understanding it fully from the code snippet since it appears to be from an older version. My understanding is that you are checking if there is enough range to paste, and if not, you are adding enough columns to paste the data without issues.

    Regards,

    Priyam

  • Posted 23 August 2024, 8:53 am EST - Updated 23 August 2024, 9:04 am EST

    Attaching the paste event in capture mode has been helpful. I’ll be testing it thoroughly and will reach out if I need any further assistance.

    Thank you so much for your patience and support.

  • Posted 26 August 2024, 12:56 am EST

    Hi,

    We are happy that your query has been resolved.

    You could always create new tickets for new queries/issues.

    Regards,

    Priyam

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels