Issue #1895Opened March 15, 2019by simplecommerce0 reactions

[QUESTION] Drag component over canvas with script, script appended multiple times.

Question

Hi, not sure if this is a bug or not.

But I noticed a weird behavior, when I drag a block that has a component that contains a script function, it seems to append it into the canvas before its being dropped.

And as you drop it, it appends another time, the script.

If you never drop the block and just drag over and out over and out, it appends as many times as possible.

And it never seems to clearn when I click clear canvas, I had to manually do:

editor.Canvas.getCanvasView().getJsContainer().innerHTML = '';

To clear the canvas JS.

Here is a screen shot of the issue on your demo page.

image

Answers (3)

simplecommerceMarch 17, 20190 reactions

So I dug around and figured that it was the updateScript method in the canvasView that was being called every time a script property is found on a component, regardless if its still being dragged or not over the canvas.

I did some patching to test and it seemed to have fixed the issue.

I had to overwrite it this way as I did not want to modify the original code directly, in case it gets fixed in the future.

Didn't know how to detect if the model was currently being dragged, only noticed that when the component is dropped in the canvas, updateScript is called, modelOpt had an extra attribute at, so relied on this.

Until someone makes a better, cleaner fix.

    const canvasView = editor.Canvas.getCanvasView();
    canvasView.updateScript = function(view) {
      // check if at attribute exists, if not assume we are still dragging
      if (!isUndefined(view.modelOpt.at)) {
        const model = view.model;
        const id = model.getId();        

        // check if we have previously inserted the script, if so, remove it
        let previousScript = this.getJsContainer().querySelector(`script[data-model-id="${id}"]`);
        if (previousScript !== null) previousScript.parentElement.remove();
        
        if (!view.scriptContainer) {
          view.scriptContainer = document.createElement('div');
          this.getJsContainer().appendChild(view.scriptContainer);
        }

        view.el.id = id;
        view.scriptContainer.innerHTML = '';
        // In editor, I make use of setTimeout as during the append process of elements
        // those will not be available immediately, therefore 'item' variable
        const script = document.createElement('script');
 
        // set custom attribute for script tag, in order to detect it, to remove it when dragging the same block within the canvas
        script.setAttribute('data-model-id', id);

        script.innerHTML = `
            setTimeout(function() {
              var item = document.getElementById('${id}');
              if (!item) return;
              (function(){
                ${model.getScriptString()};
              }.bind(item))()
            }, 1);`;
        // #873
        // Adding setTimeout will make js components work on init of the editor
        setTimeout(() => view.scriptContainer.appendChild(script), 0);
      }
    }
simplecommerceMarch 31, 20190 reactions

My previous solution did not work, so I had to scrap it, so I re-opened the issue.

artfApril 3, 20190 reactions

Hi @simplecommerce if you think it's a bug, please open an issue by FOLLOWING the template and create a reproducible live demo of the issue. It's really important because as we don't have a lot of free time we risk to waste a big part of it on debugging issue not related to the library itself

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.