Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    New to the CF scene
    Join Date
    Jul 2002
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Good way to flatten a hierarchy?

    I've been struggling with a good way to eliminate a node in the middle of a hierarchy, and attach its children to its parent. This is the structure I'm working on:

    parent
        theNode
            child
            child
            child

    and I want to get

    parent
        child
        child
        child

    I tried iterating through the NodeList of theNode, but it's live, which is no good for this operation.

    Ideas?
    Last edited by David Kurtz; 09-19-2002 at 10:05 PM.

  • #2
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    You are looking for the DOM2 Traversal interface. Read about it at www.w3.org

    Currently, the only browser to support any of it is Mozilla/NS7, and of which is missing the NodeIterator interface (but does have NodeFilter and TreeWalker).

    *Very* powerful way of navigating the node hierchy, and is a shame that Microsoft really doesn't seem to care about supporting any DOM2 in IE, among several other powerful standards...

  • #3
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Yes, but for an IE solution, use it's proprietary removeNode() method. It's only paremeter is a boolean value that indicates whether or not the children should be removed as well. 'false' is the default
    Code:
    <div style="color:blue" id="div1" onClick="this.removeNode();">
    	<span>hello</span><br>
    	<span>world</span><br>
    	<div style="color:red" id="div2" onClick="this.removeNode();">
    		<span>hello</span><br>
    		<span>world</span><br>
    	</div>
    </div>
    Pretty durn handy if you ask me, and unlike some of IE's other crap, something I'd like to see in the DOM. Works in IE5+

    Note:The node being removed MUST have an ID, otherwise it's children will be removed too.
    Last edited by beetle; 09-19-2002 at 11:09 PM.
    My Site | fValidate | My Brainbench | MSDN | Gecko | xBrowser DOM | PHP | Ars | PVP
    “Minds are like parachutes. They don't work unless they are open”
    “Maturity is simply knowing when to not be immature”

  • #4
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Node.prototype.removeNode = function() { this.parentNode.removeChild(this) };

    Emulates removeNode() when removing all the nodes...

    Anyway, I misread your question - DOM2 Traversal is excellent for traversing the DOM, but not manipulating it (it actually is incapable of changing it, you need to use other DOM implementations such as Range or Core for that).

    Anyway, assume that refToNode is a reference to the node you want to remove, and reparent its children to its parent:

    var parent = refToNode.parentNode;

    var range = document.createRange();
    range.selectNodeContents(refToNode);
    // initializes a range and selects the node's children


    parent.replaceChild(range.extractContents(), refToNode);
    // remove refToNode's children, return as a doc frag, replace refToNode with the document fragment


    This is DOM2 Range mixed in with a touch of DOM2 Core. This only works in Moz.

  • #5
    New Coder
    Join Date
    May 2004
    Posts
    22
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Grabbing nodes from fragmented selection?

    Well, back again.

    My question I think is some what related to this subject.

    I need to be able to format or delete nodes that a given range covers.


    Example:



    Here is the text a user can select:
    --------------------------------------------------
    Subhead.
    This is the paragraph I will be testing today.
    Here is the second line of the paragraph. Weeeeee!
    --------------------------------------------------

    Here is the underling html:
    ----------------------------------------------------------------
    <DIV>Subhead.</DIV>
    <DIV>This is the paragraph I will be testing today.</DIV>
    <DIV>Here is the second line of the paragraph. Weeeeee!</DIV>
    ----------------------------------------------------------------

    Now say the user selects this text:
    ---------------------------
    be testing today.
    Here is the second
    ---------------------------



    I need to grab the any of the nodes that that selection passes over.
    So for this example I need to grab these two nodes . . .

    <DIV>This is the paragraph I will be testing today.</DIV>
    <DIV>Here is the second line of the paragraph. Weeeeee!</DIV>

    based on the user selection shown above. Again this is for IE. I've toyed around quite a bit and can't seem to find a way to do this.

  • #6
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    var sel = window.getSelection().getRangeAt(0).cloneRange();
    sel.setStartBefore(sel.startContainer);
    sel.setEndAfter(sel.endContainer);


    sel is now the range you desire, in Mozilla at least. IE should have some simple TextRange commands to do the same.

  • #7
    New Coder
    Join Date
    May 2004
    Posts
    22
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Here is how I got it working in IE, don't know if it's the best but it works.


    Code:
    //Move through all the children.
    for (var h=0;h<this.edit.body.children.length;h++) {
    			
    //create an empty textRange and move it to enclose the contents of the current child
    var childSel = this.edit.selection.createRange();
    				
    //move this range to the current child
    childSel.moveToElementText(this.edit.body.children[h]);
    
    //Check to see if the selection starts in the current child node.
    if(sel.compareEndPoints("StartToEnd", childSel) == -1 && 
    (sel.compareEndPoints("StartToStart", childSel) == 1 || 
    sel.compareEndPoints("StartToStart", childSel) == 0))
    {
    //Do whatever to this.edit.body.children[h]
    }
    
    
    //Check to see if the current child node is in the middle of the selection
    if(sel.compareEndPoints("StartToEnd", childSel) == -1 && 
    sel.compareEndPoints("StartToStart", childSel) == -1 && 
    sel.compareEndPoints("EndToStart", childSel) == 1 && 
    sel.compareEndPoints("EndToEnd", childSel) == 1)
    {
    //Do whatever to this.edit.body.children[h]
    }
    
    //Check to see if the selection ends in the current child node.
    if(sel.compareEndPoints("EndToStart", childSel) == 1 && 
    (sel.compareEndPoints("EndToEnd", childSel) == -1 || 
    sel.compareEndPoints("EndToEnd", childSel) == 0))
    {
    //Do whatever to this.edit.body.children[h]
    }
    
    }
    I could have done it by just checking if the child node was NOT in the selection area but for the sake of making it easy for next person who works with this code to see what is happening, I did it this way.
    Last edited by iceboxqs; 05-20-2004 at 01:34 AM.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •