Fillip Peyton
Fillip Peyton

Reputation: 3657

HTML Input Element has no method 'isValid'

I have a javascript class c and I am trying to call its method isValid() on the onClick event of a input submit button. I have c in a set of script tags below my submit button currently. When I click on the submit button, I get

Uncaught TypeError: Object #<HTMLInputElement> has no method 'isValid'

After some messing around, I try placing the same submit button at the bottom of the page, below the class script. This allows the method to be called correctly.

Here's my javascript:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
var c = {
        container : $('#c_c'),
        r1 : 0,
        r2 : 0,
        c_i : "",
        createCaptcha : function(){
            var newHtml;

            this.r1 = this.randomNumber(10);
            this.r2 = this.randomNumber(10);
            // alert(this.r1 + this.r2);

            newHtml += "<p>What is " + this.r1 + " plus " + this.r2 + "?<br/><input type='text' name='c'></p>";

            this.container.html(newHtml);
        },
        isValid : function(){
            // alert(this.r1);
            this.c_i = $('input[name="c"]');
            if (this.r1 + this.r2 == this.c_i.val()) {
                alert('correct!');
                return true;
            } else{
                alert('incorrect =[');
                return false;
            }
        },
        randomNumber : function(max){ return Math.floor(Math.random()*(max+1)); }
    }
    c.createCaptcha();
</script>

And here is my button:

<input id="form_0001_ao_submit_input" type="button" name="SUBMIT" value="Submit" style="color:#fff; font-size: 18px; height: 30px; width: 250px; background-color: #00a94f;" onClick="c.isValid();">

I also have a span with an ID on the page. This is what is referenced in createCaptcha() (Sorry I missed this vital piece of info =[):

<span id="c_c"></span>

So here's what the page looks like:

<span id="c_c"></span>
<input id="form_0001_ao_submit_input" type="button" name="SUBMIT" value="Submit" style="color:#fff; font-size: 18px; height: 30px; width: 250px; background-color: #00a94f;" onClick="c.isValid();">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
    var c = {
        container : $('#c_c'),
        r1 : 0,
        r2 : 0,
        c_i : "",
        createCaptcha : function(){
            var newHtml;

            this.r1 = this.randomNumber(10);
            this.r2 = this.randomNumber(10);
            // alert(this.r1 + this.r2);

            newHtml += "<p>What is " + this.r1 + " plus " + this.r2 + "?<br/><input type='text' name='c'></p>";

            this.container.html(newHtml);
        },
        isValid : function(){
            // alert(this.r1);
            this.c_i = $('input[name="c"]');
            if (this.r1 + this.r2 == this.c_i.val()) {
                alert('correct!');
                return true;
            } else{
                alert('incorrect =[');
                return false;
            }
        },
        randomNumber : function(max){ return Math.floor(Math.random()*(max+1)); }
    }
    c.createCaptcha();
</script>

It definitely seems like having the call to the method of the not yet defined c object is not allowing the method to run, which makes sense.

What would be the best way to aleviate this, without having to move the script to the top of the page (as performance wise, js is better placed at the bottom)? Thanks for the help!

Upvotes: 0

Views: 2802

Answers (3)

Marlon Bernardes
Marlon Bernardes

Reputation: 13843

I would do the following changes to your code:

  1. Remove var "c" from the global scope. This scope should be used very carefully. Imagine if another javascript file also declared a var named "c" (shame on them) using this scope. It would've been overwritten by you.

  2. Remove the "onClick" attribute declared directly on the input.

  3. Since you're using jQuery, you could declare your code inside the "ready" method (which is executed right after the DOM is loaded - no matter where your place your script. Like this:



    $(function(){
        //c now is inside a function, so it's not declared on the global scope
        var c = {
           // ... your code
        };  

        //creates the captcha when the DOM is loaded
        c.createCaptcha(); 

        $('#form_0001_ao_submit_input').click(function(){
            c.isValid();
        });

    });

Also consider extracting your javascript code to another file (and import it as you did with jQuery) so the browsers will be able to cache it for faster loading.

Upvotes: 1

Tom
Tom

Reputation: 21

Maybe you can add an event listener to the input object later in your code. With JQuery:

$("#form_0001_ao_submit_input").click(function() { c.isValid(); });

(after declaring c)

Upvotes: 2

BenR
BenR

Reputation: 2936

Your input element is trying to access the global variable c.

Simply change your JavaScript to explicitly declare c as a global variable as such:

window.c = {
    ...
};

Working example: http://jsfiddle.net/ud66S/1/

Upvotes: -1

Related Questions