Skip to content Skip to sidebar Skip to footer

Javascript Call Functions From Element Events Without Global Scope

In an externally loaded javascript file (using jQuery) I have: $(function() { function foo() { console.log('bar'); } } However in the HTML when I try and call: <

Solution 1:

you could attach it to the global window object:

$(function() {
    window.foo = function() {
        console.log("bar");
    }
}

Solution 2:

Is it possible keeping the actual function call in the HTML (on the a tag) and have it work?

No. To use that method on the HTML element, onclick=foo(), then the function foo must be in the global scope.

Defining the function without the var keyword would allow it to enter the global scope:

$(function() {
   foo = function() { console.log('bar'); }
});

But it's never good to pollute the global scope, so why not namespace it?

$(function() {
   var ns = 'MYNAMESPACE';
   window[ns] = window[ns] || {}; //create a global namespacewindow[ns].foo = function() { console.log('bar'); }
});

<ahref="#"onclick="MYNAMESPACE.foo()">Call foo</a>

Solution 3:

Is it possible keeping the actual function call in the HTML (on the a tag) and have it work?

No, if your function foo is not in the global scope or on one of a few special global objects then the HTML cannot find your function and there is nothing you can do in the HTML to change that. For reference, your function foo is in a local scope, not in the global scope. So, for the HTML to remain unchanged, you would have to move foo to the global scope or to one of a few global objects.

There are a bunch of reasons why it is not a great practice to embed function calls directly in the HTML. One main reason is that it requires that those functions be globally scoped which, in itself, is not a good practice.

Since you already are using jQuery, you could simply change your code to this:

$(function() {
    functionfoo() {
        console.log("bar");
    }

    $("#callme").click(foo);
}

<a id="callme">Call foo</a>

Or, if you have multiple <a> tags that want the same click behavior, you can do this:

$(function() {
    functionfoo() {
        console.log("bar");
    }

    $(".callme").click(foo);
}

<a class="callme">Call foo</a>
<aclass="callme">Call foo</a>

Or, either of these constructs could use an anonymous function:

$(function() {
    $(".callme").click(function(e) {
        console.log("bar");
    });
}

<a class="callme">Call foo</a>
<aclass="callme">Call foo</a>

Removing all code references from the actual HTML is referred to as Unobstrusive Javascript and is considered a good practice by many. You can read about that practice here:

What is Unobtrusive JavaScript and Why it’s Important?

Wikipedia - Unobtrusive JavaScript

W3 - The principles of unobtrusive JavaScript

Solution 4:

The scope of event handler content attributes is

  • The global scope
  • The document
  • The form owner (if any)
  • The element (if any)

That means that the foo function must be a property of one of those in order to use

<aonclick="foo()">Call foo</a>

Some examples:

(function() {
  window.foo = function() {
    alert("bar");
  }
})();
<aonclick="foo()">Call foo</a>

(function() {
  document.foo = function() {
    alert("bar");
  }
})();
<aonclick="foo()">Call foo</a>

(function() {
  document.querySelector('form').foo = function() {
    alert("bar");
  }
})();
<form><buttononclick="foo()">Call foo</button></form>

(function() {
  Element.prototype.foo = function() {
    alert("bar");
  }
})();
<aonclick="foo()">Call foo</a>

(function() {
  document.querySelector('a').foo = function() {
    alert("bar");
  }
})();
<aonclick="foo()">Call foo</a>

However, I would suggest using event handlers IDL attributes or, even better, event listeners.

Solution 5:

Try

window.onerror = function(e) {
  console.log(e)
}

$(function() {

  functionfoo() {
    console.log("bar");
  }

  (function_foo() {
    return $(this).queue("foo", [function(next) {
      foo(); returnnext()}, _foo])
  }).call(this);

});
<scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script><aonclick="jQuery(document).dequeue('foo')">Call foo</a>

Post a Comment for "Javascript Call Functions From Element Events Without Global Scope"