views:

41

answers:

2

Is there a way to remove the id attribute of every node in a range or fragment?

Update: I finally found out that the bug I'm struggling with is based on a <[script]> being included in a range, and therefore unexpectedly cloned, when a chrome user does a ctrl+a. My goal would be to remove any instance of <[script]> from the range (or doc fragment), such that it is not replicated when cloned.

A: 

yes: http://api.jquery.com/removeAttr/

matpol
The OP's asking about DOM Ranges, not elements.
Tim Down
A solution without a library would be preferable in this instance - even as much as I love jquery.
Matrym
Andy E
I'm writing a script that I need to be library independent so that I don't limit others' in their use of it.
Matrym
oops - should have read the question properly - seems all the questions on SO use jquery these days!
matpol
+1  A: 

You may be able to use a TreeWalker, which works in pretty much all the browers that Range works in.

function actOnElementsInRange(range, func) {
    function isContainedInRange(el, range) {
        var elRange = range.cloneRange();
        elRange.selectNode(el);
        return range.compareBoundaryPoints(Range.START_TO_START, elRange) <= 0
                && range.compareBoundaryPoints(Range.END_TO_END, elRange) >= 0;
    }

    var rangeStartElement = range.startContainer;
    if (rangeStartElement.nodeType == 3) {
        rangeStartElement = rangeStartElement.parentNode;
    }

    var rangeEndElement = range.endContainer;
    if (rangeEndElement.nodeType == 3) {
        rangeEndElement = rangeEndElement.parentNode;
    }

    var isInRange = function(el) {
        return (el === rangeStartElement || el === rangeEndElement ||
                    isContainedInRange(el, range))
            ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
    };

    var container = range.commonAncestorContainer;
    if (container.nodeType != 1) {
        container = container.parentNode;
    }

    var walker = document.createTreeWalker(document,
        NodeFilter.SHOW_ELEMENT, isInRange, false);

    while (walker.nextNode()) {
        func(walker.currentNode);
    }
}

actOnElementsInRange(range, function(el) {
    el.removeAttribute("id");
});
Tim Down
Thanks Tim - you're being very helpful. But I'm not sure it worked. I set up a test page here: http://latentmotion.com/link-building/test-clone.html
Matrym
Seems to be working for me. What are you seeing that's wrong? By the way, I've just updated my answer to remove a logging statement I'd accidentally left in.
Tim Down