Commits

mic  committed 0110ca2

move version2 to master take 2

  • Participants
  • Parent commits e9acec1

Comments (0)

Files changed (6)

File libs/pure.js

+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+
+	PURE Unobtrusive Rendering Engine for HTML
+
+	Licensed under the MIT licenses.
+	More information at: http://www.opensource.org
+
+	Copyright (c) 2009 Michael Cvilic - BeeBole.com
+
+	Thanks to Rog Peppe for the functional JS jump
+	revision: 2.23
+
+* * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $p, pure = $p = function(){
+	var sel = arguments[0], 
+		ctxt = false;
+
+	if(typeof sel === 'string'){
+		ctxt = arguments[1] || false;
+	}
+	return $p.core(sel, ctxt);
+};
+
+$p.core = function(sel, ctxt, plugins){
+	//get an instance of the plugins
+	var plugins = getPlugins(),
+		templates = [];
+
+	//search for the template node(s)
+	if(typeof sel === 'string'){
+		templates = plugins.find(ctxt || document, sel);
+		templates.length === 0 && error('The template "' + sel + '" was not found');
+	}else if(typeof sel === 'object'){
+		templates = [sel];
+	}
+	
+	for(var i = 0, ii = templates.length; i < ii; i++){
+		plugins[i] = templates[i];
+	}
+	plugins.length = ii;
+
+	// set the signature string that will be replaced at render time
+	var Sig = '_s' + Math.floor( Math.random() * 1000000 ) + '_',
+		// another signature to prepend to attributes and avoid checks: style, height, on[events]...
+		attPfx = '_a' + Math.floor( Math.random() * 1000000 ) + '_',
+		// rx to parse selectors, e.g. "+tr.foo[class]"
+		selRx = /^(\+)?([^\@\+]+)?\@?([^\+]+)?(\+)?$/,
+		// set automatically attributes for some tags
+		autoAttr = {
+			IMG:'src',
+			INPUT:'value'
+		};
+	
+	return plugins;
+
+
+	/* * * * * * * * * * * * * * * * * * * * * * * * * *
+		core functions
+	 * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+	// error utility
+	function error(e){
+		alert(e);
+		if(typeof console !== 'undefined'){
+			console.log(e);
+			debugger;
+		}
+		throw('pure error: ' + e);
+	}
+	
+	//return a new instance of plugins
+	function getPlugins(){
+		var plugins = $p.plugins,
+			f = function(){};
+		f.prototype = plugins;
+
+		// do not overwrite functions if external definition
+		f.prototype.compile    = plugins.compile || compile;
+		f.prototype.render     = plugins.render || render;
+		f.prototype.autoRender = plugins.autoRender || autoRender;
+		f.prototype.find       = plugins.find || find;
+		
+		// give the compiler and the error handling to the plugin context
+		f.prototype._compiler  = compiler;
+		f.prototype._error     = error;
+ 
+		return new f();
+	}
+	
+	// returns the outer HTML of a node
+	function outerHTML(node){
+		// if IE take the internal method otherwise build one
+		return node.outerHTML || (
+			function(n){
+        		var div = document.createElement('div'), h;
+	        	div.appendChild( n.cloneNode(true) );
+				h = div.innerHTML;
+				div = null;
+				return h;
+			})(node);
+	}
+
+	// check if the argument is an array
+	function isArray(o){
+		return Object.prototype.toString.call( o ) === "[object Array]";
+	}
+	
+	// returns the string generator function
+	function wrapquote(qfn, f){
+		return function(ctxt){
+			return qfn('' + f(ctxt));
+		};
+	}
+
+	// convert a JSON HTML structure to a dom node and returns the leaf
+	function domify(ns, pa){
+		pa = pa || document.createDocumentFragment();
+		var nn, leaf;
+		for(var n in ns){
+			nn = document.createElement(n);
+			pa.appendChild(nn);
+			if(typeof ns[n] === 'object'){
+				leaf = domify(ns[n], nn);
+			}else{
+				leaf = document.createElement(ns[n]);
+				nn.appendChild(leaf);
+			}
+		}
+		return leaf;
+	};
+	
+		// default find using querySelector when available on the browser
+	function find(n, sel){
+		if(typeof n === 'string'){
+			sel = n;
+			n = false;
+		}
+		if(typeof document.querySelectorAll !== 'undefined'){
+			return (n||document).querySelectorAll( sel );
+		}else{
+			error('You can test PURE standalone with: iPhone, FF3.5+, Safari4+ and IE8+\n\nTo run PURE on your browser, you need a JS library/framework with a CSS selector engine');
+		}
+	}
+	
+	// create a function that concatenates constant string
+	// sections (given in parts) and the results of called
+	// functions to fill in the gaps between parts (fns).
+	// fns[n] fills in the gap between parts[n-1] and parts[n];
+	// fns[0] is unused.
+	// this is the inner template evaluation loop.
+	function concatenator(parts, fns){
+		return function(ctxt){
+			var strs = [ parts[ 0 ] ],
+				n = parts.length,
+				fnVal, pVal, attLine, pos;
+
+			for(var i = 1; i < n; i++){
+				fnVal = fns[i]( ctxt );
+				pVal = parts[i];
+				
+				// if the value is empty and attribute, remove it
+				if(fnVal === ''){
+					attLine = strs[ strs.length - 1 ];
+					if( ( pos = attLine.search( /[\w]+=\"?$/ ) ) > -1){
+						strs[ strs.length - 1 ] = attLine.substring( 0, pos );
+						pVal = pVal.substr( 1 );
+					}
+				}
+				
+				strs[ strs.length ] = fnVal;
+				strs[ strs.length ] = pVal;
+			}
+			return strs.join('');
+		};
+	}
+
+	// parse and check the loop directive
+	function parseloopspec(p){
+		var m = p.match( /^(\w+)\s*<-\s*(\S+)?$/ );
+		if(m === null){
+			error('bad loop spec: "' + p + '"');
+		}
+		if(m[1] === 'item'){
+			error('"item<-..." is a reserved word for the current running iteration.\n\nPlease choose another name for your loop.');
+		}
+		if( !m[2] ){ //undefined or space(IE) 
+			m[2] = function(ctxt){return ctxt.data;};
+		}
+		return {name: m[1], sel: m[2]};
+	}
+
+	// parse a data selector and return a function that
+	// can traverse the data accordingly, given a context.
+	function dataselectfn(sel){
+		if(typeof(sel) === 'function'){
+			return sel;
+		}
+		//check for a valid js variable name with hyphen(for properties only) and $
+		var m = sel.match(/^[a-zA-Z$_][\w$]*(\.[\w$-]*[^\.])*$/);
+		if(m === null){
+			var found = false, s = sel, parts = [], pfns = [], i = 0, retStr;
+			// check if literal
+			if(/\'|\"/.test( s.charAt(0) )){
+				if(/\'|\"/.test( s.charAt(s.length-1) )){
+					retStr = s.substring(1, s.length-1);
+					return function(){ return retStr; };
+				}
+			}else{
+				// check if literal + #{var}
+				while((m = s.match(/#\{([^{}]+)\}/)) !== null){
+					found = true;
+					parts[i++] = s.slice(0, m.index);
+					pfns[i] = dataselectfn(m[1]);
+					s = s.slice(m.index + m[0].length, s.length);
+				}
+			}
+			if(!found){
+				error('bad data selector syntax: ' + sel);
+			}
+			parts[i] = s;
+			return concatenator(parts, pfns);
+		}
+		m = sel.split('.');
+		return function(ctxt){
+			var data = ctxt.data;
+			if(!data){
+				return '';
+			}
+			var	v = ctxt[m[0]],
+				i = 0;
+			if(v){
+				data = v.item;
+				i += 1;
+			}
+			var n = m.length;
+			for(; i < n; i++){
+				if(!data){break;}
+				data = data[m[i]];
+			}
+			return (!data && data !== 0) ? '':data;
+		};
+	}
+
+	// wrap in an object the target node/attr and their properties
+	function gettarget(dom, sel, isloop){
+		var osel, prepend, selector, attr, append, target = [];
+		if( typeof sel === 'string' ){
+			osel = sel;
+			var m = sel.match(selRx);
+			if( !m ){
+				error( 'bad selector syntax: ' + sel );
+			}
+			
+			prepend = m[1];
+			selector = m[2];
+			attr = m[3];
+			append = m[4];
+			
+			if(selector === '.' || ( !selector && attr ) ){
+				target[0] = dom;
+			}else{
+				target = plugins.find(dom, selector);
+			}
+			if(!target || target.length === 0){
+				return error('The node "' + sel + '" was not found in the template');
+			}
+		}else{
+			// autoRender node
+			prepend = sel.prepend;
+			attr = sel.attr;
+			append = sel.append;
+			target = [dom];
+		}
+		
+		if( prepend || append ){
+			if( prepend && append ){
+				error('append/prepend cannot take place at the same time');
+			}else if( isloop ){
+				error('no append/prepend/replace modifiers allowed for loop target');
+			}else if( append && isloop ){
+				error('cannot append with loop (sel: ' + osel + ')');
+			}
+		}
+		var setstr, getstr, quotefn, isStyle, isClass, attName;
+		if(attr){
+			isStyle = (/^style$/i).test(attr);
+			isClass = (/^class$/i).test(attr);
+			attName = isClass ? 'className' : attr;
+			setstr = function(node, s) {
+				node.setAttribute(attPfx + attr, s);
+				if (attName in node && !isStyle) {
+					node[attName] = '';
+				}
+				if (node.nodeType === 1) {
+					node.removeAttribute(attr);
+					isClass && node.removeAttribute(attName);
+				}
+			};
+			if(isStyle) {
+				getstr = function(node){ return node.style.cssText; };
+			}else if(isClass) {
+				getstr = function(node){ return node.className;	};
+			}else{
+				getstr = function(node){ return node.getAttribute(attr); };
+			}
+			if (isStyle || isClass) {//IE no quotes special care
+				quotefn = function(s){ return s.replace(/\"/g, '&quot;'); };
+			}else {
+				quotefn = function(s){ return s.replace(/\"/g, '&quot;').replace(/\s/g, '&nbsp;'); };
+			}
+		}else{
+			if(isloop){
+				setstr = function(node, s){
+					// we can have a null parent node
+					// if we get overlapping targets.
+					var pn = node.parentNode;
+					if(pn){
+						//replace node with s
+						var t = document.createTextNode(s);
+						node.parentNode.insertBefore(t, node.nextSibling);
+						node.parentNode.removeChild(node);
+					}
+				};
+			}else{
+				getstr = function(node){ return node.innerHTML; };
+				setstr = function(node, s){ node.innerHTML = s; };
+			}
+			quotefn = function(s){ return s; };
+		}
+		var setfn;
+		if(prepend){
+			setfn = function(node, s){ setstr( node, s + getstr( node ) );};
+		}else if(append){
+			setfn = function(node, s){ setstr( node, getstr( node ) + s );};
+		}else{
+			setfn = function(node, s){ setstr( node, s );};
+		}
+		return {attr: attr, nodes: target, set: setfn, sel: osel, quotefn: quotefn};
+	}
+
+	function setsig(target, n){
+		var sig = Sig + n + ':';
+		for(var i = 0; i < target.nodes.length; i++){
+			// could check for overlapping targets here.
+			target.set( target.nodes[i], sig );
+		}
+	}
+
+	// read de loop data, and pass it to the inner rendering function
+	function loopfn(name, dselect, inner){
+		return function(ctxt){
+			var a = dselect(ctxt),
+				old = ctxt[name],
+				temp = { items : a },
+				strs = [],
+				buildArg = function(idx){
+					ctxt.items = a;
+					ctxt.pos = temp.pos = idx;
+					ctxt.item = temp.item = a[ idx ];
+					strs.push( inner( ctxt ) );
+				};
+			ctxt[name] = temp;
+			if( isArray(a) ){
+				//loop on array
+				for(var i = 0, ii = a.length || 0; i < ii; i++){  
+					buildArg(i); 
+				}
+			}else{
+				//loop on collections
+				for(var prop in a){
+					a.hasOwnProperty( prop ) && buildArg(prop); 
+				}
+			}
+			typeof old !== 'undefined' ? ctxt[name] = old : delete ctxt[name];
+			return strs.join('');
+		};
+	}
+	// generate the template for a loop node
+	function loopgen(dom, sel, loop, fns){
+		var already = false;
+		var p;
+		for(var i in loop){
+			if(loop.hasOwnProperty(i)){
+				if(already){
+					error('cannot have more than one loop on a target');
+				}
+				p = i;
+				already = true;
+			}
+		}
+		if(!p){
+			error('no loop spec');
+		}
+		var dsel = loop[p];
+		// if it's a simple data selector then we default to contents, not replacement.
+		if(typeof(dsel) === 'string' || typeof(dsel) === 'function'){
+			loop = {};
+			loop[p] = {root: dsel};
+			return loopgen(dom, sel, loop, fns);
+		}
+		var spec = parseloopspec(p),
+			itersel = dataselectfn(spec.sel),
+			target = gettarget(dom, sel, true),
+			nodes = target.nodes;
+			
+		for(i = 0; i < nodes.length; i++){
+			// could check for overlapping loop targets here by checking that
+			// root is still ancestor of node.
+			var node = nodes[i],
+				inner = compiler(node, dsel);
+			fns[fns.length] = wrapquote(target.quotefn, loopfn(spec.name, itersel, inner));
+			target.nodes = [node];		// N.B. side effect on target.
+			setsig(target, fns.length - 1);
+		}
+	}
+	
+	function getAutoNodes(n, data){
+		var ns = n.getElementsByTagName('*'),
+			an = [],
+			openLoops = {a:[],l:{}},
+			cspec,
+			isNodeValue,
+			i, ii, j, jj, ni, cs, cj;
+		//for each node found in the template
+		for(i = -1, ii = ns.length; i < ii; i++){
+			ni = i > -1 ?ns[i]:n;
+			if(ni.nodeType === 1 && ni.className !== ''){
+				//when a className is found
+				cs = ni.className.split(' ');
+				// for each className 
+				for(j = 0, jj=cs.length;j<jj;j++){
+					cj = cs[j];
+					// check if it is related to a context property
+					cspec = checkClass(cj, ni.tagName);
+					// if so, store the node, plus the type of data
+					if(cspec !== false){
+						isNodeValue = (/nodevalue/i).test(cspec.attr);
+						if(cspec.sel.indexOf('@') > -1 || isNodeValue){
+							ni.className = ni.className.replace('@'+cspec.attr, '');
+							if(isNodeValue){
+								cspec.attr = false;
+							} 
+						}
+						an.push({n:ni, cspec:cspec});
+					}
+				}
+			}
+		}
+		return an;
+		
+		function checkClass(c, tagName){
+			// read the class
+			var ca = c.match(selRx),
+				attr = ca[3] || autoAttr[tagName],
+				cspec = {prepend:!!ca[1], prop:ca[2], attr:attr, append:!!ca[4], sel:c},
+				i, ii, loopi, loopil, val;
+			// check in existing open loops
+			for(i = openLoops.a.length-1; i >= 0; i--){
+				loopi = openLoops.a[i];
+				loopil = loopi.l[0];
+				val = loopil && loopil[cspec.prop];
+				if(typeof val !== 'undefined'){
+					cspec.prop = loopi.p + '.' + cspec.prop;
+					if(openLoops.l[cspec.prop] === true){
+						val = val[0];
+					}
+					break;
+				}
+			}
+			// not found check first level of data
+			if(typeof val === 'undefined'){
+				val = isArray(data) ? data[0][cspec.prop] : data[cspec.prop];
+				// nothing found return
+				if(typeof val === 'undefined'){
+					return false;
+				}
+			}
+			// set the spec for autoNode
+			if(isArray(val)){
+				openLoops.a.push( {l:val, p:cspec.prop} );
+				openLoops.l[cspec.prop] = true;
+				cspec.t = 'loop';
+			}else{
+				cspec.t = 'str';
+			}
+			return cspec;
+		}
+	}
+
+	// returns a function that, given a context argument,
+	// will render the template defined by dom and directive.
+	function compiler(dom, directive, data, ans){
+		var fns = [];
+		// autoRendering nodes parsing -> auto-nodes
+		ans = ans || data && getAutoNodes(dom, data);
+		if(data){
+			var j, jj, cspec, n, target, nodes, itersel, node, inner;
+			// for each auto-nodes
+			while(ans.length > 0){
+				cspec = ans[0].cspec;
+				n = ans[0].n;
+				ans.splice(0, 1);
+				if(cspec.t === 'str'){
+					// if the target is a value
+					target = gettarget(n, cspec, false);
+					setsig(target, fns.length);
+					fns[fns.length] = wrapquote(target.quotefn, dataselectfn(cspec.prop));
+				}else{
+					// if the target is a loop
+					itersel = dataselectfn(cspec.sel);
+					target = gettarget(n, cspec, true);
+					nodes = target.nodes;
+					for(j = 0, jj = nodes.length; j < jj; j++){
+						node = nodes[j];
+						inner = compiler(node, false, data, ans);
+						fns[fns.length] = wrapquote(target.quotefn, loopfn(cspec.sel, itersel, inner));
+						target.nodes = [node];
+						setsig(target, fns.length - 1);
+					}
+				}
+			}
+		}
+		// read directives
+		var target, dsel;
+		for(var sel in directive){
+			if(directive.hasOwnProperty(sel)){
+				dsel = directive[sel];
+				if(typeof(dsel) === 'function' || typeof(dsel) === 'string'){
+					// set the value for the node/attr
+					target = gettarget(dom, sel, false);
+					setsig(target, fns.length);
+					fns[fns.length] = wrapquote(target.quotefn, dataselectfn(dsel));
+				}else{
+					// loop on node
+					loopgen(dom, sel, dsel, fns);
+				}
+			}
+		}
+        // convert node to a string 
+        var h = outerHTML(dom), pfns = [];
+		// IE adds an unremovable "selected, value" attribute
+		// hard replace while waiting for a better solution
+        if (dom.tagName === 'OPTION' && h.indexOf(attPfx + 'selected') > 0) {
+            h = h.replace(/\sselected\s/, ' ');
+        } else if (dom.tagName === 'INPUT' && h.indexOf(attPfx + 'value') > 0) {
+            h = h.replace(/\svalue=("|')('|")\s/, ' ');
+        }
+		
+        // remove attribute prefix
+        h = h.split(attPfx).join('');
+
+		// slice the html string at "Sig"
+		var parts = h.split( Sig ), p;
+		// for each slice add the return string of 
+		for(var i = 1; i < parts.length; i++){
+			p = parts[i];
+			// part is of the form "fn-number:..." as placed there by setsig.
+			pfns[i] = fns[ parseInt(p, 10) ];
+			parts[i] = p.substring( p.indexOf(':') + 1 );
+		}
+		return concatenator(parts, pfns);
+	}
+	// compile the template with directive
+	// if a context is passed, the autoRendering is triggered automatically
+	// return a function waiting the data as argument
+	function compile(directive, ctxt, template){
+		var rfn = compiler( ( template || this[0] ).cloneNode(true), directive, ctxt);
+		return function(data, context){
+			context = context || data;
+			return rfn({data: data, context:context});
+		};
+	}
+	//compile with the directive as argument
+	// run the template function on the context argument
+	// return an HTML string 
+	// should replace the template and return this
+	function render(ctxt, directive){
+		var fn = typeof directive === 'function' ? directive : plugins.compile( directive, false, this[0] );
+		for(var i = 0, ii = this.length; i < ii; i++){
+			this[i] = replaceWith( this[i], fn( ctxt, false ));
+		}
+		context = null;
+		return this;
+	}
+
+	// compile the template with autoRender
+	// run the template function on the context argument
+	// return an HTML string 
+	function autoRender(ctxt, directive){
+		var fn = plugins.compile( directive, ctxt, this[0] );
+		for(var i = 0, ii = this.length; i < ii; i++){
+			this[i] = replaceWith( this[i], fn( ctxt, false));
+		}
+		context = null;
+		return this;
+	}
+	
+	function replaceWith(elm, html){
+		var div = document.createElement('DIV'),
+			tagName = elm.tagName.toLowerCase(),
+			ne, pa;
+		if((/td|tr|th/).test(tagName)){
+			var parents = {	tr:{table:'tbody'}, td:{table:{tbody:'tr'}}, th:{table:{thead:'tr'}} };
+			pa = domify( parents[ tagName ] );
+		}else if( ( /tbody|thead|tfoot/ ).test( tagName )){
+			pa = document.createElement('table');
+		}else{
+			pa = document.createElement('span');
+		}
+		var ep = elm.parentNode;
+		// avoid IE mem leak
+		ep.insertBefore(pa, elm);
+		ep.removeChild(elm);
+		pa.innerHTML = html;
+		ne = pa.firstChild;
+		ep.insertBefore(ne, pa);
+		ep.removeChild(pa);
+		elm = ne;
+
+		pa = ne = ep = null;
+		return elm;
+	}
+};
+
+$p.plugins = {};
+
+$p.libs = {
+	dojo:function(){
+		if(typeof document.querySelector === 'undefined'){
+			$p.plugins.find = function(n, sel){
+				return dojo.query(sel, n);
+			};
+		}
+	},
+	domassistant:function(){
+		if(typeof document.querySelector === 'undefined'){
+			$p.plugins.find = function(n, sel){
+				return $(n).cssSelect(sel);
+			};
+		}
+		DOMAssistant.attach({ 
+			publicMethods : [ 'compile', 'render', 'autoRender'],
+			compile:function(directive, ctxt){ return $p(this).compile(directive, ctxt); },
+			render:function(ctxt, directive){ return $( $p(this).render(ctxt, directive) )[0]; },
+			autoRender:function(ctxt, directive){ return $( $p(this).autoRender(ctxt, directive) )[0]; }
+		});
+	},
+	jquery:function(){
+		if(typeof document.querySelector === 'undefined'){
+			$p.plugins.find = function(n, sel){
+				return $(n).find(sel);
+			};
+		}
+		jQuery.fn.extend({
+			compile:function(directive, ctxt){ return $p(this[0]).compile(directive, ctxt); },
+			render:function(ctxt, directive){ return jQuery( $p( this[0] ).render( ctxt, directive ) ); },
+			autoRender:function(ctxt, directive){ return jQuery( $p( this[0] ).autoRender( ctxt, directive ) ); }
+		});
+	},
+	mootools:function(){
+		if(typeof document.querySelector === 'undefined'){
+			$p.plugins.find = function(n, sel){
+				return $(n).getElements(sel);
+			};
+		}
+		Element.implement({
+			compile:function(directive, ctxt){ return $p(this).compile(directive, ctxt); },
+			render:function(ctxt, directive){ return $p(this).render(ctxt, directive); },
+			autoRender:function(ctxt, directive){ return $p(this).autoRender(ctxt, directive); }
+		});
+	},
+	prototype:function(){
+		if(typeof document.querySelector === 'undefined'){
+			$p.plugins.find = function(n, sel){
+				n = n === document ? n.body : n;
+				return typeof n === 'string' ? $$(n) : $(n).select(sel);
+			};
+		}
+		Element.addMethods({
+			compile:function(element, directive, ctxt){ return $p(element).compile(directive, ctxt); }, 
+			render:function(element, ctxt, directive){ return $p(element).render(ctxt, directive); }, 
+			autoRender:function(element, ctxt, directive){ return $p(element).autoRender(ctxt, directive); }
+		});
+	},
+	sizzle:function(){
+		if(typeof document.querySelector === 'undefined'){
+			$p.plugins.find = function(n, sel){
+				return Sizzle(sel, n);
+			};
+		}
+	},
+	sly:function(){
+		if(typeof document.querySelector === 'undefined'){  
+			$p.plugins.find = function(n, sel){
+				return Sly(sel, n);
+			};
+		}
+	}
+};
+
+// get lib specifics if available
+(function(){
+	var libkey = 
+		typeof dojo         !== 'undefined' && 'dojo' || 
+		typeof DOMAssistant !== 'undefined' && 'domassistant' ||
+		typeof jQuery       !== 'undefined' && 'jquery' || 
+		typeof MooTools     !== 'undefined' && 'mootools' ||
+		typeof Prototype    !== 'undefined' && 'prototype' || 
+		typeof Sizzle       !== 'undefined' && 'sizzle' ||
+		typeof Sly          !== 'undefined' && 'sly';
+		
+	libkey && $p.libs[libkey]();
+})();

File libs/pure_packed.js

+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+
+    PURE Unobtrusive Rendering Engine for HTML
+
+    Licensed under the MIT licenses.
+    More information at: http://www.opensource.org
+
+    Copyright (c) 2009 Michael Cvilic - BeeBole.com
+
+	Thanks to Rog Peppe for the functional JS jump
+    revision: 2.23
+
+* * * * * * * * * * * * * * * * * * * * * * * * * */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('9 $p,2p=$p=6(){9 a=2q[0],1V=I;7(x a===\'16\'){1V=2q[1]||I}8 $p.2r(a,1V)};$p.2r=6(l,q,r){9 r=2s(),1c=[];7(x l===\'16\'){1c=r.J(q||F,l);1c.y===0&&G(\'2t 2u "\'+l+\'" 2v 2w 2x\')}A 7(x l===\'1W\'){1c=[l]}B(9 i=0,M=1c.y;i<M;i++){r[i]=1c[i]}r.y=M;9 u=\'3f\'+1C.2y(1C.2z()*2A)+\'1X\',1m=\'3g\'+1C.2y(1C.2z()*2A)+\'1X\',1Y=/^(\\+)?([^\\@\\+]+)?\\@?([^\\+]+)?(\\+)?$/,2B={3h:\'3i\',2C:\'2D\'};8 r;6 G(e){3j(e);7(x 2E!==\'C\'){2E.3k(e);3l}3m(\'2p G: \'+e);}6 2s(){9 a=$p.X,f=6(){};f.Q=a;f.Q.H=a.H||H;f.Q.N=a.N||N;f.Q.O=a.O||O;f.Q.J=a.J||J;f.Q.3n=1n;f.Q.3o=G;8 3p f()}6 1Z(b){8 b.1Z||(6(n){9 a=F.1d(\'3q\'),h;a.20(n.2F(11));h=a.1D;a=17;8 h})(b)}6 1E(o){8 3r.Q.3s.3t(o)==="[1W 3u]"}6 1o(b,f){8 6(a){8 b(\'\'+f(a))}}6 21(a,b){b=b||F.3v();9 c,1p;B(9 n 1e a){c=F.1d(n);b.20(c);7(x a[n]===\'1W\'){1p=21(a[n],c)}A{1p=F.1d(a[n]);c.20(1p)}}8 1p};6 J(n,a){7(x n===\'16\'){a=n;n=I}7(x F.2G!==\'C\'){8(n||F).2G(a)}A{G(\'3w 3x 12 2H 3y 22: 3z, 3A.5+, 3B+ 3C 3D+\\n\\3E 3F 2H 2I 2J 3G, 3H 3I a 3J 3K/3L 22 a 3M 13 3N\')}}6 23(c,d){8 6(a){9 b=[c[0]],n=c.y,1F,1q,1G,1r;B(9 i=1;i<n;i++){1F=d[i](a);1q=c[i];7(1F===\'\'){1G=b[b.y-1];7((1r=1G.3O(/[\\w]+=\\"?$/))>-1){b[b.y-1]=1G.24(0,1r);1q=1q.3P(1)}}b[b.y]=1F;b[b.y]=1q}8 b.25(\'\')}}6 2K(p){9 m=p.1s(/^(\\w+)\\s*<-\\s*(\\S+)?$/);7(m===17){G(\'26 18 2L: "\'+p+\'"\')}7(m[1]===\'1t\'){G(\'"1t<-..." 3Q a 3R 3S B 27 3T 3U 3V.\\n\\3W 3X 3Y 28 B 2J 18.\')}7(!m[2]){m[2]=6(a){8 a.1H}}8{28:m[1],14:m[2]}}6 1f(c){7(x(c)===\'6\'){8 c}9 m=c.1s(/^[a-3Z-Z$1X][\\w$]*(\\.[\\w$-]*[^\\.])*$/);7(m===17){9 d=I,s=c,1I=[],1g=[],i=0,29;7(/\\\'|\\"/.12(s.2M(0))){7(/\\\'|\\"/.12(s.2M(s.y-1))){29=s.24(1,s.y-1);8 6(){8 29}}}A{2N((m=s.1s(/#\\{([^{}]+)\\}/))!==17){d=11;1I[i++]=s.2O(0,m.2P);1g[i]=1f(m[1]);s=s.2O(m.2P+m[0].y,s.y)}}7(!d){G(\'26 1H 13 2Q: \'+c)}1I[i]=s;8 23(1I,1g)}m=c.1J(\'.\');8 6(a){9 b=a.1H;7(!b){8\'\'}9 v=a[m[0]],i=0;7(v){b=v.1t;i+=1}9 n=m.y;B(;i<n;i++){7(!b){2R}b=b[m[i]]}8(!b&&b!==0)?\'\':b}}6 1u(c,d,e){9 f,R,13,D,P,K=[];7(x d===\'16\'){f=d;9 m=d.1s(1Y);7(!m){G(\'26 13 2Q: \'+d)}R=m[1];13=m[2];D=m[3];P=m[4];7(13===\'.\'||(!13&&D)){K[0]=c}A{K=r.J(c,13)}7(!K||K.y===0){8 G(\'2t 1v "\'+d+\'" 2v 2w 2x 1e 27 2u\')}}A{R=d.R;D=d.D;P=d.P;K=[c]}7(R||P){7(R&&P){G(\'P/R 2a 40 41 42 27 43 44\')}A 7(e){G(\'2S P/R/19 45 46 B 18 K\')}A 7(P&&e){G(\'2a P 22 18 (14: \'+f+\')\')}}9 g,1a,T,1w,1h,1x;7(D){1w=(/^2T$/i).12(D);1h=(/^47$/i).12(D);1x=1h?\'1i\':D;g=6(a,s){a.48(1m+D,s);7(1x 1e a&&!1w){a[1x]=\'\'}7(a.2U===1){a.2V(D);1h&&a.2V(1x)}};7(1w){1a=6(a){8 a.2T.49}}A 7(1h){1a=6(a){8 a.1i}}A{1a=6(a){8 a.4a(D)}}7(1w||1h){T=6(s){8 s.19(/\\"/g,\'&2W;\')}}A{T=6(s){8 s.19(/\\"/g,\'&2W;\').19(/\\s/g,\'&4b;\')}}}A{7(e){g=6(a,s){9 b=a.1K;7(b){9 t=F.4c(s);a.1K.2b(t,a.4d);a.1K.2c(a)}}}A{1a=6(a){8 a.1D};g=6(a,s){a.1D=s}}T=6(s){8 s}}9 h;7(R){h=6(a,s){g(a,s+1a(a))}}A 7(P){h=6(a,s){g(a,1a(a)+s)}}A{h=6(a,s){g(a,s)}}8{D:D,L:K,2X:h,14:f,T:T}}6 1y(a,n){9 b=u+n+\':\';B(9 i=0;i<a.L.y;i++){a.2X(a.L[i],b)}}6 2d(e,f,g){8 6(c){9 a=f(c),2e=c[e],1L={2Y:a},2f=[],2g=6(b){c.2Y=a;c.1r=1L.1r=b;c.1t=1L.1t=a[b];2f.2h(g(c))};c[e]=1L;7(1E(a)){B(9 i=0,M=a.y||0;i<M;i++){2g(i)}}A{B(9 d 1e a){a.2i(d)&&2g(d)}}x 2e!==\'C\'?c[e]=2e:4e c[e];8 2f.25(\'\')}}6 2j(a,b,c,d){9 e=I;9 p;B(9 i 1e c){7(c.2i(i)){7(e){G(\'2a 4f 4g 4h 4i 18 2I a K\')}p=i;e=11}}7(!p){G(\'2S 18 2L\')}9 f=c[p];7(x(f)===\'16\'||x(f)===\'6\'){c={};c[p]={4j:f};8 2j(a,b,c,d)}9 g=2K(p),1z=1f(g.14),K=1u(a,b,11),L=K.L;B(i=0;i<L.y;i++){9 h=L[i],1A=1n(h,f);d[d.y]=1o(K.T,2d(g.28,1z,1A));K.L=[h];1y(K,d.y-1)}}6 2Z(n,d){9 e=n.4k(\'*\'),2k=[],1j={a:[],l:{}},z,1M,i,M,j,1k,Y,1N,2l;B(i=-1,M=e.y;i<M;i++){Y=i>-1?e[i]:n;7(Y.2U===1&&Y.1i!==\'\'){1N=Y.1i.1J(\' \');B(j=0,1k=1N.y;j<1k;j++){2l=1N[j];z=30(2l,Y.15);7(z!==I){1M=(/4l/i).12(z.D);7(z.14.1O(\'@\')>-1||1M){Y.1i=Y.1i.19(\'@\'+z.D,\'\');7(1M){z.D=I}}2k.2h({n:Y,z:z})}}}}8 2k;6 30(c,a){9 b=c.1s(1Y),D=b[3]||2B[a],z={R:!!b[1],U:b[2],D:D,P:!!b[4],14:c},i,M,1P,1Q,V;B(i=1j.a.y-1;i>=0;i--){1P=1j.a[i];1Q=1P.l[0];V=1Q&&1Q[z.U];7(x V!==\'C\'){z.U=1P.p+\'.\'+z.U;7(1j.l[z.U]===11){V=V[0]}2R}}7(x V===\'C\'){V=1E(d)?d[0][z.U]:d[z.U];7(x V===\'C\'){8 I}}7(1E(V)){1j.a.2h({l:V,p:z.U});1j.l[z.U]=11;z.t=\'18\'}A{z.t=\'31\'}8 z}}6 1n(a,b,c,d){9 e=[];d=d||c&&2Z(a,c);7(c){9 j,1k,z,n,f,L,1z,1v,1A;2N(d.y>0){z=d[0].z;n=d[0].n;d.4m(0,1);7(z.t===\'31\'){f=1u(n,z,I);1y(f,e.y);e[e.y]=1o(f.T,1f(z.U))}A{1z=1f(z.14);f=1u(n,z,11);L=f.L;B(j=0,1k=L.y;j<1k;j++){1v=L[j];1A=1n(1v,I,c,d);e[e.y]=1o(f.T,2d(z.14,1z,1A));f.L=[1v];1y(f,e.y-1)}}}}9 f,1l;B(9 g 1e b){7(b.2i(g)){1l=b[g];7(x(1l)===\'6\'||x(1l)===\'16\'){f=1u(a,g,I);1y(f,e.y);e[e.y]=1o(f.T,1f(1l))}A{2j(a,g,1l,e)}}}9 h=1Z(a),1g=[];7(a.15===\'4n\'&&h.1O(1m+\'4o\')>0){h=h.19(/\\4p\\s/,\' \')}A 7(a.15===\'2C\'&&h.1O(1m+\'2D\')>0){h=h.19(/\\4q=("|\')(\'|")\\s/,\' \')}h=h.1J(1m).25(\'\');9 k=h.1J(u),p;B(9 i=1;i<k.y;i++){p=k[i];1g[i]=e[4r(p,10)];k[i]=p.24(p.1O(\':\')+1)}8 23(k,1g)}6 H(c,d,e){9 f=1n((e||E[0]).2F(11),c,d);8 6(a,b){b=b||a;8 f({1H:a,2m:b})}}6 N(a,b){9 c=x b===\'6\'?b:r.H(b,I,E[0]);B(9 i=0,M=E.y;i<M;i++){E[i]=2n(E[i],c(a,I))}2m=17;8 E}6 O(a,b){9 c=r.H(b,a,E[0]);B(9 i=0,M=E.y;i<M;i++){E[i]=2n(E[i],c(a,I))}2m=17;8 E}6 2n(a,b){9 c=F.1d(\'4s\'),15=a.15.4t(),1B,W;7((/32|1R|33/).12(15)){9 d={1R:{1S:\'2o\'},32:{1S:{2o:\'1R\'}},33:{1S:{34:\'1R\'}}};W=21(d[15])}A 7((/2o|34|4u/).12(15)){W=F.1d(\'1S\')}A{W=F.1d(\'4v\')}9 e=a.1K;e.2b(W,a);e.2c(a);W.1D=b;1B=W.4w;e.2b(1B,W);e.2c(W);a=1B;W=1B=e=17;8 a}};$p.X={};$p.35={1T:6(){7(x F.1b===\'C\'){$p.X.J=6(n,a){8 1T.4x(a,n)}}},36:6(){7(x F.1b===\'C\'){$p.X.J=6(n,a){8 $(n).4y(a)}}37.4z({4A:[\'H\',\'N\',\'O\'],H:6(a,b){8 $p(E).H(a,b)},N:6(a,b){8 $($p(E).N(a,b))[0]},O:6(a,b){8 $($p(E).O(a,b))[0]}})},38:6(){7(x F.1b===\'C\'){$p.X.J=6(n,a){8 $(n).J(a)}}1U.4B.4C({H:6(a,b){8 $p(E[0]).H(a,b)},N:6(a,b){8 1U($p(E[0]).N(a,b))},O:6(a,b){8 1U($p(E[0]).O(a,b))}})},39:6(){7(x F.1b===\'C\'){$p.X.J=6(n,a){8 $(n).4D(a)}}3a.4E({H:6(a,b){8 $p(E).H(a,b)},N:6(a,b){8 $p(E).N(a,b)},O:6(a,b){8 $p(E).O(a,b)}})},Q:6(){7(x F.1b===\'C\'){$p.X.J=6(n,a){n=n===F?n.4F:n;8 x n===\'16\'?$$(n):$(n).4G(a)}}3a.4H({H:6(a,b,c){8 $p(a).H(b,c)},N:6(a,b,c){8 $p(a).N(b,c)},O:6(a,b,c){8 $p(a).O(b,c)}})},3b:6(){7(x F.1b===\'C\'){$p.X.J=6(n,a){8 3c(a,n)}}},3d:6(){7(x F.1b===\'C\'){$p.X.J=6(n,a){8 3e(a,n)}}}};(6(){9 a=x 1T!==\'C\'&&\'1T\'||x 37!==\'C\'&&\'36\'||x 1U!==\'C\'&&\'38\'||x 4I!==\'C\'&&\'39\'||x 4J!==\'C\'&&\'Q\'||x 3c!==\'C\'&&\'3b\'||x 3e!==\'C\'&&\'3d\';a&&$p.35[a]()})();',62,294,'||||||function|if|return|var||||||||||||||||||||||||typeof|length|cspec|else|for|undefined|attr|this|document|error|compile|false|find|target|nodes|ii|render|autoRender|append|prototype|prepend||quotefn|prop|val|pa|plugins|ni|||true|test|selector|sel|tagName|string|null|loop|replace|getstr|querySelector|templates|createElement|in|dataselectfn|pfns|isClass|className|openLoops|jj|dsel|attPfx|compiler|wrapquote|leaf|pVal|pos|match|item|gettarget|node|isStyle|attName|setsig|itersel|inner|ne|Math|innerHTML|isArray|fnVal|attLine|data|parts|split|parentNode|temp|isNodeValue|cs|indexOf|loopi|loopil|tr|table|dojo|jQuery|ctxt|object|_|selRx|outerHTML|appendChild|domify|with|concatenator|substring|join|bad|the|name|retStr|cannot|insertBefore|removeChild|loopfn|old|strs|buildArg|push|hasOwnProperty|loopgen|an|cj|context|replaceWith|tbody|pure|arguments|core|getPlugins|The|template|was|not|found|floor|random|1000000|autoAttr|INPUT|value|console|cloneNode|querySelectorAll|PURE|on|your|parseloopspec|spec|charAt|while|slice|index|syntax|break|no|style|nodeType|removeAttribute|quot|set|items|getAutoNodes|checkClass|str|td|th|thead|libs|domassistant|DOMAssistant|jquery|mootools|Element|sizzle|Sizzle|sly|Sly|_s|_a|IMG|src|alert|log|debugger|throw|_compiler|_error|new|div|Object|toString|call|Array|createDocumentFragment|You|can|standalone|iPhone|FF3|Safari4|and|IE8|nTo|run|browser|you|need|JS|library|framework|CSS|engine|search|substr|is|reserved|word|current|running|iteration|nPlease|choose|another|zA|take|place|at|same|time|modifiers|allowed|class|setAttribute|cssText|getAttribute|nbsp|createTextNode|nextSibling|delete|have|more|than|one|root|getElementsByTagName|nodevalue|splice|OPTION|selected|sselected|svalue|parseInt|DIV|toLowerCase|tfoot|span|firstChild|query|cssSelect|attach|publicMethods|fn|extend|getElements|implement|body|select|addMethods|MooTools|Prototype'.split('|'),0,{}))

File tutorial/fp.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+	<script>
+		function jsonp(src){
+			var s = document.createElement("script");
+			s.charset = "UTF-8";
+			s.src = encodeURI(src);
+			document.body.appendChild(s);
+			return s;
+		};
+		function urlParam(name, w){
+			w = w || window;
+			var rx = new RegExp('[\&|\?]'+name+'=([^\&\#]+)');
+			var val = w.location.href.match(rx);
+			return !val ? '':val[1];
+		};
+	</script>
+</head>
+<body>
+	<script>
+		jsonp( 'http://friendpaste.com/' + urlParam('fp') + '.js' );
+	</script>
+</body>
+</html>

File tutorial/tuto1.html

+<html>
+<head>
+
+	<title>PURE Unobtrusive Rendering Engine</title>
+
+	<script src="../libs/jquery.js"></script>
+	<script src="../libs/pure.js"></script>
+
+</head>
+<body>
+
+	<!-- the HTML template -->
+	Hello <a class="who" href="#"></a>
+	
+	<script>
+
+		// the JSON data we want to render
+		var data = {'who':'BeeBole!'};
+
+		// run the rendering
+		$('a').autoRender(data);
+
+	</script>
+
+</body>
+</html>

File tutorial/tuto2.html

+<html>
+<head>
+
+	<title>PURE Unobtrusive Rendering Engine</title>
+
+	<script src="../libs/jquery.js"></script>
+	<script src="../libs/pure.js"></script>
+
+</head>
+<body>
+
+	<!-- 
+		same example as before but with an attribute assignment
+		note the property@attribute notation
+		'who@value' means place the value of the property who in the value attribute
+	-->
+	Hello <a class="who site@href"></a>
+
+	<script>
+		var data = {'who':'BeeBole!', site:'http://beebole.com'};
+		$('a').autoRender(data);
+	</script>
+
+</body>
+</html>

File tutorial/tuto3.html

+<html>
+<head>
+	<title>PURE Unobtrusive Rendering Engine</title>
+	<script src="../libs/jquery.js"></script>
+	<script src="../libs/pure.js"></script>
+</head>
+<body>
+	<!-- HTML template -->
+	<ul>
+		<!-- Explanation of the classes of the LI:
+			* 	"animals" points to an array and will trigger an iteration
+			
+			* 	"name" points to the property within the array and will set 
+				the node value of the LI
+		 -->
+		<li class="animals name"></li>
+	</ul>
+
+	<script>
+		// animals is an array and will trigger an iteration
+		var data = {
+			animals:[
+				{name:'bird'},
+				{name:'cat'},
+				{name:'dog'},
+				{name:'mouse'}
+			]
+		};
+		
+		$('ul').autoRender(data);
+	</script>
+</body>
+</html>