<commit_before>import * as inode from "./inode";

import { VNode } from "./vnode";

import { getDoc, vdoc, firstChild } from "./access";

import { create } from "./seq";

import { Step } from "./access";

export function str2array(str, ar, idx){
	for (var i=0, strLen=str.length; i<strLen; i++) {
		//ar.push(str.codePointAt(i));
		ar[idx++] = str.codePointAt(i);
	}
	return idx;
}

export function array2str(ar,i){
	var str = "",l = ar.length;
	for (; i<l; i++) {
		str += String.fromCodePoint(ar[i]);
	}
	return str;
}

export function convert(v){
	var i = parseFloat(v);
	if(!isNaN(i)) return i;
	if(v === "true" || v === "false") return v !== "false";
	return v;
}

function docAttrType(k) {
	switch (k) {
	case "DOCTYPE": return 11;
	default: return 7;
	}
}

function Nil() {
}

Nil.prototype.next = function(){
	return { done: true };
};

/**
 * Create a flat buffer from the document tree
 * @param  {VNode} doc The document
 * @return {ArrayBuffer}  A flat buffer
 */
export function toL3($doc /*, to2D = false, schema = null*/){
	var cx = this && this.vnode ? this : inode;
	return getDoc.bind(cx)($doc).concatMap(doc => {
		//var schemaIter = schema ? docIter(schema) : new Nil();
		//var schemaEntry = schemaIter.next();
		return vdoc.bind(cx)(firstChild.bind(cx)(doc)).concatMap(function (node) {
			let type = node.type;
			if (type == 17) return [17];
			if(type == 1) {
				var d = [];
				for(let attr of node.attrEntries()) Array.prototype.push.call(d,2,attr[0],3,attr[1]);
				return Array.prototype.push.call(d,1,node.name);
			}
			if(type == 3) return [3,node.value];
			// if there's a schema entry and all schema props are equal then the node has a schema entry
			// else if there's a schema entry, the value is not there (which was assumed valid)
			// else write the node name + type
			// if indexInParent is not equal, we skipped a schema entry
			// TODO allow partial schema somewhere in the document tree
			//let nodeHasSchema = !schemaEntry.done && schemaEntry.depth == depth && schemaEntry.name == name;
			// if this node has a schema, continue with next, else skip and try with next entry
			//if (nodeHasSchema) schemaEntry = schemaIter.next();
			/*var nameIndex = 0;
			if (typeof name === "string" && !nodeHasSchema) {
				if (!names[name]) {
					names[name] = ++j;
					out[i++] = 15;
					i = str2array(name, out, i);
				}
				nameIndex = names[name];
			}
			// TODO use text for values unless there's a schema
			//  always store type
			out[i++] = type;
			out[i++] = depth;
			if (!nodeHasSchema && nameIndex) out[i++] = nameIndex;
			if (type == 1) {
				// TODO how to serialize attrs with schema?
				for (let attr of node.attrEntries()) {
					let name = attr[0],
						attrname = "@" + name;
					if (!names[attrname]) {
						names[attrname] = ++j;
						out[i++] = 15;
						i = str2array(name, out, i);
					}
					out[i++] = 2;
					out[i++] = names[attrname];
					i = str2array(attr[1], out, i);
				}
			} else if (type == 3) {
				i = str2array(node.value, out, i);
			} else if (type == 12) {
				i = str2array(node.value + "", out, i);
			}*/
		});
	});
}
/*
export function fromL3(l3, schema = null) {
	var names = {},
		n = 15,
		parents = [],
		parentTypes = [],
		depth = 15;
	var cx = this && this.vnode ? this : inode;
	// TODO DOCTYPE / processing instructions
	var doc = cx.emptyINode(9, "#document", cx.emptyAttrMap());
	parents[depth] = doc;
	parentTypes[depth] = 9;
	var schemaIter = schema ? docIter(schema) : new Nil();
	var schemaEntry = schemaIter.next();
	const process = function (entry) {
		let type = entry[0];
		let hasSchema = false,
			skipSchema = false,
			schemaName;
		// TODO have attributes accept any type
		if (!type) {
			// assume schema
			hasSchema = true;
			type = schemaEntry.type;
			schemaName = schemaEntry.name;
		}
		if (type == 2) {
			let parent = parents[depth];
			let name = names[entry[1]];
			parent = cx.setAttribute(parent, name, array2str(entry, 2));
		} else if (type == 7 || type == 11) {
			doc = cx.setAttribute(doc, entry[1] == 11 ? 10 : 7, array2str(entry, 2));
		} else if (type == 15) {
			n++;
			names[n] = array2str(entry, 1);
		} else {
			depth = entry[1];
			let parent = parents[depth - 1];
			let parentType = parentTypes[depth - 1];
			let node, name, valIndex;
			if (type == 1 || type == 5 || type == 6) {
				name = names[entry[2]];
				if (name) {
					if (hasSchema && schemaName != name) skipSchema = true;
				} else {
					name = schemaName;
				}
				if (parents[depth]) {
					parents[depth] = cx.finalize(parents[depth]);
				}
				node = cx.emptyINode(type, name, cx.emptyAttrMap());
				parents[depth] = node;
				parentTypes[depth] = type;
			} else if (type == 3 || type == 12) {
				if (parentType == 1 || parentType == 9) {
					name = cx.count(parent);
					valIndex = 2;
				} else {
					name = names[entry[2]];
					if (name) {
						if (hasSchema && schemaName != name) skipSchema = true;
					} else {
						name = schemaName;
					}
					valIndex = 3;
				}
				let val = type == 3 ? array2str(entry, valIndex) : convert(array2str(entry, valIndex));
				node = cx.ivalue(type, name, val);
			}
			if (parent) parent = cx.push(parent, [name, node]);
		}
	};
	var entry = [];
	for (var i = 0, l = l3.length; i < l; i++) {
		var x = l3[i];
		if (x < 16 && x != 9 && x != 10 && x != 13) {
			if(i>0) process(entry);
			entry = [];
		}
		entry.push(x);
	}
	process(entry);
	return cx.finalize(parents[15]);
}
*/
const isLeaf = type => type == 2 || type == 3 || type == 4 || type == 7 || type == 8 || type == 10 || type == 12 || type == 16;
const isBranch = type => type == 1 || type == 5 || type == 6 || type == 9 || type == 11 || type == 14 || type == 15;

function VNodeBuffer(nodes = []) {
	this.nodes = nodes;
}

VNodeBuffer.prototype.add = function (v) {
	this.nodes.unshift(v);
};

VNodeBuffer.prototype.count = function () {
	return this.nodes.length;
};

VNodeBuffer.prototype.flush = function (sink, count = 1) {
	var s = this.count();
	while(s >= count){
		//console.log("FLUSH",s,count);
		sink.next(this.nodes.pop());
		--s;
	}
};

export function fromL3Stream(o,bufSize=1) {
	const cx = this && "vnode" in this ? this : inode;
	let ndepth = 0,
		stack = [],
		open = [],
		parents = [],
		openTuples = {},
		buffered = null,
		buf = new VNodeBuffer();
	const checkStack = function() {
		var l = stack.length;
		if (!l) return;
		const type = stack[0];
		const ol = open.length - 1;
		const last = open[ol],
			parent = parents[ol];
		const isClose = type == 17;
		// buffered is used to add attributes to elements before they're emitted
		// here buffered is released before anything else is processed (except attrs)
		if (last == 1 && buffered !== null && type != 2) {
			// console.log("buf",buffered.name);
			buf.add(buffered);
			buffered = null;
		}
		if (isClose) {
			open.pop();
			parents.pop();
			//console.log("closing",ndepth,parent.inode);
			--ndepth;
			stack = [];
			return buf.add(new Step(parent));
		} else {
			var _inode = void 0,
				name = void 0,
				key = void 0,
				_isBranch = isBranch(type);
			if (_isBranch) {
				ndepth++;
				switch (type) {
				case 1:
				{
					name = stack[1];
					_inode = { $type: type, $name: name, $children: [] };
					_inode.$attrs = {};
					if (last == 6) {
						// emit inode /w key
						key = openTuples[ndepth];
						//console.log("picked up tuple",ndepth,key);
						openTuples[ndepth] = undefined;
					}
					if (parent) parent.push([key, _inode]);
					open.push(type);
					// TODO use cx.vnode()
					let depth = parent ? parent.depth + 1 : 1;
					let node = new VNode(cx, _inode, _inode.$type, name, key, isLeaf(type) ? _inode.valueOf() : null, parent, depth);
					// buffer attributes
					buffered = node;
					//console.log("opening element",ndepth,name, buffered);
					parents.push(node);
					stack = [];
					return;
				}
				case 9:
					name = "#document";
					_inode = { $name: name, $children: [] };
					break;
				case 11:
					name = "#document-fragment";
					_inode = { $name: name, $children: [] };
					break;
				case 14:
					name = stack[1];
					_inode = { $name: name, $args: [] };
					break;
				case 15:
					_inode = { $name: name, $args: [] };
					break;
				case 5:
					_inode = []; //{$type:type,$children:[]};
					break;
				case 6:
					// never emit until all tuples are closed
					_inode = {};
					break;
				}
				if (last == 6) {
					// must be an open tuple
					key = openTuples[ndepth - 1];
					openTuples[ndepth - 1] = undefined;
					//console.log("picked up tuple",ndepth,key);
				}
				if (parent) {
					parent.push([key, _inode]);
				}
				open.push(type);
			} else {
				if (type == 2) {
					// new model:
					// - create tuple inode
					// - don't emit tuple, but tuple value /w key
					openTuples[ndepth] = stack[1];
					//console.log("opening tuple",ndepth,stack[1]);
					stack = [];
					return;
				} else {
					var value = stack[1];
					if(type == 12) value = JSON.parse(value);
					_inode = new value.constructor(value);
					if (openTuples[ndepth] !== undefined) {
						key = openTuples[ndepth];
						//console.log("picked up tuple",ndepth,key);
						openTuples[ndepth] = undefined;
						if (last == 6) {
							if (parent) parent.push([key, _inode]);
						} else if (last == 1) {
							parent.attr(key, value);
							stack = [];
							return;
						} else {
							// error
						}
					} else {
						if (parent) parent.push([null, _inode]);
					}
				}
			}
			stack = [];
			var depth = parent ? parent.depth + 1 : type == 9 || type == 11 ? 0 : 1;
			var node = new VNode(cx, _inode, type, name, key, isLeaf(type) ? _inode.valueOf() : null, parent, depth);
			if (_isBranch) {
				parents.push(node);
			}
			//console.log("buf",node.name);
			buf.add(node);
		}
	};
	return create(function (sink) {
		return o.subscribe({
			next: cur => {
				// this will be the new version of streaming-fromL3!
				if (typeof cur == "number") {
					try {
						checkStack();
					} catch (err) {
						return sink.error(err);
					}
					buf.flush(sink, bufSize);
				}
				stack.push(cur);
			},
			complete: () => {
				try {
					checkStack();
				} catch (err) {
					return sink.error(err);
				}
				// flush all
				buf.flush(sink);
				sink.complete();
			}
		});
	});
}
<commit_msg>added toJS<commit_after>import * as inode from "./inode";

import { VNode } from "./vnode";

import { getDoc, vdoc, firstChild } from "./access";

import { create } from "./seq";

import { Step } from "./access";

import { camelCase } from "./util";

export function str2array(str, ar, idx){
	for (var i=0, strLen=str.length; i<strLen; i++) {
		//ar.push(str.codePointAt(i));
		ar[idx++] = str.codePointAt(i);
	}
	return idx;
}

export function array2str(ar,i){
	var str = "",l = ar.length;
	for (; i<l; i++) {
		str += String.fromCodePoint(ar[i]);
	}
	return str;
}

export function convert(v){
	var i = parseFloat(v);
	if(!isNaN(i)) return i;
	if(v === "true" || v === "false") return v !== "false";
	return v;
}

function docAttrType(k) {
	switch (k) {
	case "DOCTYPE": return 11;
	default: return 7;
	}
}

function Nil() {
}

Nil.prototype.next = function(){
	return { done: true };
};

/**
 * Create a flat buffer from the document tree
 * @param  {VNode} doc The document
 * @return {ArrayBuffer}  A flat buffer
 */
export function toL3($doc /*, to2D = false, schema = null*/){
	var cx = this && this.vnode ? this : inode;
	return getDoc.bind(cx)($doc).concatMap(doc => {
		//var schemaIter = schema ? docIter(schema) : new Nil();
		//var schemaEntry = schemaIter.next();
		return vdoc.bind(cx)(firstChild.bind(cx)(doc)).concatMap(function (node) {
			let type = node.type;
			if (type == 17) return [17];
			if(type == 1) {
				var d = [];
				for(let attr of node.attrEntries()) Array.prototype.push.call(d,2,attr[0],3,attr[1]);
				return Array.prototype.push.call(d,1,node.name);
			}
			if(type == 3) return [3,node.value];
			// if there's a schema entry and all schema props are equal then the node has a schema entry
			// else if there's a schema entry, the value is not there (which was assumed valid)
			// else write the node name + type
			// if indexInParent is not equal, we skipped a schema entry
			// TODO allow partial schema somewhere in the document tree
			//let nodeHasSchema = !schemaEntry.done && schemaEntry.depth == depth && schemaEntry.name == name;
			// if this node has a schema, continue with next, else skip and try with next entry
			//if (nodeHasSchema) schemaEntry = schemaIter.next();
			/*var nameIndex = 0;
			if (typeof name === "string" && !nodeHasSchema) {
				if (!names[name]) {
					names[name] = ++j;
					out[i++] = 15;
					i = str2array(name, out, i);
				}
				nameIndex = names[name];
			}
			// TODO use text for values unless there's a schema
			//  always store type
			out[i++] = type;
			out[i++] = depth;
			if (!nodeHasSchema && nameIndex) out[i++] = nameIndex;
			if (type == 1) {
				// TODO how to serialize attrs with schema?
				for (let attr of node.attrEntries()) {
					let name = attr[0],
						attrname = "@" + name;
					if (!names[attrname]) {
						names[attrname] = ++j;
						out[i++] = 15;
						i = str2array(name, out, i);
					}
					out[i++] = 2;
					out[i++] = names[attrname];
					i = str2array(attr[1], out, i);
				}
			} else if (type == 3) {
				i = str2array(node.value, out, i);
			} else if (type == 12) {
				i = str2array(node.value + "", out, i);
			}*/
		});
	});
}
/*
export function fromL3(l3, schema = null) {
	var names = {},
		n = 15,
		parents = [],
		parentTypes = [],
		depth = 15;
	var cx = this && this.vnode ? this : inode;
	// TODO DOCTYPE / processing instructions
	var doc = cx.emptyINode(9, "#document", cx.emptyAttrMap());
	parents[depth] = doc;
	parentTypes[depth] = 9;
	var schemaIter = schema ? docIter(schema) : new Nil();
	var schemaEntry = schemaIter.next();
	const process = function (entry) {
		let type = entry[0];
		let hasSchema = false,
			skipSchema = false,
			schemaName;
		// TODO have attributes accept any type
		if (!type) {
			// assume schema
			hasSchema = true;
			type = schemaEntry.type;
			schemaName = schemaEntry.name;
		}
		if (type == 2) {
			let parent = parents[depth];
			let name = names[entry[1]];
			parent = cx.setAttribute(parent, name, array2str(entry, 2));
		} else if (type == 7 || type == 11) {
			doc = cx.setAttribute(doc, entry[1] == 11 ? 10 : 7, array2str(entry, 2));
		} else if (type == 15) {
			n++;
			names[n] = array2str(entry, 1);
		} else {
			depth = entry[1];
			let parent = parents[depth - 1];
			let parentType = parentTypes[depth - 1];
			let node, name, valIndex;
			if (type == 1 || type == 5 || type == 6) {
				name = names[entry[2]];
				if (name) {
					if (hasSchema && schemaName != name) skipSchema = true;
				} else {
					name = schemaName;
				}
				if (parents[depth]) {
					parents[depth] = cx.finalize(parents[depth]);
				}
				node = cx.emptyINode(type, name, cx.emptyAttrMap());
				parents[depth] = node;
				parentTypes[depth] = type;
			} else if (type == 3 || type == 12) {
				if (parentType == 1 || parentType == 9) {
					name = cx.count(parent);
					valIndex = 2;
				} else {
					name = names[entry[2]];
					if (name) {
						if (hasSchema && schemaName != name) skipSchema = true;
					} else {
						name = schemaName;
					}
					valIndex = 3;
				}
				let val = type == 3 ? array2str(entry, valIndex) : convert(array2str(entry, valIndex));
				node = cx.ivalue(type, name, val);
			}
			if (parent) parent = cx.push(parent, [name, node]);
		}
	};
	var entry = [];
	for (var i = 0, l = l3.length; i < l; i++) {
		var x = l3[i];
		if (x < 16 && x != 9 && x != 10 && x != 13) {
			if(i>0) process(entry);
			entry = [];
		}
		entry.push(x);
	}
	process(entry);
	return cx.finalize(parents[15]);
}
*/
const isLeaf = type => type == 2 || type == 3 || type == 4 || type == 7 || type == 8 || type == 10 || type == 12 || type == 16;
const isBranch = type => type == 1 || type == 5 || type == 6 || type == 9 || type == 11 || type == 14 || type == 15;

function VNodeBuffer(nodes = []) {
	this.nodes = nodes;
}

VNodeBuffer.prototype.add = function (v) {
	this.nodes.unshift(v);
};

VNodeBuffer.prototype.count = function () {
	return this.nodes.length;
};

VNodeBuffer.prototype.flush = function (sink, count = 1) {
	var s = this.count();
	while(s >= count){
		//console.log("FLUSH",s,count);
		sink.next(this.nodes.pop());
		--s;
	}
};

export function fromL3Stream(o,bufSize=1) {
	const cx = this && "vnode" in this ? this : inode;
	let ndepth = 0,
		stack = [],
		open = [],
		parents = [],
		openTuples = {},
		buffered = null,
		buf = new VNodeBuffer();
	const checkStack = function() {
		var l = stack.length;
		if (!l) return;
		const type = stack[0];
		const ol = open.length - 1;
		const last = open[ol],
			parent = parents[ol];
		const isClose = type == 17;
		// buffered is used to add attributes to elements before they're emitted
		// here buffered is released before anything else is processed (except attrs)
		if (last == 1 && buffered !== null && type != 2) {
			// console.log("buf",buffered.name);
			buf.add(buffered);
			buffered = null;
		}
		if (isClose) {
			open.pop();
			parents.pop();
			//console.log("closing",ndepth,parent.inode);
			--ndepth;
			stack = [];
			return buf.add(new Step(parent));
		} else {
			var _inode = void 0,
				name = void 0,
				key = void 0,
				_isBranch = isBranch(type);
			if (_isBranch) {
				ndepth++;
				switch (type) {
				case 1:
				{
					name = stack[1];
					_inode = { $type: type, $name: name, $children: [] };
					_inode.$attrs = {};
					if (last == 6) {
						// emit inode /w key
						key = openTuples[ndepth];
						//console.log("picked up tuple",ndepth,key);
						openTuples[ndepth] = undefined;
					}
					if (parent) parent.push([key, _inode]);
					open.push(type);
					// TODO use cx.vnode()
					let depth = parent ? parent.depth + 1 : 1;
					let node = new VNode(cx, _inode, _inode.$type, name, key, isLeaf(type) ? _inode.valueOf() : null, parent, depth);
					// buffer attributes
					buffered = node;
					//console.log("opening element",ndepth,name, buffered);
					parents.push(node);
					stack = [];
					return;
				}
				case 9:
					name = "#document";
					_inode = { $name: name, $children: [] };
					break;
				case 11:
					name = "#document-fragment";
					_inode = { $name: name, $children: [] };
					break;
				case 14:
					name = stack[1];
					_inode = { $name: name, $args: [] };
					break;
				case 15:
					_inode = { $name: name, $args: [] };
					break;
				case 5:
					_inode = []; //{$type:type,$children:[]};
					break;
				case 6:
					// never emit until all tuples are closed
					_inode = {};
					break;
				}
				if (last == 6) {
					// must be an open tuple
					key = openTuples[ndepth - 1];
					openTuples[ndepth - 1] = undefined;
					//console.log("picked up tuple",ndepth,key);
				}
				if (parent) {
					parent.push([key, _inode]);
				}
				open.push(type);
			} else {
				if (type == 2) {
					// new model:
					// - create tuple inode
					// - don't emit tuple, but tuple value /w key
					openTuples[ndepth] = stack[1];
					//console.log("opening tuple",ndepth,stack[1]);
					stack = [];
					return;
				} else {
					var value = stack[1];
					if(type == 12) value = JSON.parse(value);
					_inode = new value.constructor(value);
					if (openTuples[ndepth] !== undefined) {
						key = openTuples[ndepth];
						//console.log("picked up tuple",ndepth,key);
						openTuples[ndepth] = undefined;
						if (last == 6) {
							if (parent) parent.push([key, _inode]);
						} else if (last == 1) {
							parent.attr(key, value);
							stack = [];
							return;
						} else {
							// error
						}
					} else {
						if (parent) parent.push([null, _inode]);
					}
				}
			}
			stack = [];
			var depth = parent ? parent.depth + 1 : type == 9 || type == 11 ? 0 : 1;
			var node = new VNode(cx, _inode, type, name, key, isLeaf(type) ? _inode.valueOf() : null, parent, depth);
			if (_isBranch) {
				parents.push(node);
			}
			//console.log("buf",node.name);
			buf.add(node);
		}
	};
	return create(function (sink) {
		return o.subscribe({
			next: cur => {
				// this will be the new version of streaming-fromL3!
				if (typeof cur == "number") {
					try {
						checkStack();
					} catch (err) {
						return sink.error(err);
					}
					buf.flush(sink, bufSize);
				}
				stack.push(cur);
			},
			complete: () => {
				try {
					checkStack();
				} catch (err) {
					return sink.error(err);
				}
				// flush all
				buf.flush(sink);
				sink.complete();
			}
		});
	});
}

const constructormap = {
	1: "e",
	2: "a",
	3: "x",
	4: "r",
	5: "l",
	6: "m",
	7: "p",
	8: "c",
	12: "x",
	14: "f",
	15: "q"
};

export function toJS(o) {
	return o.reduce((ret, node) => {
		// this will be the new version of streaming-fromL3!
		let type = node.type;
		let isClose = type == 17;
		let fn = "n."+constructormap[type];
		if (!isClose) {
			if (isBranch(type)) {
				switch (type) {
				case 1:
				case 14:
					{
						let name = node.name;
						if (type == 14) {
							// TODO camelCasing
							var prefix = /[$]/.test(name) ? "" : /:/.test(name) ? name.replace(/^([^:]*):.*$/, "$1") + "." : "n.";
							name = !name ? "seq" : camelCase(name);
							ret += prefix + name + "(";
						}
					}
					break;
				case 15:
					{
						//let qname = isTuple ? stack[2] : stack[1];
						//qname = /[$:]/g.test(qname) ? qname.replace(/:/, ".") : qname;
						ret += "n.seq($ => (";
					}
					break;
				case 5:
				case 6:
					{
						ret += fn + "(";
					}
					break;
				}
			} else {
				let value = type == 12 ? node.value : "\""+node.value+"\"";
				ret += value + ",";
			}
		} else {
			ret = ret.replace(/,$/, "");
			// call quote with params, etc using closure!
			ret += node.node.type == 15 ? "))," : "),";
		}
		return ret;
	}, "").map(ret => ret.replace(/,$/, ""));
}
<|endoftext|>


<commit_before>
(function(window, module) {
	'use strict';

	// environment variables
	var isNode = !!module.id;

	// recursive requirements
	var recursion = {
			_globals: {
				require : isNode ? require : false,
				module  : isNode ? module  : false
			}
		};

	// queuing mechanism
	function Queue(owner, that) {
		this._methods = [];
		this._owner = owner;
		this._that = that;
		this._paused = false;
	}
	Queue.prototype = {
		push: function(fn) {
			this._methods.push(fn);
			if (!this._paused) this.flush();
		},
		unshift: function(fn) {
			this._methods.unshift(fn);
			if (!this._paused) this.flush();
		},
		flush: function() {
			var fn,
				args = arguments;
			if (this._paused) return;
			while (this._methods[0]) {
				fn = this._methods.shift();
				fn.apply(this._that, args);
				if (fn._paused) {
					this._paused = true;
					break;
				}
			}
		}
	};

	// observer
	var observer = function() {
		var stack = {};

		return {
			on: function(type, fn) {
				if (!stack[type]) {
					stack[type] = [];
				}
				stack[type].unshift(fn);
			},
			off: function(type, fn) {
				if (!stack[type]) return;
				var i = stack[type].indexOf(fn);
				stack[type].splice(i,1);
			},
			emit: function(type, detail) {
				if (!stack[type]) return;
				var event = {
						type         : type,
						detail       : detail,
						isCanceled   : false,
						cancelBubble : function() {
							this.isCanceled = true;
						}
					},
					len = stack[type].length;
				while(len--) {
					if (event.isCanceled) return;
					stack[type][len](event);
				}
			}
		};
	};

	// thread enabler
	var thread = {
		init: function() {
			return this;
		},
		work_handler: function(event) {
			var args = Array.prototype.slice.call(event.data, 1),
				func = event.data[0],
				ret  = tree[func].apply(tree, args);

			// return process finish
			postMessage([func, ret]);
		},
		setup: function(tree) {
			var url    = window.URL || window.webkitURL,
				script = 'var tree = {'+ this.parse(tree).join(',') +'};',
				blob   = new Blob([script + 'self.addEventListener("message", '+ this.work_handler.toString() +', false);'],
									{type: 'text/javascript'}),
				worker = new Worker(url.createObjectURL(blob));

			// thread pipe
			worker.onmessage = function(event) {
				var args = Array.prototype.slice.call(event.data, 1),
					func = event.data[0];
				thread.observer.emit('thread:'+ func, args);
			};

			return worker;
		},
		call_handler: function(func, worker, callback) {
			return function() {
				var args = Array.prototype.slice.call(arguments);

				// add method name
				args.unshift(func);

				// listen for 'done'
				thread.observer.on('thread:'+ func, function(event) {
					callback(event.detail[0]);
				});

				// start worker
				worker.postMessage(args);
			};
		},
		compile: function(hash, callback) {
			var isFunc = typeof(hash) === 'function',
				worker = this.setup(isFunc ? {func: hash} : hash),
				obj    = {},
				fn;
			// create return object
			if (isFunc) {
				obj.func = this.call_handler('func', worker, callback);
				return obj.func;
			} else {
				for (fn in hash) {
					obj[fn] = this.call_handler(fn, worker, callback);
				}
				return obj;
			}
		},
		parse: function(tree, isArray) {
			var hash = [],
				key,
				val,
				v;

			for (key in tree) {
				v = tree[key];
				// handle null
				if (v === null) {
					hash.push(key +':null');
					continue;
				}
				// handle undefined
				if (v === undefined) {
					hash.push(key +':undefined');
					continue;
				}
				switch (v.constructor) {
					case Date:     val = 'new Date('+ v.valueOf() +')';           break;
					case Object:   val = '{'+ this.parse(v).join(',') +'}';       break;
					case Array:    val = '['+ this.parse(v, true).join(',') +']'; break;
					case String:   val = '"'+ v.replace(/"/g, '\\"') +'"';        break;
					case RegExp:
					case Function:
						val = v.toString();
						val = val.replace(/\bself\b/g, 'this.'+ key);
						break;
					default:
						val = v;
				}
				if (isArray) hash.push(val);
				else hash.push(key +':'+ val);
			}
			return hash;
		},
		// simple event emitter
		observer: observer()
	};

	// cors request
	function CORSreq(owner, url, hash, key) {
		var method = 'GET',
			xhr = new XMLHttpRequest();
		if ('withCredentials' in xhr) {
			xhr.open(method, url, true);
		} else if (typeof XDomainRequest != 'undefined') {
			xhr = new XDomainRequest();
			xhr.open(method, url);
		} else {
			// no-support -> fallback: JSReq ?
			throw 'XHR not supported';
		}
		xhr.hash   = hash;
		xhr.key    = key;
		xhr.owner  = owner;
		xhr.onload = this.doload;
		return xhr;
	}
	CORSreq.prototype = {
		doload: function(event) {
			var resp = JSON.parse(event.target.responseText),
				args = [],
				isDone = true,
				name;
			if (this.hash) {
				this.hash[this.key] = resp;

				for (name in this.hash) {
					if (typeof(this.hash[name]) === 'string') isDone = false;
				}
				if (isDone) {
					args.push(this.hash._single ? this.hash._single : this.hash);
				}
			}
			this.owner.queue._paused = false;
			this.owner.queue.flush.apply(this.owner.queue, args);
		}
	};

	// QureJS class
	function Qure() {
		var that = {};
		this.queue = new Queue(this, that);

		this._globals = {
				require : isNode ? require : false,
				module  : isNode ? module  : false
			};

		return this;
	}
	Qure.prototype = {
		fork: function() {
			return new Qure();
		},
		wait: function(duration) {
			var self = this,
				fn = function() {
					setTimeout(function() {
						self.queue._paused = false;
						self.queue.flush();
					}, duration || 0);
				};
			fn._paused = true;
			this.queue.push(fn);
			return this;
		},
		then: function(fn) {
			var self = this,
				func = function() {
					var args = [];
					if (self._globals.res) {
						args.push(self._globals.res);
						delete self._globals.res;
					} else {
						args = arguments;
					}
					fn.apply(self.queue._that, args);
				};
			this.queue.push(func);
			return this;
		},
		load: function(url, hash, key) {
			var self = this,
				fn = function() {
					var cors = new CORSreq(self, url, hash, key);
					cors.send();
				};
			if (typeof(url) === 'object') {
				for (var name in url) {
					this.load(url[name], url, name);
				}
				return this;
			} else if (!hash) {
				this.load({_single: url});
				return this;
			}
			fn._paused = true;
			this.queue.push(fn);
			return this;
		},
		declare: function(record) {
			var self = this,
				func = function() {
					var str,
						args,
						body;
					if (typeof(record) === 'function') {
						record = {
							single_recursive_func: record
						};
					}
					for (var fn in record) {
						if (typeof record[fn] !== 'function') {
							recursion[fn] = record[fn];
							continue;
						}
						str  = record[fn].toString();
						args = str.match(/functio.+?\((.*?)\)/)[1].split(',');
						body = str.match(/functio.+?\{([\s\S]*)\}/i)[1].trim();
						// modify function body
						body = body.replace(/\bself\b/g,    'this._fn_'+ fn);
						body = body.replace(/\brequire\b/g, 'this._globals.require');
						body = body.replace(/\bmodule\b/g,  'this._globals.module');
						// append function body
						args.push(body);
						// prepeare recursion
						self['_fn_'+ fn] = Function.apply({}, args);
					}
				};
			this.queue.push(func);
			return this;
		},
		thread: function(record) {
			var self = this,
				func = function() {
					self._compiled = thread.compile(record, function() {
						self.resume.apply(self, arguments);
					});
				};
			this.queue.unshift(func);
			return this;
		},
		run: function() {
			var self = this,
				args = [].slice.apply(arguments),
				fn = function() {
					var name = (self._fn_single_recursive_func) ? 'single_recursive_func' : args.shift();

					if (self['_fn_'+ name]) {
						self._globals.res = self['_fn_'+ name].apply(self, args);
					} else {
						self.pause();
						self._compiled[name].apply(self, args);
					}
				};
			//fn._paused = true;
			this.queue.push(fn);
			return this;
		},
		precede: function(fn) {
			this.queue.unshift(fn);
			return this;
		},
		resume: function() {
			this.queue._paused = false;
			this.queue.flush.apply(this.queue, arguments);
			return this;
		},
		pause: function(fn) {
			fn = fn || function() {};
			fn._paused = true;
			this.queue.unshift(fn);
			return this;
		}
	};

	// Export
	window.Qure = module.exports = new Qure();

})(
	typeof window !== 'undefined' ? window : {},
	typeof module !== 'undefined' ? module : {}
);
<commit_msg>renaming variable<commit_after>
(function(window, module) {
	'use strict';

	// environment variables
	var isNode = !!module.id;

	// recursive requirements
	var recursion = {
			_globals: {
				require : isNode ? require : false,
				module  : isNode ? module  : false
			}
		};

	// queuing mechanism
	function Queue(owner, that) {
		this._methods = [];
		this._owner = owner;
		this._that = that;
		this._paused = false;
	}
	Queue.prototype = {
		push: function(fn) {
			this._methods.push(fn);
			if (!this._paused) this.flush();
		},
		unshift: function(fn) {
			this._methods.unshift(fn);
			if (!this._paused) this.flush();
		},
		flush: function() {
			var fn,
				args = arguments;
			if (this._paused) return;
			while (this._methods[0]) {
				fn = this._methods.shift();
				fn.apply(this._that, args);
				if (fn._paused) {
					this._paused = true;
					break;
				}
			}
		}
	};

	// observer
	var observer = function() {
		var stack = {};

		return {
			on: function(type, fn) {
				if (!stack[type]) {
					stack[type] = [];
				}
				stack[type].unshift(fn);
			},
			off: function(type, fn) {
				if (!stack[type]) return;
				var i = stack[type].indexOf(fn);
				stack[type].splice(i,1);
			},
			emit: function(type, detail) {
				if (!stack[type]) return;
				var event = {
						type         : type,
						detail       : detail,
						isCanceled   : false,
						cancelBubble : function() {
							this.isCanceled = true;
						}
					},
					len = stack[type].length;
				while(len--) {
					if (event.isCanceled) return;
					stack[type][len](event);
				}
			}
		};
	};

	// thread enabler
	var thread = {
		init: function() {
			return this;
		},
		work_handler: function(event) {
			var args = Array.prototype.slice.call(event.data, 1),
				func = event.data[0],
				ret  = tree[func].apply(tree, args);

			// return process finish
			postMessage([func, ret]);
		},
		setup: function(tree) {
			var url    = window.URL || window.webkitURL,
				script = 'var tree = {'+ this.parse(tree).join(',') +'};',
				blob   = new Blob([script + 'self.addEventListener("message", '+ this.work_handler.toString() +', false);'],
									{type: 'text/javascript'}),
				worker = new Worker(url.createObjectURL(blob));

			// thread pipe
			worker.onmessage = function(event) {
				var args = Array.prototype.slice.call(event.data, 1),
					func = event.data[0];
				thread.observer.emit('thread:'+ func, args);
			};

			return worker;
		},
		call_handler: function(func, worker, callback) {
			return function() {
				var args = Array.prototype.slice.call(arguments);

				// add method name
				args.unshift(func);

				// listen for 'done'
				thread.observer.on('thread:'+ func, function(event) {
					callback(event.detail[0]);
				});

				// start worker
				worker.postMessage(args);
			};
		},
		compile: function(hash, callback) {
			var isFunc = typeof(hash) === 'function',
				worker = this.setup(isFunc ? {func: hash} : hash),
				obj    = {},
				fn;
			// create return object
			if (isFunc) {
				obj.func = this.call_handler('func', worker, callback);
				return obj.func;
			} else {
				for (fn in hash) {
					obj[fn] = this.call_handler(fn, worker, callback);
				}
				return obj;
			}
		},
		parse: function(tree, isArray) {
			var hash = [],
				key,
				val,
				prop;

			for (key in tree) {
				prop = tree[key];
				// handle null
				if (prop === null) {
					hash.push(key +':null');
					continue;
				}
				// handle undefined
				if (prop === undefined) {
					hash.push(key +':undefined');
					continue;
				}
				switch (prop.constructor) {
					case Date:     val = 'new Date('+ prop.valueOf() +')';           break;
					case Object:   val = '{'+ this.parse(prop).join(',') +'}';       break;
					case Array:    val = '['+ this.parse(prop, true).join(',') +']'; break;
					case String:   val = '"'+ prop.replace(/"/g, '\\"') +'"';        break;
					case RegExp:
					case Function:
						val = prop.toString();
						val = val.replace(/\bself\b/g, 'this.'+ key);
						break;
					default:
						val = prop;
				}
				if (isArray) hash.push(val);
				else hash.push(key +':'+ val);
			}
			return hash;
		},
		// simple event emitter
		observer: observer()
	};

	// cors request
	function CORSreq(owner, url, hash, key) {
		var method = 'GET',
			xhr = new XMLHttpRequest();
		if ('withCredentials' in xhr) {
			xhr.open(method, url, true);
		} else if (typeof XDomainRequest != 'undefined') {
			xhr = new XDomainRequest();
			xhr.open(method, url);
		} else {
			// no-support -> fallback: JSReq ?
			throw 'XHR not supported';
		}
		xhr.hash   = hash;
		xhr.key    = key;
		xhr.owner  = owner;
		xhr.onload = this.doload;
		return xhr;
	}
	CORSreq.prototype = {
		doload: function(event) {
			var resp = JSON.parse(event.target.responseText),
				args = [],
				isDone = true,
				name;
			if (this.hash) {
				this.hash[this.key] = resp;

				for (name in this.hash) {
					if (typeof(this.hash[name]) === 'string') isDone = false;
				}
				if (isDone) {
					args.push(this.hash._single ? this.hash._single : this.hash);
				}
			}
			this.owner.queue._paused = false;
			this.owner.queue.flush.apply(this.owner.queue, args);
		}
	};

	// QureJS class
	function Qure() {
		var that = {};
		this.queue = new Queue(this, that);

		this._globals = {
				require : isNode ? require : false,
				module  : isNode ? module  : false
			};

		return this;
	}
	Qure.prototype = {
		fork: function() {
			return new Qure();
		},
		wait: function(duration) {
			var self = this,
				fn = function() {
					setTimeout(function() {
						self.queue._paused = false;
						self.queue.flush();
					}, duration || 0);
				};
			fn._paused = true;
			this.queue.push(fn);
			return this;
		},
		then: function(fn) {
			var self = this,
				func = function() {
					var args = [];
					if (self._globals.res) {
						args.push(self._globals.res);
						delete self._globals.res;
					} else {
						args = arguments;
					}
					fn.apply(self.queue._that, args);
				};
			this.queue.push(func);
			return this;
		},
		load: function(url, hash, key) {
			var self = this,
				fn = function() {
					var cors = new CORSreq(self, url, hash, key);
					cors.send();
				};
			if (typeof(url) === 'object') {
				for (var name in url) {
					this.load(url[name], url, name);
				}
				return this;
			} else if (!hash) {
				this.load({_single: url});
				return this;
			}
			fn._paused = true;
			this.queue.push(fn);
			return this;
		},
		declare: function(record) {
			var self = this,
				func = function() {
					var str,
						args,
						body;
					if (typeof(record) === 'function') {
						record = {
							single_recursive_func: record
						};
					}
					for (var fn in record) {
						if (typeof record[fn] !== 'function') {
							recursion[fn] = record[fn];
							continue;
						}
						str  = record[fn].toString();
						args = str.match(/functio.+?\((.*?)\)/)[1].split(',');
						body = str.match(/functio.+?\{([\s\S]*)\}/i)[1].trim();
						// modify function body
						body = body.replace(/\bself\b/g,    'this._fn_'+ fn);
						body = body.replace(/\brequire\b/g, 'this._globals.require');
						body = body.replace(/\bmodule\b/g,  'this._globals.module');
						// append function body
						args.push(body);
						// prepeare recursion
						self['_fn_'+ fn] = Function.apply({}, args);
					}
				};
			this.queue.push(func);
			return this;
		},
		thread: function(record) {
			var self = this,
				func = function() {
					self._compiled = thread.compile(record, function() {
						self.resume.apply(self, arguments);
					});
				};
			this.queue.unshift(func);
			return this;
		},
		run: function() {
			var self = this,
				args = [].slice.apply(arguments),
				fn = function() {
					var name = (self._fn_single_recursive_func) ? 'single_recursive_func' : args.shift();

					if (self['_fn_'+ name]) {
						self._globals.res = self['_fn_'+ name].apply(self, args);
					} else {
						self.pause();
						self._compiled[name].apply(self, args);
					}
				};
			//fn._paused = true;
			this.queue.push(fn);
			return this;
		},
		precede: function(fn) {
			this.queue.unshift(fn);
			return this;
		},
		resume: function() {
			this.queue._paused = false;
			this.queue.flush.apply(this.queue, arguments);
			return this;
		},
		pause: function(fn) {
			fn = fn || function() {};
			fn._paused = true;
			this.queue.unshift(fn);
			return this;
		}
	};

	// Export
	window.Qure = module.exports = new Qure();

})(
	typeof window !== 'undefined' ? window : {},
	typeof module !== 'undefined' ? module : {}
);
<|endoftext|>


<commit_before>"use strict";

function Reuq(app) {
  var rq = this;
  this.templates = {};
  this.app = app;
  this.app.resources = app.resources || {};
  this.app.locals = app.locals || {};
  this.utils = this.getUtils();

  this._storeTemplates();
  // submit
  $('body').on('submit', '[rq-form]:not([rq-tmpl] [rq-form]):not([rq-tmpl][rq-form])', function(e) {
    e.preventDefault();
    rq.utils.submit($(this))
  });

  (function(rq) {
    var resources = rq.app.resources;
    var locals = rq.app.locals || {};

    Object.keys(locals).forEach(function(name) {
      rq.setLocal(name, rq.getLocal(name));
    });
    //load all resources set to autoload
    Object.keys(resources).forEach(function(resourceName) {
      // if autoload is not set, autoload it by default
      if (resources[resourceName]['autoload'] === undefined || resources[resourceName]['autoload']) {
        rq.getResource(resourceName, true);
        rq.render(resourceName, null);
      }
    });

    rq.addEvents();
    // should this be run 1st inetead?
    if (typeof rq.app.onInit === 'function') {
      rq.app.onInit.apply(rq);
    }
  })(this);
}

//render
Reuq.prototype.render = function(templateName, data) {
  var processedTemplate = this._processTemplate(templateName, data);
  this._render(templateName, processedTemplate);
}

Reuq.prototype._processTemplate = function(templateName, data) {
  var rq = this;

  function sanitize(value) {
    var blacklist = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      "'": '''
    };
    return value.replace(/[&<>"']/g, function(m) {
      return blacklist[m];
    })
  }

  function isDynamicProperty(property) {
    return property[0] === "@";
  }

  function getDynamicPropertyValue(property, data) {
    // remove '@' character
    var expression = property.slice(1)
    return rq.app.dynamicProperties[expression].apply(rq, [data]);
  }

  function getPropertyValue(property, data){
    return isDynamicProperty(property) ? getDynamicPropertyValue(property, data) : data[property]
  }

  function compile(template, data) {
    var $template = $(template)

    //process ifs
    $template.find('[rq-if]').each(function(id, el) {
      var $el = $(el);
      var condition = $el.attr('rq-if');
      $el.removeAttr('rq-if');

      if (!getPropertyValue(condition, data)) {
        $el.remove();
      }
    })

    //process if-nots
    $template.find('[rq-if-not]').each(function(id, el) {
      var $el = $(el);
      var condition = $el.attr('rq-if-not');
      $el.removeAttr('rq-if-not');

      if (getPropertyValue(condition, data)) {
        $el.remove();
      }
    });

    template = $template.prop('outerHTML');

    template = template.replace(/\[\[(\w+|@\w+)\]\]/g, function() {
      var expression = arguments[1];
      // parse value to string
      var value = "" + (getPropertyValue(expression, data));
      return sanitize(value);
    });
    return template;
  }

  var templateObj = this.templates[templateName];
  var resourceName = templateObj.resourceName;
  var template = templateObj.html;
  var $template = $(template);

  // process rq-rsrc-loading
  if (resourceName && this.app.resources[resourceName].loading) {
    $template.not('[rq-rsrc-loading], [rq-rsrc-loading] *').remove();
  } else {
    $template.find('[rq-rsrc-loading], [rq-rsrc-loading] *').remove();
  }

  //process iteration
  $template.find('[rq-iter], [rq-iter-self]').each(function(id, el) {
    var $el = $(el);

    if ($el.is("[rq-iter]")) {
      var listKey = $el.attr('rq-iter');
      var list = data[listKey] || [];
    } else {
      // then it's rq-iter-self
      var list = data || [];
    }
    list.forEach(function(listItem) {
      var $compiled = $(compile($el.prop('outerHTML'), listItem));
      $compiled.removeAttr('rq-iter');
      $el.after($compiled);
    });
    $el.remove();
  });

  template = $template.prop('outerHTML');
  $template = $(compile(template, data))

  //process src
  $template.find('[rq-src]').each(function(id, el) {
    var $el = $(el);
    $el.attr('src', $el.attr('rq-src'));
    $el.removeAttr('rq-src');
  })

  return $template.prop('outerHTML');
}

Reuq.prototype._render = function(templateName, processedTemplate) {
  //remove previously rendered template
  $('[from-tmpl=' + templateName + ']').remove();

  var $template = $('[rq-tmpl][rq-tmpl=' + templateName + ']');
  var $newTemplate = $(processedTemplate).removeAttr('hidden').removeAttr('rq-tmpl');
  $newTemplate.attr('from-tmpl', templateName);
  $template.after($newTemplate);
  this.addEvents($newTemplate);
}

Reuq.prototype.cacheIsValid = function(resourceName) {
  var resource = this.app.resources[resourceName]

  if (resource.shouldReload) {
    return false;
  } else {
    var cacheTimeout = resource.cacheTimeout || 10; //minutes
    var timeoutDate = new Date(resource.updatedAt.getTime() + cacheTimeout * 60000);
    return timeoutDate > new Date();
  }
}

Reuq.prototype.invalidateResourceCache = function(resourceName) {
  this.app.resources[resourceName].shouldReload = true;
}

Reuq.prototype.getResource = function(resourceName, force, cb) {
  // coerce optional arguments to appropriate values
  if (arguments.length < 3 && typeof force === 'function') {
    cb = force;
    force = false;
  }
  var rq = this;
  var resource = this.app.resources[resourceName];
  if (resource.data && !force && this.cacheIsValid(resourceName)) {
    cb(resource.data);
  } else {
    resource.loading = true;

    var url = typeof resource.url === 'function' ? resource.url(this) : resource.url;
    $.ajax({
      url: url,
      dataType: "json",
      beforeSend: function(xhr) {
        Object.keys(resource.headers || {}).forEach(function(header) {
          xhr.setRequestHeader(header, resource.headers[header]);
        })
      },
      success: function(resp) {
        resource.loading = false;
        resource.loaded = true;

        rq.setResource(resourceName, resource.dataKey ? resp[resource.dataKey] : resp);

        if (typeof cb === 'function') {
          cb(resource.data);
        }
      }
    })
  }
}

Reuq.prototype.setResource = function(resourceName, data) {
  var rq = this;
  var resource = this.app.resources[resourceName];
  resource.data = data;
  resource.shouldReload = false;
  resource.updatedAt = new Date();
  this.runResourceSubscribers(resourceName, data);

  $('[rq-tmpl][rq-rsrc=' + resourceName + ']:not([manual-render])').each(function(id, el) {
    rq.render($(el).attr('rq-tmpl'), data);
  });
}

Reuq.prototype.runResourceSubscribers = function(resourceName, data) {
  var resource = this.app.resources[resourceName];
  data = data || resource.data;
  this.runSubscribers(resource.subscribers, data)
}

Reuq.prototype.updateResource = function(resourceName, cb) {
  var rq = this;
  this.getResource(resourceName, function(data) {
    rq.setResource(resourceName, cb(data));
  });
}

Reuq.prototype.setLocal = function(name, data) {
  var rq = this;
  // add fallback in case it's a newly dynamically set local
  var local = this.app.locals[name] = this.app.locals[name] || {};
  local.data = data;
  this.runLocalSubscribers(name, data);

  $('[rq-tmpl][rq-local=' + name + ']:not([manual-render])').each(function(id, el) {
    rq.render($(el).attr('rq-tmpl'), data);
  });
}

Reuq.prototype.getLocal = function(name) {
  return this.app.locals[name].data;
}

Reuq.prototype.updateLocal = function(name, cb) {
  var data = this.getLocal(name);
  this.setLocal(name, cb(data));
}

Reuq.prototype.runLocalSubscribers = function(name, data) {
  var local = this.app.locals[name];
  data = data || local.data;
  this.runSubscribers(local.subscribers, data);
}

Reuq.prototype.runSubscribers = function(subscribers, data) {
  var rq = this;
  if (subscribers) {
    subscribers.forEach(function(subscriber) {
      var path = subscriber.split('.');
      var fn = rq.app[path[0]][path[1]];
      fn.apply(rq, [data]);
    })
  }
}

//storeTemplates
Reuq.prototype._storeTemplates = function() {
  var rq = this;
  $('[rq-tmpl]').each(function(id, el) {
    var $el = $(el);
    rq.templates[$el.attr('rq-tmpl')] = {
      html: $el.prop('outerHTML'),
      dom: $el,
      localDataName: $el.attr('rq-local'),
      resourceName: $el.attr('rq-rsrc')
    };
  });
}

Reuq.prototype.addEvents = function($dom) {
  $dom = $dom || $('body');
  var rq = this;
  var evtSelector = '[rq-evt]:not([rq-tmpl] [rq-evt]):not([rq-tmpl][rq-evt])';
  $dom.find(evtSelector).addBack(evtSelector).each(function(id, el) {
    var $el = $(el);
    var evtConfig = $el.attr('rq-evt').split(' ')
    var evtType = evtConfig[0];
    var evtHandler = rq.app.eventHandlers[evtConfig[1]];
    $el.on(evtType, function(e) {
      var handlerArgs = [{event: e, target: $el}].concat(evtConfig.slice(2))
      evtHandler.apply(rq, handlerArgs);
    })
  });
}

Reuq.prototype.getUtils = function() {
  var rq = this;

  return {
    submit: function(form) {
      var data = form.serialize();
      var url = form.attr('action');
      var type = form.attr('method');

      var beforeSend = function(xhr) {
        var headersKey = form.attr('rq-form-headers');
        if (headersKey) {
          var headers = rq.app.fn[headersKey].apply(rq);
          Object.keys(headers || {}).forEach(function(header) {
            xhr.setRequestHeader(header, headers[header]);
          })
        }
      }

      $.ajax({ type: type, url: url, data: data, beforeSend: beforeSend })
        .done(function(data, status, jqXHR) {
          var cb = form.attr('rq-cb-done');
          if (cb) {
            rq.app.callbacks[cb].apply(rq, [data, status, form]);
          }
        })
        .fail(function(jqXHR, status, error) {
          var cb = form.attr('rq-cb-fail');
          if (cb) {
            rq.app.callbacks[cb](error, status, form, jqXHR);
          }
        });
    }
  }
}

$('head').append('<style type="text/css">[rq-tmpl] {display: none !important;}</style>');
window.Rq = window.Reuq = Reuq;
<commit_msg>refactor: access subscribers sensibly<commit_after>"use strict";

function Reuq(app) {
  var rq = this;
  this.templates = {};
  this.app = app;
  this.app.resources = app.resources || {};
  this.app.locals = app.locals || {};
  this.utils = this.getUtils();

  this._storeTemplates();
  // submit
  $('body').on('submit', '[rq-form]:not([rq-tmpl] [rq-form]):not([rq-tmpl][rq-form])', function(e) {
    e.preventDefault();
    rq.utils.submit($(this))
  });

  (function(rq) {
    var resources = rq.app.resources;
    var locals = rq.app.locals || {};

    Object.keys(locals).forEach(function(name) {
      rq.setLocal(name, rq.getLocal(name));
    });
    //load all resources set to autoload
    Object.keys(resources).forEach(function(resourceName) {
      // if autoload is not set, autoload it by default
      if (resources[resourceName]['autoload'] === undefined || resources[resourceName]['autoload']) {
        rq.getResource(resourceName, true);
        rq.render(resourceName, null);
      }
    });

    // should this be run 1st inetead?
    if (typeof rq.app.onInit === 'function') {
      rq.app.onInit.apply(rq);
    }
  })(this);
}

//render
Reuq.prototype.render = function(templateName, data) {
  var processedTemplate = this._processTemplate(templateName, data);
  this._render(templateName, processedTemplate);
}

Reuq.prototype._processTemplate = function(templateName, data) {
  var rq = this;

  function sanitize(value) {
    var blacklist = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      "'": '''
    };
    return value.replace(/[&<>"']/g, function(m) {
      return blacklist[m];
    })
  }

  function isDynamicProperty(property) {
    return property[0] === "@";
  }

  function getDynamicPropertyValue(property, data) {
    // remove '@' character
    var expression = property.slice(1)
    return rq.app.dynamicProperties[expression].apply(rq, [data]);
  }

  function getPropertyValue(property, data){
    return isDynamicProperty(property) ? getDynamicPropertyValue(property, data) : data[property]
  }

  function compile(template, data) {
    var $template = $(template)

    //process ifs
    $template.find('[rq-if]').each(function(id, el) {
      var $el = $(el);
      var condition = $el.attr('rq-if');
      $el.removeAttr('rq-if');

      if (!getPropertyValue(condition, data)) {
        $el.remove();
      }
    })

    //process if-nots
    $template.find('[rq-if-not]').each(function(id, el) {
      var $el = $(el);
      var condition = $el.attr('rq-if-not');
      $el.removeAttr('rq-if-not');

      if (getPropertyValue(condition, data)) {
        $el.remove();
      }
    });

    template = $template.prop('outerHTML');

    template = template.replace(/\[\[(\w+|@\w+)\]\]/g, function() {
      var expression = arguments[1];
      // parse value to string
      var value = "" + (getPropertyValue(expression, data));
      return sanitize(value);
    });
    return template;
  }

  var templateObj = this.templates[templateName];
  var resourceName = templateObj.resourceName;
  var template = templateObj.html;
  var $template = $(template);

  // process rq-rsrc-loading
  if (resourceName && this.app.resources[resourceName].loading) {
    $template.not('[rq-rsrc-loading], [rq-rsrc-loading] *').remove();
  } else {
    $template.find('[rq-rsrc-loading], [rq-rsrc-loading] *').remove();
  }

  //process iteration
  $template.find('[rq-iter], [rq-iter-self]').each(function(id, el) {
    var $el = $(el);

    if ($el.is("[rq-iter]")) {
      var listKey = $el.attr('rq-iter');
      var list = data[listKey] || [];
    } else {
      // then it's rq-iter-self
      var list = data || [];
    }
    list.forEach(function(listItem) {
      var $compiled = $(compile($el.prop('outerHTML'), listItem));
      $compiled.removeAttr('rq-iter');
      $el.after($compiled);
    });
    $el.remove();
  });

  template = $template.prop('outerHTML');
  $template = $(compile(template, data))

  //process src
  $template.find('[rq-src]').each(function(id, el) {
    var $el = $(el);
    $el.attr('src', $el.attr('rq-src'));
    $el.removeAttr('rq-src');
  })

  return $template.prop('outerHTML');
}

Reuq.prototype._render = function(templateName, processedTemplate) {
  //remove previously rendered template
  $('[from-tmpl=' + templateName + ']').remove();

  var $template = $('[rq-tmpl][rq-tmpl=' + templateName + ']');
  var $newTemplate = $(processedTemplate).removeAttr('hidden').removeAttr('rq-tmpl');
  $newTemplate.attr('from-tmpl', templateName);
  $template.after($newTemplate);
  this.addEvents($newTemplate);
}

Reuq.prototype.cacheIsValid = function(resourceName) {
  var resource = this.app.resources[resourceName]

  if (resource.shouldReload) {
    return false;
  } else {
    var cacheTimeout = resource.cacheTimeout || 10; //minutes
    var timeoutDate = new Date(resource.updatedAt.getTime() + cacheTimeout * 60000);
    return timeoutDate > new Date();
  }
}

Reuq.prototype.invalidateResourceCache = function(resourceName) {
  this.app.resources[resourceName].shouldReload = true;
}

Reuq.prototype.getResource = function(resourceName, force, cb) {
  // coerce optional arguments to appropriate values
  if (arguments.length < 3 && typeof force === 'function') {
    cb = force;
    force = false;
  }
  var rq = this;
  var resource = this.app.resources[resourceName];
  if (resource.data && !force && this.cacheIsValid(resourceName)) {
    cb(resource.data);
  } else {
    resource.loading = true;

    var url = typeof resource.url === 'function' ? resource.url(this) : resource.url;
    $.ajax({
      url: url,
      dataType: "json",
      beforeSend: function(xhr) {
        Object.keys(resource.headers || {}).forEach(function(header) {
          xhr.setRequestHeader(header, resource.headers[header]);
        })
      },
      success: function(resp) {
        resource.loading = false;
        resource.loaded = true;

        rq.setResource(resourceName, resource.dataKey ? resp[resource.dataKey] : resp);

        if (typeof cb === 'function') {
          cb(resource.data);
        }
      }
    })
  }
}

Reuq.prototype.setResource = function(resourceName, data) {
  var rq = this;
  var resource = this.app.resources[resourceName];
  resource.data = data;
  resource.shouldReload = false;
  resource.updatedAt = new Date();
  this.runResourceSubscribers(resourceName, data);

  $('[rq-tmpl][rq-rsrc=' + resourceName + ']:not([manual-render])').each(function(id, el) {
    rq.render($(el).attr('rq-tmpl'), data);
  });
}

Reuq.prototype.runResourceSubscribers = function(resourceName, data) {
  var resource = this.app.resources[resourceName];
  data = data || resource.data;
  this.runSubscribers(resource.subscribers, data)
}

Reuq.prototype.updateResource = function(resourceName, cb) {
  var rq = this;
  this.getResource(resourceName, function(data) {
    rq.setResource(resourceName, cb(data));
  });
}

Reuq.prototype.setLocal = function(name, data) {
  var rq = this;
  // add fallback in case it's a newly dynamically set local
  var local = this.app.locals[name] = this.app.locals[name] || {};
  local.data = data;
  this.runLocalSubscribers(name, data);

  $('[rq-tmpl][rq-local=' + name + ']:not([manual-render])').each(function(id, el) {
    rq.render($(el).attr('rq-tmpl'), data);
  });
}

Reuq.prototype.getLocal = function(name) {
  return this.app.locals[name].data;
}

Reuq.prototype.updateLocal = function(name, cb) {
  var data = this.getLocal(name);
  this.setLocal(name, cb(data));
}

Reuq.prototype.runLocalSubscribers = function(name, data) {
  var local = this.app.locals[name];
  data = data || local.data;
  this.runSubscribers(local.subscribers, data);
}

Reuq.prototype.runSubscribers = function(subscribers, data) {
  var rq = this;
  if (subscribers) {
    subscribers.forEach(function(subscriber) {
      var fn = rq.app.subscribers[subscriber];
      fn.apply(rq, [data]);
    })
  }
}

//storeTemplates
Reuq.prototype._storeTemplates = function() {
  var rq = this;
  $('[rq-tmpl]').each(function(id, el) {
    var $el = $(el);
    rq.templates[$el.attr('rq-tmpl')] = {
      html: $el.prop('outerHTML'),
      dom: $el,
      localDataName: $el.attr('rq-local'),
      resourceName: $el.attr('rq-rsrc')
    };
  });
}

Reuq.prototype.addEvents = function($dom) {
  $dom = $dom || $('body');
  var rq = this;
  var evtSelector = '[rq-evt]:not([rq-tmpl] [rq-evt]):not([rq-tmpl][rq-evt])';
  $dom.find(evtSelector).addBack(evtSelector).each(function(id, el) {
    var $el = $(el);
    var evtConfig = $el.attr('rq-evt').split(' ')
    var evtType = evtConfig[0];
    var evtHandler = rq.app.eventHandlers[evtConfig[1]];
    $el.on(evtType, function(e) {
      var handlerArgs = [{event: e, target: $el}].concat(evtConfig.slice(2))
      evtHandler.apply(rq, handlerArgs);
    })
  });
}

Reuq.prototype.getUtils = function() {
  var rq = this;

  return {
    submit: function(form) {
      var data = form.serialize();
      var url = form.attr('action');
      var type = form.attr('method');

      var beforeSend = function(xhr) {
        var headersKey = form.attr('rq-form-headers');
        if (headersKey) {
          var headers = rq.app.fn[headersKey].apply(rq);
          Object.keys(headers || {}).forEach(function(header) {
            xhr.setRequestHeader(header, headers[header]);
          })
        }
      }

      $.ajax({ type: type, url: url, data: data, beforeSend: beforeSend })
        .done(function(data, status, jqXHR) {
          var cb = form.attr('rq-cb-done');
          if (cb) {
            rq.app.callbacks[cb].apply(rq, [data, status, form]);
          }
        })
        .fail(function(jqXHR, status, error) {
          var cb = form.attr('rq-cb-fail');
          if (cb) {
            rq.app.callbacks[cb](error, status, form, jqXHR);
          }
        });
    }
  }
}

$('head').append('<style type="text/css">[rq-tmpl] {display: none !important;}</style>');
window.Rq = window.Reuq = Reuq;
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------------------------------------------- //
// no
// ----------------------------------------------------------------------------------------------------------------- //

var no = {};

// ----------------------------------------------------------------------------------------------------------------- //

no.inherits = function(ctor, base, mixin) {
    var F = function() {};
    F.prototype = base.prototype;
    var proto = ctor.prototype = new F();
    ctor.prototype.constructor = ctor;

    if (mixin) {
        no.extend(proto, mixin);
    }

    return ctor;
};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    @param {!Object} dest
    @param {...!Object} srcs
    @return {!Object}
*/
no.extend = function(dest) {
    var srcs = [].slice.call(arguments, 1);

    for (var i = 0, l = srcs.length; i < l; i++) {
        var src = srcs[i];
        for (var key in src) {
            dest[key] = src[key];
        }
    }

    return dest;
};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    Do not clone functions, only data.
    @param {!Object} dest
    @param {!Object} src
    @return {!Object}
*/
no.extendRecursive = function(dest, src) {
    for (var key in src) {
        var value = src[key];

        if (value instanceof Array) {
            var ar = dest[key] = [];
            for (var j = 0, m = value.length; j < m; j++) {
                var item = value[j];
                ar[j] = (typeof item === 'object') ? no.extendRecursive( {}, item ) : item;
            }

        } else if (typeof value === 'object') {
            dest[key] = no.extendRecursive( {}, value );

        } else {
            dest[key] = value;

        }
    }

    return dest;
};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    Пустая функция. No operation.
*/
no.pe = function() {};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    @param {string} className
    @param {Element} context
    @return {(Element|undefined)}
*/
//  FIXME: Мне не нравится использовать jQuery в noscript'е,
//  со временем я хочу выпилить jQuery совсем.
//  Пока что вот так странно.
if ((typeof document !== 'undefined') && document.getElementsByClassName) {

    no.byClass = function(className, context) {
        context = context || document;
        return context.getElementsByClassName(className);
    };

} else {

    no.byClass = function(className, context) {
        context = context || document;
        return $(context).find('.' + className);
    };

}

// ----------------------------------------------------------------------------------------------------------------- //

/**
    @param {Element} oldNode
    @param {Element} newNode
*/
no.replaceNode = function(oldNode, newNode) {
    oldNode.parentNode.replaceChild(newNode, oldNode);
};

// ----------------------------------------------------------------------------------------------------------------- //

no.todo = function() {
    throw new Error('Unimplemented');
};

no.html2node = function(html) {
    var div = document.createElement('div');
    div.innerHTML = html;

    return div.firstChild;
};

no.parseQuery = function(s) {
    var o = {};

    s.split('&').forEach(function(s) {
        var p = s.split('=');
        //  FIXME: decode-бла-бла.
        o[ p[0] ] = p[1];
    });

    return o;
};

/**
 *
 * @param mode
 * @param json
 * @param v
 */
no.tmpl = function(json, mode, v) {
    no.todo();
};

/**
 * Производит первоначальную инициализацию.
 */
no.init = function() {
    no.action.init();
    no.initMainView();
};

/**
 * Инициализирует корневой View.
 */
no.initMainView = function() {
    var mainView = no.View.create('app');
    mainView.node = document.getElementById('app');

    /**
     * Корневой View.
     * @type {no.View}
     */
    no.MAIN_VIEW = mainView;
};

//  ---------------------------------------------------------------------------------------------------------------  //

if (typeof window === 'undefined') {
    module.exports = no;
}

//  ---------------------------------------------------------------------------------------------------------------  //

<commit_msg>route init<commit_after>/**
 * noscrpt
 * @namespace
 */
var no = {};

// ----------------------------------------------------------------------------------------------------------------- //

no.inherits = function(ctor, base, mixin) {
    var F = function() {};
    F.prototype = base.prototype;
    var proto = ctor.prototype = new F();
    ctor.prototype.constructor = ctor;

    if (mixin) {
        no.extend(proto, mixin);
    }

    return ctor;
};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    @param {!Object} dest
    @param {...!Object} srcs
    @return {!Object}
*/
no.extend = function(dest) {
    var srcs = [].slice.call(arguments, 1);

    for (var i = 0, l = srcs.length; i < l; i++) {
        var src = srcs[i];
        for (var key in src) {
            dest[key] = src[key];
        }
    }

    return dest;
};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    Do not clone functions, only data.
    @param {!Object} dest
    @param {!Object} src
    @return {!Object}
*/
no.extendRecursive = function(dest, src) {
    for (var key in src) {
        var value = src[key];

        if (value instanceof Array) {
            var ar = dest[key] = [];
            for (var j = 0, m = value.length; j < m; j++) {
                var item = value[j];
                ar[j] = (typeof item === 'object') ? no.extendRecursive( {}, item ) : item;
            }

        } else if (typeof value === 'object') {
            dest[key] = no.extendRecursive( {}, value );

        } else {
            dest[key] = value;

        }
    }

    return dest;
};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    Пустая функция. No operation.
*/
no.pe = function() {};

// ----------------------------------------------------------------------------------------------------------------- //

/**
    @param {string} className
    @param {Element} context
    @return {(Element|undefined)}
*/
//  FIXME: Мне не нравится использовать jQuery в noscript'е,
//  со временем я хочу выпилить jQuery совсем.
//  Пока что вот так странно.
if ((typeof document !== 'undefined') && document.getElementsByClassName) {

    no.byClass = function(className, context) {
        context = context || document;
        return context.getElementsByClassName(className);
    };

} else {

    no.byClass = function(className, context) {
        context = context || document;
        return $(context).find('.' + className);
    };

}

// ----------------------------------------------------------------------------------------------------------------- //

/**
    @param {Element} oldNode
    @param {Element} newNode
*/
no.replaceNode = function(oldNode, newNode) {
    oldNode.parentNode.replaceChild(newNode, oldNode);
};

// ----------------------------------------------------------------------------------------------------------------- //

no.todo = function() {
    throw new Error('Unimplemented');
};

no.html2node = function(html) {
    var div = document.createElement('div');
    div.innerHTML = html;

    return div.firstChild;
};

no.parseQuery = function(s) {
    var o = {};

    s.split('&').forEach(function(s) {
        var p = s.split('=');
        //  FIXME: decode-бла-бла.
        o[ p[0] ] = p[1];
    });

    return o;
};

/**
 *
 * @param mode
 * @param json
 * @param v
 */
no.tmpl = function(json, mode, v) {
    no.todo();
};

/**
 * Производит первоначальную инициализацию noscript.
 */
no.init = function() {
    no.action.init();
    no.router.init();

    no.initMainView();
};

/**
 * Инициализирует корневой View.
 */
no.initMainView = function() {
    var mainView = no.View.create('app');
    mainView.node = document.getElementById('app');

    /**
     * Корневой View.
     * @type {no.View}
     */
    no.MAIN_VIEW = mainView;
};

//  ---------------------------------------------------------------------------------------------------------------  //

if (typeof window === 'undefined') {
    module.exports = no;
}

//  ---------------------------------------------------------------------------------------------------------------  //

<|endoftext|>


<commit_before>define(function (require) {

	/**

	 ox is an element wrapper.

	 */

	function ox(selector) {
		var element = document.querySelector(selector);
		oxWrap(element);
		return element;
	}
	function oxWrap(element){
		if (element.ox == undefined)new OxElement(element);
	}

	// private constructor
	function OxElement(element) {
		this.element = element;
		this.element.ox = this;

		new ox.DOMEvents(this.element);
		this.on = element.on;
		this.once = element.once;
		this.off = element.off;
		this.trigger = element.trigger;

		// convenience accessors
		this.style = this.element.style;
		this.classList = this.element.classList;
	}

	OxElement.prototype = {
		select: function (selector) {
			return ox.select(selector);
		},
		selectAll: function (selector) {
			return ox.selectAll(selector, this);
		},
		css: function (arg1, arg2) {
			if (typeof arg1 == "string") {
				this.style[arg1] = arg2;
			} else {
				// object
				for (var key in arg1) {
					this.style[key] = arg1[key];
				}
			}
		},
		attr: function (name, value) {
			this.setAttribute(name, value);
			if (value == undefined) return this.getAttribute(name);
		},
		prepend: function (element) {
			this.element.insertBefore(element, this.element.childNodes[0]);
		},
		append: function (element) {
			this.element.appendChild(element);
		},
		remove: function () {
			this.parentNode.removeChild(this.element);
		}

	};

	ox.select = function (selector) {
		var el = document.querySelector(selector);
		oxWrap(el);
		return el;
	};
	ox.selectAll = function (selector, parent) {
		parent = parent || document;
		var els = parent.querySelectorAll(selector);
		for (var i = 0, maxi = els.length; i < maxi; i++) {
			var el = els[i];
			oxWrap(el);
		}
		return els;
	};

	ox.create = function(type, content){
		var el = document.createElement(type);
		oxWrap(el);
		if(typeof content == 'string'){
			el.innerHTML = content;
		}else if(content instanceof Element){
			el.appendChild(content);
		}
		return el;
	};

	ox.ajax = function (path, callback) {
		//TODO
		callback();
	};

	ox.loadImage = function (src, callback) {
		var img = new Image();
		img.crossOrigin = "anonymous";
		if (callback) {
			img.addEventListener('load', function () {
				callback(img);
			});
		}
		img.src = src;
		return img;
	};

	ox.Events = require("Events");
	ox.FrameImpulse = require("FrameImpulse");

	return ox;

});
<commit_msg>dom events interface<commit_after>define(function (require) {

	/**

	 ox is an element wrapper.

	 */

	function ox(selector) {
		var element = document.querySelector(selector);
		oxWrap(element);
		return element;
	}
	function oxWrap(element){
		if (element.ox == undefined)new OxElement(element);
	}

	// private constructor
	function OxElement(element) {
		this.element = element;
		this.element.ox = this;

		new ox.DOMEvents(this.element);
		this.on = element.on;
		this.once = element.once;
		this.off = element.off;
		this.trigger = element.trigger;

		// convenience accessors
		this.style = this.element.style;
		this.classList = this.element.classList;
	}

	OxElement.prototype = {
		select: function (selector) {
			return ox.select(selector);
		},
		selectAll: function (selector) {
			return ox.selectAll(selector, this);
		},
		css: function (arg1, arg2) {
			if (typeof arg1 == "string") {
				this.style[arg1] = arg2;
			} else {
				// object
				for (var key in arg1) {
					this.style[key] = arg1[key];
				}
			}
		},
		attr: function (name, value) {
			this.setAttribute(name, value);
			if (value == undefined) return this.getAttribute(name);
		},
		prepend: function (element) {
			this.element.insertBefore(element, this.element.childNodes[0]);
		},
		append: function (element) {
			this.element.appendChild(element);
		},
		remove: function () {
			this.parentNode.removeChild(this.element);
		}

	};

	ox.select = function (selector) {
		var el = document.querySelector(selector);
		oxWrap(el);
		return el;
	};
	ox.selectAll = function (selector, parent) {
		parent = parent || document;
		var els = parent.querySelectorAll(selector);
		for (var i = 0, maxi = els.length; i < maxi; i++) {
			var el = els[i];
			oxWrap(el);
		}
		return els;
	};

	ox.create = function(type, content){
		var el = document.createElement(type);
		oxWrap(el);
		if(typeof content == 'string'){
			el.innerHTML = content;
		}else if(content instanceof Element){
			el.appendChild(content);
		}
		return el;
	};

	ox.ajax = function (path, callback) {
		//TODO
		callback();
	};

	ox.loadImage = function (src, callback) {
		var img = new Image();
		img.crossOrigin = "anonymous";
		if (callback) {
			img.addEventListener('load', function () {
				callback(img);
			});
		}
		img.src = src;
		return img;
	};

	ox.Events = require("Events");
	ox.DOMEvents = require("DOMEvents");
	ox.FrameImpulse = require("FrameImpulse");

	return ox;

});
<|endoftext|>


<commit_before>
//
// HTML5 Placeholder Attribute Polyfill (Span)
//
// Author: James Brumond <james@jbrumond.me> (http://www.jbrumond.me)
//

(function(window, document, undefined) {

	// Don't run the polyfill if it isn't needed
	if ('placeholder' in document.createElement('input')) {
		document.placeholderPolyfill = function() { /*  no-op */ };
		document.placeholderPolyfill.active = false;
		return;
	}

	// Fetch NodeLists of the needed element types
	var inputs = document.getElementsByTagName('input');
	var textareas = document.getElementsByTagName('textarea');

	//
	// Define the exposed polyfill methods for manual calls
	//
	document.placeholderPolyfill = function(elems) {
		elems = elems ? validElements(elems) : validElements(inputs, textareas);
		each(elems, polyfillElement);
	};

	// Expose whether or not the polyfill is in use (false means native support)
	document.placeholderPolyfill.active = true;

	// Run automatically
	document.placeholderPolyfill();

// -------------------------------------------------------------

	// Use mutation events for auto-updating
	if (document.addEventListener) {
		document.addEventListener('DOMAttrModified', document.placeholderPolyfill);
		document.addEventListener('DOMNodeInserted', document.placeholderPolyfill);
	}

	// Use onpropertychange for auto-updating
	else if (document.attachEvent && 'onpropertychange' in document) {
		document.attachEvent('onpropertychange', document.placeholderPolyfill);
	}

	// No event-based auto-update
	else {
		// pass
	}

// -------------------------------------------------------------

	// Add some basic default styling for placeholders
	firstStylesheet().addRule('.-placeholder', 'color: #888;', 0);

// -------------------------------------------------------------

	//
	// Polyfill a single, specific element
	//
	function polyfillElement(elem) {
		// If the element is already polyfilled, skip it
		if (elem.__placeholder) {
			return updatePlaceholder();
		}

		// Is there already a value in the field? If so, don't replace it with the placeholder
		var placeholder;
		drawPlaceholder();
		checkPlaceholder();

		// Define the events that cause these functions to be fired
		addEvent(elem, 'keyup', checkPlaceholder);
		addEvent(elem, 'keyDown', checkPlaceholder);
		addEvent(elem, 'blur', checkPlaceholder);
		addEvent(elem, 'focus', hidePlaceholder);
		addEvent(elem, 'click', hidePlaceholder);
		addEvent(placeholder, 'click', hidePlaceholder);
		addEvent(window, 'resize', redrawPlaceholder);

		// Use mutation events for auto-updating
		if (elem.addEventListener) {
			addEvent(elem, 'DOMAttrModified', updatePlaceholder);
		}

		// Use onpropertychange for auto-updating
		else if (elem.attachEvent && 'onpropertychange' in elem) {
			addEvent(elem, 'propertychange', updatePlaceholder);
		}

		// No event-based auto-update
		else {
			// pass
		}

		function drawPlaceholder() {
			placeholder = elem.__placeholder = createElement('span', {
				innerHTML: getPlaceholderFor(elem),
				style: {
					position: 'absolute',
					display: 'none',
					margin: '0',
					padding: '0',
					cursor: 'text'
				}
			});

			elem.parentNode.appendChild(placeholder);

			redrawPlaceholder();
		}

		function redrawPlaceholder() {
			// Update some basic styles to match that of the input
			var zIndex = getStyle(elem, 'zIndex');
			zIndex = (zIndex === 'auto') ? 99999 : zIndex;
			setStyle(placeholder, {
				zIndex: (zIndex || 99999) + 1,
				backgroundColor: 'transparent'
			});

			// Fix an old IE bug
			if (elem.offsetParent && getStyle(elem.offsetParent, 'position') === 'static') {
				elem.offsetParent.style.position = 'relative';
			}

			// Reposition the span to make sure it stays in place
			var offset = getOffset(elem);
			setStyle(placeholder, {
				top: offset.top + 'px',
				left: offset.left + 'px'
			});
		}

		function updatePlaceholder() {
			placeholder.innerHTML = getPlaceholderFor(elem);
			redrawPlaceholder();
		}

		function checkPlaceholder(event) {
			if (elem.value) {
                                var nofocus = true;
                                if (event && event.type ){
                                      nofocus = event.type === 'blur';
                                }
                                hidePlaceholder(event, nofocus);
			} else {
				showPlaceholder();
			}
		}

		function showPlaceholder() {
			placeholder.style.display = 'block';
			addClass(placeholder, '-placeholder');
			addClass(elem, '-placeholder-input');
		}

		function hidePlaceholder(event, suppressFocus) {
			placeholder.style.display = 'none';
			removeClass(placeholder, '-placeholder');
			removeClass(elem, '-placeholder-input');
			if (! suppressFocus) {
				elem.focus();
			}
		}
	}

// -------------------------------------------------------------

	//
	// Build a list of valid (can have a placeholder) elements from the given parameters
	//
	function validElements() {
		var result = [ ];

		each(arguments, function(arg) {
			if (typeof arg.length !== 'number') {
				arg = [ arg ];
			}

			result.push.apply(result, filter(arg, isValidElement));
		});

		return result;
	}

	//
	// Check if a given element supports the placeholder attribute
	//
	function isValidElement(elem) {
		var tag = (elem.nodeName || '').toLowerCase();
		return (tag === 'textarea' || (tag === 'input' && (elem.type === 'text' || elem.type === 'password')));
	}

// -------------------------------------------------------------

	function addEvent(obj, event, func) {
		if (obj.addEventListener) {
			obj.addEventListener(event, func, false);
		} else if (obj.attachEvent) {
			obj.attachEvent('on' + event, func);
		}
	}

	function removeEvent(obj, event, func) {
		if (obj.removeEventListener) {
			obj.removeEventListener(event, func, false);
		} else if (obj.detachEvent) {
			obj.detachEvent('on' + event, func);
		}
	}

// -------------------------------------------------------------

	function each(arr, func) {
		if (arr.forEach) {
			return arr.forEach(func);
		}

		for (var i = 0, c = arr.length; i < c; i++) {
			func.call(null, arr[i], i, arr);
		}
	}

	function filter(arr, func) {
		if (arr.filter) {
			return arr.filter(func);
		}

		var result = [ ];
		for (var i = 0, c = arr.length; i < c; i++) {
			if (func.call(null, arr[i], i, arr)) {
				result.push(arr[i]);
			}
		}

		return result;
	}

// -------------------------------------------------------------

	var regexCache = { };
	function classNameRegex(cn) {
		if (! regexCache[cn]) {
			regexCache[cn] = new RegExp('(^|\\s)+' + cn + '(\\s|$)+', 'g');
		}

		return regexCache[cn];
	}

	function addClass(elem, cn) {
		elem.className += ' ' + cn;
	}

	function removeClass(elem, cn) {
		elem.className = elem.className.replace(classNameRegex(cn), ' ');
	}

// -------------------------------------------------------------

	// Internet Explorer 10 in IE7 mode was giving me the wierest error
	// where e.getAttribute('placeholder') !== e.attributes.placeholder.nodeValue
	function getPlaceholderFor(elem) {
		return elem.getAttribute('placeholder') || (elem.attributes.placeholder && elem.attributes.placeholder.nodeValue) || '';
	}

// -------------------------------------------------------------

	// Get the first stylesheet in the document, or, if there are none, create/inject
	// one and return it.
	function firstStylesheet() {
		var sheet = document.styleSheets && document.styleSheets[0];
		if (! sheet) {
			var head = document.head || document.getElementsByTagName('head')[0];
			var style = document.createElement('style');
			style.appendChild(document.createTextNode(''));
			document.head.appendChild(style);
			sheet = style.sheet;
		}
		return sheet;
	}

// -------------------------------------------------------------

	// Used internally in getStyle()
	function getStyleValue(elem, prop) {
		if (elem.currentStyle) {
			return elem.currentStyle[prop];
		} else if (window.getComputedStyle) {
			return document.defaultView.getComputedStyle(elem, null)[prop];
		} else if (prop in elem.style) {
			return elem.style[prop];
		}
		return null;
	}

	// Get a style property from an element
	function getStyle(elem, prop) {
		var style;
		if (elem.parentNode == null) {
			elem = document.body.appendChild(elem);
			style = getStyleValue(elem, prop);
			elem = document.body.removeChild(elem);
		} else {
			style = getStyleValue(elem, prop);
		}
		return style;
	}

	// Set style properties to an element
	function setStyle(elem, props) {
		for (var i in props) {
			if (props.hasOwnProperty(i)) {
				elem.style[i] = props[i];
			}
		}
	}

// -------------------------------------------------------------

	// Create an element
	function createElement(tag, props) {
		var elem = document.createElement(tag);
		for (var i in props) {
			if (props.hasOwnProperty(i)) {
				if (i === 'style') {
					setStyle(elem, props[i]);
				} else if (i === 'innerHTML') {
					elem.innerHTML = props[i];
				} else {
					elem.setAttribute(i, props[i]);
				}
			}
		}
		return elem;
	}

// -------------------------------------------------------------

	// Find the offset position of a given element
	function getOffset(elem) {
		return {
			top:
				elem.offsetTop +
				parseFloat(getStyle(elem, 'paddingTop')) +
				parseFloat(getStyle(elem, 'borderTopWidth')),
			left:
				elem.offsetLeft +
				parseFloat(getStyle(elem, 'paddingLeft')) +
				parseFloat(getStyle(elem, 'borderLeftWidth'))
		};
	}

}(window, document));
<commit_msg>Fixes 'regexCache' is null or not an object<commit_after>
//
// HTML5 Placeholder Attribute Polyfill (Span)
//
// Author: James Brumond <james@jbrumond.me> (http://www.jbrumond.me)
//

(function(window, document, undefined) {
        // MSIE8 does not allow vars between functions...
	var regexCache = { };

	// Don't run the polyfill if it isn't needed
	if ('placeholder' in document.createElement('input')) {
		document.placeholderPolyfill = function() { /*  no-op */ };
		document.placeholderPolyfill.active = false;
		return;
	}

	// Fetch NodeLists of the needed element types
	var inputs = document.getElementsByTagName('input');
	var textareas = document.getElementsByTagName('textarea');

	//
	// Define the exposed polyfill methods for manual calls
	//
	document.placeholderPolyfill = function(elems) {
		elems = elems ? validElements(elems) : validElements(inputs, textareas);
		each(elems, polyfillElement);
	};

	// Expose whether or not the polyfill is in use (false means native support)
	document.placeholderPolyfill.active = true;

	// Run automatically
	document.placeholderPolyfill();

// -------------------------------------------------------------

	// Use mutation events for auto-updating
	if (document.addEventListener) {
		document.addEventListener('DOMAttrModified', document.placeholderPolyfill);
		document.addEventListener('DOMNodeInserted', document.placeholderPolyfill);
	}

	// Use onpropertychange for auto-updating
	else if (document.attachEvent && 'onpropertychange' in document) {
		document.attachEvent('onpropertychange', document.placeholderPolyfill);
	}

	// No event-based auto-update
	else {
		// pass
	}

// -------------------------------------------------------------

	// Add some basic default styling for placeholders
	firstStylesheet().addRule('.-placeholder', 'color: #888;', 0);

// -------------------------------------------------------------

	//
	// Polyfill a single, specific element
	//
	function polyfillElement(elem) {
		// If the element is already polyfilled, skip it
		if (elem.__placeholder) {
			return updatePlaceholder();
		}

		// Is there already a value in the field? If so, don't replace it with the placeholder
		var placeholder;
		drawPlaceholder();
		checkPlaceholder();

		// Define the events that cause these functions to be fired
		addEvent(elem, 'keyup', checkPlaceholder);
		addEvent(elem, 'keyDown', checkPlaceholder);
		addEvent(elem, 'blur', checkPlaceholder);
		addEvent(elem, 'focus', hidePlaceholder);
		addEvent(elem, 'click', hidePlaceholder);
		addEvent(placeholder, 'click', hidePlaceholder);
		addEvent(window, 'resize', redrawPlaceholder);

		// Use mutation events for auto-updating
		if (elem.addEventListener) {
			addEvent(elem, 'DOMAttrModified', updatePlaceholder);
		}

		// Use onpropertychange for auto-updating
		else if (elem.attachEvent && 'onpropertychange' in elem) {
			addEvent(elem, 'propertychange', updatePlaceholder);
		}

		// No event-based auto-update
		else {
			// pass
		}

		function drawPlaceholder() {
			placeholder = elem.__placeholder = createElement('span', {
				innerHTML: getPlaceholderFor(elem),
				style: {
					position: 'absolute',
					display: 'none',
					margin: '0',
					padding: '0',
					cursor: 'text'
				}
			});

			elem.parentNode.appendChild(placeholder);

			redrawPlaceholder();
		}

		function redrawPlaceholder() {
			// Update some basic styles to match that of the input
			var zIndex = getStyle(elem, 'zIndex');
			zIndex = (zIndex === 'auto') ? 99999 : zIndex;
			setStyle(placeholder, {
				zIndex: (zIndex || 99999) + 1,
				backgroundColor: 'transparent'
			});

			// Fix an old IE bug
			if (elem.offsetParent && getStyle(elem.offsetParent, 'position') === 'static') {
				elem.offsetParent.style.position = 'relative';
			}

			// Reposition the span to make sure it stays in place
			var offset = getOffset(elem);
			setStyle(placeholder, {
				top: offset.top + 'px',
				left: offset.left + 'px'
			});
		}

		function updatePlaceholder() {
			placeholder.innerHTML = getPlaceholderFor(elem);
			redrawPlaceholder();
		}

		function checkPlaceholder(event) {
			if (elem.value) {
                                var nofocus = true;
                                if (event && event.type ){
                                      nofocus = event.type === 'blur';
                                }
                                hidePlaceholder(event, nofocus);
			} else {
				showPlaceholder();
			}
		}

		function showPlaceholder() {
			placeholder.style.display = 'block';
			addClass(placeholder, '-placeholder');
			addClass(elem, '-placeholder-input');
		}

		function hidePlaceholder(event, suppressFocus) {
			placeholder.style.display = 'none';
			removeClass(placeholder, '-placeholder');
			removeClass(elem, '-placeholder-input');
			if (! suppressFocus) {
				elem.focus();
			}
		}
	}

// -------------------------------------------------------------

	//
	// Build a list of valid (can have a placeholder) elements from the given parameters
	//
	function validElements() {
		var result = [ ];

		each(arguments, function(arg) {
			if (typeof arg.length !== 'number') {
				arg = [ arg ];
			}

			result.push.apply(result, filter(arg, isValidElement));
		});

		return result;
	}

	//
	// Check if a given element supports the placeholder attribute
	//
	function isValidElement(elem) {
		var tag = (elem.nodeName || '').toLowerCase();
		return (tag === 'textarea' || (tag === 'input' && (elem.type === 'text' || elem.type === 'password')));
	}

// -------------------------------------------------------------

	function addEvent(obj, event, func) {
		if (obj.addEventListener) {
			obj.addEventListener(event, func, false);
		} else if (obj.attachEvent) {
			obj.attachEvent('on' + event, func);
		}
	}

	function removeEvent(obj, event, func) {
		if (obj.removeEventListener) {
			obj.removeEventListener(event, func, false);
		} else if (obj.detachEvent) {
			obj.detachEvent('on' + event, func);
		}
	}

// -------------------------------------------------------------

	function each(arr, func) {
		if (arr.forEach) {
			return arr.forEach(func);
		}

		for (var i = 0, c = arr.length; i < c; i++) {
			func.call(null, arr[i], i, arr);
		}
	}

	function filter(arr, func) {
		if (arr.filter) {
			return arr.filter(func);
		}

		var result = [ ];
		for (var i = 0, c = arr.length; i < c; i++) {
			if (func.call(null, arr[i], i, arr)) {
				result.push(arr[i]);
			}
		}

		return result;
	}

// -------------------------------------------------------------

	function classNameRegex(cn) {
		if (! regexCache[cn]) {
			regexCache[cn] = new RegExp('(^|\\s)+' + cn + '(\\s|$)+', 'g');
		}

		return regexCache[cn];
	}

	function addClass(elem, cn) {
		elem.className += ' ' + cn;
	}

	function removeClass(elem, cn) {
		elem.className = elem.className.replace(classNameRegex(cn), ' ');
	}

// -------------------------------------------------------------

	// Internet Explorer 10 in IE7 mode was giving me the wierest error
	// where e.getAttribute('placeholder') !== e.attributes.placeholder.nodeValue
	function getPlaceholderFor(elem) {
		return elem.getAttribute('placeholder') || (elem.attributes.placeholder && elem.attributes.placeholder.nodeValue) || '';
	}

// -------------------------------------------------------------

	// Get the first stylesheet in the document, or, if there are none, create/inject
	// one and return it.
	function firstStylesheet() {
		var sheet = document.styleSheets && document.styleSheets[0];
		if (! sheet) {
			var head = document.head || document.getElementsByTagName('head')[0];
			var style = document.createElement('style');
			style.appendChild(document.createTextNode(''));
			document.head.appendChild(style);
			sheet = style.sheet;
		}
		return sheet;
	}

// -------------------------------------------------------------

	// Used internally in getStyle()
	function getStyleValue(elem, prop) {
		if (elem.currentStyle) {
			return elem.currentStyle[prop];
		} else if (window.getComputedStyle) {
			return document.defaultView.getComputedStyle(elem, null)[prop];
		} else if (prop in elem.style) {
			return elem.style[prop];
		}
		return null;
	}

	// Get a style property from an element
	function getStyle(elem, prop) {
		var style;
		if (elem.parentNode == null) {
			elem = document.body.appendChild(elem);
			style = getStyleValue(elem, prop);
			elem = document.body.removeChild(elem);
		} else {
			style = getStyleValue(elem, prop);
		}
		return style;
	}

	// Set style properties to an element
	function setStyle(elem, props) {
		for (var i in props) {
			if (props.hasOwnProperty(i)) {
				elem.style[i] = props[i];
			}
		}
	}

// -------------------------------------------------------------

	// Create an element
	function createElement(tag, props) {
		var elem = document.createElement(tag);
		for (var i in props) {
			if (props.hasOwnProperty(i)) {
				if (i === 'style') {
					setStyle(elem, props[i]);
				} else if (i === 'innerHTML') {
					elem.innerHTML = props[i];
				} else {
					elem.setAttribute(i, props[i]);
				}
			}
		}
		return elem;
	}

// -------------------------------------------------------------

	// Find the offset position of a given element
	function getOffset(elem) {
		return {
			top:
				elem.offsetTop +
				parseFloat(getStyle(elem, 'paddingTop')) +
				parseFloat(getStyle(elem, 'borderTopWidth')),
			left:
				elem.offsetLeft +
				parseFloat(getStyle(elem, 'paddingLeft')) +
				parseFloat(getStyle(elem, 'borderLeftWidth'))
		};
	}

}(window, document));
<|endoftext|>


<commit_before>(function (global, factory) {
  if (typeof module === "object" && typeof module.exports === "object") {
    // CMD
    // all dependencies need to passed as parameters manually,
    // will not require here.
    module.exports = factory;
  } else if (typeof define === 'function' && define.amd) {
    // AMD. Register as parrot
    // TODO how to define the jquery plugin here?
    define('parrot', ['jquery', 'jsface'], factory);
  } else {
    // in browser, global is window.
    // all dependencies were loaded already.
    // bootstrap and jquery's plugin are all attached to jquery,
    // expose $sk and all components to window.
    factory(global, jQuery, jsface);
  }
}(typeof window !== "undefined" ? window : this, function (window, jQuery, jsface, DO_NOT_EXPOSE_SK_TO_GLOBAL) {
  var _sk = window.$sk;
  var $sk = {};
  window.$sk = $sk;

  $sk.noConflict = function () {
    window.$sk = _sk;
    return $sk;
  };

  // insert all source code here
  // sk body here
  $sk.isInValid = function (obj) {
    if (obj === undefined || obj == null || isNaN(obj) ) {
      return true;
    } else {
      return false;
    }
  };

  // reset to old $sk
  if (typeof DO_NOT_EXPOSE_SK_TO_GLOBAL != 'undefined' && DO_NOT_EXPOSE_SK_TO_GLOBAL === true) {
    window.$sk = _sk;
  }
  return $sk;
}));
<commit_msg>Update sk.js<commit_after>(function (global, factory) {
  if (typeof module === "object" && typeof module.exports === "object") {
    // CMD
    // all dependencies need to passed as parameters manually,
    // will not require here.
    module.exports = factory;
  } else if (typeof define === 'function' && define.amd) {
    // AMD. Register as sk
    // TODO how to define the jquery plugin here?
    define('sk', ['jquery', 'jsface'], factory);
  } else {
    // in browser, global is window.
    // all dependencies were loaded already.
    // bootstrap and jquery's plugin are all attached to jquery,
    // expose $sk and all components to window.
    factory(global, jQuery, jsface);
  }
}(typeof window !== "undefined" ? window : this, function (window, jQuery, jsface, DO_NOT_EXPOSE_SK_TO_GLOBAL) {
  var _sk = window.$sk;
  var $sk = {};
  window.$sk = $sk;

  $sk.noConflict = function () {
    window.$sk = _sk;
    return $sk;
  };

  // insert all source code here
  // sk body here
  $sk.isInValid = function (obj) {
    if (obj === undefined || obj == null || isNaN(obj) ) {
      return true;
    } else {
      return false;
    }
  };

  // reset to old $sk
  if (typeof DO_NOT_EXPOSE_SK_TO_GLOBAL != 'undefined' && DO_NOT_EXPOSE_SK_TO_GLOBAL === true) {
    window.$sk = _sk;
  }
  return $sk;
}));
<|endoftext|>


<commit_before>/* @flow */

const k = (x: number) : number => x + 5

k('fd')
<commit_msg>Linting on flow works, removed test file<commit_after><|endoftext|>


<commit_before>import QUnit from 'steal-qunit';
import * as MultiSelect from './multi-select';
import $ from 'jquery';

var vm = new MultiSelect.VM({
  list: ['Testing 123']
});

QUnit.module('Initialize multi-select');

QUnit.test('getItemFromOption', function(assert) {
  var option = $('<option value="one">One</option>'),
    item = MultiSelect.getItemFromOption(option[0]);

  assert.deepEqual(item, {value: 'one', text: 'One', isSelected: false}, 'Should create item from OPTION');
});

QUnit.test('makeArr', function(assert) {
  assert.ok(true, 'The amounts match');
  var arrayLike = {
    0: 0,
    1: 1,
    length: 2
  };
  var array = MultiSelect.makeArr(arrayLike);
  assert.ok(array instanceof Array, 'Should return type array');
  assert.deepEqual(array, [0,1], 'Should have correct data');
});<commit_msg>test: added a test for getItems<commit_after>import QUnit from 'steal-qunit';
import * as MultiSelect from './multi-select';
import $ from 'jquery';

var vm = new MultiSelect.VM({
  list: ['Testing 123']
});

QUnit.module('Initialize multi-select');

QUnit.test('getItemFromOption', function(assert) {
  var option = $('<option value="one">One</option>'),
    item = MultiSelect.getItemFromOption(option[0]);

  assert.deepEqual(item, {value: 'one', text: 'One', isSelected: false}, 'Should create item from OPTION');
});

QUnit.test('getItems', function(assert) {
  var nodeList = $('
<option value="1">One</option><option value="2" selected>Two</option>123456
')[0].children,
    items = MultiSelect.getItems(nodeList);

  assert.deepEqual(items, [{value: '1', text: 'One', isSelected: false},{value: '2', text: 'Two', isSelected: true}], 'Should create items from a node list');
});

QUnit.test('makeArr', function(assert) {
  assert.ok(true, 'The amounts match');
  var arrayLike = {
    0: 0,
    1: 1,
    length: 2
  };
  var array = MultiSelect.makeArr(arrayLike);
  assert.ok(array instanceof Array, 'Should return type array');
  assert.deepEqual(array, [0,1], 'Should have correct data');
});<|endoftext|>