RunzWitScissors
RunzWitScissors

Reputation: 33

Why is my function not playing nice with .ready?

I built my script in javascript and then decided to convert it to jQuery to simplify future functionality. When I added the .ready around my script my function is no longer visible. From my understanding about how .ready works its contents should only fire after the DOM has been created. So I would expect to see the result of console.log(userInput) - I've taken out most of the code for example purposes. But when I run the program firebug shows "ReferenceError: getInput is not defined".

Here is my html:

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
    <script src="script/script.js"></script>
</head>
<body>
    <form>
        Input: <input type="text" name="userInput" id="userInput" autofocus><br>
        <input type="button" value="Submit" name="Submit" onclick="getInput()">
    </form>
</body>
</html>

Here is my script:

    $(document).ready(function() {
        function getInput() {
            var userInput = $('#userInput').val(); 
            console.log(userInput);
        }
    });

If I remove the .ready function everything works as expected but I'm not sure why there is a conflict. I read this post (What exactly does $(document).ready guarantee?) which mentions adding an onload function, which I attempted, but I still got the same error.

Why is .ready causing a conflict? I don't need it but it still doesn't make sense to me. Can someone explain what the issue is or point me to a post that explains it?

Upvotes: 0

Views: 49

Answers (6)

adeneo
adeneo

Reputation: 318312

You've made the mistake of using inline event handlers with jQuery.

Inline event handlers require the function to be available in the global scope (window.functionName), while document.ready has it's own scope that is not global, hence the function defined inside document.ready is not available to the inline event handler.

What you should've done, was use more jQuery

<form id="myForm">
    Input: <input type="text" name="userInput" id="userInput" autofocus>
    <br />
    <input type="submit" value="Submit">
</form>

-

$(document).ready(function() {
    $('#myForm').on('submit', function(e) {
        e.preventDefault();

        var userInput = $('#userInput').val(); 
        console.log(userInput);
    });
});

Using an actual submit button, and the forms submit event seems more appropriate.

Upvotes: 3

vegas2033
vegas2033

Reputation: 250

I create a JsFiddle for you. I made a few modifications to it and instead of adding the onclick event to your button, I added the listener in the javascript.

The problem comes from the fact that you bind the listener in your HTML but look for it in your jquery. You can either create the function outside of the .ready() which you said worked for you or bind the event in jQuery as below.

<body>
<form>
    Input: <input type="text" name="userInput" id="userInput" autofocus><br>
    <input type="button" value="Submit" name="Submit" id="submit">
</form>

$(document).ready(function() {
    $('#submit').on('click', function(){
        alert($('#userInput').val());
    });
});

Fiddle: https://jsfiddle.net/uj981130/

Best

Upvotes: 0

Zayn Ali
Zayn Ali

Reputation: 4925

You are defining function in document.ready closure which has it's own scope so while executing your function with onclick attribute won't work. because it's not in the global scope. Instead just bind your function with window so that onclick can find it. use this

$(document).ready(function() {
    window.getInput = function() {
        var userInput = $('#userInput').val(); 
        console.log(userInput);
    }
});

or you can get the same thing using jquery which is recommended

Input: <input type="text" name="userInput" id="userInput" autofocus><br>

<input type="button" value="Submit" name="Submit" id="submit-button">

$(document).ready(function() {
    $("#submit-button").click(function() {
        var userInput = $("#userInput").val();
        console.log(userInput);
    });
});

Upvotes: 0

Arun Ghosh
Arun Ghosh

Reputation: 7754

The function scope is limited with the document ready function callback. So you need to refer it via globally accessible variable:

MyModule = {}; 
$(document).ready(function() {
    MyModule.getInput = function() {
        var userInput = $('#userInput').val(); 
        console.log(userInput);
    }
});

Now you can access it via MyModule.getInput

And as far as I can see there is no need to put this function under document ready.

Upvotes: 0

Christos
Christos

Reputation: 53958

You could achieve that you want, changing a bit both your html and js code.

$(document).ready(function() {
    // attach an even handler for the click event
    // on the elements that have the class js-submit
    $('.js-submit').click(function(){

        // get the value of the input.
        var userInput = $("#userInput").val();

        console.log(userInput);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
        Input: <input type="text" name="userInput" id="userInput" autofocus><br>
        <input type="button" value="Submit" name="Submit" class="js-submit">
    </form>

Upvotes: 1

Elentriel
Elentriel

Reputation: 1237

They are on different context. That is, the onclick is looking at it on the global context, while the function is defined inside the .ready unnamed function. Either bind your click handler inside the .ready, or define your function outside of it.

Upvotes: 0

Related Questions