Skip to content

Instantly share code, notes, and snippets.

@Zirak
Created December 17, 2011 13:21
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Zirak/1490195 to your computer and use it in GitHub Desktop.
Save Zirak/1490195 to your computer and use it in GitHub Desktop.
Basic DOM element manipulation
//creating an element is easy peasy
var divElem = document.createElement( 'div' );
//divElem is now a div element. it's not related to the any other element or
// node, it's free-range.
//to add it to the body element, for example:
document.body.appendChild( divElem );
//splendidsimo!
//setting the properties of the element is as easy as editing any other object
divElem.id = 'chuckNorris';
//or:
divElem[ 'id' ] = 'chuckNorris';
document.getElementById( 'chuckNorris' ) === divElem;
//the only exception is class names. instead of simply saying
// divElem.class = 'greasedLightning', we have to do
divElem.className = 'greasedLightning';
//not a big hindrance, though. it's because class is a reserved word in js, so
// you can't use it in dot notation
//not comes the annoying part: cross-browser compatibility. some of you may be
// wondering in ever-so-surprised faces, "but how do we set an element's text?
// huh? huh!? HUH!? YOU CROOK, YOU PROMISED US KNOWLEDGE YOU SON OF A BI-"
// worry not, you weird purple-faced man!
//the w3c, WWW Consortium, says that the textContent property of an element
// is, well, its text property.
//so, to get the text of the head element:
document.head.textContent;
//and set it:
divElem.textContent = 'Spidermonkey';
//Chrome, firefox, opera and safari all conform to this standard
//however, Internet Explorer says "I MAEK OWN STANDARDS", doesn't conform to
// the standard, and instead offers an innerText property
document.head.innerText;
divElem.innerText = 'Spidermonkey';
//the only browser not supporting this property (at the time of writing) is FF.
//"help us, oh please help us! we are not strong enough to make this work!"
// fear not, now-green-faced citizen! here's a way to make a cross-browser
// element-text-setting function:
var text = (function () {
//create a div element, and test whether it has a textContent property
//if it does, set textProp to 'textContent', otherwise set it to 'innerText'
var textProp = 'textContent' in document.createElement( 'div' ) ?
'textContent' : 'innerText';
return function ( elem, text ) {
//if a text parameter is passed, set the element's text
if ( text !== undefined ) {
elem[ textProp ] = text;
}
//return the element's text
return elem[ textProp ];
};
}());
text( divElem ); //"Spidermonkey"
text( divElem, 'One div to rule them all'); //"One div to rule them all"
//HOWEVER! at times you may want to just add a certain piece of text to an
// element. instead of doing
text( divElem, text(divElem) + ' smurfs' );
//there's a standard, cross-browser, sexy way
//text is also a type of element, called a Text Node. creating one is nearly
// like creating any other element:
var textNode = document.createTextNode( ' smurfs' );
divElem.appendChild( textNode );
//"but what if I want to set the text node's value to something else!?"
textNode.nodeValue = ' something else';
//"amazing!" indeed it is, you weird man
//as an excercise, let's say you want to turn this:
var pokemon = [
{
name : 'Psyduck',
level : 42,
nickname : 'hickie' //it's a long, sad story
},
{
name : 'Mankey',
level : 42,
nickname : 'The Raging Bull'
}
];
//into this:
/*
<table>
<tbody>
<tr>
<td>Psyduck</td>
<td>42</td>
<td>hickie</td>
</tr>
<tr>
<td>Mankey</td>
<td>42</td>
<td>The Raging Bull</td>
</tr>
</tbody>
</table>
*/
var table = document.createElement( 'table' ),
tbody = document.createElement( 'tbody' );
table.appendChild( tbody );
pokemon.forEach(function (poke) {
var tr = document.createElement( 'tr' );
for ( var detail in poke ) {
if ( poke.hasOwnProperty(detail) ) {
var td = document.createElement( 'td' );
td.appendChild(
document.createTextNode( poke[detail] )
);
tr.appendChild( td );
}
}
tbody.appendChild( tr );
});
@Raynos
Copy link

Raynos commented Dec 18, 2011

text( divElem, text(divElem) + ' smurfs' ); RAGEQUIT

This is a jQuery. anti pattern. for the love of god never write code like this.

divElem.firstChild.data += 'smurfs';

@Raynos
Copy link

Raynos commented Dec 18, 2011

textNode.nodeValue = ' something else'; DOING IT WRONG

.nodeValue is wrong, use .data. read the damn dom4 spec.CharacterData.data

@Raynos
Copy link

Raynos commented Dec 18, 2011

for ( var detail in poke ) { if ( poke.hasOwnProperty(detail) ) { DOING IT WRONG

for the love god use Object.keys

Object.keys(poke).foreach(createTD)

@Raynos
Copy link

Raynos commented Dec 18, 2011

td.appendChild(document.createTextNode( poke[detail] )); DOING IT WRONG

We both know you want td.textContent = poke[detail];

@Zirak
Copy link
Author

Zirak commented Dec 18, 2011

@Raynos:

  1. Yes, I know. I condoned that method.
  2. meh, both are legit. Good to know about .data
  3. I'm still not attached to Object.keys, need more time to get used to it.
  4. Well, you do, I don't.

@Raynos
Copy link

Raynos commented Dec 18, 2011

@titani

  1. I only skim read o/

  2. your right, they are the same however CharacterData.data is more specific then Node.nodeValue. Note that Node.nodeValue is a no-op on a non-CharacterData node. and note that elem.nodeValue === null and elem.data === undefined

  3. Object.keys is simply the more efficient way to enumerate over own enumerable property names of an object. Do a jsperf, it's always faster. If you don't like using functions then iterate over the keys array

    var keys = Object.keys(poke); for (var i = 0, len = keys.length; i < len; i++) { // do stuff }

4: elem.textContent = foo is the same as removeAllChildNodes(elem);elem.appendChild(document.createTextNode(foo);

@Zirak
Copy link
Author

Zirak commented Dec 19, 2011

@Raynos
3. I'll give Object.keys another shot
4. And if I do not want to call removeAllChildNodes?

@Raynos
Copy link

Raynos commented Dec 19, 2011

@titani

4: then obvouisly you don't want to use .textContent. However in the particular example it doesn't matter because removeAllChildNodes is a no-op (there are no childNodes) and .textContent is faster and simpler in that case.

@nickiannone
Copy link

@ALL lol, so much cursing in a code review...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment