Skip to content
Browse files

allow hash # character to be used in JS variable name

  • Loading branch information...
1 parent 0624bec commit ae7e76b2cad553a5c12e176a4c76d7b07903f8b0 @pure committed Nov 2, 2013
Showing with 351 additions and 5 deletions.
  1. +2 −2 libs/pure.js
  2. +2 −2 libs/pure.min.js
  3. +346 −0 v3_preview/pure.js
  4. +1 −1 v3_preview/pure3.html
View
4 libs/pure.js
@@ -7,7 +7,7 @@
Copyright (c) 2013 Michael Cvilic - BeeBole.com
Thanks to Rog Peppe for the functional JS jump
- revision: 2.82
+ revision: 2.83
*/
var $p = function(){
@@ -200,7 +200,7 @@ $p.core = function(sel, ctxt, plugins){
};
}
//check for a valid js variable name with hyphen(for properties only), $, _ and :
- var m = sel.match(/^[\da-zA-Z\$_\@][\w\$:\-]*(\.[\w\$:\-]*[^\.])*$/),
+ var m = sel.match(/^[\da-zA-Z\$_\@\#][\w\$:\-\#]*(\.[\w\$:\-\#]*[^\.])*$/),
found = false, s = sel, parts = [], pfns = [], i = 0, retStr;
if(m === null){
View
4 libs/pure.min.js
@@ -7,13 +7,13 @@
Copyright (c) 2013 Michael Cvilic - BeeBole.com
Thanks to Rog Peppe for the functional JS jump
- revision: 2.82
+ revision: 2.83
*/
var $p=function(){var d=arguments,e=d[0],o=false;if(typeof e==="string")o=d[1]||false;else if(e&&!e[0]&&!e.length)e=[e];return $p.core(e,o)},pure=$p;
$p.core=function(d,e,o){function u(a){typeof console!=="undefined"&&console.log(a);throw"pure error: "+a;}function O(){var a=$p.plugins,b=function(){};b.prototype=a;b.prototype.compile=a.compile||P;b.prototype.render=a.render||Q;b.prototype.autoRender=a.autoRender||R;b.prototype.find=a.find||S;b.prototype._compiler=B;b.prototype._error=u;return new b}function G(a){return a.outerHTML||function(b){var g=document.createElement("div");g.appendChild(b.cloneNode(true));return g.innerHTML}(a)}function C(a,
b){return function(g){return a(String(b.call(g.item||g.context,g)))}}function S(a,b){if(typeof a==="string"){b=a;a=false}return(a||document).querySelectorAll(b)}function H(a,b){return function(g){var c=[a[0]],i=a.length,h,k,l,f,n;try{for(n=1;n<i;n++){h=b[n].call(this,g);k=a[n];if(h===""){l=c[c.length-1];if((f=l.search(/[^\s]+=\"?$/))>-1){c[c.length-1]=l.substring(0,f);k=k.substr(1)}}c[c.length]=h;c[c.length]=k}return c.join("")}catch(m){if(console&&console.log)console.log(m.stack||m.message+" ("+
m.type+(m.arguments?", "+m.arguments.join("-"):"")+"). Use Firefox or Chromium/Chrome to get a full stack of the error. ");return""}}}function T(a){var b=a.match(/^(\w+)\s*<-\s*(\S+)?$/);b===null&&u('bad loop spec: "'+a+'"');b[1]==="item"&&u('"item<-..." is a reserved word for the current running iteration.\n\nPlease choose another name for your loop.');if(!b[2]||b[2].toLowerCase()==="context")b[2]=function(g){return g.context};else if(b[2]&&b[2].indexOf("context")===0)b[2]=x(b[2].replace(/^context\.?/,
-""));return{name:b[1],sel:b[2]}}function x(a){if(typeof a==="function")return function(f){f=a.call(f.item||f.context||f,f);return!f&&f!==0?"":f};var b=a.match(/^[\da-zA-Z\$_\@][\w\$:\-]*(\.[\w\$:\-]*[^\.])*$/),g=false,c=a,i=[],h=[],k=0,l;if(b===null){if(/\'|\"/.test(c.charAt(0))){if(/\'|\"/.test(c.charAt(c.length-1))){l=c.substring(1,c.length-1);return function(){return l}}}else for(;(b=c.match(/#\{([^{}]+)\}/))!==null;){g=true;i[k++]=c.slice(0,b.index);h[k]=x(b[1]);c=c.slice(b.index+b[0].length,
+""));return{name:b[1],sel:b[2]}}function x(a){if(typeof a==="function")return function(f){f=a.call(f.item||f.context||f,f);return!f&&f!==0?"":f};var b=a.match(/^[\da-zA-Z\$_\@\#][\w\$:\-\#]*(\.[\w\$:\-\#]*[^\.])*$/),g=false,c=a,i=[],h=[],k=0,l;if(b===null){if(/\'|\"/.test(c.charAt(0))){if(/\'|\"/.test(c.charAt(c.length-1))){l=c.substring(1,c.length-1);return function(){return l}}}else for(;(b=c.match(/#\{([^{}]+)\}/))!==null;){g=true;i[k++]=c.slice(0,b.index);h[k]=x(b[1]);c=c.slice(b.index+b[0].length,
c.length)}if(!g)return function(){return a};i[k]=c;return H(i,h)}b=a.split(".");return function(f){var n=f.context||f,m=f[b[0]];f=0;var s;if(m&&typeof m.item!=="undefined"){f+=1;if(b[f]==="pos")return m.pos;n=m.item}for(m=b.length;f<m;){if(!n)break;s=n[b[f]];n=typeof s==="function"?s.call(n):s;f++}return!n&&n!==0?"":n}}function D(a,b,g){var c,i,h,k,l,f=[],n,m,s,t,r;if(typeof b==="string"){c=b;(l=b.match(I))||u("bad selector syntax: "+b);i=l[1];h=l[2];k=l[3];l=l[4];if(h==="."||!h&&k)f[0]=a;else f=
o.find(a,h);if(!f||f.length===0)return u('The node "'+b+'" was not found in the template:\n'+G(a).replace(/\t/g," "))}else{i=b.prepend;k=b.attr;l=b.append;f=[a]}if(i||l)if(i&&l)u("append/prepend cannot take place at the same time");else if(g)u("no append/prepend/replace modifiers allowed for loop target");else l&&g&&u("cannot append with loop (sel: "+c+")");if(k){s=/^style$/i.test(k);r=(t=/^class$/i.test(k))?"className":k;n=function(j,q){j.setAttribute(J+k,q);if(j[r]&&!s)try{j[r]=""}catch(p){}if(j.nodeType===
1){j.removeAttribute(k);t&&j.removeAttribute(r)}};m=s||t?s?function(j){return j.style.cssText}:function(j){return j.className}:function(j){return j.getAttribute(k)};a=function(j){return j.replace(/\"/g,"&quot;")};i=i?function(j,q){n(j,q+m(j))}:l?function(j,q){n(j,m(j)+q)}:function(j,q){n(j,q)}}else{i=g?function(j,q){var p=j.parentNode;if(p){p.insertBefore(document.createTextNode(q),j.nextSibling);p.removeChild(j)}else u("The template root, can't be looped.")}:i?function(j,q){j.insertBefore(document.createTextNode(q),
View
346 v3_preview/pure.js
@@ -0,0 +1,346 @@
+/*!
+ Pure Unobtrusive Rendering Engine for HTML
+
+ Dual licensed under GPL Version 2 or the MIT licenses
+ More information at: http://www.opensource.org
+
+ Copyright (c) 2013 Michael Cvilic - http://beebole.com
+
+ revision: 3.0
+*/
+var $p = function( sel, doc ){
+ if( typeof sel === 'string' ){
+ doc = doc || false;
+ }else if( sel && !sel[0] && !sel.length ){
+ sel = [ sel ];
+ }
+ return new $p.core( sel, doc );
+};
+
+$p.core = function(sel, doc){
+ // error utility
+ var error = function(e){
+ if( console !== undefined ){
+ console.log(e);
+ }
+ throw('pure error: ' + e);
+ },
+
+ // check if the argument is an array - thanks salty-horse (Ori Avtalion)
+ isArray = Array.isArray ?
+ function(o) {
+ return Array.isArray(o);
+ } :
+ function(o) {
+ return Object.prototype.toString.call(o) === "[object Array]";
+ },
+ find = function(n, sel){
+ //a node set is passed
+ if(typeof sel !== 'string'){
+ return sel;
+ }
+ if(typeof n === 'string'){
+ sel = n;
+ n = false;
+ }
+ if( document.querySelectorAll !== undefined ){
+ return (n||document).querySelectorAll( sel );
+ }
+ //else
+ return error('querySelectorAll not supported');
+
+ },
+ buildTargets = function(that, sel, doc){
+ //find all nodes for the selector
+ var targets = find(doc || document, sel),
+ i,
+ l = targets.length;
+
+ //fill an array of the nodes attached to $p
+ for( i = 0; i < l; i++ ){
+ that[i] = targets[i];
+ }
+ //give an array like length
+ that.length = l;
+
+ return that;
+ },
+ ctxt;
+
+ this.compile = function(directives){
+ var selector,
+ root = this[0],
+ allNodes = root.getElementsByTagName('*'),
+ actions = [],
+ setAction = function(root, directive, selSpec){
+ var nodes = selSpec.selector && selSpec.selector !== '.' ? find( root, selSpec.selector ) : [root],
+ i,
+ l = nodes.length,
+
+
+ readData = function(data, path){
+ var p = path.split( '.' ),
+ v = data[ p[0] ],
+ i = 0,
+ n = p.length;
+
+ if(v && v.item){
+ i += 1;
+ if( p[ i ] === 'pos' ){
+ //allow pos to be kept by string. Tx to Adam Freidin
+ return v.pos;
+ } //else
+ data = v.item;
+ }
+
+ while( i < n ){
+ if(!data){break;}
+ data = data[ p[ i++ ] ];
+ }
+
+ //return an empty string if no value found
+ return ( !data && data !== 0 ) ? '' : data;
+ },
+
+ getIndex = function(node, allNodes){
+
+ var l = allNodes.length;
+ while(l--){
+ if( allNodes[ l ] === node ){
+ break;
+ }
+ }
+ return l;
+ },
+ nodeIndex,
+
+ loop = function(nodeIndex, directive){
+
+ var node = allNodes[ nodeIndex ],
+ getLoopDef = function( directive ){
+
+ var loopDef = {/*
+ filter, sort, loopSpec, directive
+ */},
+ parseLoopSpec = function(p){
+ var m = p.match( /^(\w+)\s*<-\s*(\S+)?$/ );
+ if(m === null){
+ error('"' + p + '" must have the format row<-rows');
+ }
+ 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] || (m[2] && (/context/i).test(m[2]))){ //undefined or space(IE)
+ m[2] = function(data){return data.context;};
+ }
+ return {itemName: m[1], arrayName: m[2]};
+ },
+ ds,
+ sel;
+
+ for(sel in directive){
+
+ ds = directive[ sel ];
+ if( sel === 'filter'){
+
+ loopDef.filter = ds;
+
+ }else if( sel === 'sort'){
+
+ loopDef.sorter = ds;
+
+ }else{
+
+ loopDef.loopSpec = parseLoopSpec( sel );
+ if( loopDef.loopSpec ){
+ loopDef.directive = ds;
+ }else{
+ error( sel + ' is not a valid loop property: row<-rows, filter,' );
+ }
+
+ }
+ }
+
+ return loopDef;
+
+ },
+ loopDef = getLoopDef( directive ),
+ dfrag = document.createDocumentFragment(),
+ arr = [],
+ templateNode = node.cloneNode( true ),
+ parentNode = node.parentNode,
+ compiled = $p( templateNode ).compile( loopDef.directive );
+
+ return function(data){
+
+ var items = readData( data, loopDef.loopSpec.arrayName ),
+ il = items.length,
+ tempCtxt = { context:ctxt },
+ innerLoop = function(dfrag, tempCtxt, loopCtxt, item, node, pos){
+ //for each entry prepare the parameters for function directives, and sub templates
+ tempCtxt.item = loopCtxt.item = item;
+ tempCtxt.node = loopCtxt.node = node;
+ tempCtxt.pos = loopCtxt.pos = pos;
+
+ //call the compiled template on item context, and return the resulting node
+ return dfrag.appendChild( compiled( tempCtxt ).cloneNode(true) );
+ },
+ loopCtxt,
+ pos;
+
+ loopCtxt = tempCtxt[ loopDef.loopSpec.itemName ] = {};
+ tempCtxt.items = loopCtxt.items = items;
+
+ if( isArray(items) ){
+ for( pos = 0 ; pos < il; pos++ ){
+ arr.push( innerLoop(dfrag, tempCtxt, loopCtxt, items[pos], node, pos) );
+ }
+ }else{
+ for(pos in items){
+ arr.push( innerLoop(dfrag, tempCtxt, loopCtxt, items[pos], node, pos) );
+ }
+ }
+
+ //insert the loop elements in the fresh loop template
+ parentNode.replaceChild( dfrag, node );
+
+ };
+ },
+
+ single = function(nodeIndex, directive, sel){
+
+ var node = allNodes[ nodeIndex ],
+ isStyle, isClass, attName, attSet, get, set, init;
+
+ if(sel.attr){
+ isStyle = sel.attr.toLowerCase() === 'style';
+ isClass = sel.attr.toLowerCase() === 'class';
+ attName = isClass ? 'className' : sel.attr;
+ attSet = function(node, s) {
+ if(!s && s !== 0){
+ if (attName in node && !isStyle) {
+ try{
+ node[attName] = ''; //needed for IE to properly remove some attributes
+ }catch(e){ error(e); } //FF4 gives an error sometimes -> try/catch
+ }
+ //no more nodeType check since
+ node.removeAttribute( attName );
+ }else{
+ node.setAttribute( attName, s );
+ }
+ };
+ if ( isStyle ) { //IE
+ get = function(n){
+ return n.style.cssText;
+ };
+ }else if ( isClass ) { //IE
+ get = function( n ){
+ return n.className;
+ };
+ }else {
+ get = function(n){
+ return n.getAttribute( sel.attr );
+ };
+ }
+
+ if(sel.prepend){
+ init = get( node ) || '';
+ set = function(s){
+ attSet( node, s + init );
+ };
+ }else if(sel.append){
+ init = get( node ) || '';
+ set = function(s){
+ attSet( node, init + s );
+ };
+ }else{
+ set = function(s){
+ attSet( node, s );
+ };
+ }
+ }else{
+ if (sel.prepend) {
+ set = function(s) { node.insertBefore( document.createTextNode(s), node.firstChild ); };
+ } else if (sel.append) {
+ set = function(s) { node.appendChild( document.createTextNode(s) );};
+ } else {
+ set = function(s) {
+ while (node.firstChild) { node.removeChild(node.firstChild); }
+ node.appendChild( document.createTextNode(s) );
+ };
+ }
+ }
+ return function(data, nodeIndex){
+ set( String( readData( data, directive ) ) || directive );
+ };
+ };
+
+ if(l === 0){
+ error( 'Selector "' + sel.selector + '" do not match any node in the template' );
+ }
+
+ for(i = 0; i < l; i++ ){
+ nodeIndex = getIndex( nodes[i], allNodes );
+ actions.push(
+ ( typeof directive === 'object' ? loop : single )( nodeIndex, directive, selSpec )
+ );
+ }
+
+ },
+
+ forEachSelected = function(root, sel, directive, setAction){
+ var sels = sel.split( /\s*,\s*/ ), //allow selector separation by quotes
+ selRx = /^(\+)?([^\@\+]+)?\@?([^\+]+)?(\+)?$/, //valid selector check
+ s,
+ selSpec,
+ i = sels.length;
+
+ while( i-- ){
+
+ s = sels[ i ].match( selRx );
+ if( !s ){
+ error( 'bad selector syntax: ' + sel );
+ }
+
+ selSpec = {
+ prepend: s[1],
+ selector: s[2],
+ attr: s[3],
+ append: s[4]
+ };
+
+ setAction(root, directive, selSpec);
+
+ }
+
+ };
+
+ for( selector in directives ){
+ forEachSelected( root, selector, directives[ selector ], setAction );
+ }
+
+ return function( data ){
+ ctxt = ctxt || data;
+ var i,
+ l = actions.length;
+
+ for( i = 0; i < l; i++ ){
+ actions[nodeIndex](data, nodeIndex);
+ }
+
+ return root;
+
+ };
+ };
+
+ this.render = function(data, directive){
+ var i = -1, l = this.length,
+ compiled = typeof directive === 'function' ? directive : this.compile( directive );
+ while( ++i < l ){
+ this[ i ] = compiled( data );
+ }
+ return this;
+ };
+
+ return buildTargets( this, sel, doc );
+};
View
2 v3_preview/pure3.html
@@ -1,7 +1,7 @@
<html>
<head>
<title>PURE Unobtrusive Rendering Engine</title>
- <script src="pure3.js"></script>
+ <script src="pure.js"></script>
</head>
<body>
<!-- HTML template -->

0 comments on commit ae7e76b

Please sign in to comment.
Something went wrong with that request. Please try again.