ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
533 lines (440 loc) • 13.3 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
factory((global.SimpleDOM = {}));
}(this, function (exports) { 'use strict';
function Node(nodeType, nodeName, nodeValue) {
this.nodeType = nodeType;
this.nodeName = nodeName;
this.nodeValue = nodeValue;
this.childNodes = new ChildNodes(this);
this.parentNode = null;
this.previousSibling = null;
this.nextSibling = null;
this.firstChild = null;
this.lastChild = null;
}
Node.prototype._cloneNode = function() {
return new Node(this.nodeType, this.nodeName, this.nodeValue);
};
Node.prototype.cloneNode = function(deep) {
var node = this._cloneNode();
if (deep) {
var child = this.firstChild, nextChild = child;
while (nextChild) {
nextChild = child.nextSibling;
node.appendChild(child.cloneNode(true));
child = nextChild;
}
}
return node;
};
Node.prototype.appendChild = function(node) {
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
insertFragment(node, this, this.lastChild, null);
return node;
}
if (node.parentNode) { node.parentNode.removeChild(node); }
node.parentNode = this;
var refNode = this.lastChild;
if (refNode === null) {
this.firstChild = node;
this.lastChild = node;
} else {
node.previousSibling = refNode;
refNode.nextSibling = node;
this.lastChild = node;
}
return node;
};
function insertFragment(fragment, newParent, before, after) {
if (!fragment.firstChild) { return; }
var firstChild = fragment.firstChild;
var lastChild = firstChild;
var node = firstChild;
firstChild.previousSibling = before;
if (before) {
before.nextSibling = firstChild;
} else {
newParent.firstChild = firstChild;
}
while (node) {
node.parentNode = newParent;
lastChild = node;
node = node.nextSibling;
}
lastChild.nextSibling = after;
if (after) {
after.previousSibling = lastChild;
} else {
newParent.lastChild = lastChild;
}
}
Node.prototype.insertBefore = function(node, refNode) {
if (refNode == null) {
return this.appendChild(node);
}
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
insertFragment(node, this, refNode ? refNode.previousSibling : null, refNode);
return;
}
if (node.parentNode) { node.parentNode.removeChild(node); }
node.parentNode = this;
var previousSibling = refNode.previousSibling;
if (previousSibling) {
previousSibling.nextSibling = node;
node.previousSibling = previousSibling;
} else {
node.previousSibling = null;
}
refNode.previousSibling = node;
node.nextSibling = refNode;
if (this.firstChild === refNode) {
this.firstChild = node;
}
};
Node.prototype.removeChild = function(refNode) {
if (this.firstChild === refNode) {
this.firstChild = refNode.nextSibling;
}
if (this.lastChild === refNode) {
this.lastChild = refNode.previousSibling;
}
if (refNode.previousSibling) {
refNode.previousSibling.nextSibling = refNode.nextSibling;
}
if (refNode.nextSibling) {
refNode.nextSibling.previousSibling = refNode.previousSibling;
}
refNode.parentNode = null;
refNode.nextSibling = null;
refNode.previousSibling = null;
};
Node.ELEMENT_NODE = 1;
Node.ATTRIBUTE_NODE = 2;
Node.TEXT_NODE = 3;
Node.CDATA_SECTION_NODE = 4;
Node.ENTITY_REFERENCE_NODE = 5;
Node.ENTITY_NODE = 6;
Node.PROCESSING_INSTRUCTION_NODE = 7;
Node.COMMENT_NODE = 8;
Node.DOCUMENT_NODE = 9;
Node.DOCUMENT_TYPE_NODE = 10;
Node.DOCUMENT_FRAGMENT_NODE = 11;
Node.NOTATION_NODE = 12;
function ChildNodes(node) {
this.node = node;
}
ChildNodes.prototype.item = function(index) {
var child = this.node.firstChild;
for (var i = 0; child && index !== i; i++) {
child = child.nextSibling;
}
return child;
};
function Element(tagName) {
tagName = tagName.toUpperCase();
this.nodeConstructor(1, tagName, null);
this.attributes = [];
this.tagName = tagName;
}
Element.prototype = Object.create(Node.prototype);
Element.prototype.constructor = Element;
Element.prototype.nodeConstructor = Node;
Element.prototype._cloneNode = function() {
var node = new Element(this.tagName);
node.attributes = this.attributes.map(function(attr) {
return { name: attr.name, value: attr.value, specified: attr.specified };
});
return node;
};
Element.prototype.getAttribute = function(_name) {
var attributes = this.attributes;
var name = _name.toLowerCase();
var attr;
for (var i=0, l=attributes.length; i<l; i++) {
attr = attributes[i];
if (attr.name === name) {
return attr.value;
}
}
return '';
};
Element.prototype.setAttribute = function(_name, _value) {
var attributes = this.attributes;
var name = _name.toLowerCase();
var value;
if (typeof _value === 'string') {
value = _value;
} else {
value = '' + _value;
}
var attr;
for (var i=0, l=attributes.length; i<l; i++) {
attr = attributes[i];
if (attr.name === name) {
attr.value = value;
return;
}
}
attributes.push({
name: name,
value: value,
specified: true // serializer compat with old IE
});
};
Element.prototype.removeAttribute = function(name) {
var attributes = this.attributes;
for (var i=0, l=attributes.length; i<l; i++) {
var attr = attributes[i];
if (attr.name === name) {
attributes.splice(i, 1);
return;
}
}
};
function DocumentFragment() {
this.nodeConstructor(11, '#document-fragment', null);
}
DocumentFragment.prototype._cloneNode = function() {
return new DocumentFragment();
};
DocumentFragment.prototype = Object.create(Node.prototype);
DocumentFragment.prototype.constructor = DocumentFragment;
DocumentFragment.prototype.nodeConstructor = Node;
function Text(text) {
this.nodeConstructor(3, '#text', text);
}
Text.prototype._cloneNode = function() {
return new Text(this.nodeValue);
};
Text.prototype = Object.create(Node.prototype);
Text.prototype.constructor = Text;
Text.prototype.nodeConstructor = Node;
function Comment(text) {
this.nodeConstructor(8, '#comment', text);
}
Comment.prototype._cloneNode = function() {
return new Comment(this.nodeValue);
};
Comment.prototype = Object.create(Node.prototype);
Comment.prototype.constructor = Comment;
Comment.prototype.nodeConstructor = Node;
function RawHTMLSection(text) {
this.nodeConstructor(-1, "#raw-html-section", text);
}
RawHTMLSection.prototype = Object.create(Node.prototype);
RawHTMLSection.prototype.constructor = RawHTMLSection;
RawHTMLSection.prototype.nodeConstructor = Node;
function Document() {
this.nodeConstructor(9, '#document', null);
this.documentElement = new Element('html');
this.head = new Element('head');
this.body = new Element('body');
this.documentElement.appendChild(this.head);
this.documentElement.appendChild(this.body);
this.appendChild(this.documentElement);
}
Document.prototype = Object.create(Node.prototype);
Document.prototype.constructor = Document;
Document.prototype.nodeConstructor = Node;
Document.prototype.createElement = function(tagName) {
return new Element(tagName);
};
Document.prototype.createTextNode = function(text) {
return new Text(text);
};
Document.prototype.createComment = function(text) {
return new Comment(text);
};
Document.prototype.createRawHTMLSection = function(text) {
return new RawHTMLSection(text);
};
Document.prototype.createDocumentFragment = function() {
return new DocumentFragment();
};
function HTMLParser(tokenize, document, voidMap) {
this.tokenize = tokenize;
this.document = document;
this.voidMap = voidMap;
this.parentStack = [];
}
HTMLParser.prototype.isVoid = function(element) {
return this.voidMap[element.nodeName] === true;
};
HTMLParser.prototype.pushElement = function(token) {
var el = this.document.createElement(token.tagName);
for (var i=0;i<token.attributes.length;i++) {
var attr = token.attributes[i];
el.setAttribute(attr[0], attr[1]);
}
if (this.isVoid(el)) {
return this.appendChild(el);
}
this.parentStack.push(el);
};
HTMLParser.prototype.popElement = function(token) {
var el = this.parentStack.pop();
if (el.nodeName !== token.tagName.toUpperCase()) {
throw new Error('unbalanced tag');
}
this.appendChild(el);
};
HTMLParser.prototype.appendText = function(token) {
var text = this.document.createTextNode(token.chars);
this.appendChild(text);
};
HTMLParser.prototype.appendComment = function(token) {
var comment = this.document.createComment(token.chars);
this.appendChild(comment);
};
HTMLParser.prototype.appendChild = function(node) {
var parentNode = this.parentStack[this.parentStack.length-1];
parentNode.appendChild(node);
};
HTMLParser.prototype.parse = function(html/*, context*/) {
// TODO use context for namespaceURI issues
var fragment = this.document.createDocumentFragment();
this.parentStack.push(fragment);
var tokens = this.tokenize(html);
for (var i=0, l=tokens.length; i<l; i++) {
var token = tokens[i];
switch (token.type) {
case 'StartTag':
this.pushElement(token);
break;
case 'EndTag':
this.popElement(token);
break;
case 'Chars':
this.appendText(token);
break;
case 'Comment':
this.appendComment(token);
break;
}
}
return this.parentStack.pop();
};
function HTMLSerializer(voidMap) {
this.voidMap = voidMap;
}
HTMLSerializer.prototype.openTag = function(element) {
return '<' + element.nodeName.toLowerCase() + this.attributes(element.attributes) + '>';
};
HTMLSerializer.prototype.closeTag = function(element) {
return '</' + element.nodeName.toLowerCase() + '>';
};
HTMLSerializer.prototype.isVoid = function(element) {
return this.voidMap[element.nodeName] === true;
};
HTMLSerializer.prototype.attributes = function(namedNodeMap) {
var buffer = '';
for (var i=0, l=namedNodeMap.length; i<l; i++) {
buffer += this.attr(namedNodeMap[i]);
}
return buffer;
};
HTMLSerializer.prototype.escapeAttrValue = function(attrValue) {
return attrValue.replace(/[&"]/g, function(match) {
switch(match) {
case '&':
return '&';
case '\"':
return '"';
}
});
};
HTMLSerializer.prototype.attr = function(attr) {
if (!attr.specified) {
return '';
}
if (attr.value) {
return ' ' + attr.name + '="' + this.escapeAttrValue(attr.value) + '"';
}
return ' ' + attr.name;
};
HTMLSerializer.prototype.escapeText = function(textNodeValue) {
return textNodeValue.replace(/[&<>]/g, function(match) {
switch(match) {
case '&':
return '&';
case '<':
return '<';
case '>':
return '>';
}
});
};
HTMLSerializer.prototype.text = function(text) {
return this.escapeText(text.nodeValue);
};
HTMLSerializer.prototype.rawHTMLSection = function(text) {
return text.nodeValue;
};
HTMLSerializer.prototype.comment = function(comment) {
return '<!--'+comment.nodeValue+'-->';
};
HTMLSerializer.prototype.serializeChildren = function(node) {
var buffer = '';
var next = node.firstChild;
if (next) {
buffer += this.serialize(next);
while(next = next.nextSibling) {
buffer += this.serialize(next);
}
}
return buffer;
};
HTMLSerializer.prototype.serialize = function(node) {
var buffer = '';
// open
switch (node.nodeType) {
case 1:
buffer += this.openTag(node);
break;
case 3:
buffer += this.text(node);
break;
case -1:
buffer += this.rawHTMLSection(node);
break;
case 8:
buffer += this.comment(node);
break;
default:
break;
}
buffer += this.serializeChildren(node);
if (node.nodeType === 1 && !this.isVoid(node)) {
buffer += this.closeTag(node);
}
return buffer;
};
var _voidMap = {
AREA: true,
BASE: true,
BR: true,
COL: true,
COMMAND: true,
EMBED: true,
HR: true,
IMG: true,
INPUT: true,
KEYGEN: true,
LINK: true,
META: true,
PARAM: true,
SOURCE: true,
TRACK: true,
WBR: true
};
exports.Node = Node;
exports.Element = Element;
exports.DocumentFragment = DocumentFragment;
exports.Document = Document;
exports.HTMLParser = HTMLParser;
exports.HTMLSerializer = HTMLSerializer;
exports.voidMap = _voidMap;
}));
//# sourceMappingURL=simple-dom.js.map