docs: 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.context;
        if(!data){
          return '';
        }
        var  v = ctxt[m[0]],
          i = 0;
        if(v && v.item){
          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;
      };
    }