Re: [whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments

2013-07-28 Thread Tab Atkins Jr.
I strongly agree with the use-case, and think some feature for this
would be very helpful.

[Mixing up your emails for reply convenience.]
On Sat, Jul 27, 2013 at 11:25 AM, Ojan Vafai o...@chromium.org wrote:
 On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote:
 var iterator = document.querySelectorAll('div').iterator(); --- does some
 magic to not precompute the whole list

Can you describe this magic?  It would be nice if this were somehow
possible, but I'm not sure how it would be.

 There are many places where we expose SequenceNode or NodeList that can't
 easily be replaced with hand-rolled DOM walking (e.g. getNamedFlows).

 You could imagine NodeIterator taking a SequenceNode/NodeList as an
 argument to it's constructor instead of adding an iterator method, but I
 find the NodeIterator interface to be clunky and awkward.

Yeah, having the ability to produce these iterators for any of the
currently-static Node lists would be great.  But again, not sure how
the magic would work. :/

 while (let current = iterator.next()) { ... }

 And next always does the walk from the current node. So, if you add a div
 before the current node, this specific iterator won't hit it, but if you
 add a div after it would. I'm not sure what should happen though if you
 remove the node that's the current node. I think I'm OK with the iterator
 just returning null for the next() call in that case.


 Thinking more on this, I think we could make next() still work in the case
 where you remove the node by pointing current at the previous node in the
 tree. Then you could do things like:

 while (let current = iterator.next()) { current.remove(); }

This should be an ES iterator, rather than a custom DOM thing that
looks almost exactly like an ES iterator.

 I think the methods we'd want here are next, previous, first and last. That
 way you can walk the iterator forward or backward. This doesn't overlap
 well with NodeIterator's current API.

How useful is it to be able to walk an iterator in both directions at
the same time?  I suppose we can produce an iterator subclass that
also has the additional methods we want.

~TJ


Re: [whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments

2013-07-28 Thread James Greene
I think it makes sense, too. That said, if the goal is to REPLACE the
NodeIterator and TreeWalker APIs completely, it wouldn't be all that
valuable for me as my most common use case has always been to get TEXT
NODES from under a root node based on some CSS filtering of its ancestor
nodes. If the proposed API used only CSS query selectors without also
allowing the additional NodeType filtering provided whatToShow, then it
could not not be used to directly gather text nodes.

Might be OK to leave text nodes out... not sure how others use NIs/TWs.

Sincerely,
   James Greene
On Jul 28, 2013 11:24 AM, Tab Atkins Jr. jackalm...@gmail.com wrote:

 I strongly agree with the use-case, and think some feature for this
 would be very helpful.

 [Mixing up your emails for reply convenience.]
 On Sat, Jul 27, 2013 at 11:25 AM, Ojan Vafai o...@chromium.org wrote:
  On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote:
  var iterator = document.querySelectorAll('div').iterator(); --- does
 some
  magic to not precompute the whole list

 Can you describe this magic?  It would be nice if this were somehow
 possible, but I'm not sure how it would be.

  There are many places where we expose SequenceNode or NodeList that
 can't
  easily be replaced with hand-rolled DOM walking (e.g. getNamedFlows).
 
  You could imagine NodeIterator taking a SequenceNode/NodeList as an
  argument to it's constructor instead of adding an iterator method, but I
  find the NodeIterator interface to be clunky and awkward.

 Yeah, having the ability to produce these iterators for any of the
 currently-static Node lists would be great.  But again, not sure how
 the magic would work. :/

  while (let current = iterator.next()) { ... }
 
  And next always does the walk from the current node. So, if you add a
 div
  before the current node, this specific iterator won't hit it, but if you
  add a div after it would. I'm not sure what should happen though if you
  remove the node that's the current node. I think I'm OK with the
 iterator
  just returning null for the next() call in that case.
 
 
  Thinking more on this, I think we could make next() still work in the
 case
  where you remove the node by pointing current at the previous node in the
  tree. Then you could do things like:
 
  while (let current = iterator.next()) { current.remove(); }

 This should be an ES iterator, rather than a custom DOM thing that
 looks almost exactly like an ES iterator.

  I think the methods we'd want here are next, previous, first and last.
 That
  way you can walk the iterator forward or backward. This doesn't overlap
  well with NodeIterator's current API.

 How useful is it to be able to walk an iterator in both directions at
 the same time?  I suppose we can produce an iterator subclass that
 also has the additional methods we want.

 ~TJ



Re: [whatwg] Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments

2013-07-28 Thread Boris Zbarsky

On 7/27/13 10:58 AM, Ojan Vafai wrote:

var iterator = document.querySelectorAll('div').iterator(); --- does
some magic to not precompute the whole list


Well, so... not precompute but make it some sort of live, or not 
precompute but represent a frozen set of nodes?


What should happen with this situation:

  var list = document.querySelectorAll('div');
  var iterator = list.iterator();

Should the list of nodes be precomputed in this case?

Basically, the magic sounds like it's ... very magical.  Magical enough 
that authors would have a tough time with this setup, even ignoring 
implementation concerns.


-Boris


Re: [whatwg] Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments

2013-07-28 Thread Ojan Vafai
On Sun, Jul 28, 2013 at 11:10 AM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 7/27/13 10:58 AM, Ojan Vafai wrote:

 var iterator = document.querySelectorAll('**div').iterator(); --- does
 some magic to not precompute the whole list


 Well, so... not precompute but make it some sort of live, or not
 precompute but represent a frozen set of nodes?

 What should happen with this situation:

   var list = document.querySelectorAll('**div');
   var iterator = list.iterator();

 Should the list of nodes be precomputed in this case?

 Basically, the magic sounds like it's ... very magical.  Magical enough
 that authors would have a tough time with this setup, even ignoring
 implementation concerns.


I was just picturing lazy computing the list. You don't need to compute the
list until you query the length or index into the NodeList, at which point,
if it's a static NodeList, you compute the whole thing in one go. If all
you ever do is grab the iterator, then no need to compute the list. So, the
example you give above would not precompute.

Now that I put it in writing, the obvious problem with this is that it's a
change in semantics. If you querySelectorAll and then modify the DOM before
reading the length or an index, then you get a different list. :(


Re: [whatwg] Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments

2013-07-28 Thread Jonas Sicking
On Sun, Jul 28, 2013 at 1:59 PM, Ojan Vafai o...@chromium.org wrote:
 On Sun, Jul 28, 2013 at 11:10 AM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 7/27/13 10:58 AM, Ojan Vafai wrote:

 var iterator = document.querySelectorAll('div').iterator(); --- does
 some magic to not precompute the whole list


 Well, so... not precompute but make it some sort of live, or not
 precompute but represent a frozen set of nodes?

 What should happen with this situation:

   var list = document.querySelectorAll('div');
   var iterator = list.iterator();

 Should the list of nodes be precomputed in this case?

 Basically, the magic sounds like it's ... very magical.  Magical enough
 that authors would have a tough time with this setup, even ignoring
 implementation concerns.


 I was just picturing lazy computing the list. You don't need to compute the
 list until you query the length or index into the NodeList, at which point,
 if it's a static NodeList, you compute the whole thing in one go. If all you
 ever do is grab the iterator, then no need to compute the list. So, the
 example you give above would not precompute.

 Now that I put it in writing, the obvious problem with this is that it's a
 change in semantics. If you querySelectorAll and then modify the DOM before
 reading the length or an index, then you get a different list. :(

It's not just a change in semantics, it's a change in behavior. To
keep the same behavior you would have to make the static NodeList
observe the DOM and precompute itself as soon as the DOM was modified.

I.e. static NodeLists would incur the same performance problems that
Ryosuke expressed concern about that live NodeLists have.

So yeah, I don't think it's an option.

In general, I'm not a big fan of anything that adds capabilities to
all NodeLists. This has been brought up in the past when people
suggested adding the ability to observe changes to all NodeLists.

It's not at all obvious to me that in *all* situations where we use
NodeLists that it is desired to be able to iterate the results lazily.
Requiring that might force implementations to spend a lot of time
implementing something that doesn't have use cases.

We should think of NodeLists as simple Arrays. And it's clear that we
don't want to force any function that returns an Array to be able to
lazily compute that Array using an iterator. Keep in mind that the
laziness is observable, so it's not a valid implementation strategy to
only do the lazyness where there are clear performance benefits.

/ Jonas