This would be an ideal use case for XPath.


On Mar 5, 10:35 am, Walter Lee Davis <[email protected]> wrote:
> Thanks, yes that might work. But I am trying to write something which  
> is structure-agnostic, since it goes in a plug-in for a Web design  
> application, and I have no idea how people will want to use it. Alex's  
> suggestion allows me to do the very least (and therefore resist the  
> urge to screw up) while still offering an unsurprising result in a  
> wide range of layout situations.
>
> Walter
>
> On Mar 5, 2010, at 8:08 AM, Eric wrote:
>
>
>
> > Hi,
>
> > All the proposed solutions are very nice example of coding, but
> > however you may ask yourself this question:
> > "If there is no easy way to do the processing I want with my data
> > structure, am I sure I am using the right data structure?"
>
> > In other words, instead of coding heavy processing functions couldn't
> > you just change your DOM structure to optimize whatever processing you
> > need to do with them.
>
> > In your case, adding a DIV around each "H3-P-P-P..." sequence would do
> > the trick.
>
> > Alex: Very nice implementation!
>
> > Eric
>
> > On Feb 23, 6:20 pm, Walter Lee Davis <[email protected]> wrote:
> >> Wow, thanks very much Alex!
>
> >> Walter
>
> >> On Feb 23, 2010, at 11:28 AM, Alex Wallace wrote:
>
> >>> Here's a slightly better version, as it crawls the tree itself
> >>> instead of grabbing and filtering all of the element's
> >>> nextSiblings(). Since it avoids the call to recursivelyCollect()
> >>> it's a bit faster (with 10 siblings after the requested node, it's
> >>> about 20% faster - when I upped it to about 40 elements after the
> >>> node, it ran well over 250% faster). If you have a lot of nodes to
> >>> filter for the accordion, I'd definitely use this version.
>
> >>> function fasterSameTagSiblings(element) {
> >>>    element = $(element);
> >>>    var results = [], node = element.nextSibling, tag;
> >>>    while (node = node.nextSibling) {
> >>>            if (node.nodeType === 1) {
> >>>                    tag = tag || node.tagName.toLowerCase();
> >>>                    if (node.tagName.toLowerCase() === tag)
> >>>                            results.push(node)
> >>>                    else
> >>>                            break;
> >>>            }
> >>>    }
> >>>    return results;
> >>> }
>
> >>> Cheers,
> >>> Alex
>
> >>> Micro-optimization for sure, but it was bugging me. :)
>
> >>>    function fasterSameTagSiblings(element) {
> >>>            element = $(element);
> >>>            var results = [], node = element.nextSibling, tag;
> >>>            while (node = node.nextSibling) {
> >>>                    if (node.nodeType === 1) {
> >>>                            tag = tag || node.tagName.toLowerCase();
> >>>                            if (node.tagName.toLowerCase() === tag)
> >>>                                    results.push(node)
> >>>                            else
> >>>                                    break;
> >>>                    }
> >>>            }
> >>>            return results;
> >>>    }
>
> >>> On Mon, Feb 22, 2010 at 8:24 PM, Walter Lee Davis
> >>> <[email protected]> wrote:
> >>> The heads and the paragraphs are all at the same level, and I don't
> >>> want all the paragraphs, just the ones between "this" head and the
> >>> next head. (It's for an accordion effect.) So while
> >>> up('div').select('p') would do exactly what you say, it would leave
> >>> me where I started.
>
> >>> Thanks,
>
> >>> Walter
>
> >>> On Feb 22, 2010, at 5:46 PM, Matt Foster wrote:
>
> >>> This is probably too obvious to be right but if you're simply  
> >>> looking
> >>> for all of the paragraph tags at that level could you simply go up  
> >>> to
> >>> the parent and select down from there?
>
> >>> On Feb 22, 12:57 pm, Paul Kim <[email protected]> wrote:
> >>> Hi Alex, thanks for the tip. I've modified the function based on
> >>> your tip
> >>> and your example function:
>
> >>>    function consecutiveSameTagSiblings(element) {
> >>>        var element = $(element);
> >>>        var nextSiblings = element.nextSiblings();
> >>>        var similarElements = [];
> >>>        similarElements.push(element);
> >>>        for (var i=0; i< nextSiblings.length; i++) {
> >>>            if (element.tagName == nextSiblings[i].tagName) {
> >>>                similarElements.push(nextSiblings[i]);
> >>>            }
> >>>            else {
> >>>                break;
> >>>            }
> >>>        }
> >>>        return similarElements;
> >>>    }
>
> >>> On Mon, Feb 22, 2010 at 9:50 AM, Alex Wallace
> >>> <[email protected]>wrote:
>
> >>> Paul, one recommendation: store the results of
> >>> element.nextSiblings() in a
> >>> local variable outside of the loop. DOM traversals are pretty slow.
>
> >>> Best,
> >>> Alex
>
> >>> On Mon, Feb 22, 2010 at 12:28 PM, Paul Kim <[email protected]>  
> >>> wrote:
>
> >>> Hi Walter, if you want to get all similar elements up to but not
> >>> including
> >>> the next head, I would use Prototype's Element.nextSiblings() to  
> >>> loop
> >>> through all elements with the same tagName and break when the
> >>> tagName is
> >>> different. Here is a function I created just now that would
> >>> hopefully do
> >>> what you want:
>
> >>> function getSimilarElements(element) {
> >>>    var element = $(element);
> >>>    var similarElements = new Array();
> >>>    for (var i=0; i< element.nextSiblings().length; i++) {
> >>>        if (element.tagName == element.nextSiblings()[i].tagName) {
> >>>            similarElements[i] = element.nextSiblings()[i];
> >>>        }
> >>>        else {
> >>>            break;
> >>>        }
> >>>    }
> >>>    return similarElements;
> >>> }
>
> >>> Here is the entire example as well:
>
> >>> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
> >>>     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
> >>> <html xmlns="http://www.w3.org/1999/xhtml";>
> >>> <head>
> >>> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
> >>> <title>Demo</title>
> >>> <script type="text/javascript" src="
> >>>http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js
> >>> "></script>
> >>> <script type="text/javascript" src="
> >>>http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.3/
> >>> scriptaculou...
> >>> "></script>
> >>> <script type="text/javascript">
> >>> document.observe("dom:loaded", function() {
> >>>    function getSimilarElements(element) {
> >>>        var element = $(element);
> >>>        var similarElements = new Array();
> >>>        for (var i=0; i< element.nextSiblings().length; i++) {
> >>>            if (element.tagName == element.nextSiblings()
> >>> [i].tagName) {
> >>>                similarElements[i] = element.nextSiblings()[i];
> >>>            }
> >>>            else {
> >>>                break;
> >>>            }
> >>>        }
> >>>        return similarElements;
> >>>    }
>
> >>>    console.log(getSimilarElements('foo'));
> >>> });
> >>> </script>
> >>> <style type="text/css">
> >>> body {margin:0; padding:0;}
> >>> </style>
> >>> </head>
> >>> <body>
> >>> <div>
> >>> <h3>first header</h3>
> >>> <p id="foo">first paragraph</p>
> >>> <p>second paragraph</p>
> >>> <h3>second header</h3>
> >>> <p>third paragraph</p>
> >>> <p>fourth paragraph</p>
> >>> <p>fifth paragraph</p>
> >>> <h3>third header</h3>
> >>> <p>sixth paragraph</p>
> >>> <p>seventh paragraph</p>
> >>> </div>
> >>> </body>
> >>> </html>
>
> >>> On Mon, Feb 22, 2010 at 8:22 AM, Walter Lee Davis
> >>> <[email protected]>wrote:
>
> >>> Thanks very much. I was looking in the wrong place for the
> >>> functionality
> >>> I need. You've given me the bones I need to build on.
>
> >>> Walter
>
> >>> On Feb 22, 2010, at 11:07 AM, Alex Wallace wrote:
>
> >>>  I whipped up something that should handle the task, although I'm  
> >>> sure
> >>> this could be optimized using the nextElementSibling. This version
> >>> grabs
> >>> nextSiblings() and then filters them, but the faster way would be to
> >>> iterate
> >>> over the `element.nextSibling` and break when it encounters a
> >>> different tag
> >>> name (instead of finding them all, which is bound to be slower).
>
> >>> But here goes:
>
> >>>       function consecutiveSameTagSiblings(element) {
> >>>               element = $(element);
> >>>               var siblings = element.nextSiblings(), results = [];
> >>>               if (!siblings[0]) return results;
> >>>               var tagName = siblings[0].tagName.toLowerCase();
> >>>               for (var i = 0, sibling; sibling = siblings[i]; ++i) {
> >>>                       if (sibling.tagName.toLowerCase() === tagName)
> >>>                               results.push(sibling);
> >>>                       else
> >>>                               break;
> >>>               }
> >>>               return results;
> >>>       }
>
> >>> Best,
> >>> Alex
>
> >>> On Mon, Feb 22, 2010 at 10:38 AM, Walter Lee Davis
> >>> <[email protected]>
> >>> wrote:
> >>> Hmmm. That's not a documented function. I had a look at the source,
> >>> and
> >>> I can't see how it works. It accepts a node as its only argument,
> >>> and it
> >>> doesn't seem to perform any comparison as it executes. How then
> >>> would I get
> >>> it to stick to just the one type of sibling, and how would I get it
> >>> to stop
> >>> when it ran out of similar siblings?
>
> >>> Thanks as always for any pointers.
>
> >>> Walter
>
> >>> On Feb 22, 2010, at 10:29 AM, Alex Wallace wrote:
>
> >>> You'll want to leverage Prototype's nextElementSibling function.  
> >>> That
> >>> function grabs element.nextSibling and traverses until it finds an
> >>> an actual
> >>> element (by checking nodeType).
>
> >>> You could wrap a function around that which stores the tagName of  
> >>> the
> >>> first element it matches, and then continues to find
> >>> nextElementSibling
> >>> until it either returns null, or break when the tagName doesn't
> >>> match the
> >>> original tagName.
>
> >>> Take a look at the innards of Element.adjacent and
> >>> Element.nextElementSibling for an idea of what I mean.
>
> >>> Best,
> >>> Alex
>
> >>> On Mon, Feb 22, 2010 at 12:00 AM, Walter Lee Davis
> >>> <[email protected]>
> >>> wrote:
> >>> I have a structure like this inside a parent DIV:
>
> >>> H3
> >>> P
> >>> P
> >>> H3
> >>> P
> >>> P
> >>> P
> >>> H3
> >>> P
> >>> P
>
> >>> And I'd like to be able to get the paragraphs between two heads, or
> >>> between the last head and the end of the parent DIV.
> >>> Element.adjacent('p')
> >>> doesn't do what I need --
>
> ...
>
> read more »

-- 
You received this message because you are subscribed to the Google Groups 
"Prototype & script.aculo.us" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en.

Reply via email to