1

So i tried to modified the original jQuery's val() method using the following code

(function ($) {
    var original_val = jQuery.fn.val;
    jQuery.fn.val = function( value ) {
        var elem = this[0], val = undefined;

        // Set for value first, if its undefined
        val = value ? value : "";

        if (elem){
            if (elem.hasAttribute('thisattribute')){
                if (val){
                    if (typeof val === 'number'){
                        // Do something here if val is a typeof number
                    }
                } else {
                    // Do something here if val doesn't exist
                }
            }
        }

        console.log("Let me see what is value ::: ", val);
        console.log("Let me see what is elem ::: ", elem);

        return original_val.apply(this, [val]);
    }
})(jQuery);

Using the code above, i check if the input element has a certain attribute on it, then proceed with modifying the value, before passing it to the original jQuery's val() method.

Using this method i managed to modify the value when i use the following code

$(id).val(10000)

But when i tried to retrieve the value using bottom code, it failed

$(id).val()

Some more, i can no longer chain the val() method with other method like trim() after i modified it, as it throws me the following error

Uncaught TypeError: input.val(...).trim is not a function

What did i do wrong here?

Fred A
  • 1,602
  • 1
  • 24
  • 41

1 Answers1

2

It's because your code is always providing an argument to the original val when calling it, even when being used as a getter. So the original val always thinks it's being called to set the value.

I'd make the getter case an early exit from the function, right near the top:

if (!arguments.length) {
    return original_val.call(this);
}

(That's the same check jQuery does.)


Some side notes:

  • This:

    return original_val.apply(this, [val]);
    

    can be more efficiently written like this:

    return original_val.call(this, val);
    

    No need to create that array.

  • In a couple of places, you're testing for falsiness but the code seems to be meant to check for undefined instead


Live Example, see *** comments:

(function($) {
    var original_val = jQuery.fn.val;
    jQuery.fn.val = function(value) {
        // *** Early exit when used as a getter
        if (!arguments.length) {
            return original_val.call(this);
        }
        var elem = this[0],
            val = undefined;

        // Set for value first, if its undefined
        // *** Note: This converts any falsy value to "", not just undefined.
        // *** Later you have a check for `val` being a number. `0` is falsy.
        val = value ? value : "";

        if (elem) {
            if (elem.hasAttribute('thisattribute')) {
                if (val) { // *** Again, 0 is falsy
                    if (typeof val === 'number') {
                        // Do something here if val is a typeof number
                    }
                } else {
                    // Do something here if val doesn't exist
                }

                // Just for the purposes of demonstration:
                val = val.toUpperCase ? val.toUpperCase() : val;
            }
        }

        console.log("Let me see what is value ::: ", val);
        console.log("Let me see what is elem ::: ", elem);

        return original_val.call(this, val);
    }
})(jQuery);


// *** Setting a value
$("#txt").val("foo");
// *** Reading a value
console.log($("#txt").val());
<input type="text" id="txt" value="" thisattribute="">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
scraaappy
  • 2,830
  • 2
  • 19
  • 29
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Exactly hitting the point. Thanks! Btw can i modify the value of the val() if i use it as a getter. For example, using val() to get value from a text input, i will get a '1,000' of string type but i want to return it as 1000 of number type. Is this possible? – Fred A Dec 07 '18 at 01:55
  • 1
    @FredA - Easily. In the early-exit above: `return +original_val.call(this).replace(/,/g, "");` :-) – T.J. Crowder Dec 07 '18 at 06:46
  • What is the purpose of that + on that +original? – Fred A Dec 10 '18 at 16:36
  • 1
    @FredA - That's one of many ways to convert a string to a number. I give a rundown of the various options [in this answer](https://stackoverflow.com/questions/28994839/why-does-string-to-number-comparison-work-in-javascript/28994875#28994875). – T.J. Crowder Dec 10 '18 at 16:38