Skip to content
This repository has been archived by the owner on Jul 6, 2020. It is now read-only.

Commit

Permalink
Merges branch 'event-listeners'.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdotcode committed Mar 7, 2016
2 parents 5fb84fa + 5d12564 commit c2bd180
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 26 deletions.
32 changes: 17 additions & 15 deletions dist/lmth.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 51 additions & 10 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@

'use strict';

function Node(name, isVoid, id, class_, style, attributes, content, children) {
function Node(name, isVoid, id, class_, style, listeners, attributes, content, children) {
if (!(this instanceof Node)) {
throw new Error("Uh-oh. You're creating a new Node without using the `new` keyword. This isn't allowed because Bad Stuff happens when you do that. What you more than likely want is one of the element functions attached to the Node object like so: `lmth.div(...)`. If you actually did want to create a plain node, you should use `Node.new(name, isVoid, id, class, style, attributes, content, children)` and avoid the manual construction with `new` where possible. If you really, really, really want to create a node with `new`, you can do so like this: `new Node(name, isVoid, class, style, attributes, content, children)`.");
throw new Error("Uh-oh. You're creating a new Node without using the `new` keyword. This isn't allowed because Bad Stuff happens when you do that. What you more than likely want is one of the element functions attached to the Node object like so: `lmth.div(...)`. If you actually did want to create a plain node, you should use `Node.new(name, isVoid, id, class, style, listeners, attributes, content, children)` and avoid the manual constructor call with `new` where possible. If you really, really, really did want to create a node with `new`, you can do so like this: `new Node(name, isVoid, class, style, listeners, attributes, content, children)`.");
}

this.name = name;
this.isVoid = isVoid;
this.id = id;
this.class = class_;
this.style = style;
this.listeners = listeners;
this.attributes = attributes;
this.content = content;
this.children = children;
Expand All @@ -38,8 +39,8 @@ Node.prototype.toString = function toString() {
return JSON.stringify(this);
};

Node.new = function new_(name, isVoid, id, class_, style, attributes, content, children) {
return new Node(name, isVoid, id, class_, style, attributes, content, children);
Node.new = function new_(name, isVoid, id, class_, style, listeners, attributes, content, children) {
return new Node(name, isVoid, id, class_, style, listeners, attributes, content, children);
};

/* 'Primitive' defined here is a strict subset of all actual JavaScript
Expand Down Expand Up @@ -74,13 +75,27 @@ function isString(x) {
return toString.call(x) === '[object String]';
}

function addListener(event, listener, nodeListeners) {
var eventListeners = nodeListeners[event];

if (!eventListeners) {
// Coerce the listener into an array of listeners if it isn't
// already one.
nodeListeners[event] = [].concat(listener);
} else {
eventListeners.push(listener);
}
}

/* Takes either a list of classes and attributes as a string, or a hash of
* attributes and normalizes them into the format used when creating new Nodes.
* */
function parseAttributes(attributes) {
var nodeAttributes = {
id : null,
class: [],
id : null,
class: [],
style: null,
listeners: {},
};

if (isString(attributes)) {
Expand All @@ -98,12 +113,20 @@ function parseAttributes(attributes) {
});
} else if (isObject(attributes)) {
Object.keys(attributes).forEach(function addAttribute(attribute) {
nodeAttributes[attribute] = attributes[attribute];
var property = attributes[attribute];

if (attribute.startsWith('on') &&
(typeof(property) === 'function' || Array.isArray(property))) {
addListener(attribute.slice(2), property, nodeAttributes.listeners);
} else {
nodeAttributes[attribute] = property;
}
});

if (!Array.isArray(nodeAttributes.class)) {
nodeAttributes.class = nodeAttributes.class.split(' ');
}

}

return nodeAttributes;
Expand Down Expand Up @@ -143,11 +166,13 @@ Node.createElement = function createElement(name, options) {
var id = nodeAttributes.id;
var class_ = nodeAttributes.class;
var style = nodeAttributes.style;
var listeners = nodeAttributes.listeners;
delete nodeAttributes.id;
delete nodeAttributes.class;
delete nodeAttributes.style;
delete nodeAttributes.listeners;

return Node.new(name, isVoid, id, class_, style, nodeAttributes, content, children);
return Node.new(name, isVoid, id, class_, style, listeners, nodeAttributes, content, children);
}
};

Expand Down Expand Up @@ -188,9 +213,17 @@ Node.voidElements.forEach(function addElement(element) {
Node.addElement(element, {isVoid: true});
});

Node.prototype.on = function(event, listener) {
var node = this;

addListener(event, listener, node.listeners);

return node;
}

/* Provides an immutable view of a node; removing its children. */
Node.freeze = function freeze(node) {
return Node.new(node.name, node.isVoid, node.id, node.class, node.style, node.attributes, node.content, []);
return Node.new(node.name, node.isVoid, node.id, node.class, node.style, node.listeners, node.attributes, node.content, []);
};

/* Transforms a node tree into a nested list by taking each node and applying
Expand Down Expand Up @@ -360,6 +393,14 @@ Node.prototype.toDOM = function toDOM(document_) {
root.setAttribute('style', renderStyle(node.style));
}

if (node.listeners) {
Object.keys(node.listeners).forEach(function addEvents(event) {
node.listeners[event].forEach(function addListener(listener) {
root.addEventListener(event, listener);
});
});
}

// Explicit coercive comparison because the only non-valid values here
// are `null` and `undefined` (other other falsy values are perfectly
// valid here).
Expand Down Expand Up @@ -393,7 +434,7 @@ Node.appendListToDOM = function appendListToDOM(parent, nodeList, document_) {

return Node;

}));
// And without faith it is impossible to please God, because anyone who comes
// to Him must believe that He exists and that He rewards those who earnestly
// seek Him. - Hebrews 11:6
}));
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lmth",
"version": "4.0.0",
"version": "5.0.0-rc2",
"description": "A \"type-safe\" HTML DSL for JavaScript environments.",
"main": "lib/index.js",
"scripts": {
Expand Down

0 comments on commit c2bd180

Please sign in to comment.