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

2013-08-13 Thread Ryosuke Niwa
On Jul 28, 2013, at 10:29 AM, James Greene james.m.gre...@gmail.com wrote:

 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.

NodeIterator already has an ability to only include text nodes.

It appears to me that we can also add an ability to match a selector.

e.g.  var nodeIterator = document.createNodeIterator(root, 
NodeFilter.SHOW_TEXT, null, 'div a');

can find all text nodes under elements that match 'div a'.


On Jul 27, 2013, at 1:04 PM, Ojan Vafai o...@chromium.org wrote:

 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.
 
 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.

NodeIterator has nextNode() and previousNode() already.  Why can't we add 
firstNode() and lastNode()?


On Jul 27, 2013, at 11:25 AM, Ojan Vafai o...@chromium.org wrote:

 Realized this should probably be a new thread...
 
 
 On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote:
 
 On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc wrote:
 I think these are good points of what is lost by using static NodeLists. I
 still feel pretty strongly though that these benefits don't outweigh the
 costs. If we want to give people most of the benefits of live NodeLists
 without the costs we could expose an iterator API:
 
 var iterator = document.querySelectorAll('div').iterator(); --- does some
 magic to not precompute the whole list
 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 gets the performance benefits of live NodeLists, I think meets the

What happens when you remove the previous node during the iteration?

- R. Niwa



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



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

2013-07-27 Thread Ojan Vafai
Realized this should probably be a new thread...


On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote:

 On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Thu, Jul 25, 2013 at 9:05 AM, Boris Zbarsky bzbar...@mit.edu wrote:
  On 7/24/13 10:42 PM, Jussi Kalliokoski wrote:
 
  Argh, I had forgotten about live NodeLists. OK, this is a reason that
  resonates with me and justifies calling these methods obsolete. Too bad
  these methods are so badly flawed
 
 
  Fwiw, I think the performance impact of live NodeLists is ... unclear.
 Their
  existence does mean that you have to deal with DOM mutations changing
 the
  lists, but them being live also means you can make the list getters much
  faster in cases when the caller doesn't actually want the entire list.

 And, as importantly, it also means that for multiple consecutive calls
 to get the list, say inside of a loop, can return the same result
 object. I.e. you don't have to re-walk the DOM for every iteration
 through the loop.


 I think these are good points of what is lost by using static NodeLists. I
 still feel pretty strongly though that these benefits don't outweigh the
 costs. If we want to give people most of the benefits of live NodeLists
 without the costs we could expose an iterator API:

 var iterator = document.querySelectorAll('div').iterator(); --- does some
 magic to not precompute the whole list
 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 gets the performance benefits of live NodeLists, I think meets the
 main use-cases of not wanting to walk the whole DOM, but doesn't require
 the browser to do a lot of metadata tracking as you go.

 Ojan



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

2013-07-27 Thread James Greene
Isn't that what the NodeIterator and TreeWalker APIs are for?

Sincerely,
   James Greene
On Jul 27, 2013 1:25 PM, Ojan Vafai o...@chromium.org wrote:

 Realized this should probably be a new thread...


 On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote:

  On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc wrote:
 
  On Thu, Jul 25, 2013 at 9:05 AM, Boris Zbarsky bzbar...@mit.edu
 wrote:
   On 7/24/13 10:42 PM, Jussi Kalliokoski wrote:
  
   Argh, I had forgotten about live NodeLists. OK, this is a reason that
   resonates with me and justifies calling these methods obsolete. Too
 bad
   these methods are so badly flawed
  
  
   Fwiw, I think the performance impact of live NodeLists is ... unclear.
  Their
   existence does mean that you have to deal with DOM mutations changing
  the
   lists, but them being live also means you can make the list getters
 much
   faster in cases when the caller doesn't actually want the entire list.
 
  And, as importantly, it also means that for multiple consecutive calls
  to get the list, say inside of a loop, can return the same result
  object. I.e. you don't have to re-walk the DOM for every iteration
  through the loop.
 
 
  I think these are good points of what is lost by using static NodeLists.
 I
  still feel pretty strongly though that these benefits don't outweigh the
  costs. If we want to give people most of the benefits of live NodeLists
  without the costs we could expose an iterator API:
 
  var iterator = document.querySelectorAll('div').iterator(); --- does
 some
  magic to not precompute the whole list
  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 gets the performance benefits of live NodeLists, I think meets the
  main use-cases of not wanting to walk the whole DOM, but doesn't require
  the browser to do a lot of metadata tracking as you go.
 
  Ojan
 



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

2013-07-27 Thread Ojan Vafai
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.

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.


On Sat, Jul 27, 2013 at 12:42 PM, James Greene james.m.gre...@gmail.comwrote:

 Isn't that what the NodeIterator and TreeWalker APIs are for?

 Sincerely,
James Greene
 On Jul 27, 2013 1:25 PM, Ojan Vafai o...@chromium.org wrote:

 Realized this should probably be a new thread...


 On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote:

  On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc
 wrote:
 
  On Thu, Jul 25, 2013 at 9:05 AM, Boris Zbarsky bzbar...@mit.edu
 wrote:
   On 7/24/13 10:42 PM, Jussi Kalliokoski wrote:
  
   Argh, I had forgotten about live NodeLists. OK, this is a reason
 that
   resonates with me and justifies calling these methods obsolete. Too
 bad
   these methods are so badly flawed
  
  
   Fwiw, I think the performance impact of live NodeLists is ...
 unclear.
  Their
   existence does mean that you have to deal with DOM mutations changing
  the
   lists, but them being live also means you can make the list getters
 much
   faster in cases when the caller doesn't actually want the entire
 list.
 
  And, as importantly, it also means that for multiple consecutive calls
  to get the list, say inside of a loop, can return the same result
  object. I.e. you don't have to re-walk the DOM for every iteration
  through the loop.
 
 
  I think these are good points of what is lost by using static
 NodeLists. I
  still feel pretty strongly though that these benefits don't outweigh the
  costs. If we want to give people most of the benefits of live NodeLists
  without the costs we could expose an iterator API:
 
  var iterator = document.querySelectorAll('div').iterator(); --- does
 some
  magic to not precompute the whole list
  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 gets the performance benefits of live NodeLists, I think meets the
  main use-cases of not wanting to walk the whole DOM, but doesn't require
  the browser to do a lot of metadata tracking as you go.
 
  Ojan