[ 7 posts ]

Marc

YUI Contributor

  • Offline
  • Profile
Tags:

node existence shorthand

Post Posted: Wed Dec 14, 2011 7:49 am
+0-
Hi,

I find myself writing code such as this all the time:

Code:
var add2network = Y.one('a.add2network');
   if(add2network)
      add2network.on('click',function(e){
         Y.use('msa-network','msa-action','msa-generic',function(A){
         A.DoSomething(e.currentTarget);
         });
      });



I seems like a very verbose way to test for the existence of a node and create an onClick. Is there a good shorthand for this?

I would like to write something like
var add2network = Y.one('a.add2network') && add2network.on('click', function() [...]

but I don't know of a way to reference the object on the left hand of the operator as it is not yet assigned to add2network.

Any ideas?

Marc

Eric Ferraiuolo

YUI Developer

  • Username: ericf
  • Joined: Mon Jan 12, 2009 8:26 pm
  • Posts: 380
  • Location: Boston, MA
  • Twitter: ericf
  • GitHub: ericf
  • Gists: ericf
  • IRC: eric_f
  • YUI Developer
  • Offline
  • Profile
Tags:

Re: node existence shorthand

Post Posted: Wed Dec 14, 2011 8:14 am
+0-
You can just use `Y.on()` directly: http://yuilibrary.com/yui/docs/api/clas ... #method_on

Code:
Y.on('click', function (e) { /* ... */ }, 'a.add2network');

Jeff Pihach

YUI Contributor

  • Username: hatch
  • Joined: Wed Dec 08, 2010 9:20 am
  • Posts: 37
  • Twitter: fromanegg
  • GitHub: hatched
  • Gists: hatched
  • IRC: hatch
  • Offline
  • Profile

Re: node existence shorthand

Post Posted: Wed Dec 14, 2011 8:29 am
+0-
Hi Marc,

Y.all() will always return a NodeList so you can use that instead.

Y.all('#your-id').on('click', function(e) { /* ... */ });

But both eric's and my solutions only check once so if its added after the fact you will need to check again. Delegate may be a better solution to your problem.

Nate Cavanaugh

YUI Contributor

  • Offline
  • Profile

Re: node existence shorthand

Post Posted: Mon Jan 02, 2012 4:14 pm
+0-
Hi guys,
From what I remember, Y.on() adds a timer onto the page which polls until the element is on the page.
With using Y.all, it's 3 times slower than using Y.one, so there are definite downsides to using either method.

It would be nice if there was a way to keep the same performance benefit of Y.one, but have it return a stub object that can be operated on (but does nothing).
I've thought many times about how this could be done (creating a generic element that doesn't exist in node, and if no match is found, work on that), but every way that I've thought about just leads to weird scenarios (if I set the styles on this stub, but then in another method try to read the same value, it would be wrong).

So using the slower Y.all() may be the only option that is workable (except that not all of the methods on node are available on nodelist).
But I have noticed that the node/nodelist dichotomy ends up causing a lot of confusion and boilerplate if checks.

It'd be nice to resolve this in a way that had all the benefits and none of the drawbacks :)

@Marc:
If your goal is to just have it on one line, this might be workable (though still verbose):
Code:
var add2network = Y.one('a.add2network'), add2network && add2network.on('click', function(event) {});

Juan Ignacio Dopazo

YUI Contributor

  • Username: jdopazo
  • Joined: Fri Oct 02, 2009 5:39 am
  • Posts: 620
  • Location: Buenos Aires, Argentina
  • Twitter: juandopazo
  • GitHub: juandopazo
  • Gists: juandopazo
  • Offline
  • Profile
Tags:

Re: node existence shorthand

Post Posted: Tue Jan 03, 2012 4:44 am
+0-
I usually don't check if Y.one returns null or not, so that when it does I get an error. Silent errors are really hard to find afterwards. Don't you find it better to get an exception if something goes wrong?

Luke Smith

YUI Contributor

  • Username: lsmith
  • Joined: Thu Aug 28, 2008 7:50 am
  • Posts: 510
  • Location: Sunnyvale
  • Twitter: ls_n
  • GitHub: lsmith
  • Gists: lsmith
  • IRC: ls_n
  • YUI Developer
  • Offline
  • Profile

Re: node existence shorthand

Post Posted: Wed Jan 04, 2012 10:25 am
+1-
I don't recommend relying on the polling behavior of Y.on because it can introduce race conditions.

Y.all().on() is a bit of an antipattern (or at least code smell) because Y.all is meant to capture multiple elements, and using NodeList's on() method to iteratively attach listeners to a collection is an indication that delegation should be used. You can use it if your goal is brevity, but in maintenance mode, seeing that code pattern can lead to use of the should-be-delegate pattern. Y.all() being three times slower shouldn't affect runtime performance in a measurable way because you're using it to attach event listeners. There should be few of these operations going on. If there are more, that's another sign that you should be using delegation.

@natecavenaugh, You might remember there was a time when Node and NodeList were merged, providing the stub you're talking about, but it ended up causing more trouble and impacted performance, so it was pulled. To @jdopazo's point, preserving empty Node's to allow method calls to noop (well, there is always a slight cost) hid bugs. Whether you allow the node method call to fail outright or wrap subsequent calls in an if (node) block is your call, of course. It's a question of cost tradeoffs:

1. Y.all().on() is easier in development, but slower at run time and risks antipattern adoption

2. Y.on() is faster than Y.one().on() and defers creating a Node for the subscribing element until the event is triggered, but can introduce race conditions, and you may need the Node for other operations anyway

3. var node = Y.one(); node && node.on() or if (node) { node.on() } is more verbose, making it slower at dev time, but is stable and fast

4. Y.one().on() is terse and fast, but potentially fragile

5. var node; (node = Y.one()) && node.on() is another option, akin to what the OP was asking for, and like #3 it's fast and stable, but it's a bit idiomatic, which can impact maintenance time.

Pick your poison :)

Nate Cavanaugh

YUI Contributor

  • Offline
  • Profile

Re: node existence shorthand

Post Posted: Wed Jan 11, 2012 4:10 pm
+0-
Heya Luke,
Thanks for listing all of those tradeoffs. I do vaguely remember when Node and NodeList were merged, but I from what I recall, it was during the PR and it was a bit flaky at the time.

To a couple of your points:

1. I don't think Y.all().on is drastically that bad, only because delegation doesn't work for all scenarios. For instance, if the common parent of a set of elements happens to be the body tag, then delegation falls apart (the performance hit of parsing up the dom tree and running through the selector engine gets pretty expensive for every click, given a deep enough DOM and given the browser *cough*IE*cough*).
It comes to a tradeoff between speed up front or speed during interaction.
But as you said, that's why it's there, for cases like that.

2. After so much time with the Node/NodeList paradigm, I will say, the jQuery approach of only providing composite elements is not only easier to explain to new members of a team, but also just more pleasant to write.
Basically, there are 3 factors that make it more enjoyable to work with:
A. Only 1 API to remember (currently, Node and NodeList have different method calls, and trying to remember which one is appropriate, or even having to take the time to look up which type of object I'm working with, more often than not gets in the way).
B. Using one method as a getter/setter (seems like a small thing, but it does make one less thing to fiddle with).
C. Makes 1-off actions much less verbose and easier to write.

Of course, the tradeoff is performance and debugging (though on debugging composite elements, it only *hides* the bugs better, but I haven't found *finding* the bugs any harder).

3. I sometimes wonder if it would be handy to have a wrapping util that is much less fragile than DOM or Node and can work with either a single or multiple objects.
This could just be me preferring terser code over performance/debugging, but I think the dicotomy of the API leads to some thinking over the API and detracts from the goal of the code.

Just my 2 cents, and thanks for going so in depth Luke :)
  [ 7 posts ]
Display posts from previous:  Sort by  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum