Override jQuery .val() function?

Viewed 23207

Is there a way to easily override jQuery's val() function?

The reason I want to override it is that I want to add some processing each time a value is set for an element. And I don't want to make another custom value setter, such as myVal().

6 Answers

You can store a reference to the original val function, then override it and do your processing, and later invoke it with call, to use the right context:

(function ($) {
  var originalVal = $.fn.val;
  $.fn.val = function(value) {
    if (typeof value != 'undefined') {
      // setter invoked, do processing
    }
    return originalVal.call(this, value);
  };
})(jQuery);

Note that you can distinguish between a getter call $(selector).val(); and a setter call $(selector).val('new value'); just by checking if the value argument is undefined or not.

If I am understanding you right, something like this should do the trick just fine:

jQuery.fn.val = function (new_val) {
    alert("You set a val! How wonderful!");
    this.value = new_val;
};

Just make sure you include the regular functionality: getting values of selects and so on. Just stick that code after after the regular jQuery library.

With this code you can override the "get" and "set" of .val() for specific elements:

(function () {

    var __val = $.fn.val;
    $.fn.val = function (value) {
        if (this[0] && (this[0].$val_get || this[0].$val_set)) {
            if (arguments.length === 0) return this[0].$val_get();
            else return this[0].$val_set(value) || this;
        }
        return __val.apply(this, arguments);
    };

})();

Now you have to create two function properties on the DOM element - $val_get and $val_set:

<input type="text" id="myInput" />
<input type="text" id="someOtherInput" />

<script>

    $('#myInput')[0].$val_get = function () {
        console.log('Got value from myInput!');
        return this.value;
    };

    $('#myInput')[0].$val_set = function (value) {
        console.log('Set value of myInput!');
         this.value = value;
    }

    //----

    $('#myInput').val('Hello!'); //Console: "Got value from myInput!"
    $('#myInput').val(); //Hello! | Console: "Set value to myInput!"

    $('#someOtherInput').val('Hello!'); //Console: ""
    $('#someOtherInput').val(); //Hello! | Console: ""

</script>

This is useful for creating components that orchestrate multiple controls.

JsFiddle: https://jsfiddle.net/oj4gt2ye/6/

Related