How do I do OuterHTML in firefox?
Asked Answered
C

11

37

Part of my code I get the OuterHTML propery

"<LI onclick="TabClicked(this, 'SearchName', 'TabGroup1');">Name "

so I can do stuff involing parsing it.

There is no OuterHTML property in javascript on firefox though and I can't find an alternative way to get this string. Ideas?

Carriecarrier answered 9/11, 2009 at 13:4 Comment(6)
From your example it is not clear what would you like to accomplish and where do you use this property.Juvenal
All I want is the text in the OnClick event as a string, so I can do things with it.Carriecarrier
If all you want is the onclick, then use elm.getAttribute("onclick").Recoil
Yeah you'd think so, but heavy googling showed me getattribute was buggy and broken in every browser, and getattributenode was the solution;)Carriecarrier
Okay, then use getAttributeNode instead. That still doesn't explain why you want outerHTML (although there are other reasons you might want it, of course)Felicio
The reason I wanted this was because I had some javascript that scanned for onclick events and did some funky stuff with it, to make a tab control. It was a while ago, and I didn't know jquery =)Carriecarrier
C
0

Figured it out!

child.getAttributeNode("OnClick").nodeValue;

getAttribute didn't work, but getAttributeNode worked great ;D

Carriecarrier answered 9/11, 2009 at 14:4 Comment(2)
background info for those interested in "getAttribute didn't work": #1834473Wavelet
I can't see any specific explanation of why getAttribute is different to getAttributeNode in the linkCarriecarrier
A
68

Here's the function we use in pure.js:

function outerHTML(node){
    return node.outerHTML || new XMLSerializer().serializeToString(node);
}

To use it the DOM way:

outerHTML(document.getElementById('theNode'));

And it works cross browsers

EDIT: WARNING! There is a trouble with XMLSerializer, it generates an XML(XHTML) string.
Which means you can end up with a tags like <div class="team" /> instead of
<div class="team"></div>
Some browsers do not like it. I had some pain with Firefox 3.5 recently.

So for our pure.js lib we came back to the old and safe way:

function outerHTML(node){
    // if IE, Chrome take the internal method otherwise build one
  return node.outerHTML || (
      function(n){
          var div = document.createElement('div'), h;
          div.appendChild( n.cloneNode(true) );
          h = div.innerHTML;
          div = null;
          return h;
      })(node);
  }
Alter answered 29/9, 2010 at 7:31 Comment(5)
Firefox 11 will support outerHTML natively - see bugzilla.mozilla.org/show_bug.cgi?id=92264Wavelet
@Wavelet wow... a 10 year request finally answered! Thanks for the updateAlter
Golfed down: document.createElement('_').appendChild(node.cloneNode(true)).innerHTMLPrudenceprudent
@yckart, Interesting. But Chrome does not seem to like '_', and you forgot a parentNode to get the outer tag. However something like document.createElement('div').appendChild( n.cloneNode(true) ).parentNode.innerHTML works quite well. Thanks!Alter
@Alter Whoops... I had just an iPhone and my head. No chance to test it before ;)Prudenceprudent
W
18

The proper approach (for non-IE browsers) is:

var sOuterHTML = new XMLSerializer().serializeToString(oElement);
Wellgroomed answered 9/11, 2009 at 13:57 Comment(1)
Pay attention that XMLSerializer generates XML(XHTML) and then do things like <div /> instead of <div></div>. See my answer here.Alter
L
12

If you are willing to use jQuery then it's relatively simple:

$('<div>').append( $(ElementSelector).clone() ).html();

This will get the outer HTML of multiple elements if multiple elements are selected.

Lemley answered 10/9, 2010 at 17:57 Comment(1)
Great answer, thanks! Worked perfectly. Very simple and clean.Trioecious
P
7

outerHTML is now supported by Firefox:

From Firefox 11 for developers

Firefox 11 shipped on March 13, 2012. This article provides information about the new features and key bugs fixed in this release, as well as links to more detailed documentation for both web developers and add-on developers.

  • The element.outerHTML property is now supported on HTML elements.
Polygon answered 10/4, 2012 at 16:56 Comment(0)
L
2

Try this: http://snipplr.com/view/5460/outerhtml-in-firefox/:

if (document.body.__defineGetter__) { 
   if (HTMLElement) {
      var element = HTMLElement.prototype;
      if (element.__defineGetter__) {
         element.__defineGetter__("outerHTML",
           function () {
              var parent = this.parentNode;
              var el = document.createElement(parent.tagName);
              el.appendChild(this);
              var shtml = el.innerHTML;
              parent.appendChild(this);
              return shtml;
           }
         );
      }
   }
}
Leonoraleonore answered 9/11, 2009 at 13:18 Comment(2)
The problem with that page is that it falls into a discussion with people saying the original example is wrong, so I am quite confused by it.Carriecarrier
Actually the guy who says it's wrong later says it does work - have you tried it?Leonoraleonore
B
2

For the reason that W3C does not include outerHTML property, you just need add following:

if (typeof (HTMLElement) != "undefined" && !window.opera)  
{  
    HTMLElement.prototype._____defineGetter_____("outerHTML", function()  
    {  
        var a = this.attributes, str = "<" + this.tagName, i = 0; for (; i < a.length; i++)  
            if (a[i].specified)  
            str += " " + a[i].name + '="' + a[i].value + '"';  
        if (!this.canHaveChildren)  
            return str + " />";  
        return str + ">" + this.innerHTML + "</" + this.tagName + ">";  
    });  
    HTMLElement.prototype._____defineSetter_____("outerHTML", function(s)  
    {  
        var r = this.ownerDocument.createRange();  
        r.setStartBefore(this);  
        var df = r.createContextualFragment(s);  
        this.parentNode.replaceChild(df, this);  
        return s;  
    });  
    HTMLElement.prototype._____defineGetter_____("canHaveChildren", function()  
    {  
        return !/^(area|base|basefont|col|frame|hr|img|br|input|isindex|link|meta|param)$/.test(this.tagName.toLowerCase());   
    });  
} 
Brookweed answered 29/3, 2010 at 7:13 Comment(0)
C
1

How about something simple like this (not fully tested):

function outerHTML(node) {
    var el;
    if (node.outerHTML) {
        return node.outerHTML;
    } else if (node.parentNode && node.parentNode.nodeType == 1) {
        var el = document.createElement(node.parentNode.nodeName);
        el.appendChild( node.cloneNode(true) );
        return el.innerHTML;
    }
    return "";
}
Commensurable answered 9/11, 2009 at 14:7 Comment(0)
P
1

Try:

(function(ele, html)
{if (typeof(ele.outerHTML)=='undefined')
    {var r=ele.ownerDocument.createRange();
     r.setStartBefore(ele);
     ele.parentNode.replaceChild(r.createContextualFragment(html), ele);
    }
 else
     {ele.outerHTML=html;
     }
})(aEle, aHtml);

for diyism

Padraig answered 18/5, 2010 at 12:35 Comment(0)
R
0

If all you want is the onclick attribute, then try the following: This assumes that you did not set the event using attachEvent or addEventListener.

elm.getAttribute("onclick");

If you want to make an outerHTML string (just promise not to take it apart after you make it):

function outerHTML(elm){
  var ret = "<"+elm.tagName;
  for(var i=0; i<elm.attributes.length; i++){
    var attr = elm.attributes[i];
    ret += " "+attr.name+"=\""+attr.nodeValue.replace(/"/, "\"")+"\"";
  }
  ret += ">";
  ret += elm.innerHTML+"</"+elm.tagName+">";
  return ret;
}

This function should do the trick in most cases, but it does not take namespaces into account.

Recoil answered 9/11, 2009 at 13:21 Comment(3)
I remember trying getattribute but I couldn't work out how to get the text out of it... if it's possible it's much neater than outerhtmlCarriecarrier
Tried your function but it just came back with temp = "<LI undefined="undefined" undefined="undefined" undefined="undefined" undefined="undefined" undefined="undefined" undefined="undefined" undefined="undefined" undefined="undefined"... etc.Carriecarrier
Modify this by adding an if (attr) {...} and the undefined attributes will not be enumerated in the result.Hayrack
C
0

Figured it out!

child.getAttributeNode("OnClick").nodeValue;

getAttribute didn't work, but getAttributeNode worked great ;D

Carriecarrier answered 9/11, 2009 at 14:4 Comment(2)
background info for those interested in "getAttribute didn't work": #1834473Wavelet
I can't see any specific explanation of why getAttribute is different to getAttributeNode in the linkCarriecarrier
I
0

I know this is an old thread but if anyone finds this with Google (like I did) - I tried all these solutions and none of them worked out-of-the-box, since none handled both the getting and setting properties of outerHTML. I found this: which worked for me:

// Implement the outerHTML property for browsers that don't support it.
// Assumes that the browser does support innerHTML, has an extensible 
// Element.prototype, and allows getters and setters to be defined.
(function() {
// If we already have outerHTML return without doing anything
if (document.createElement("div").outerHTML) return;

// Return the outer HTML of the element referred to by this
function outerHTMLGetter() {
    var container = document.createElement("div"); // Dummy element
    container.appendChild(this.cloneNode(true));   // Copy this to dummy
    return container.innerHTML;                    // Return dummy content
}

// Set the outer HTML of the this element to the specified value
function outerHTMLSetter(value) {
    // Create a dummy element and set its content to the specified value
    var container = document.createElement("div");
    container.innerHTML = value;
    // Move each of the nodes from the dummy into the document
    while(container.firstChild)  // Loop until container has no more kids
        this.parentNode.insertBefore(container.firstChild, this);
    // And remove the node that has been replaced
    this.parentNode.removeChild(this);
}

// Now use these two functions as getters and setters for the 
// outerHTML property of all Element objects. Use ES5 Object.defineProperty
// if it exists and otherwise fall back on __defineGetter__ and Setter__.
if (Object.defineProperty) {
    Object.defineProperty(Element.prototype, "outerHTML", {
                              get: outerHTMLGetter,
                              set: outerHTMLSetter,
                              enumerable: false, configurable: true
                          });
}
else {
    Element.prototype.__defineGetter__("outerHTML", outerHTMLGetter);
    Element.prototype.__defineSetter__("outerHTML", outerHTMLSetter);
}
}());

Kudos: https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/chapter-15/implementing-the-outerhtml

Inoculate answered 28/4, 2013 at 14:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.