|
View:
New views
14 Messages
—
Rating Filter:
Alert me
|
|
|
behaviors contextI'm trying to implement a Drupal.behavior. I realize my behavior
function is passed a "context". But it's unclear to me what that context will be. If I understand correctly, when the behavior is first invoked, it is passed document, a variable built into javascript. Later, when some module's javascript adds content to the page, my behavior will be invoked again. This time, context could be anything. The module which added the content can pass whatever. So for example in ahah.js, Drupal.attachBehaviors() is passed a jquery object representing the new content. While in modules/views/js/ajax.js, Drupal.attachBehaviors() is passed a string or id, either of which could be used in a jquery selector. Do I have this right? What I need is the javascript element (not jquery object) that is the added content. Does anyone have a snippet of code which returns this, given a context? Thanks, -Dave |
|
|
Re: behaviors contextAs far as the context goes, yes -- you are at the mercy of whatever
called Drupal.attachBehaviors(). So it's not all that reliable. Typically, the whole CSS :not() pseudo-class combined with a 'processed-' class is used to help you find segments that have not been processed already. There are ample examples of this inside of Drupal's JS libraries. Matt On Fri, May 29, 2009 at 12:36 PM, David Cohen <drupal@...> wrote: > I'm trying to implement a Drupal.behavior. I realize my behavior > function is passed a "context". But it's unclear to me what that > context will be. > > If I understand correctly, when the behavior is first invoked, it is > passed document, a variable built into javascript. > > Later, when some module's javascript adds content to the page, my > behavior will be invoked again. This time, context could be anything. > The module which added the content can pass whatever. So for example in > ahah.js, Drupal.attachBehaviors() is passed a jquery object representing > the new content. While in modules/views/js/ajax.js, > Drupal.attachBehaviors() is passed a string or id, either of which could > be used in a jquery selector. > > Do I have this right? > > What I need is the javascript element (not jquery object) that is the > added content. Does anyone have a snippet of code which returns this, > given a context? > > Thanks, -Dave > > -- http://technosophos.com http://querypath.org |
|
|
Re: behaviors contextDavid Cohen wrote:
> I'm trying to implement a Drupal.behavior. I realize my behavior > function is passed a "context". But it's unclear to me what that > context will be. The context is supposed to be the element to be processed--not a jQuery object but the page element. See the 5 - 6 upgrade notes: http://drupal.org/node/114774#javascript-behaviors However, this fact may have been lost along the way. |
|
|
Re: behaviors context> What I need is the javascript element (not jquery object)
> that is the added content. Does anyone have a snippet of > code which returns this, given a context? If I'm not mistaken: var new_content = $(context).get(0); sun |
|
|
Re: behaviors context> The context is supposed to be the element to be
> processed--not a jQuery object but the page element. See the > 5 - 6 upgrade notes: > http://drupal.org/node/114774#javascript-behaviors > > However, this fact may have been lost along the way. Note that even misc/ahah.js passes an jQuery object: if (new_content.parents('html').length > 0) { Drupal.attachBehaviors(new_content); } However, passing a string as context sounds a bit wrong. Behaviors usually expect a DOM element. sun |
|
|
Re: behaviors contextThus my original claim: You are at the mercy of whatever calls
Drupal.attachBehaviors(). Unless you are absolutely positive you can account for all use cases (and thus all callings of Drupal.attach()), you're better off ignoring context. Matt On Fri, May 29, 2009 at 1:04 PM, Daniel F. Kudwien <news@...> wrote: >> The context is supposed to be the element to be >> processed--not a jQuery object but the page element. See the >> 5 - 6 upgrade notes: >> http://drupal.org/node/114774#javascript-behaviors >> >> However, this fact may have been lost along the way. > > Note that even misc/ahah.js passes an jQuery object: > > if (new_content.parents('html').length > 0) { > Drupal.attachBehaviors(new_content); > } > > > However, passing a string as context sounds a bit wrong. Behaviors usually > expect a DOM element. > > sun > > -- http://technosophos.com http://querypath.org |
|
|
Re: behaviors contextMatt wrote:
> Thus my original claim: You are at the mercy of whatever calls > Drupal.attachBehaviors(). Unless you are absolutely positive you can > account for all use cases (and thus all callings of Drupal.attach()), > you're better off ignoring context. I totally disagree. It's either a jquery object or something you can easily make into a jquery object. Using $(context) should always work and you can get a DOM element using $(context).get(0). Ignoring context will lead to poor performance. |
|
|
Re: behaviors contextSo just to clarify, will the context always refer to a single element?
In other words should my code be: $elem = $(context).get(0); do_my_behavior($elem); or, more like: $(context).each(function () { $elem = $(this).get(0); do_my_behavior($elem); }); And in the first invocation, when context == document, will $(document).get(0) return the document? Thanks everyone for helping me understand. -Dave On Fri, 29 May 2009 11:44 -0700, "Earl Miles" <merlin@...> wrote: > I totally disagree. It's either a jquery object or something you can > easily make into a jquery object. Using $(context) should always work > and you can get a DOM element using $(context).get(0). Ignoring context > will lead to poor performance. |
|
|
Re: behaviors contextThe other issue with using context is that it is unreliable for a
second reason: behaviors may actually misbehave when focusing on only a small portion of the DOM. Example: context contains several rows of a table, and you are adding odd/even classes to a table in a behavior. If a behavior is fed just the modified rows, this may lead to unexpected behavior (Reason: there may be other rows not fed into the context, thus throwing off odd/even counts). That's a basic example. In the JS book I wrote, I provided a more elaborate examples of contexts causing problems. And there are still others -- like cases where AHAH content has its own JS which may modify your DOM further. But the basic principle is the same: Assuming that the attachBehaviors call is passing you what you need is not a good assumption. And since attachBehaviors can be called from anywhere (not just in AHAH/AJAX callbacks) and for any reason, it's dangerous to presume you know what you're getting. re: performance... in most cases you are talking a negligible difference. DOM optimization in mainstream browsers is good enough that a search through an entire document is almost always "fast enough". Shaving 10 msecs off of that time isn't going to make much of a difference (assuming you could actually shave that much from the search time). There are two patterns in Drupal JS to "prevent" the same behavior from processing the same data twice. One is the :not(processed-X) pattern, which seems to be pretty reliable, and is pretty much entirely in the hands of the author of the behavior (barring a misanthrope who decides to remove your processed classes). The other is the context, which requires that both the caller of attachBehavior() and the behavior have the same set of assumptions about what is being passed in and what needs operating on. This is not always the case, and there are easy-to-reproduce gotchas (like zebra striping, AHAH'd JavaScript that alters the DOM, and so on). Matt On Fri, May 29, 2009 at 1:44 PM, Earl Miles <merlin@...> wrote: > Matt wrote: >> >> Thus my original claim: You are at the mercy of whatever calls >> Drupal.attachBehaviors(). Unless you are absolutely positive you can >> account for all use cases (and thus all callings of Drupal.attach()), >> you're better off ignoring context. > > I totally disagree. It's either a jquery object or something you can easily > make into a jquery object. Using $(context) should always work and you can > get a DOM element using $(context).get(0). Ignoring context will lead to > poor performance. > -- http://technosophos.com http://querypath.org |
|
|
Re: behaviors contextNo -- the context will refer to whatever is passed into
Drupal.attachBehaviors(). In Drupal core, that will be a DOM Element or a jQuery object. I know of no guarantee that the jQuery will always point to one DOM element (though I know of no place in Drupal core where more than one is passed in). For contributed modules... I suppose you are at the liberty of the contrib developers. Matt On Fri, May 29, 2009 at 2:03 PM, David Cohen <drupal@...> wrote: > So just to clarify, will the context always refer to a single element? > In other words should my code be: > > $elem = $(context).get(0); > do_my_behavior($elem); > > or, more like: > > $(context).each(function () { > $elem = $(this).get(0); > do_my_behavior($elem); > }); > > > And in the first invocation, when context == document, will > $(document).get(0) return the document? > > Thanks everyone for helping me understand. > > -Dave > > > On Fri, 29 May 2009 11:44 -0700, "Earl Miles" <merlin@...> wrote: >> I totally disagree. It's either a jquery object or something you can >> easily make into a jquery object. Using $(context) should always work >> and you can get a DOM element using $(context).get(0). Ignoring context >> will lead to poor performance. > -- http://technosophos.com http://querypath.org |
|
|
Re: behaviors context> re: performance... in most cases you are talking a negligible
> difference. DOM optimization in mainstream browsers is good > enough that a search through an entire document is almost > always "fast enough". Shaving 10 msecs off of that time isn't > going to make much of a difference (assuming you could > actually shave that much from the search time). Now, you do the math: 10 ms * ~20+ behaviors = 200+ ms With each module/behavior you add, the performance gets worse. > There are two patterns in Drupal JS to "prevent" the same > behavior from processing the same data twice. One is the > :not(processed-X) pattern, which seems to be pretty reliable, > and is pretty much entirely in the hands of the author of the > behavior (barring a misanthrope who decides to remove your > processed classes). ...which equally cannot solve your trivial zebra-striping table row example. Once your table :is(.processed), your behavior can't (shouldn't) process it again. sun |
|
|
Re: behaviors context2009/5/29 David Cohen <drupal@...>:
> So just to clarify, will the context always refer to a single element? > In other words should my code be: > > $elem = $(context).get(0); > do_my_behavior($elem); > > or, more like: > > $(context).each(function () { > $elem = $(this).get(0); > do_my_behavior($elem); > }); It should be more like this: Drupal.behaviors.myBehavior = function(context) { $(context).each(function () { // 'this' is a DOM Element. do_my_behavior(this); }); }; or you can include your selector and use context as it is supposed to be used: Drupal.behaviors.myBehavior = function(context) { $('.my-behavior-class:not(.my-behavior-processed)', context).each(function () { // 'this' is a DOM Element. do_my_behavior(this); $(this).addClass('my-behavior-processed'); }); }; Henrique > > > And in the first invocation, when context == document, will > $(document).get(0) return the document? > > Thanks everyone for helping me understand. > > -Dave > > > On Fri, 29 May 2009 11:44 -0700, "Earl Miles" <merlin@...> wrote: >> I totally disagree. It's either a jquery object or something you can >> easily make into a jquery object. Using $(context) should always work >> and you can get a DOM element using $(context).get(0). Ignoring context >> will lead to poor performance. > |
|
|
Re: behaviors contextOn Fri, May 29, 2009 at 2:59 PM, Daniel F. Kudwien
<news@...> wrote: > Now, you do the math: > > 10 ms * ~20+ behaviors = 200+ ms Actually, I was figuring 10ms for LOTS of behaviors. Not PER behavior. A selector should clearly take well under 10ms. Any additional overhead for a behavior is going to be the same regardless of whether you use context or selectors. >> There are two patterns in Drupal JS to "prevent" the same >> behavior from processing the same data twice. One is the >> :not(processed-X) pattern, which seems to be pretty reliable, >> and is pretty much entirely in the hands of the author of the >> behavior (barring a misanthrope who decides to remove your >> processed classes). > > ...which equally cannot solve your trivial zebra-striping table row example. > Once your table :is(.processed), your behavior can't (shouldn't) process it > again. Oh, come on... you wouldn't drop a zebra stripe processed class on the table, would you? You'd drop it on the row. And if you found rows in a table without striping, you'd re-process the entire table. The problem occurs only when you assume the context is passing sufficient information for your behavior. The context may in fact be providing less information than you need, and you are at the liberty of whatever called attachBehavior() in the first place (which may not be something in core -- there's no way to tell). Consequently, it's better to rely on the document itself, not just the context. Matt -- http://technosophos.com http://querypath.org |
|
|
Re: behaviors context> The problem occurs only when you assume the context is passing
> sufficient information for your behavior. The context may in fact be > providing less information than you need, and you are at the liberty > of whatever called attachBehavior() in the first place (which may not > be something in core -- there's no way to tell). Consequently, it's > better to rely on the document itself, not just the context. Sometimes you can't just rely on the document. For an example see the popups module. It attaches the behaviors to the body of the popup window. If a popup is built from an AHAH callback you wouldn't want to reapply the behaviors to the entire document for a popup that's just part of it. You'd want to apply it to just the new area. If someone misuses attachBehaviors() should the behaviors be required to deal with that? They can't foresee everything and there are times where you want to attach behaviors to something other than the document. If they misuse attachBehaviors that would be a bug in their code. |
| Free embeddable forum powered by Nabble | Forum Help |