Skip to content

Instantly share code, notes, and snippets.

@jacobrask
Forked from neilj/gist:1532562
Created August 30, 2012 08:24
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jacobrask/3524145 to your computer and use it in GitHub Desktop.
Save jacobrask/3524145 to your computer and use it in GitHub Desktop.
DOM sugar
// DOM sugar
// ==================================================================
// Modified version of Neil Jenkins' "Sugared DOM" <https://gist.github.com/3524145>
//
// Usage
// ------------------------------------------------------------------
// var make = domsugar(document);
//
// make( 'p.foo#bar', { hidden: true }, [ make( 'span' ) ] );
// => <p class="foo" id="bar" hidden><span></span></p>
//
// make( '.bar', [ '<b></b>' ] );
// make( '.bar', { text: '<b></b>' } );
// => <div class="bar">&lt;b&gt;&lt/b&gt;</div>
//
// make( 'div', [ make( 'b', [ 'Foo', make( 'i' ) ] ) ] );
// make( 'div', { html: '<b>Foo<i></i></b>' } );
// => <div><b>Foo<i></i></b></div>
//
// var myDiv = document.createElement( 'div' );
// make( myDiv, { id: 'foo' } );
// => <div id="foo"></div>
(function () {
'use strict';
var domsugar = function ( doc ) {
// instanceOf is faster, but not when used with a custom document.
var isArray = Array.isArray || function( obj ) {
return Object.prototype.toString.call( obj ) === '[object Array]';
};
// Some properties need to be direct, other are common ones and setting
// them directly is faster than setAttribute.
var directProperties = { 'class': 'className', className: 'className',
defaultValue: 'defaultValue', 'for': 'htmlFor', html: 'innerHTML',
id: 'id', name: 'name', src: 'src', text: 'textContent',
title: 'title', value: 'value' };
// Object lookup is faster than indexOf.
var booleanProperties = { checked: 1, defaultChecked: 1, disabled: 1,
hidden: 1, multiple: 1, selected: 1 };
var setProperty = function ( el, key, value ) {
var prop = directProperties[ key ];
if ( prop ) {
el[ prop ] = ( value == null ? '' : '' + value );
} else if ( booleanProperties[ key ] ) {
el[ key ] = !!value;
} else if ( value == null ) {
el.removeAttribute( key );
} else {
el.setAttribute( key, '' + value );
}
};
var appendChildren = function ( el, children ) {
var i, l, node;
for ( i = 0, l = children.length; i < l; i += 1 ) {
node = children[i];
if ( node ) {
if ( isArray( node ) ) {
appendChildren( el, node );
} else {
if ( typeof node === 'string' ) {
node = doc.createTextNode( node );
}
el.appendChild( node );
}
}
}
};
var splitter = /(#|\.)/;
return function ( tag, props, children ) {
if ( isArray( props ) ) {
children = props;
props = null;
}
if ( !tag ) { tag = 'div'; }
var parts, name, el,
i, j, l, node, prop;
if ( typeof tag === 'string' && splitter.test( tag ) ) {
parts = tag.split( splitter );
tag = parts[0];
if ( !props ) { props = {}; }
for ( i = 1, j = 2, l = parts.length; j < l; i += 2, j += 2 ) {
name = parts[j];
if ( parts[i] === '#' ) {
props.id = name;
} else {
props.className = props.className ?
props.className + ' ' + name : name;
}
}
}
el = typeof tag === 'string' ? doc.createElement( tag ) : tag;
if ( props ) {
for ( prop in props ) {
setProperty( el, prop, props[ prop ] );
}
}
if ( children ) {
appendChildren( el, children );
}
return el;
};
};
// Export as CommonJS module or as browser global
if ( typeof module !== 'undefined' && module.exports ) {
module.exports = domsugar;
} else {
window.domsugar = domsugar;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment