简体   繁体   中英

re: jQuery; binding global ajax events to non-DOM objects

Basic module question here: I can get the global handlers to work fine if I abandon my module pattern, but this test code doesn't work and I'm having great difficulty figuring out why:

var MyModule = (function($, my) {
  $(my).ajaxStart(function() { window.alert("ajax start"); });

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

  return my;
}(jQuery, MyModule || {}));

The handler attached to the MyModule instance never runs when the ajax call executes. If I instead attach the handler to $(document) it works just fine, but i'm curious why that global event doesn't seem to be binding correctly to the module object.

EDIT: Here's an even simpler example:

var x = {};
$(x).ajaxStart(function() { window.alert("foo"); } );
$.ajax(SOME_AJAX_SETTINGS);

If I replace $(x) with $(document) , it works... it just seems that I can't bind ajaxStart (or the other global ajax events) to non-DOM objects?


@Nucleon, this doesn't seem completely correct to me, and here's an example of why:

var item = {foo: function() { window.alert("shorthand"); } };
$(item).bind("foo", function () { window.alert("longhand"); } );
window.alert("about to trigger (locally)");
$(item).trigger("foo");
window.alert("now we triggerHandler (locally)");
$(item).triggerHandler("foo");

here, the (custom) event "foo" is bound via two patterns, and the different trigger methods show the pattern specificity... you'll get the "longhand" alert twice and the "shorthand" alert once.

now, you can also fire off a global event with $.event.trigger("foo") (BUT, no equivalent global triggerHandler exists). the problem is if you add this code to the end:

window.alert("now we trigger (globally)");
$.event.trigger("foo");

neither handler is run for this global event triggering.

IF, however, you replace item with some DOM-type element -- as you suggest above -- then both the local AND global events are handled, with the caveat that the "shorthand" handler now won't work*. so it appears that while local handling works with non-DOM objects, it's specifically global handling that doesn't work.

-m

*the shorthand handler stops working because the shorthand pattern ONLY applies to non-DOM objects. i personally think this "shorthand" behavior of non-DOM objects should be removed from jQuery. very few people know about it, and it's only documented in one obscure sentence on the global jQuery object page... it's behavior could drive people who aren't aware of it crazy since it implicitly does a binding step that folks are likely not aware of.


ah, okay... the $.event.trigger functionality isn't public, though it's used by the underlying event-firing mechanisms. i guess i just shouldn't be using it. turns out this behavior has been challenging for the jQuery devs to implement correctly, and it looks like they're abandoning it completely (or that's what i gathered from this bug report being marked "fixed": DEPRECATE AJAX "GLOBAL" EVENT BEHAVIOR ).

but i'm still a bit confused about .trigger being documented as behaving the same way for DOM or non-DOM objects, as only one of the following alerts are run:

var plain = {foo: function() { window.alert("plain"); } };
var dom = $("<div></div>");
dom.foo = function() { window.alert("dom"); };
console.log(plain.foo); // make sure we see function foo on the plain object.
console.log(dom.foo); // now make sure we see function foo on the DOM object.
$(plain).trigger("foo"); // raises the "plain" window alert.
$(dom).trigger("foo"); // raises no alert.

i guess this means the foo property set on dom isn't actually a "proper" JS property in the traditional sense (despite it showing up correctly when inspecting the object on the console)?

note: this is all now for the sake of knowledge -- as i'll just take the advice of the "fix" in the bug link above and just attach all my AJAX (and other global) events to document , since it appears it'll be the enforced behavior in jQuery 1.9. but i've already taken the blue pill and feel like i'm too far down the rabbit hole to climb back out.

Simply replace

var x = {};

with

var x = $("<div></div>");

Javascript events require binding to valid DOM objects (not just javascript objects). Now, it is not required that the DOM objects are actually attached anywhere. Javascript's event system is based off of bubbling events up and down a hierarchy chain of the available and relevant DOM objects. A simple {} does not qualify.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM