views:

64172

answers:

9

Tags can have multiple attributes. The order in which attributes appear in the code does not matter. For example:

<a href="#" title="#">
<a title="#" href="#">

How can I "normalize" the HTML in Javascript, so the order of the attributes is always the same? I don't care which order is chosen, as long as it is always the same.

UPDATE: my original goal was to make it easier to diff (in JavaScript) 2 HTML pages with slight differences. Because users could use different software to edit the code, the order of the attributes could change. This make the diff too verbose.

ANSWER: Well, first thanks for all the answers. And YES, it is possible. Here is how I've managed to do it. This is a proof of concept, it can certainly be optimized:

function sort_attributes(a, b) {
  if( a.name == b.name) {
    return 0;
  }

  return (a.name < b.name) ? -1 : 1;
}

$("#original").find('*').each(function() {
  if (this.attributes.length > 1) {
    var attributes = this.attributes;
    var list = [];

    for(var i =0; i < attributes.length; i++) {
      list.push(attributes[i]);
    }

    list.sort(sort_attributes);

    for(var i = 0; i < list.length; i++) {
      this.removeAttribute(list[i].name, list[i].value);
    }

    for(var i = 0; i < list.length; i++) {
      this.setAttribute(list[i].name, list[i].value);
    }
  }
});

Same thing for the second element of the diff, $('#different'). Now $('#original').html() and $('#different').html() show HTML code with attributes in the same order.

+666  A: 

The student asked the master, "Does an HTML element have the Buddha nature?"

The teacher responded, "Mu."

What is the reflection of a heron on the pond after the heron has flown away?

What is the order of attributes in an HTML element after the element has been transformed into an orderless map by the HTML parser and made available as a DOM node?

The rice is harvested and threshed. Some grains grew low on the stalks, some high. Which is which in your dinner bowl?

Pointy
I think, I have been enlightened...
plaes
Almost wish this was a novelty account. *Almost*.
Vince
51 (and counting) people have a funny definition of the word _useful_.
Motti
@Motti the only 100% useful answer to this question is "It is impossible". This answer is 100% useful, 100% funny and 100% original. 71 people think so.
Andrey
1 person (and counting) have no sense of humor.
Tamás Szelei
After you write your code, you wash your bowl.
Trip
@Motti: the rice metaphor is probably the most crucial part in understanding the response.
Jonno_FTW
@plaes sticking feathers up your butt does not make you a chicken.
YHVH
@Tamás I'm not counting more than one. :)
Epaga
@Epaga: As I recently saw this site, I excepted far more downvotes.
Tamás Szelei
[THE HORDES OF REDDIT RAIN DOWN UPON US](http://www.reddit.com/r/programming/comments/dtp5y/buddhism_to_the_rescue/)
Evan Carroll
@Evan Carroll - Poor Julien :-)
Pointy
Thank you Master Foo.
Dennis
Okay, I need to ask this - What is **mu**?
Lazer
I felt my mind expand after reading this. True story.
MattC
Apparently the path to StackOverflow enlightenment is lies within extensive, thoughtful, yet sideways answers in the `HTML` tag.
Sean Vieira
@Lazer: 'undefined'. http://en.wikipedia.org/wiki/Mu_%28negative%29
Paul Nathan
-1 Down voting just because it has so many up-votes.
Icode4food
I may have misunderstood or failed to interpret this answer, because I feel that this is a comment rather than an answer.
Eikern
So I looked it up, in that context "無"(Mu) means "It has not.".
Margus
Is that what people write when they don't know the answer, but still want to show off?
Julien
+8  A: 

you can try open HTML tab in firebug, the attributes are always in same order

tsurahman
This isn't really helpful on its own. That's because it is re-creating the HTML from the DOM, and however this happens has a particular attribute iteration order (or Firebug sorts them manually). Julien could take advantage of this and use the same method to write out HTML.
Matt Kantor
+63  A: 

JavaScript doesn't actually see a web page in the form of text-based HTML, but rather as a tree structure known as the DOM, or Document Object Model. The order of HTML element attributes in the DOM is not defined (in fact, as Svend comments, they're not even part of the DOM), so the idea of sorting them at the point where JavaScript runs is irrelevant.

I can only guess what you're trying to achieve. If you're trying to do this to improve JavaScript/page performance, most HTML document renderers already presumably put a lot of effort into optimising attribute access, so there's little to be gained there.

If you're trying to order attributes to make gzip compression of pages more effective as they're sent over the wire, understand that JavaScript runs after that point in time. Instead, you may want to look at things that run server-side instead, though it's probably more trouble than it's worth.

Tung Nguyen
I agree!!......
Trufa
JavaScript can run server-side.
Matt Kantor
Attributes are not considered part of the document tree (which uses ordering naturally). So while Attr inherits the Node interface, DOM Core 2 specifies these fields to be null for attributes http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-637646024
Svend
@Matt: That's true, but not what the OP meant, I'm sure...
musicfreak
+33  A: 

Take the HTML and parse into a DOM structure. Then take the DOM structure, and write it back out to HTML. While writing, sort the attributes using any stable sort. Your HTML will now be normalized with regard to attributes.

This is a general way to normalize things. (parse non-normalized data, then write it back out in normalized form).

I'm not sure why you'd want to Normalize HTML, but there you have it. Data is data. ;-)

Kim Bruning
Do you have a code example. I tried to do do something similar, it did not work.
Julien
+2  A: 

The question "What is the need for this?" Answer: It makes the code more readable and easier to understand.

Why most UI sucks... Many programmers fail to understand the need for simplifying the users job. In this case, the users job is reading and understanding the code. One reason to order the attributes is for the human who has to debug and maintain the code. An ordered list, which the program becomes familiar with, makes his job easier. He can more quickly find attributes, or realize which attributes are missing, and more quickly change attribute values.

signedbit
Methinks you have not thought about the question for long enough; even a working solution to the question would not address what you say here, true though it may be.
Clint Tseng
@signedbit Why do you suppose that the OP would want to do this with Javascript? It's *possible* that a server-side (build time?) Javascript solution was in mind, but it's unlikely that somebody experienced enough to do that would have failed to mention it in a Stackoverflow post. It's also possible that the OP is implementing an in-browser HTML editor, but that also seems doubtful.
Pointy
+1  A: 

This only matters when someone is reading the source, so for me it's semantic attributes first, less semantic ones next...

There are exceptions of course, if you have for example consecutive <li>'s, all with one attribute on each and others only on some, you may want to ensure the shared ones are all at the start, followed by individual ones, eg.

<li a="x">A</li>
<li a="y" b="t">B</li>
<li a="z">C</li>

(Even if the "b" attribute is more semantically useful than "a")

You get the idea.

Ali
+5  A: 

Actually, I can think of a few good reasons. One would be comparison for identity matching and for use with 'diff' type tools where it is quite annoying that semantically equivalent lines can be marked as "different".

The real question is "Why in Javascript"?

This question "smells" of "I have a problem and I think I have an answer...but I have a problem with my answer, too."

If the OP would explain why they want to do this, their chances of getting a good answer would go up dramatically.

Benjamin Franz
+4  A: 

@0xStackTrace: Perhaps more appropriate: alt text

ldog
+3  A: 

This is a proof of concept, it can certainly be optimized:

function sort_attributes(a, b) {
  if( a.name == b.name) {
    return 0;
  }

  return (a.name < b.name) ? -1 : 1;
 }

$("#original").find('*').each(function() {
  if (this.attributes.length > 1) {
    var attributes = this.attributes;
    var list = [];

    for(var i =0; i < attributes.length; i++) {
      list.push(attributes[i]);
    }

     list.sort(sort_attributes);

    for(var i = 0; i < list.length; i++) {
      this.removeAttribute(list[i].name, list[i].value);
    }

     for(var i = 0; i < list.length; i++) {
       this.setAttribute(list[i].name, list[i].value);
    }
  }
 });

Same thing for the second element of the diff, $('#different'). Now $('#original').html() and $('#different').html() show HTML code with attributes in the same order.

Julien