-
Notifications
You must be signed in to change notification settings - Fork 0
/
minx.min.js
1 lines (1 loc) · 10.8 KB
/
minx.min.js
1
if(Array.prototype.equals)console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");Array.prototype.equals=function(array){if(!array)return false;if(this.length!==array.length)return false;for(let i=0,l=this.length;i<l;i++){if(this[i]instanceof Array&&array[i]instanceof Array){if(!this[i].equals(array[i]))return false}else if(this[i]!==array[i]){return false}}return true};Object.defineProperty(Array.prototype,"equals",{enumerable:false});const methods=["push","pop","shift","unshift","splice","sort","reverse"];const MinxArray=Object.create(Array.prototype);methods.forEach(method=>{let _array=MinxArray[method];Object.defineProperty(MinxArray,method,{writable:true,enumerable:true,configurable:true,value:function(){let _arguments=arguments;let _len=arguments.length;let _args=new Array(_len);while(_len--){_args[_len]=_arguments[_len]}let _res=_array.apply(this,_args);let ob=this.__ob__;let inserted;switch(method){case"push":inserted=_args;break;case"unshift":inserted=_args;break;case"splice":inserted=_args.slice(2);break}if(inserted){ob.observeArray(inserted)}ob.dep.notify();return _res}})});class Observer{constructor(data){this.value=data;this.dep=new Depend;Reflect.defineProperty(data,"__ob__",{value:this,configurable:true,writable:true});Array.isArray(data)?this.observeArray(data):this.walk(data)}static observe(value){if(!value||typeof value!=="object")return;if(Object.hasOwnProperty.call(value,"__ob__")&&value.__ob__ instanceof Observer){return value.__ob__}else{return new Observer(value)}}observeArray(arr){arr.__proto__=MinxArray;arr.forEach(item=>{Observer.observe(item)})}walk(data){Object.keys(data).forEach(key=>{let _old=data[key];let _childOb=Observer.observe(_old);let dep=new Depend;Reflect.defineProperty(data,key,{enumerable:true,configurable:true,get:function(){if(Depend.currentWatcher){dep.depend();if(_childOb)_childOb.dep.depend()}return _old},set:function(val){if(val!==_old){_old=val;_childOb=Observer.observe(val);dep.notify()}}})})}}function template(text,context){let re=/{{ *([^}{]+)? *}}/g,code="var $$out=[];\nwith(this){",cursor=0,match;let add=function(line,js){js?code+="$$out.push("+line+");\n":code+=line!=""?'$$out.push("'+line.replace(/"/g,'\\"')+'");\n':"";return add};while(match=re.exec(text)){add(text.slice(cursor,match.index))(match[1],true);cursor=match.index+match[0].length}add(text.substr(cursor,text.length-cursor));code+='};\nreturn $$out.join("");';return new Function(code.replace(/[\r\t\n]/g,"")).apply(context)}class Compile{constructor(node,vm){this.$vm=vm;this._fns=this.$vm._methods;this.$node=node;this.compile(node)}compile(node){switch(node.nodeType){case 1:if(node.getAttribute("x-for")){this.list(node);return}if(node.hasAttributes()){node.$aindex=0;for(;node.$aindex<node.attributes.length;++node.$aindex){let _attr=node.attributes[node.$aindex];switch(_attr.name){case"x-model":this.model(node);break;case"x-if":this.xif(node);break;default:_attr.name.split(":")[0]==="x-on"?this.event(node,_attr):this.attr(node,_attr);break}}}node.$index=0;for(;node.$index<node.childNodes.length;++node.$index){this.compile(node.childNodes[node.$index])}break;case 3:this.tmpl(node);break}}tmpl(node){let _text=node.textContent;node.textContent=template(_text,this.$vm);let _this=this;!function(node_,text_){let res=_this.parse(_text,_this.$vm);res.forEach(item=>{new Watcher(item.parent,item.key,(old,val)=>{node_.textContent=template(text_,_this.$vm)})})}(node,_text)}parse(text,data){let re=/{{ *([^}{]+)? *}}/g,match;let _res=[];let path={var_:/^[a-zA-Z\$_][\w\$]*/,str_:/^\'.*?\'|^\".*?\"/,dot_:/^\./,var2_:/^\['([a-zA-Z\$_][\w\$]*)'\]/,var3_:/^\["([a-zA-Z\$_][\w\$]*)"\]/,spa_:/^ /,pal_:/^\(/,par_:/^\)/,op_:/^(\+|-|\*|\/|\|\&|\%|\^|\!|>|<|\?|:|!==|===|>=|<=)/,num_:/^\d+/,com_:/^,/};let walk=function(str){let cap;while(str){if(cap=path.spa_.exec(str)){str=str.substring(cap[0].length);continue}if(cap=path.com_.exec(str)){str=str.substring(cap[0].length);continue}if(cap=path.pal_.exec(str)||path.par_.exec(str)){str=str.substring(cap[0].length);continue}if(cap=path.str_.exec(str)){str=str.substring(cap[0].length);continue}if(cap=path.op_.exec(str)){str=str.substring(cap[0].length);continue}if(cap=path.dot_.exec(str)){str=str.substring(cap[0].length);if(cap=path.var_.exec(str)){str=str.substring(cap[0].length);continue}console.log("!!!error!!!")}if(cap=path.num_.exec(str)){str=str.substring(cap[0].length);continue}if(cap=path.var_.exec(str)){let _path="";str=str.substring(cap[0].length);_path+=cap[0];while(str){if(cap=path.var2_.exec(str)||path.var3_.exec(str)){str=str.substring(cap[0].length);_path+="."+cap[1];continue}if(cap=path.dot_.exec(str)){str=str.substring(cap[0].length);_path+=".";if(cap=path.var_.exec(str)){str=str.substring(cap[0].length);_path+=cap[0];continue}console.log("!!!error!!!");return _res}break}let value=Compile.getValue(data,_path);value&&_res.push(value);continue}console.log("error");return _res}};while(match=re.exec(text)){walk(match[1])}return _res}xif(node){const _cond=node.getAttribute("x-if");node.removeAttribute("x-if");node.$aindex-=1;const _value=Compile.getValue(this.$vm,_cond);node.style.visibility=_value.value?"visible":"hidden";new Watcher(_value.parent,_value.key,(old,val)=>{node.style.visibility=val?"visible":"hidden"})}list(node){let _attr=node.getAttribute("x-for");node.removeAttribute("x-for");let _item=_attr.split(":")[0];let _itemName=_item;let _indexName=null;if(/\(/.exec(_item)){let match=/\( *([a-zA-Z\$]+[\w]*), *([a-zA-Z\$]+[\w]*) *\)/g.exec(_item);_itemName=match[1];_indexName=match[2]}let _listName=_attr.split(":")[1];let _data=Compile.getValue(this.$vm,_listName);let _parent=node.parentNode;let _subs=[];_data.value.forEach((item,index)=>{const _clone=node.cloneNode(true);_clone.removeAttribute("x-for");let item_data={};item_data[_itemName]=item;if(_indexName)item_data[_indexName]=index;item_data.__proto__=this.$vm;new Observer(item_data);new Compile(_clone,item_data);_subs.push(_clone);node.parentNode.insertBefore(_clone,node);node.parentNode.$index+=1});let _this=this;let anchor=document.createTextNode("");!function(node_,anchor_,subs){new Watcher(_data.parent,_data.key,(old,val)=>{subs.forEach(_sub=>{_sub.remove()});subs=[];val.forEach((item,index)=>{const _clone=node_.cloneNode(true);let item_data={};item_data[_itemName]=item;if(_indexName)item_data[_indexName]=index;item_data.__proto__=_this.$vm;let _c=new Compile(_clone,item_data);subs.push(_clone);anchor_.parentNode.insertBefore(_clone,anchor_)})})}(node.cloneNode(true),anchor,_subs);node.parentNode.insertBefore(anchor,node);node.parentNode.removeChild(node)}attr(node,attr){let _meta=attr.name.split(":");if(_meta[0]==="x-attr"||_meta[0]===""){let _callback=_meta[1]==="class"?(old,val)=>{node.classList.remove(old);node.classList.add(val)}:(old,val)=>node.setAttribute(attr.name.split(":")[1],val);let _res="";attr.value.split("+").forEach(item=>{if(!/'/g.test(item)){let _value=Compile.getValue(this.$vm,item.replace(" ",""));_res+=_value.value;new Watcher(_value.parent,_value.key,_callback)}else{_res+=item.replace(/'/g,"")}});_meta[1]==="class"?!node.classList.contains(_res)?node.classList.add(_res):"":node.setAttribute(_meta[1],_res);node.removeAttribute(attr.name);node.$aindex-=1}}event(node,attr){let _meta=attr.name.split(":");if(_meta[0]==="x-on"){let _reName=/([\w\$]+)/,_reArgs=/\(([^\(\)]+)\)/,_reArg=/([\w\.\$\']+)/g;let _args=[];let _fn=node.getAttribute(attr.name);let _matchName=_reName.exec(_fn);let _fnName=_matchName[1];if(_reArgs.test(_fn)){let _argsText=_reArgs.exec(_fn)[1];let _matchArg;while(_matchArg=_reArg.exec(_argsText)){!/'/g.test(_matchArg[1])?_args.push(Compile.getValue(this.$vm,_matchArg[1]).value):_args.push(_matchArg[1].replace(/'/g,""))}}node.removeAttribute(attr.name);node.$aindex-=1;node.addEventListener(_meta[1],this._fns[_fnName].bind(node,_args))}}model(node){const _model=node.getAttribute("x-model");node.removeAttribute("x-model");node.$aindex-=1;let _data=Compile.getValue(this.$vm,_model);node.tagName==="INPUT"?node.value=_data.value:node.innerText=_data.value;node.addEventListener("input",function(event){_data.parent[_data.key]=node.value});new Watcher(_data.parent,_data.key,(old,val)=>{node.tagName==="INPUT"?node.value=val:node.innerText=val})}static getValue(data,path){const _list=path.split(".");let _data=data;let _parent=data;let _key;_list.forEach(item=>{!_data?console.log("#getValue[null]:",_parent,item):"";if(["Function","Array","Object","Reflect","String","Number","RegExp"].indexOf(item)!==-1||typeof _data==="string"&&(typeof _data[item]==="function"||item==="length")||Array.isArray(_data)&&(["concat","separator","pop","push","reverse","shift","slice","sort","splice","unshift"].indexOf(item)!==-1||item==="length")){console.log("#getValue[build-in]:",item);return _data===data?null:{value:_data,parent:_parent,key:_key}}if(!_data||!(item in _data)){console.log("#getValue[null]:",_parent,item);return null}_parent=_data;_key=item;_data=_data[item]});return _data===data?null:{value:_data,parent:_parent,key:_key}}}class Watcher{constructor(host,key,cb){this._cb=cb;this._host=host;this._key=key;this.depIds={};Depend.currentWatcher=this;this.value=!Array.isArray(this._host[this._key])?this._host[this._key]:this._host[this._key].slice();Depend.currentWatcher=null}update(){let _val=this._host[this._key];let _old=this.value;if(_val!==_old||Array.isArray(this.value)&&!_val.equals(_old)){this.value=!Array.isArray(_val)?_val:_val.slice();this._cb.call(this._host,_old,_val)}}addDep(depend){if(!this.depIds.hasOwnProperty(depend.id)){depend.add(this);this.depIds[depend.id]=depend}}}let uid=0;class Depend{constructor(){this.id=++uid;this.watchers=[]}add(watcher){this.watchers.push(watcher)}notify(){this.watchers.forEach(watcher=>{watcher.update()})}depend(){Depend.currentWatcher.addDep(this)}}Depend.currentWatcher=null;function Router(){}Router.hash={get(key){if(key&&this.value){let temp=new RegExp(key+"=([^&]+)").exec(this.value);if(temp){return temp[1]}}return null},set(key,value){let pattern=new RegExp(key+"=([^&]+)");let _hash=key+"="+value.toString();pattern.exec(this.value)?_hash=this.value.replace(pattern,_hash):_hash=this.value+"&"+_hash;window.location.hash="!/"+_hash},change(callback){window.onhashchange=callback}};Reflect.defineProperty(Router.hash,"value",{get(){return window.location.hash.slice(3)},set(value){let _hash="";Object.keys(value).forEach(key=>{_hash+="&"+key+"="+value[key].toString()});window.location.hash="!/"+_hash.slice(1)}});class Minx{constructor(options){this._data=options.data;this._methods=options.methods;this.$node=options.$.nodeType?options.$:document.querySelector(options.$);let self=this;Object.keys(this._data).forEach(key=>{Reflect.defineProperty(self,key,{configurable:true,enumerable:true,get:function(){return self._data[key]},set:function(val){self._data[key]=val}})});new Observer(this._data);new Compile(this.$node,this)}}