David Mark's Javascript Daily - Volume #3 - Tip #6 - How to Get andSet HTML

Discussion in 'Javascript' started by David Mark, Nov 15, 2011.

  1. David Mark

    David Mark Guest

    How to Get and Set HTML

    Setting the inner HTML of an element is often useful. When making
    complicated changes to the document tree, allowing the parser to do
    most of the work is often the most efficient solution. The question
    of whether to deal with a string or object representation of a DOM
    structure comes up often in applications that update portions of a
    document with XHR results.

    Despite there being no standard behind the innerHTML property and the
    somewhat awkward feel of dealing with serialized DOM structures, I
    virtually always choose the string over the (XML) document object.
    It's much simpler, faster, requires less code, less function calls
    and, having debuted in IE 4, has enough successful history behind it
    to be trusted.

    You've probably heard there are bugs galore with this property, but
    most implementation differences can hardly be considered bugs. This
    is another Microsoft invention that has been copied by every other
    browser vendor. Microsoft explicitly disallowed modifying table
    structures with this property. For example, you can replace entire
    TABLE elements, but you can't replace a row, column group, etc. There
    are existing (and standard) objects to modify table structures:-

    http://msdn.microsoft.com/en-us/library/ms537484(v=vs.85).aspx

    Follow the link at the bottom to the DOM 1 recommendation to find all
    of the information you need to modify table structures without
    stooping to setting inner HTML.

    Same goes for SELECT elements, which also have specialized objects to
    modify their structure (e.g. add and remove options). As with most
    form controls, they are very easy to manipulate with standard code
    that works in virtually every script-enabled browser ever made (even
    NN 4!) See the same DOM recommendation.

    Keeping these facts in mind during design can save a world of time.
    I've found that most designs can do just fine sticking to the
    innerHTML properties of DIV elements (and perhaps the occasional TD or
    TR, which won't change the structure of containing tables).

    The simplest rendition of the setter with simplified feature
    detection*:-

    // NOTE: Don't use this rendition with anything but DIV's

    // Degrades in IE 3 :)

    if (document.documentElement && 'string' == typeof
    document.documentElement.innerHTML) {
    var setHTML = function(el, html) {
    el.innerHTML = html;
    };
    }

    Trying to move a complicated project with lots of developers over to
    this way of setting HTML? During development, you may want to add
    something like:-

    if (el.tagName.toLowerCase() != 'div') {
    throw new Error('Please only set inner HTML of DIV elements!');
    }

    ....at the outset (and remove on deployment of course). All of the
    trouble-making code will become apparent. Eventually, even the
    developers who don't read documentation will get the message about not
    modifying anything other than DIV's with the setHTML function.

    Why would you even bother to wrap that functionality? For one,
    because you need the feature detection. Never mind that virtually
    every browser made to date has this property. Your applications
    should degrade gracefully in those (past or future) browsers that are
    the exceptions. Why even try to memorize which host objects and
    properties are omnipresent at the moment the function is written?
    Just include appropriate feature detection/testing in all function
    renditions.

    if (setHTML) {
    // Put HTML setting application here
    }

    Also, however unlikely in this case, you might want to replace setHTML
    with a more complicated rendition in some future application. You
    might consider the debug version with the argument validation to be an
    alternate rendition. I prefer to think of it as a debug version of
    the same rendition.

    But a better question is why you would want to try to modify table
    structures by setting inner HTML. Sure, it can be be done in a
    roundabout way. Ultimately it comes down to doing what you were
    trying to avoid in the first place (i.e. manually appending nodes one
    at a time). My Library (and the rest) all go through a lot of
    rigamorale to try to make such operations "work" (as best they can)
    with varied results. This is what GP libraries do. They don't help
    developers avoid costly mistakes. They hide the costly mistakes
    behind a "concise" API. If you could only see the mess that goes on
    behind the scenes of these things, you'd be in a much better position
    to make sound design decisions. Furthermore, you wouldn't be left
    with code that can only be reasonably expected to "work" in five or
    six of the latest versions of the "core" browsers in their default
    configurations *today*.

    Every time I hear "don't reinvent the wheel", I think of how many old
    versions of jQuery, Dojo, Prototype, Mootools, etc. there are broken
    down and rusting on the side of the highway. Also have to wonder what
    the average Web developer wants with the "perfect" innerHTML wrapper.
    Sure lots of library authors (typically excited and ambitious
    beginners) are keen to provide such a thing (as best they can). But
    who in their right mind would be in the market for it, particularly
    when it is likely a clunky multi-browser facade as opposed to a clean
    cross-browser solution? Which strategy do you think will save time in
    the long run? Which strategy will the monolithic libraries/framework
    always eschew for not having enough mass appeal?

    See the problem with such libraries? They constantly strive to
    overreach both practicality and the collective ability of their
    authors because they are all in some sort of ridiculous competition to
    be the most popular library. Does being the most popular lead to
    better solutions? Of course not; jQuery is a prime example of a
    script getting (much) worse as it grows more popular. It's not hard
    to understand why: too many cooks with too many contexts, too many
    suggestions, etc. You end up with one fuzzily-defined context (e.g.
    works for me here, dude!) for hundreds of functions. Changing any one
    function can alter the context in which the collection is expected to
    work; it's impossible to pin such things down and no wonder that most
    libraries provide little more than a set of shiny browser icons to
    indicate their "supported" environments.

    In contrast to setting, serializing (getting) HTML from DOM structures
    is mostly useless and trying to normalize markup on the client side is
    generally a waste of time. An example of an application that does
    need to serialize HTML is an editor. But generally, HTML editors
    don't *need* to normalize the resulting markup. That's a task for a
    server side process. It's the same case as with form validation,
    except that providing a client side first defense is a much more
    complicated proposition. You have to write the server side validation
    anyway.

    * Use isHostObjectProperty to detect documentElement

    http://www.cinsoft.net/
    http://www.twitter.com/cinsoft
    http://jsperf.com/browse/david-mark
    David Mark, Nov 15, 2011
    #1
    1. Advertising

  2. Re: David Mark's Javascript Daily - Volume #3 - Tip #6 - How to Getand Set HTML

    David Mark schrieb:
    > Despite there being no standard behind the innerHTML property and the
    > somewhat awkward feel of dealing with serialized DOM structures, I
    > virtually always choose the string over the (XML) document object.
    > It's much simpler, faster, requires less code, less function calls
    > and, having debuted in IE 4, has enough successful history behind it
    > to be trusted.


    Why is that faster? Only because the native html parser is faster than
    the javascript interpreter?
    I could understand the use of innerHTML when it's for large static
    elements delivered as plain text per ajax - where the server can
    serialize the structure into HTML. But when it comes to elements with
    event listeners, I absolutely prefer DOM building methods.
    Using a "library" function that takes the element name, attributes,
    child nodes and event listeners as attributes, I can build dom
    structures much easier than (hand)writing serialized html strings.
    Also I can't believe that it would be faster to serialize the structure
    to a string, process this with the innerHTML parser, and then dig in the
    dom tree again to set the listeners (Thats what I really hate jQuery for).
    Using plain dom methods (document.createElement,
    document.createTextNode, el.appendChild, el.addEventListener) I've never
    experienced problems with tables or select elements, and I'm not limited
    to divs.
    Or does that only work in recent browsers?

    Bergi
    Andreas Bergmaier, Nov 15, 2011
    #2
    1. Advertising

  3. Re: David Mark's Javascript Daily - Volume #3 - Tip #6 - How to Getand Set HTML

    Am 2011-11-15 22:26, Andreas Bergmaier meinte:
    > David Mark schrieb:
    >> Despite there being no standard behind the innerHTML property and the
    >> somewhat awkward feel of dealing with serialized DOM structures, I
    >> virtually always choose the string over the (XML) document object.
    >> It's much simpler, faster, requires less code, less function calls
    >> and, having debuted in IE 4, has enough successful history behind it
    >> to be trusted.

    >
    > Why is that faster? Only because the native html parser is faster than
    > the javascript interpreter?
    > I could understand the use of innerHTML when it's for large static
    > elements delivered as plain text per ajax - where the server can
    > serialize the structure into HTML. But when it comes to elements with
    > event listeners, I absolutely prefer DOM building methods.
    > Using a "library" function that takes the element name, attributes,
    > child nodes and event listeners as attributes, I can build dom
    > structures much easier than (hand)writing serialized html strings.
    > Also I can't believe that it would be faster to serialize the structure
    > to a string, process this with the innerHTML parser, and then dig in the
    > dom tree again to set the listeners (Thats what I really hate jQuery for).
    > Using plain dom methods (document.createElement,
    > document.createTextNode, el.appendChild, el.addEventListener) I've never
    > experienced problems with tables or select elements, and I'm not limited
    > to divs.
    > Or does that only work in recent browsers?


    I only resort to innerHTML with "dumb" (and unproblematic) blobs of
    markup. Whenever I need references to single elements within the
    generated markup, I prefer the approach you outlined.

    Gregor

    --
    http://vxweb.net
    Gregor Kofler, Nov 15, 2011
    #3
  4. David Mark

    J.R. Guest

    Re: David Mark's Javascript Daily - Volume #3 - Tip #6 - How to Getand Set HTML

    On 15/11/2011 19:26, Andreas Bergmaier wrote:
    > David Mark schrieb:
    >> Despite there being no standard behind the innerHTML property and the
    >> somewhat awkward feel of dealing with serialized DOM structures, I
    >> virtually always choose the string over the (XML) document object.
    >> It's much simpler, faster, requires less code, less function calls
    >> and, having debuted in IE 4, has enough successful history behind it
    >> to be trusted.

    >
    > Why is that faster? Only because the native html parser is faster than
    > the javascript interpreter?
    > I could understand the use of innerHTML when it's for large static
    > elements delivered as plain text per ajax - where the server can
    > serialize the structure into HTML. But when it comes to elements with
    > event listeners, I absolutely prefer DOM building methods.
    > Using a "library" function that takes the element name, attributes,
    > child nodes and event listeners as attributes, I can build dom
    > structures much easier than (hand)writing serialized html strings.
    > Also I can't believe that it would be faster to serialize the structure
    > to a string, process this with the innerHTML parser, and then dig in the
    > dom tree again to set the listeners (Thats what I really hate jQuery for).
    > Using plain dom methods (document.createElement,
    > document.createTextNode, el.appendChild, el.addEventListener) I've never
    > experienced problems with tables or select elements, and I'm not limited
    > to divs.
    > Or does that only work in recent browsers?


    Searching the Internet, we can find some performance tests proving that
    innerHTML really seems to be faster than the W3C DOM methods. Of course
    results may differ significantly from browser to browser and from
    version to version. E.g. <http://www.quirksmode.org/dom/innerhtml.html>

    However, take a look at this article from Mozilla:
    <https://developer.mozilla.org/En/DOM/Element.innerHTML>

    Also: innerHTML in HTML 5
    <http://www.w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml0>

    --
    Joao Rodrigues (J.R.)
    J.R., Nov 15, 2011
    #4
  5. Re: David Mark's Javascript Daily - Volume #3 - Tip #6 - How to Get and Set HTML

    Andreas Bergmaier wrote:

    > David Mark schrieb:
    >> Despite there being no standard behind the innerHTML property and the
    >> somewhat awkward feel of dealing with serialized DOM structures, I
    >> virtually always choose the string over the (XML) document object.
    >> It's much simpler, faster, requires less code, less function calls
    >> and, having debuted in IE 4, has enough successful history behind it
    >> to be trusted.

    >
    > Why is that faster?


    Possibility: An assignment to `innerHTML' would trigger once a markup parser
    written entirely in the host environment's native programming language, such
    as C++, thereby probably being executed as machine code. Whereas with
    several DOM method calls each would trigger the native implementation,
    switching to and back from native code in the process. The stack operations
    involved in the latter, and the fact that the ECMAScript implementation
    would be single-threaded, could contribute to its being slower than the
    former.

    > Only because the native html parser is faster than the javascript
    > interpreter?


    There is no "javascript", and you have a common misconception of how code
    written in an ECMAScript implementation is being executed by a Web browser.

    > I could understand the use of innerHTML when it's for large static
    > elements delivered as plain text per ajax - where the server can
    > serialize the structure into HTML.


    What you are writing may read sophisticated and even meaningful to the
    uninitiated, but it actually makes no sense at all. I strongly suggest you
    familiarize yourself with the workings of Web server and browser – and
    perhaps English – before making further (English-language) statements on
    this topic. For example, the Web *server* does not (need to) serialize
    anything if you use XHR to request HTML markup in the response message.


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
    Thomas 'PointedEars' Lahn, Nov 16, 2011
    #5
  6. Re: David Mark's Javascript Daily - Volume #3 - Tip #6 - How to Getand Set HTML

    Thomas 'PointedEars' Lahn schrieb:
    > Andreas Bergmaier wrote:
    >
    >> Only because the native html parser is faster than the javascript
    >> interpreter?

    >
    > There is no "javascript"


    I know I should spell it "JavaScript", but when I'm writing English my
    shift key often stucks - sorry. You don't have to remind me of that, but
    thanks.

    > and you have a common misconception of how code
    > written in an ECMAScript implementation is being executed by a Web browser.


    I hope not, but isn't "interpreting code" a short form for "interpreting
    syntax, building a (implementation specific) native structure, and
    execute it when requested"?

    >> I could understand the use of innerHTML when it's for large static
    >> elements delivered as plain text per ajax - where the server can
    >> serialize the structure into HTML.

    >
    > What you are writing may read sophisticated and even meaningful to the
    > uninitiated, but it actually makes no sense at all. I strongly suggest you
    > familiarize yourself with the workings of Web server and browser – and
    > perhaps English – before making further (English-language) statements on
    > this topic. For example, the Web *server* does not (need to) serialize
    > anything if you use XHR to request HTML markup in the response message.


    No, you understood me right. A server has same structured data, for
    example in a database, which should be displayed on the client's screen.
    So either the server generates HTML markup, or it sends the data as some
    other type - e.g. json -, which could decrease the file size
    significantly. In the first case the script engine would use innerHTML,
    in the second it could either build the table with dom methods or
    serialize the data to a markup string and use innerHTML again. So which
    of the three ways is faster?

    Bergi
    Andreas Bergmaier, Nov 16, 2011
    #6
  7. Re: David Mark's Javascript Daily - Volume #3 - Tip #6 - How to Get and Set HTML

    In comp.lang.javascript message <b8aaaf65-2095-4145-8992-651aae0e9a69@p9
    g2000vbb.googlegroups.com>, Tue, 15 Nov 2011 11:47:08, David Mark
    <> posted:

    >Keeping these facts in mind during design can save a world of time.
    >I've found that most designs can do just fine sticking to the
    >innerHTML properties of DIV elements (and perhaps the occasional TD or
    >TR, which won't change the structure of containing tables).
    >
    >The simplest rendition of the setter with simplified feature
    >detection*:-
    >
    >// NOTE: Don't use this rendition with anything but DIV's



    Were you intending to imply that it is not safe with SPAN elements?

    --
    (c) John Stockton, nr London UK. ?@merlyn.demon.co.uk BP7, Delphi 3 & 2006.
    <http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
    <http://www.bancoems.com/CompLangPascalDelphiMisc-MiniFAQ.htm> clpdmFAQ;
    NOT <http://support.codegear.com/newsgroups/>: news:borland.* Guidelines
    Dr J R Stockton, Nov 16, 2011
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David Mark
    Replies:
    16
    Views:
    905
    Scott Sauyet
    Nov 11, 2011
  2. David Mark
    Replies:
    58
    Views:
    1,410
    David Mark
    Dec 6, 2011
  3. David Mark
    Replies:
    1
    Views:
    757
    David Mark
    Dec 7, 2011
  4. David Mark
    Replies:
    8
    Views:
    629
    Thomas 'PointedEars' Lahn
    Dec 10, 2011
  5. David Mark
    Replies:
    1
    Views:
    705
    dhtml
    Dec 17, 2011
Loading...

Share This Page