Skip to content

Instantly share code, notes, and snippets.

@sukima
Last active July 5, 2016 20:47
Show Gist options
  • Save sukima/92afbfbe20855a43a2387f75422a5bf8 to your computer and use it in GitHub Desktop.
Save sukima/92afbfbe20855a43a2387f75422a5bf8 to your computer and use it in GitHub Desktop.
/*\
title: $:/plugins/sukima/dombuilder/dombuilder.js
type: application/javascript
module-type: library
Micro DSL for DOM creation and stringification.
\*/
/**
* @module Utils
* @author Devin Weaver
*/
/*jshint node: true, browser: true */
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof module === 'object' && module.exports) {
module.exports = factory();
} else {
root.DomBuilder = factory();
}
})(this, function() {
/**
* Helper utility to construct complex DOM nodes easily.
*
* @class DomBuilder
* @constructor
* @param {DomBuilder|DOMElement|String} [root=div] A DOM element or string.
* If `root` is a DomBuilder it will become `root` instead
* @param {DOMDocument} [document=window.document] the document object used
* to create elements
* @public
*/
function DomBuilder(root, document) {
if (root instanceof DomBuilder) {
return root;
}
if (!(this instanceof DomBuilder)) {
return new DomBuilder(root, document);
}
this.document = document || window.document;
this.tag = root || 'div';
this.elements = [];
this.attributes = {};
this.namespace = null;
this.parent = null;
}
DomBuilder.prototype._addElement = function(element) {
var el = new DomBuilder(element, this.document);
el.parent = this;
this.elements.push(el);
return el;
};
/**
* @method add
* @param {DomBuilder|DOMElement|String} element the element to add to this
* DomBuilders elements list
* @return {DomBuilder} the new child element (DomBuilder) unless `element`
* is a DomBuilder in which case `this` is returned
* @chainable
* @public
*/
DomBuilder.prototype.add = function add(element) {
var el = this._addElement(element);
return (element instanceof DomBuilder) ? this : el;
};
/**
* @method text
* @param {String} the text to append
* @chainable
* @public
*/
DomBuilder.prototype.text = function text(content) {
var node = this.document.createTextNode(content);
this._addElement(node);
return this;
};
/**
* @method attr
* @param {String} name the attribute name
* @param {String} value the attribute value
* @chainable
* @public
*/
DomBuilder.prototype.attr = function attr(name, value) {
this.attributes[name] = $tw.utils.htmlEncode(value);
return this;
};
/**
* @method end
* @return {DomBuilder} the parent DomBuilder in the hierarchy
* @chainable
* @public
*/
DomBuilder.prototype.end = function end() {
return this.parent || this;
};
/**
* @method toDOM
* @param {DOMDocument} [document=this.document] the document object to
* propagate down the recursion chain
* @return {DOMElement} the compiled DOMElement with its child hierarchy
* @public
*/
DomBuilder.prototype.toDOM = function toDOM(document) {
var node, name;
document = document || this.document;
if (typeof this.tag === 'string') {
node = (this.namespace) ?
document.createElementNS(this.namespace, this.tag) :
document.createElement(this.tag);
} else {
node = this.tag;
}
for (name in this.attributes) {
node.setAttribute(name, this.attributes[name]);
}
this.elements.forEach(function(element) {
node.appendChild(element.toDOM(document));
});
return node;
};
/**
* @method toString
* @return {String} the HTML for this DomBuilder's hierarchy
* @public
*/
DomBuilder.prototype.toString = function toString() {
return this.toDOM().outerHTML;
};
/**
* The tag (or DOMElement) for this node.
* @property tag
* @type {String|DOMElement}
* @default div
* @private
*/
/**
* List of child elements for this DomBuilders hierarchy level.
* @property elements
* @type {Array}
* @private
*/
/**
* List of attributes to apply to this DOMElement.
* @property attributes
* @type {Object}
* @private
*/
/**
* The namespace for this DOMElement.
* @property namespace
* @type {String}
* @default null
* @private
*/
/**
* The parent DomBuilder in the hierarchy.
* @property parent
* @type {DomBuilder}
* @default null
* @private
*/
return DomBuilder;
});
/*\
title: ExamplePlugin.js
type: application/javascript
module-type: macro
Example macro using the DomBuilder.
\*/
/*jshint node: true, browser: true */
/*global $tw: false */
(function() {
exports.name = 'example';
exports.run = function(filter) {
return $tw.utils.DomBuilder('pre', this.document)
.add('code')
.add('div')
.attr('class', 'tc-alert')
.add('span').text('this is some text in a span').end()
.add('div')
.attr('class', 'my-title')
.renderText(this.wiki.getTiddlerText('$:/SiteTitle'))
.end()
.add('div')
.attr('class', 'my-tiddler')
.renderTiddler('GettingStarted').end()
.end()
.end()
.toString();
};
})();
/*\
title: $:/plugins/sukima/dombuilder/tw-dombuilder.js
type: application/javascript
module-type: utils
Defines $tw.utils.DomBuilder and extends DomBuilder with Tiddly Wiki addons.
\*/
/**
* @module Utils
* @author Devin Weaver
*/
/*jshint node: true, browser: true */
/*global $tw: false */
(function() {
/**
* @class DomBuilder
*/
var DomBuilder = require('$:/plugins/sukima/dombuilder/dombuilder');
/**
* Render a tiddler's text and construct a node tre for it.
*
* Will auto wrap the output in a `div` but will continue the chain so the
* wrapped div can be modified with `add()`, `text()`, and `attr()`.
*
* @method renderTiddler
* @param {String} title the tiddler title to render
* @return {DomBuilder} a wrapped DomBuilder with the rendered nodes within
* @chainable
* @public
*/
DomBuilder.prototype.renderTiddler = function renderTiddler(title) {
var widgetNode = $tw.wiki.makeWidget($tw.wiki.parseTiddler(title));
var container = new DomBuilder('div', this.document).toDOM();
widgetNode.render(container, null);
return this.add(container);
};
/**
* Render TiddlyWiki text and add it as a text node.
*
* @method renderText
* @param {String} text the tiddlywiki text to render
* @return {DomBuilder} a wrapped DomBuilder with the rendered nodes within
* @chainable
* @public
*/
DomBuilder.prototype.renderText = function renderText(text) {
var rendered =
$tw.wiki.renderText('text/plain', 'text/vnd.tiddlywiki', text);
return this.text(rendered);
};
$tw.utils.DomBuilder = DomBuilder;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment