Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lauriro committed Mar 21, 2014
0 parents commit 9dcb16f
Show file tree
Hide file tree
Showing 5 changed files with 577 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .travis.yml
@@ -0,0 +1,9 @@
language: node_js
node_js:
- "0.8"
- "0.10"
before_script:
- npm install istanbul coveralls
- npm install --dev
script: npm run travis-test

57 changes: 57 additions & 0 deletions README.md
@@ -0,0 +1,57 @@
[1]: https://secure.travis-ci.org/litejs/dom-lite.png
[2]: https://travis-ci.org/litejs/dom-lite
[3]: https://coveralls.io/repos/litejs/dom-lite/badge.png
[4]: https://coveralls.io/r/litejs/dom-lite
[npm package]: https://npmjs.org/package/dom-lite
[GitHub repo]: https://github.com/litejs/dom-lite


@version 0.0.1
@date 2014-03-21
@stability 2 - Unstable


DOM lite – [![Build][1]][2] [![Coverage][3]][4]
========

A minimal DOM implementation


Examples
--------

```javascript
var document = require("dom-lite").document;

var el = document.createElement("h1");
el.id = 123;
el.className = "large";

var fragment = document.createDocumentFragment();
var text1 = document.createTextNode("hello");
var text2 = document.createTextNode(" world");

fragment.appendChild(text1);
fragment.appendChild(text2);
el.appendChild(fragment);

el.toString();
// <h1 id="123" class="large">hello world</h1>
```



External links
--------------

- [GitHub repo][]
- [npm package][]



### Licence

Copyright (c) 2012 Lauri Rooden &lt;lauri@rooden.ee&gt;
[The MIT License](http://lauri.rooden.ee/mit-license.txt)


289 changes: 289 additions & 0 deletions index.js
@@ -0,0 +1,289 @@
/*
* Object
* |- Node
* |- DocumentFragment
* |- Element // skip
* | |- HTMLElement
* | |- HTML*Element // skip
* |- CharacterData // skip
* | |- Text
*/



function extend(obj, _super, extras) {
obj.prototype = Object.create(_super.prototype)
for (var key in extras) {
obj.prototype[key] = extras[key]
}
obj.prototype.constructor = obj
}



/*
* http://dom.spec.whatwg.org/#node
*/
function Node(){}

Node.prototype = {
__fake: true,
textContent: "",
nodeName: null,
parentNode: null,
childNodes: null,
firstChild: null,
lastChild: null,
previousSibling: null,
nextSibling: null,
get outerHTML() {
return this.toString()
},
appendChild: function(el) {
return this.insertBefore(el)
},
insertBefore: function(el, ref) {
var t = this
, childs = t.childNodes

if (el.parentNode) el.parentNode.removeChild(el)
el.parentNode = t

// If ref is null, insert el at the end of the list of children.
childs.splice(ref ? childs.indexOf(ref) : childs.length, 0, el)
t._updateLinks(el, ref, ref && ref.previousSibling)
return el
},
removeChild: function(el) {
var t = this
, index = t.childNodes.indexOf(el)
if (index == -1) throw new Error("NOT_FOUND_ERR")

t.childNodes.splice(index, 1)
el.parentNode = null
t._updateLinks(el.previousSibling, el.nextSibling, el)
return el
},
replaceChild: function(el, ref) {
this.insertBefore(el, ref)
return this.removeChild(ref)
},
cloneNode: function(deep) {
var key
, t = this
, node = new t.constructor(t.tagName || t.textContent)

if (t.hasAttribute) {
for (key in t) if (t.hasAttribute(key)) node[key] = t[key]
for (key in t.style) node.style[key] = t.style[key]
}

if (deep && t.childNodes) {
node.childNodes = t.childNodes.map(function(child){
return child.cloneNode(deep)
})
}
return node
},
hasChildNodes: function() {
return this.childNodes && this.childNodes.length > 0
},
_updateLinks: function() {
var el, index
, t = this
, childs = t.childNodes
, len = arguments.length

t.firstChild = childs[0] || null
t.lastChild = childs[ childs.length - 1 ] || null

if (len) while (len--) {
el = arguments[len]
if (!el) continue
childs = el.parentNode && el.parentNode.childNodes
index = childs && childs.indexOf(el) || 0
el.nextSibling = childs && childs[ index + 1 ] || null
if (el.nextSibling) el.nextSibling.previousSibling = el
el.previousSibling = index > 0 && childs[ index - 1 ] || null
if (el.previousSibling) el.previousSibling.nextSibling = el
}
},
toString: function() {
var result = this.textContent || ""

if (this.childNodes) return this.childNodes.reduce(function (memo, node) {
return memo + node
}, result)

return result
}
}


function DocumentFragment() {
this.childNodes = []
}

extend(DocumentFragment, Node, {
nodeType: 11,
nodeName: "#document-fragment"
})


function HTMLElement(tag) {
var t = this
t.nodeName = t.tagName = tag.toLowerCase()
t.childNodes = []
t.style = {}
}

var el_re = /([.#:[])([-\w]+)(?:=([-\w]+)])?]?/g

extend(HTMLElement, Node, {
nodeType: 1,
tagName: null,
style: null,
className: "",
/*
* Void elements:
* http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
*/
_voidElements: { AREA:1, BASE:1, BR:1, COL:1, EMBED:1, HR:1, IMG:1, INPUT:1,
KEYGEN:1, LINK:1, MENUITEM:1, META:1, PARAM:1, SOURCE:1, TRACK:1, WBR:1 },
hasAttribute: function(name) {
return this.hasOwnProperty(name) && !(name in HTMLElement.prototype)
},
getAttribute: function(name) {
return this.hasAttribute(name) ? this[name] : null
},
setAttribute: function(name, value) {
this[name] = value
},
removeAttribute: function(name) {
delete this.name
},
getElementById: function(id) {
if (this.id == id) return this
for (var el, found, i = 0; !found && (el = this.childNodes[i++]);) {
if (el.nodeType == 1) found = el.getElementById(id)
}
return found || null
},
getElementsByTagName: function(tag) {
var el, els = [], next = this.firstChild
tag = tag === "*" ? 1 : tag.toLowerCase()
for (var i = 0, key = tag === 1 ? "nodeType" : "nodeName"; (el = next); ) {
if (el[key] === tag) els[i++] = el
next = el.firstChild || el.nextSibling
while (!next && (el = el.parentNode)) next = el.nextSibling
}
return els
},
querySelector: function(sel) {
return this._find(sel, 1)
},
querySelectorAll: function(sel) {
return this._find(sel)
},
_find: function(sel, first) {
var el
, i = 0
, out = []
, rules = ["_"]
, tag = sel.replace(el_re, function(_, o, s, v) {
rules.push(
o == "." ? "(' '+_.className+' ').indexOf(' "+s+" ')>-1" :
o == "#" ? "_.id=='"+s+"'" :
"_.getAttribute('"+s+"')"+(v?"=='"+v+"'":"")
)
return ""
}) || "*"
, els = this.getElementsByTagName(tag)
, fn = Function("_", "return " + rules.join("&&"))

for (; el = els[i++]; ) if (fn(el)) {
if (first) return el
out.push(el)
}
return first ? null : out
},
_getAttributesString: function() {
var key
, t = this
, attrs = []

for (key in t) if (t.hasAttribute(key)) {
attrs.push(key + '="' + t[key] + '"')
}

if (t.className) {
attrs.push('class="' + t.className + '"')
}

var style = Object.keys(t.style).reduce(function (str, key) {
return str + key + ":" + t.style[key] + ";"
}, "")
if (style) attrs.push('style="' + style + '"')

return attrs.length ? " " + attrs.join(" ") : ""
},
toString: function() {
var t = this, result = "<" + t.tagName + t._getAttributesString()

if (t._voidElements[t.tagName]) {
return result + "/>"
}

return result + ">" +
Node.prototype.toString.call(t) +
"</" + t.tagName + ">"
}
})


function Text(value) {
this.textContent = value
}

extend(Text, Node, {
nodeType: 3,
nodeName: "#text"
})

function Document(){
this.body = this.createElement("body")
}

extend(Document, Node, {
nodeType: 9,
nodeName: "#document",
createElement: function(tag) {
return new HTMLElement(tag)
},
createTextNode: function(value) {
return new Text(value)
},
createDocumentFragment: function() {
return new DocumentFragment()
},
getElementById: function(id) {
return this.body.getElementById(id)
},
getElementsByTagName: function(tag) {
return this.body.getElementsByTagName(tag)
},
querySelector: function(sel) {
return this.body.querySelector(sel)
},
querySelectorAll: function(sel) {
return this.body.querySelectorAll(sel)
}
})

module.exports = {
document: new Document,
Document: Document,
HTMLElement: HTMLElement
}


25 changes: 25 additions & 0 deletions package.json
@@ -0,0 +1,25 @@
{
"name": "dom-lite",
"version": "0.0.1",
"stability": 2,
"license": "MIT",
"author": "Lauri Rooden <lauri@rooden.ee>",
"description": "A minimal DOM implementation",
"keywords": [
"dom"
],
"main": "index.js",
"readmeFilename": "README.md",
"scripts": {
"build": "node node_modules/buildman/index.js --all",
"travis-test": "istanbul cover ./tests/index.js && (coveralls < coverage/lcov.info || exit 0)",
"test": "node tests/index.js"
},
"repository": "git://github.com/litejs/dom-lite.git",
"bugs": {
"url": "https://github.com/litejs/dom-lite/issues"
},
"devDependencies": {
"tape": "~1.0.2"
}
}

0 comments on commit 9dcb16f

Please sign in to comment.