javascripteventsgoogle-chrome-extensionevent-handlinggoogle-chrome-storage

How to save value to chrome storage without button?


Need to save input's value of type text to chrome.storage.sync.set without uses ok button.

<input id="titleUserTab" type="text">
<input id="urlUserTab" type="text">

Problem

  1. Event change of text element triggers by lost it focus. In this case, problem is need to button ok in order to lost focus.

  2. Event input of text element triggers by each keyboard's button. Problem is limits of chrome.storage.sync:

MAX_WRITE_OPERATIONS_PER_HOUR = 1800 The maximum number of set, remove, or clear operations that can be performed each hour.

MAX_WRITE_OPERATIONS_PER_MINUTE = 120 The maximum number of set, remove, or clear operations that can be performed each minute.

Description

My solution

In order to remove button ok, use the input event.

And to save the values, I added an interval and deleted the handler before the trigger time.

What do you think about this case? Maybe you have your own solution? Thanks for any help.

// onload page
function restoreUserTabContext(data) {
    titleUserTab.value = data.title;
    urlUserTab.value = data.url;

    titleUserTab.addEventListener('input', onInputUserTabContext);
    urlUserTab.addEventListener('input', onInputUserTabContext);
}

// handler
function onInputUserTabContext() {
    titleUserTab.removeEventListener('input', onInputUserTabContext);
    urlUserTab.removeEventListener('input', onInputUserTabContext);

    setTimeout(function () {
        let data = {
            title: titleUserTab.value,
            url: urlUserTab.value,
        };

        titleUserTab.addEventListener('input', onInputUserTabContext);
        urlUserTab.addEventListener('input', onInputUserTabContext);

        saveOption('dataUserTab', data);
    }, 4000);
}

function saveOption(key, value) {
    option = {};
    option[key] = value;

    chrome.storage.sync.set(option, function () {
        if (chrome.runtime.lastError) {
            console.error(chrome.runtime.lastError.message);
        }
    });
}

Solution

  • Instead of updating data for every character, we can update change on input blur event. Which will be triggered only after the input is blurred.

    So this only updates when the input is blurred (like when we click outside the input)

     function onBlur() {
            let data = {
                title: titleUserTab.value,
                url: urlUserTab.value,
            };
            saveOption('dataUserTab',data);
     }    
     titleUserTab.addEventListener('blur', onBlur);
     urlUserTab.addEventListener('blur', onBlur);
    

    But if you want the data to be updated dynamically before the blur, it's better to use debounce. So when after every change we call save function with a delay, If a new change comes before the delay is over, the delay gets cancelled and it waits for the new delay to be completed. Which is something similar to your approach, but simpler as we don't need to clear the event listeners and add them frequently. The debounce function will be like this

    function debounce(func, wait, immediate) {
    
      var timeout;
    
      return function executedFunction() {
        var context = this;
        var args = arguments;
    
        var later = function() {
          timeout = null;
          if (!immediate) func.apply(context, args);
        };
    
        var callNow = immediate && !timeout;
    
        clearTimeout(timeout);
    
        timeout = setTimeout(later, wait);
    
        if (callNow) func.apply(context, args);
      };
    };
    function onBlur() {
        let data = {
            title: titleUserTab.value,
            url: urlUserTab.value,
        };
        saveOption('dataUserTab', data);
    }
    titleUserTab.addEventListener('input', debounce(onBlur, 1000));
    urlUserTab.addEventListener('input', debounce(onBlur, 1000));
    

    The above code waits for 1 second before updating the data. ref

    We also can use lodash library for debounce