skip to Main Content

I have the following code:

let value = $(this).data('value');
value = System.decrypt(value, key);
$(this).data('value', value);

I’d like it to support chaining:

$(this)
    .data('value', (value) => System.decrypt(value, key))
    .css(…)
    .prop(…);

But as far as I see, jQuery doesn’t have a lambda version of .data(). Is there a simple way to achieve this, or I should write a plugin?

2

Answers


  1. Chosen as BEST ANSWER

    Well, I wrote the following simple helpers:

    // Updates a key. Chaining compatible.
    jQuery.fn.updateData = function (key, updateCallback)
    {
        this.data(key, updateCallback(this.data(key)));
        return this;
    };
    
    // Updates an attribute. Chaining compatible.
    jQuery.fn.updateAttr = function (attributeName, updateCallback)
    {
        this.attr(attributeName, updateCallback(this.attr(attributeName)));
        return this;
    };
    
    // Updates a property. Chaining compatible.
    jQuery.fn.updateProp = function (propName, updateCallback)
    {
        this.prop(propName, updateCallback(this.prop(propName)));
        return this;
    };
    
    // Updates a value. Chaining compatible.
    jQuery.fn.updateVal = function (updateCallback)
    {
        this.val(updateCallback(this.val()));
        return this;
    };
    

  2. I see nothing wrong in getting the initial data beforehand, and setting it later (as in your first example).
    If you want to modify the way the .data() method operates, you could rewrite it to accept a callback function to act as getter + setter and provide chainability, something among this lines:

    ($ => {
      // Store original:
      const $FnData = $.fn.data;
      // Modify .data() method
      $.fn.data = function (key, val) {
        // Run callback:
        if (typeof val === "function") {
          return this.each((_i, el) => {
            const $el = $(el);
            const valCurr = $el.data(key);
            const valNew = val.call(el, valCurr);
            $el.data(key, valNew);
          });
        }
        // Run default:
        return $FnData.apply(this, arguments);
      };
    })(jQuery);
    

    Example:

    const System = { decrypt: (val, key) => atob(key) + atob(val), }
    const key = "SGVsbG8sIA==";
    
    $("[data-value]")
      .data("value", (val) => System.decrypt(val, key))
      .text($("[data-value]").data("value"))
      .css({color: "red"});
    <h1 data-value="V29ybGQh">Test</h1>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script>
    ($ => {
      // Store original:
      const $FnData = $.fn.data;
      // Modify .data() method
      $.fn.data = function (key, val) {
        // Run callback:
        if (typeof val === "function") {
          return this.each((_i, el) => {
            const $el = $(el);
            const valCurr = $el.data(key);
            const valNew = val.call(el, valCurr);
            $el.data(key, valNew);
          });
        }
        // Run default:
        return $FnData.apply(this, arguments);
      };
    })(jQuery);
    </script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search