tags:

views:

49

answers:

4

I need to remove all attributes set on certain elements with jquery, except for a few i want to select manually. Lets say i have an image:

<img hspace="4" border="1" vspace="4" src="someimage.jpg" alt="somealt">

and i want this as result:

<img src="someimage.jpg" alt="somealt">

the only way i could think of is the .removeAttr() every single attribute. But the problem is that some times there is a style="balbla" set, i want to remove or other attr's that maybe i forgot. So i want to white list the attrs that are ok and remove all the others.

how would you do this?

A: 

Depending on the situation, you could create a new element, copy the attributes of the old one based on a whitelist, and replace; or you could transform it to a HTML string and parse it. But chances are, if you need to sanitize elements from jQuery, you are doing something wrong. What would you like to achieve?

Tgr
given is this: http://www.google.com/reader/shared/meodai and there is my result: http://meodai.ch/content_slider/ the thing is there all all sorts of attributes on those elements i want to remove.
meo
In that case, wouldn't it be better to use something [reset.css](http://meyerweb.com/eric/tools/css/reset/)-ish? There are only so many CSS attributes which can disrupt your layout.
Tgr
its not just about the layout, but the validity. And then you have the same problem. Some attr's that people set just don't exist, so its hard to reset them and to tell what influence it is gonna have on the render of the page in the browser
meo
I can't think of any situation where validity is important and sanitizing from javascript is a good way to achieve it. If you are concerned about parsers choking on invalid markup, you need to clean up the source on the server's side; bots and such won't execute the javascript. Invalid attributes will be ignored by the browser; markup that's not even well-formed will be converted into something close and well-formed by the time you could access it from javascript.
Tgr
+2  A: 

Here's a solution that iterates over the attributes list.

I'm actually only setting its value to "" (empty string), because for some reason, removeAttribute() fails when it gets to the border attribute. Investigating...

Give it a try:

var whitelist = ["src","alt"];

$('img').each(function() {
    var attributes = this.attributes;
    var i = attributes.length;
    while( i-- ) {
        var attr = attributes[i];
        if( $.inArray(attr.name,whitelist) == -1 )
            this.removeAttributeNode(attr);
    }
});​
patrick dw
perfect! now would it be possible to make a array or something with my whitelist? Its a little inconvenient to all list them in this if statement.
meo
@patrick dw: I just figured out the same before seeing this and updated into my answer but not needed now :) +1
Sarfraz
Wouldn't it be better to use `attributes[i].nodeName`.
Sarfraz
@meo - Sure, I'll update.
patrick dw
@Sarfraz - They both seem to return the same value. Not sure what the difference is.
patrick dw
@meo - Improved it a bit with while loop and `removeAttributeNode()`.
patrick dw
wow looks sexy and right to me, thank you. Already implemented for all elements not just IMG's works fine and fast!
meo
+2  A: 
<div id="container"><img id="img" hspace="4" border="1" vspace="4" src="someimage.jpg" alt="somealt">
</div>
<textarea rows="15" cols="80" id="dbg"></textarea>

And the javascript:

$('#dbg')[0].value += $('#container').html();
atts = $("#img")[0].attributes;
var img = $("#img"); //since it may remove id as well
for (var i = atts.length - 1; i >= 0; i--) {
    var name = atts[i].name;
    if (name != 'src' && name != 'alt') { //you can implement an array or other thing
        img.removeAttr(name);
    }
}

$('#dbg')[0].value += $('#container').html();

Try here: http://jsfiddle.net/drZhu/

aularon
+1  A: 

I generally prefer to not drop down to raw js DOM unless absolutely necessary when working with jQ so ill offer pure jQ solution:

$('img').each(function() {
    var e = $(this);
    var whitelist = ['src','title'];
    $.each(this.attributes, function(attr, value){
       if($.inArray(attr, whitelist) == -1) {
           e.removeAttr(attr);
       }
    });
});
prodigitalson
jQuery is very practical, but i would just use it when you have a real use of it. in this case for example you could replace your $.each by a pour javascript "for" and you would improve the speed... Especially on tasks where you have to parse html files that could be very long it could make a big difference... but your solution seams very proper to me +1
meo
Well speed over large data sets is a concern in some cases and if its an issue that would dictate "absolutely necessary". but generally speaking i start with jQuery's API for things and then optimize on a case by case basis. I use the same practice when using an ORM like Doctrine or Propel (php) do everything in that agnostic API by default, then optimize queries, or drop to raw PDO on a case by case basis. +1 for your thoughtful and accurate comment...
prodigitalson