1

What is the proper way of defining javascript functions, inside

$(document).ready(function () {
});

or just outside.

What I have is this :

$(function() {
  var html = '<div class ="new1" ><img id = "new2" onclick = "showPage(' + id + 
      ');" class = "' + id + 
      '" src="@Url.Content("~/Images/blankpageQ.jpg")" />' + 
      i + '</div>');
  $(".pageListQuiz")
    .children('div')
    .eq(numOfPages - 1)
    .append(html);

  function showPage() {
    //some actions
  }
});

and clicking on the appended image throws an exception :

Unhandled exception at line 3, column 1 in script block

0x800a1391 - JavaScript runtime error: 'showPage' is undefined

If there is a handler for this exception, the program may be safely continued.

(The js code is embedded from my c# code.). Everything works fine if I place showPage() outside anyway. I just wonder why its not working when I put it inside because I also have functions placed inside that are just working fine.

10
  • 1
    Depends on what you're wrapping in ready. If some code that depends on the DOM, it should be wrapped in ready(), other code can be move outside of ready. Also, if the JS is included at the end of <body> there's no need of ready. Commented Mar 8, 2016 at 6:45
  • that depends on what you want to achieve. Commented Mar 8, 2016 at 6:45
  • $(document).ready is irrelevant if you're not using jQuery. Commented Mar 8, 2016 at 6:46
  • 2
    @JanLeeYu If you declare a function inside ready() callback, it will not be accessible from outside of the ready() callback. If you want to call this from HTML or other places(outside of ready), move it out of ready(). Commented Mar 8, 2016 at 7:15
  • 1
    You can also try having a generic handler for all added images. You can add a class say newImage and have code $(document).on("click", ".newImage", function(event){ // Do your stuff here }). Commented Mar 8, 2016 at 7:18

3 Answers 3

1

@Tushar's Approach

Idea: Create functions and use $(document).ready() to execute necessary functions.

JSFiddle

$(document).ready(function(){
    ...
})

function showPage(el){
  console.log(el);
}

My Approach

Idea: You can have a event handler, instead of setting onclick attribute. Benefit of this approach is, you can have your markup generation logic clean.

JSFiddle


Note, you can merge both approaches. Its better to declare all functions and then use $(document).ready() as an initialization function. This will just call different functions. If you choose to use event handlers/delegates, you can export all events to different file as well and just call it.

Sign up to request clarification or add additional context in comments.

Comments

1

Function delarations are scoped just like var statements.

If you define a function inside another function, then you can only access it within the scope of that function.

If you want to access it as a global (which is what an intrinsic event attribute like onclick= does), then you either need to define it as a global or copy it into the global scope.

In this case, however, you should avoid using globals. You should also avoid using intrinsic event attributes and building HTML by mashing together strings.

This is untested but should give you the idea.

$(function () {

  var id = "something";
  var numOfPages = 2;

  var html = $("<div/>")
    .addClass("new1")
    .append(
      $("<img/>")
        .attr("id", "new2")
        .on("click", showPage.bind(null, id))
        .addClass(id)
        .attr("src", '@Url.Content("~/Images/blankpageQ.jpg")')
    );
  $(".pageListQuiz")
    .children('div')
    .eq(numOfPages - 1)
    .append(html);

  function showPage(id) { 
  }

});

Comments

1

In your example, you create an <img> element in the HTML of the page. When it is clicked, showPage() is called. Since the function is called from the global scope (as it is called from a click on the HTML, which goes into the global scope), the global scope is looked up for the existence of the showPage() function. However, it does not exist inside the global scope; it exists only in the scope of your $(function() {}) function.

If you want to access showPage() from the global scope, you need to make sure it is available there. You can either do that by defining it outside your $(function() {}) construction (a function declaration creates a new scope), or by defining a var outside your $(function() {}) construction and assigning the showPage() function to that var. For example:

var showPage;

$(function() {
    // Assign the function showPage() to the var showPage:
    showPage = function showPage() {
        // You function body.
    }
});

// showPage is now available in the global scope.

Either solution is OK. Maybe you could read up a bit on Javascript scopes and closures. That will help you understand what's happening here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.