rule
Version:
Coffeescript friendly css selector based templating
302 lines (282 loc) • 10.3 kB
JavaScript
// Generated by CoffeeScript 1.4.0
(function() {
var Rule;
Rule = (function() {
var combineRules, getPrototypeOf, indexOf, isChildOf, normalizeElement, querySelectorAll, splatify, _ref, _ref1;
function Rule(rule, template) {
if (rule) {
this.rule = rule;
}
if (template) {
this.template = template;
}
}
Rule.prototype.render = function(data, parent) {
var attribute, env, generator, index, key, lookup, position, result, rule, rules, selection, selector, value, _i, _ref, _ref1, _ref2,
_this = this;
env = this.constructor.env || Rule.env;
if (parent) {
parent = normalizeElement(parent);
} else {
parent = normalizeElement(this.template).cloneNode(true);
}
lookup = splatify(parent, {});
if (this.hasOwnProperty('rule')) {
rules = this.rule;
} else {
rules = combineRules(this);
}
for (key in rules) {
rule = rules[key];
_ref = this.constructor.split(key), selector = _ref[0], attribute = _ref[1], position = _ref[2];
if (selector && ((_ref1 = selector[0]) !== '#' && _ref1 !== '.')) {
selector = selector.toUpperCase();
}
if (selector) {
selection = lookup[selector] || [];
for (index = _i = _ref2 = selection.length - 1; _i >= 0; index = _i += -1) {
value = selection[index];
if (!isChildOf(parent, value)) {
selection.splice(index, 1);
}
}
} else {
selection = [parent];
}
generator = function(selector) {
try {
return _this.constructor.parse(rule, data, selector, _this);
} catch (error) {
console.error('RuleError: ', error.stack);
}
};
result = this.constructor.add(generator, selection, attribute, position);
}
return parent;
};
Rule.parse = function(rule, data, selector, context) {
var env, item, newRule, result, _i, _len, _ref;
env = this.constructor.env || Rule.env;
if (rule instanceof Function) {
return this.parse(rule.call(data, selector, context), data, selector, context);
} else if (rule instanceof Array) {
result = [];
for (_i = 0, _len = rule.length; _i < _len; _i++) {
item = rule[_i];
result = result.concat(this.parse(item, data, selector, context));
}
return result;
} else if (rule instanceof Rule) {
if (rule.hasOwnProperty('template')) {
return rule.render(data);
} else {
rule.render(data, selector.selection);
return void 0;
}
} else if (rule instanceof env.Node || !(rule != null)) {
return rule;
} else if ((_ref = env.$) != null ? _ref.fn.isPrototypeOf(rule) : void 0) {
return rule.get();
} else if (rule.toString !== Object.prototype.toString) {
return rule.toString();
} else if (Object.prototype.isPrototypeOf(rule)) {
newRule = new this(rule);
newRule.parent = context;
return this.parse.call(this, newRule, data, selector, context);
}
};
Rule.add = function(generator, selections, attribute, position) {
var content, element, env, parent, previous, result, selection, target, _i, _j, _len, _len1, _ref;
env = this.constructor.env || Rule.env;
result = [];
if (!(generator instanceof Function)) {
generator = (function(value) {
return value;
}).bind(this, generator);
}
for (_i = 0, _len = selections.length; _i < _len; _i++) {
selection = selections[_i];
content = generator({
selection: selection,
attribute: attribute,
position: position
});
if (!((content != null) && selection instanceof env.Element)) {
continue;
}
if ((attribute != null) && (content != null)) {
if (content instanceof Array) {
content = content.join('');
}
previous = (_ref = selection.getAttribute(attribute)) != null ? _ref : '';
selection.setAttribute(attribute, position === '<' ? content + previous : position === '>' ? previous + content : position === '-' ? content + ' ' + previous : position === '+' ? previous + ' ' + content : content);
} else {
parent = target = selection;
if (position === '-' || position === '+' || position === '=') {
parent = selection.parentElement;
}
if (position === '+') {
target = selection.nextSibling;
}
if (position === '<') {
target = selection.firstChild;
}
if (position === '>' || !(position != null)) {
target = null;
}
if (!(position != null)) {
while (selection.firstChild != null) {
selection.removeChild(selection.firstChild);
}
}
if (!(content instanceof Array)) {
content = [content];
}
for (_j = 0, _len1 = content.length; _j < _len1; _j++) {
element = content[_j];
element = !(element instanceof env.Node) ? env.document.createTextNode(element) : element;
if (position === '+') {
result.push(selection);
}
result.push(element);
if (position === '-') {
result.push(selection);
}
if (parent instanceof env.HTMLElement) {
parent.insertBefore(element, target);
}
}
if (position === '=') {
if (parent != null) {
parent.removeChild(target);
}
}
}
}
if ((position === '-' || position === '+' || position === '=') && !(attribute != null)) {
return result;
} else {
return selections;
}
};
Rule.split = function(key) {
var attribute, position, selector, _ref;
position = key.slice(-1);
if (position === '-' || position === '+' || position === '<' || position === '>' || position === '=') {
key = key.slice(0, -1);
} else {
position = void 0;
}
_ref = key.split('@', 2), selector = _ref[0], attribute = _ref[1];
if (selector === '') {
selector = void 0;
}
return [selector, attribute, position];
};
Rule.env = typeof window !== "undefined" && window !== null ? window : void 0;
indexOf = (_ref = Array.prototype.indexOf) != null ? _ref : function(item) {
var index, value, _i, _len;
for (index = _i = 0, _len = this.length; _i < _len; index = ++_i) {
value = this[index];
if (index in this && value === item) {
return index;
}
return -1;
}
};
querySelectorAll = (function(query) {
var env, _ref1;
env = this.constructor.env || Rule.env;
querySelectorAll = (_ref1 = env.document.createElement('div').querySelectorAll) != null ? _ref1 : function(query) {
return ((env.$(this)).find(query)).get();
};
return querySelectorAll(query);
}).bind(Rule);
getPrototypeOf = (_ref1 = Object.getPrototypeOf) != null ? _ref1 : function(object) {
var constructor, prototype;
prototype = object.constructor.prototype;
if ((object.hasOwnProperty('constructor' && object !== prototype)) || object === prototype) {
constructor = object.constructor;
delete object.constructor;
prototype = object.constructor.prototype;
object.constructor = constructor;
}
return prototype;
};
normalizeElement = (function(element) {
var env, _ref2;
env = this.constructor.env || Rule.env;
if ((_ref2 = env.$) != null ? _ref2.fn.isPrototypeOf(element) : void 0) {
return element.get(0);
} else if (element instanceof Function) {
return normalizeElement(element());
} else if (element[0]) {
return element[0];
} else {
return element;
}
}).bind(Rule);
combineRules = function(object) {
var key, rule, rules, _ref2;
if ((object.hasOwnProperty('constructor')) && (object.constructor === Rule)) {
return {};
}
rules = combineRules(getPrototypeOf(object));
if (object.hasOwnProperty('rule')) {
_ref2 = object.rule;
for (key in _ref2) {
rule = _ref2[key];
delete rules[key];
rules[key] = rule;
}
}
return rules;
};
splatify = function(element, hash) {
var child, elementArray, elementKey, _i, _len, _ref2, _ref3, _ref4, _ref5;
if (hash == null) {
hash = {};
}
child = element.firstElementChild;
while (child) {
if (typeof (child.getAttribute('class')) === 'string') {
_ref2 = child.getAttribute('class').split(' ');
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
elementKey = _ref2[_i];
elementKey = '.' + elementKey;
elementArray = (_ref3 = hash[elementKey]) != null ? _ref3 : hash[elementKey] = [];
elementArray.push(child);
}
}
if (child.id !== '') {
elementKey = '#' + child.id;
elementArray = (_ref4 = hash[elementKey]) != null ? _ref4 : hash[elementKey] = [];
elementArray.push(child);
}
elementKey = child.tagName.toUpperCase();
elementArray = (_ref5 = hash[elementKey]) != null ? _ref5 : hash[elementKey] = [];
elementArray.push(child);
splatify(child, hash);
child = child.nextElementSibling;
}
return hash;
};
isChildOf = function(parent, child) {
var nextParent;
nextParent = child;
while (nextParent = nextParent.parentElement) {
if (nextParent === parent) {
return true;
}
}
return false;
};
return Rule;
})();
if ((typeof module !== "undefined" && module !== null) && this.module !== module) {
module.exports = Rule;
} else {
window.Rule = Rule;
}
return Rule;
}).call(this);