Debouncing input events in panels

Has anyone had any success/is it possible to call editDocument() in a debounced “context”, i.e., use something like the UnderscoreJS _.debounce function with, say, an onchange in an <input> and then call editDocument in there? The problem I’m facing is that, of course, doing so won’t call editDocument in the same tick as the UI interaction anymore, meaning it gets impossible:

If it isn’t possible, I’ll convert this to a feature request, which is why I’ll already put a use-case here :wink:.

Use case

I’m currently writing a Markdown plugin (i.e., am extremely close to releasing it, but am now developing a panel for the first update of the plugin). In this panel, there is a textarea with which the Markdown contents of the selected text node can get edited. To avoid the problems described by @Velara in Add modal like support for panels preventing new selections, the text gets updated on user input, meaning Markdown has to get reparsed everytime. While I have a very performant Markdown parser, it still isn’t optimal that this happens every time a user enters a new character. I would therefore like to debounce the input, as demonstrated in this example of the VueJS docs: https://vuejs.org/v2/examples/ to avoid such problems.

I agree that this use case won’t be possible given the limitation Kerri described above. @kerrishotts to confirm

What does debounce do? This was the code:

new Vue({
  el: '#editor',
  data: {
    input: '# hello'
  },
  computed: {
    compiledMarkdown: function () {
      return marked(this.input, { sanitize: true })
    }
  },
  methods: {
    update: _.debounce(function (e) {
      this.input = e.target.value
    }, 300)
  }
})

Is it a way to wait 300 ms between each update? I’m doing something like this manually in my panel but maybe if there was an official method it might help? Also, are you copying to clipboard on every input change?

1 Like

Hi @Velara,

pretty much. Debounce effectively limits the number of updates per second, meaning if you type, say, 5 letters in a second, you can limit the update to only get called, e.g., 2 times per second. Still, it will always do the last update (so that nothing gets lost). For me, I read the textareas input, parse it as Markdown and update the text layer contents accordingly. Since parsing Markdown is a bit costly performance-wise (at least for doing so every time the user presses a key), debouncing would allow to limit parsing to, e.g., once per second, leading to much smoother performance and UX.

Therefore, while I’m not copying to clipboard, I’m still doing a scenegraph change requiring me to use editDocument

I’m interested in the answer as well. I’m trying to use editDocument on a click that triggers a fetch and my UI event gets disconnected from the editDocument.

Note that you might be able to use promises to solve this, since editDocument will deal with a Promise return.

I have a theory how I could get it to work. I’ll test it later and keep you updated :slightly_smiling_face:

Pseudocode

// Text to apply
let tte <- undefined

textarea.onchange =>
  if !tte
    editDocument async =>
      await delay
      apply tte to text node
  tte <- value;

Update: The idea didn’t work :laughing:. I hadn’t known editDocument (in an asynchronous state) actually blocks the UI elements…

As it looks like this won’t work (as the only way to keep the editing time frame open blocks the UI), I’m now converting this into a feature request, with the use-case described above.