一大波精简;移除对不支持ES6的浏览器的兼容代码;移除组件API,正式引入web component
							parent
							
								
									b761086606
								
							
						
					
					
						commit
						10ef2cbd97
					
				|  | @ -50,7 +50,6 @@ const PAD_END = Buffer.from(` | ||||||
|       fn(Anot) |       fn(Anot) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   window.importCss = importCss |  | ||||||
|   window.Anot = Anot |   window.Anot = Anot | ||||||
|   return Anot |   return Anot | ||||||
| })() | })() | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| { | { | ||||||
|   "name": "anot", |   "name": "anot", | ||||||
|   "version": "2.0.0", |   "version": "2.1.0", | ||||||
|   "description": "Anot - 迷你mvvm框架", |   "description": "Anot - 迷你mvvm框架", | ||||||
|   "main": "dist/anot.js", |   "main": "dist/anot.js", | ||||||
|   "files": ["dist"], |   "files": ["dist"], | ||||||
|  |  | ||||||
|  | @ -1,21 +1,17 @@ | ||||||
| /********************************************************************* | /********************************************************************* | ||||||
|  *                    全局变量及方法                                   * |  *                    全局变量及方法                                   * | ||||||
|  **********************************************************************/ |  **********************************************************************/ | ||||||
| const CSS_DEPS = {} | var bindingID = 1024 | ||||||
| let bindingID = 1024 | 
 | ||||||
| let IEVersion = 0 | var expose = generateID() | ||||||
| if (window.VBArray) { |  | ||||||
|   IEVersion = document.documentMode || (window.XMLHttpRequest ? 7 : 6) |  | ||||||
| } |  | ||||||
| let expose = generateID() |  | ||||||
| //http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function
 | //http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function
 | ||||||
| let DOC = window.document | var DOC = window.document | ||||||
| let head = DOC.head //HEAD元素
 | var head = DOC.head //HEAD元素
 | ||||||
| head.insertAdjacentHTML( | head.insertAdjacentHTML( | ||||||
|   'afterbegin', |   'afterbegin', | ||||||
|   '<anot skip class="anot-hide"><style id="anot-style">.anot-hide{ display: none!important } slot{visibility:hidden;}</style></anot>' |   '<anot skip class="anot-hide"><style id="anot-style">.anot-hide{ display: none!important } slot{visibility:hidden;}</style></anot>' | ||||||
| ) | ) | ||||||
| let ifGroup = head.firstChild | var ifGroup = head.firstChild | ||||||
| 
 | 
 | ||||||
| function log() { | function log() { | ||||||
|   // http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log
 |   // http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log
 | ||||||
|  | @ -35,22 +31,21 @@ function createMap() { | ||||||
|   return Object.create(null) |   return Object.create(null) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| let subscribers = '$' + expose | var subscribers = '$' + expose | ||||||
| 
 | 
 | ||||||
| let nullObject = {} //作用类似于noop,只用于代码防御,千万不要在它上面添加属性
 | var nullObject = {} //作用类似于noop,只用于代码防御,千万不要在它上面添加属性
 | ||||||
| let rword = /[^, ]+/g //切割字符串为一个个小块,以空格或豆号分开它们,结合replace实现字符串的forEach
 | var rword = /[^, ]+/g //切割字符串为一个个小块,以空格或豆号分开它们,结合replace实现字符串的forEach
 | ||||||
| let rw20g = /\w+/g | var rw20g = /\w+/g | ||||||
| let rsvg = /^\[object SVG\w*Element\]$/ | var rsvg = /^\[object SVG\w*Element\]$/ | ||||||
| let oproto = Object.prototype | var oproto = Object.prototype | ||||||
| let ohasOwn = oproto.hasOwnProperty | var ohasOwn = oproto.hasOwnProperty | ||||||
| let serialize = oproto.toString | var serialize = oproto.toString | ||||||
| let ap = Array.prototype | var ap = Array.prototype | ||||||
| let aslice = ap.slice | var aslice = ap.slice | ||||||
| let W3C = window.dispatchEvent | var root = DOC.documentElement | ||||||
| let root = DOC.documentElement | var anotFragment = DOC.createDocumentFragment() | ||||||
| let anotFragment = DOC.createDocumentFragment() | var cinerator = DOC.createElement('div') | ||||||
| let cinerator = DOC.createElement('div') | var class2type = { | ||||||
| let class2type = { |  | ||||||
|   '[object Boolean]': 'boolean', |   '[object Boolean]': 'boolean', | ||||||
|   '[object Number]': 'number', |   '[object Number]': 'number', | ||||||
|   '[object String]': 'string', |   '[object String]': 'string', | ||||||
|  | @ -75,9 +70,9 @@ function oneObject(array, val) { | ||||||
|   if (typeof array === 'string') { |   if (typeof array === 'string') { | ||||||
|     array = array.match(rword) || [] |     array = array.match(rword) || [] | ||||||
|   } |   } | ||||||
|   let result = {}, |   var result = {}, | ||||||
|     value = val !== void 0 ? val : 1 |     value = val !== void 0 ? val : 1 | ||||||
|   for (let i = 0, n = array.length; i < n; i++) { |   for (var i = 0, n = array.length; i < n; i++) { | ||||||
|     result[array[i]] = value |     result[array[i]] = value | ||||||
|   } |   } | ||||||
|   return result |   return result | ||||||
|  | @ -87,52 +82,3 @@ function generateID(mark) { | ||||||
|   mark = (mark && mark + '-') || 'anot-' |   mark = (mark && mark + '-') || 'anot-' | ||||||
|   return mark + (++bindingID).toString(16) |   return mark + (++bindingID).toString(16) | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /********************************************************************* |  | ||||||
|  *                   css import                                      * |  | ||||||
|  **********************************************************************/ |  | ||||||
| 
 |  | ||||||
| function getBaseUrl() { |  | ||||||
|   if (window.LIBS_BASE_URL) { |  | ||||||
|     return |  | ||||||
|   } |  | ||||||
|   let stack |  | ||||||
|   try { |  | ||||||
|     throw new Error() // 强制报错,以便捕获e.stack
 |  | ||||||
|   } catch (err) { |  | ||||||
|     stack = err.stack |  | ||||||
|   } |  | ||||||
|   stack = stack.trim().split(/[@ ]+/) |  | ||||||
|   if (window.safari) { |  | ||||||
|     stack = stack[1] |  | ||||||
|   } else { |  | ||||||
|     stack = stack.pop() |  | ||||||
|   } |  | ||||||
|   stack = stack.replace(/(:\\d+)?:\d+([\\w\\W]*)?$/i, '') |  | ||||||
|   window.LIBS_BASE_URL = stack.replace( |  | ||||||
|     /^([a-z\-]*):\/\/([^\/]+)(\/.*)?/, |  | ||||||
|     '$1://$2' |  | ||||||
|   ) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function importCss(url, baseUrl) { |  | ||||||
|   url = url.replace(/^\/+/, '/') |  | ||||||
|   if (baseUrl) { |  | ||||||
|     url = baseUrl + url |  | ||||||
|   } else { |  | ||||||
|     if (window.LIBS_BASE_URL) { |  | ||||||
|       url = window.LIBS_BASE_URL + url |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (CSS_DEPS[url]) { |  | ||||||
|     return |  | ||||||
|   } |  | ||||||
|   head.insertAdjacentHTML( |  | ||||||
|     'afterbegin', |  | ||||||
|     '<link rel="stylesheet" href="' + url + '">' |  | ||||||
|   ) |  | ||||||
|   CSS_DEPS[url] = 1 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| getBaseUrl() |  | ||||||
|  |  | ||||||
|  | @ -203,10 +203,6 @@ Anot.mix = Anot.fn.mix = function() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function cacheStore(tpye, key, val) { | function cacheStore(tpye, key, val) { | ||||||
|   if (!window[tpye]) { |  | ||||||
|     return log('该浏览器不支持本地储存' + tpye) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (this.type(key) === 'object') { |   if (this.type(key) === 'object') { | ||||||
|     for (let i in key) { |     for (let i in key) { | ||||||
|       window[tpye].setItem(i, key[i]) |       window[tpye].setItem(i, key[i]) | ||||||
|  | @ -322,8 +318,9 @@ Anot.mix({ | ||||||
|     if (node instanceof Anot) { |     if (node instanceof Anot) { | ||||||
|       node = node[0] |       node = node[0] | ||||||
|     } |     } | ||||||
|     let prop = /[_-]/.test(name) ? camelize(name) : name, |     var prop = /[_-]/.test(name) ? camelize(name) : name | ||||||
|       fn |     var fn | ||||||
|  | 
 | ||||||
|     name = Anot.cssName(prop) || prop |     name = Anot.cssName(prop) || prop | ||||||
|     if (value === void 0 || typeof value === 'boolean') { |     if (value === void 0 || typeof value === 'boolean') { | ||||||
|       //获取样式
 |       //获取样式
 | ||||||
|  | @ -331,8 +328,8 @@ Anot.mix({ | ||||||
|       if (name === 'background') { |       if (name === 'background') { | ||||||
|         name = 'backgroundColor' |         name = 'backgroundColor' | ||||||
|       } |       } | ||||||
|       let val = fn(node, name) |       var val = fn(node, name) | ||||||
|       return value === true ? parseFloat(val) || 0 : val |       return value === true ? +val || 0 : val | ||||||
|     } else if (value === '') { |     } else if (value === '') { | ||||||
|       //请除样式
 |       //请除样式
 | ||||||
|       node.style[name] = '' |       node.style[name] = '' | ||||||
|  | @ -485,7 +482,10 @@ Anot.mix({ | ||||||
|     key += '' |     key += '' | ||||||
|     let uri = location.search |     let uri = location.search | ||||||
| 
 | 
 | ||||||
|     if (!key || !uri) return null |     if (!key || !uri) { | ||||||
|  |       return null | ||||||
|  |     } | ||||||
|  |     uri = decodeURIComponent(uri) | ||||||
| 
 | 
 | ||||||
|     uri = uri.slice(1) |     uri = uri.slice(1) | ||||||
|     uri = uri.split('&') |     uri = uri.split('&') | ||||||
|  | @ -494,7 +494,7 @@ Anot.mix({ | ||||||
|     for (let i = 0, item; (item = uri[i++]); ) { |     for (let i = 0, item; (item = uri[i++]); ) { | ||||||
|       let tmp = item.split('=') |       let tmp = item.split('=') | ||||||
|       tmp[1] = tmp.length < 2 ? null : tmp[1] |       tmp[1] = tmp.length < 2 ? null : tmp[1] | ||||||
|       tmp[1] = decodeURIComponent(tmp[1]) |       tmp[1] = tmp[1] | ||||||
|       if (obj.hasOwnProperty(tmp[0])) { |       if (obj.hasOwnProperty(tmp[0])) { | ||||||
|         if (typeof obj[tmp[0]] === 'object') { |         if (typeof obj[tmp[0]] === 'object') { | ||||||
|           obj[tmp[0]].push(tmp[1]) |           obj[tmp[0]].push(tmp[1]) | ||||||
|  | @ -523,7 +523,7 @@ Anot.mix({ | ||||||
|     try { |     try { | ||||||
|       DOC.execCommand('copy') |       DOC.execCommand('copy') | ||||||
|     } catch (err) { |     } catch (err) { | ||||||
|       log('复制到粘贴板失败') |       log('复制到粘贴板失败', err) | ||||||
|     } |     } | ||||||
|     DOC.body.removeChild(ta) |     DOC.body.removeChild(ta) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -17,79 +17,6 @@ Anot.contains = function(root, el) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| if (window.SVGElement) { |  | ||||||
|   let svgns = 'http://www.w3.org/2000/svg' |  | ||||||
|   let svg = DOC.createElementNS(svgns, 'svg') |  | ||||||
|   svg.innerHTML = '<circle cx="50" cy="50" r="40" fill="red" />' |  | ||||||
|   if (!rsvg.test(svg.firstChild)) { |  | ||||||
|     // #409
 |  | ||||||
|     /* jshint ignore:start */ |  | ||||||
|     function enumerateNode(node, targetNode) { |  | ||||||
|       if (node && node.childNodes) { |  | ||||||
|         let nodes = node.childNodes |  | ||||||
|         for (let i = 0, el; (el = nodes[i++]); ) { |  | ||||||
|           if (el.tagName) { |  | ||||||
|             let svg = DOC.createElementNS(svgns, el.tagName.toLowerCase()) |  | ||||||
|             // copy attrs
 |  | ||||||
|             ap.forEach.call(el.attributes, function(attr) { |  | ||||||
|               svg.setAttribute(attr.name, attr.value) |  | ||||||
|             }) |  | ||||||
|             // 递归处理子节点
 |  | ||||||
|             enumerateNode(el, svg) |  | ||||||
|             targetNode.appendChild(svg) |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     /* jshint ignore:end */ |  | ||||||
|     Object.defineProperties(SVGElement.prototype, { |  | ||||||
|       outerHTML: { |  | ||||||
|         //IE9-11,firefox不支持SVG元素的innerHTML,outerHTML属性
 |  | ||||||
|         enumerable: true, |  | ||||||
|         configurable: true, |  | ||||||
|         get: function() { |  | ||||||
|           return new XMLSerializer().serializeToString(this) |  | ||||||
|         }, |  | ||||||
|         set: function(html) { |  | ||||||
|           let tagName = this.tagName.toLowerCase(), |  | ||||||
|             par = this.parentNode, |  | ||||||
|             frag = Anot.parseHTML(html) |  | ||||||
|           // 操作的svg,直接插入
 |  | ||||||
|           if (tagName === 'svg') { |  | ||||||
|             par.insertBefore(frag, this) |  | ||||||
|             // svg节点的子节点类似
 |  | ||||||
|           } else { |  | ||||||
|             let newFrag = DOC.createDocumentFragment() |  | ||||||
|             enumerateNode(frag, newFrag) |  | ||||||
|             par.insertBefore(newFrag, this) |  | ||||||
|           } |  | ||||||
|           par.removeChild(this) |  | ||||||
|         } |  | ||||||
|       }, |  | ||||||
|       innerHTML: { |  | ||||||
|         enumerable: true, |  | ||||||
|         configurable: true, |  | ||||||
|         get: function() { |  | ||||||
|           let s = this.outerHTML |  | ||||||
|           let ropen = new RegExp( |  | ||||||
|             '<' + this.nodeName + '\\b(?:(["\'])[^"]*?(\\1)|[^>])*>', |  | ||||||
|             'i' |  | ||||||
|           ) |  | ||||||
|           let rclose = new RegExp('</' + this.nodeName + '>$', 'i') |  | ||||||
|           return s.replace(ropen, '').replace(rclose, '') |  | ||||||
|         }, |  | ||||||
|         set: function(html) { |  | ||||||
|           if (Anot.clearHTML) { |  | ||||||
|             Anot.clearHTML(this) |  | ||||||
|             let frag = Anot.parseHTML(html) |  | ||||||
|             enumerateNode(frag, this) |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| //========================= event binding ====================
 | //========================= event binding ====================
 | ||||||
| 
 | 
 | ||||||
| let eventHooks = Anot.eventHooks | let eventHooks = Anot.eventHooks | ||||||
|  |  | ||||||
|  | @ -317,7 +317,6 @@ function observeObject(source, options) { | ||||||
|   hideProperty($vmodel, '$events', {}) |   hideProperty($vmodel, '$events', {}) | ||||||
|   hideProperty($vmodel, '$refs', {}) |   hideProperty($vmodel, '$refs', {}) | ||||||
|   hideProperty($vmodel, '$children', []) |   hideProperty($vmodel, '$children', []) | ||||||
|   hideProperty($vmodel, '$components', []) |  | ||||||
|   hideProperty($vmodel, 'hasOwnProperty', trackBy) |   hideProperty($vmodel, 'hasOwnProperty', trackBy) | ||||||
|   hideProperty($vmodel, '$mounted', mounted) |   hideProperty($vmodel, '$mounted', mounted) | ||||||
|   if (options.watch) { |   if (options.watch) { | ||||||
|  |  | ||||||
|  | @ -67,9 +67,7 @@ var newProto = { | ||||||
|       _splice.call(this.$track, 0, this.length) |       _splice.call(this.$track, 0, this.length) | ||||||
|       _splice.call(this, 0, this.length) |       _splice.call(this, 0, this.length) | ||||||
|     } |     } | ||||||
|     if (!W3C) { | 
 | ||||||
|       this.$model = toJson(this) |  | ||||||
|     } |  | ||||||
|     this.notify() |     this.notify() | ||||||
|     this._.length = this.length |     this._.length = this.length | ||||||
|   }, |   }, | ||||||
|  | @ -89,9 +87,7 @@ arrayMethods.forEach(function(method) { | ||||||
|     } |     } | ||||||
|     var result = original.apply(this, args) |     var result = original.apply(this, args) | ||||||
|     addTrack(this.$track, method, args) |     addTrack(this.$track, method, args) | ||||||
|     if (!W3C) { | 
 | ||||||
|       this.$model = toJson(this) |  | ||||||
|     } |  | ||||||
|     this.notify() |     this.notify() | ||||||
|     this._.length = this.length |     this._.length = this.length | ||||||
|     return result |     return result | ||||||
|  | @ -120,9 +116,7 @@ arrayMethods.forEach(function(method) { | ||||||
|     } |     } | ||||||
|     if (hasSort) { |     if (hasSort) { | ||||||
|       sortByIndex(this.$track, indexes) |       sortByIndex(this.$track, indexes) | ||||||
|       if (!W3C) { | 
 | ||||||
|         this.$model = toJson(this) |  | ||||||
|       } |  | ||||||
|       this.notify() |       this.notify() | ||||||
|     } |     } | ||||||
|     return this |     return this | ||||||
|  |  | ||||||
|  | @ -31,21 +31,6 @@ function camelize(target) { | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| Anot.fn.mix({ | Anot.fn.mix({ | ||||||
|   hasClass: function(cls) { |  | ||||||
|     var el = this[0] || {} //IE10+, chrome8+, firefox3.6+, safari5.1+,opera11.5+支持classList,chrome24+,firefox26+支持classList2.0
 |  | ||||||
|     return el.nodeType === 1 && el.classList.contains(cls) |  | ||||||
|   }, |  | ||||||
|   toggleClass: function(value, stateVal) { |  | ||||||
|     var className, |  | ||||||
|       i = 0 |  | ||||||
|     var classNames = String(value).match(/\S+/g) || [] |  | ||||||
|     var isBool = typeof stateVal === 'boolean' |  | ||||||
|     while ((className = classNames[i++])) { |  | ||||||
|       var state = isBool ? stateVal : !this.hasClass(className) |  | ||||||
|       this[state ? 'addClass' : 'removeClass'](className) |  | ||||||
|     } |  | ||||||
|     return this |  | ||||||
|   }, |  | ||||||
|   attr: function(name, value) { |   attr: function(name, value) { | ||||||
|     if (arguments.length === 2) { |     if (arguments.length === 2) { | ||||||
|       this[0].setAttribute(name, value) |       this[0].setAttribute(name, value) | ||||||
|  | @ -55,25 +40,24 @@ Anot.fn.mix({ | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   data: function(name, value) { |   data: function(name, value) { | ||||||
|     name = 'data-' + hyphen(name || '') |     var len = arguments.length | ||||||
|     switch (arguments.length) { |     var dataset = this[0].dataset | ||||||
|  |     name = hyphen(name || '') | ||||||
|  |     if (!name) { | ||||||
|  |       len = 0 | ||||||
|  |     } | ||||||
|  |     switch (len) { | ||||||
|       case 2: |       case 2: | ||||||
|         this.attr(name, value) |         dataset[name] = value | ||||||
|         return this |         return this | ||||||
|       case 1: |       case 1: | ||||||
|         var val = this.attr(name) |         var val = dataset[name] | ||||||
|         return parseData(val) |         return parseData(val) | ||||||
|       case 0: |       case 0: | ||||||
|         var ret = {} |         var ret = createMap() | ||||||
|         ap.forEach.call(this[0].attributes, function(attr) { |         for (var i in dataset) { | ||||||
|           if (attr) { |           ret[i] = parseData(dataset[i]) | ||||||
|             name = attr.name |         } | ||||||
|             if (!name.indexOf('data-')) { |  | ||||||
|               name = camelize(name.slice(5)) |  | ||||||
|               ret[name] = parseData(attr.value) |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }) |  | ||||||
|         return ret |         return ret | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|  | @ -159,27 +143,6 @@ Anot.fn.mix({ | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| if (root.dataset) { |  | ||||||
|   Anot.fn.data = function(name, val) { |  | ||||||
|     name = name && camelize(name) |  | ||||||
|     var dataset = this[0].dataset |  | ||||||
|     switch (arguments.length) { |  | ||||||
|       case 2: |  | ||||||
|         dataset[name] = val |  | ||||||
|         return this |  | ||||||
|       case 1: |  | ||||||
|         val = dataset[name] |  | ||||||
|         return parseData(val) |  | ||||||
|       case 0: |  | ||||||
|         var ret = createMap() |  | ||||||
|         for (name in dataset) { |  | ||||||
|           ret[name] = parseData(dataset[name]) |  | ||||||
|         } |  | ||||||
|         return ret |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Anot.parseJSON = JSON.parse | Anot.parseJSON = JSON.parse | ||||||
| 
 | 
 | ||||||
| var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/ | var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/ | ||||||
|  | @ -190,14 +153,14 @@ function parseData(data) { | ||||||
|       data === 'true' |       data === 'true' | ||||||
|         ? true |         ? true | ||||||
|         : data === 'false' |         : data === 'false' | ||||||
|           ? false |         ? false | ||||||
|           : data === 'null' |         : data === 'null' | ||||||
|             ? null |         ? null | ||||||
|             : +data + '' === data |         : +data + '' === data | ||||||
|               ? +data |         ? +data | ||||||
|               : rbrace.test(data) |         : rbrace.test(data) | ||||||
|                 ? JSON.parse(data) |         ? JSON.parse(data) | ||||||
|                 : data |         : data | ||||||
|   } catch (e) {} |   } catch (e) {} | ||||||
|   return data |   return data | ||||||
| } | } | ||||||
|  | @ -236,8 +199,8 @@ function getWindow(node) { | ||||||
|   return node.window && node.document |   return node.window && node.document | ||||||
|     ? node |     ? node | ||||||
|     : node.nodeType === 9 |     : node.nodeType === 9 | ||||||
|       ? node.defaultView |     ? node.defaultView | ||||||
|       : false |     : false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //=============================css相关==================================
 | //=============================css相关==================================
 | ||||||
|  |  | ||||||
							
								
								
									
										115
									
								
								src/13-scan.js
								
								
								
								
							
							
						
						
									
										115
									
								
								src/13-scan.js
								
								
								
								
							|  | @ -6,14 +6,6 @@ | ||||||
| var stopScan = oneObject( | var stopScan = oneObject( | ||||||
|   'area,base,basefont,br,col,command,embed,hr,img,input,link,meta,param,source,track,wbr,noscript,script,style,textarea'.toUpperCase() |   'area,base,basefont,br,col,command,embed,hr,img,input,link,meta,param,source,track,wbr,noscript,script,style,textarea'.toUpperCase() | ||||||
| ) | ) | ||||||
| function isWidget(el) { |  | ||||||
|   //如果是组件,则返回组件的名字
 |  | ||||||
|   var name = el.nodeName.toLowerCase() |  | ||||||
|   if (/^anot-([a-z][a-z0-9\-]*)$/.test(name)) { |  | ||||||
|     return RegExp.$1 |  | ||||||
|   } |  | ||||||
|   return null |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function isRef(el) { | function isRef(el) { | ||||||
|   return el.hasAttribute('ref') ? el.getAttribute('ref') : null |   return el.hasAttribute('ref') ? el.getAttribute('ref') : null | ||||||
|  | @ -57,30 +49,8 @@ function executeBindings(bindings, vmodels) { | ||||||
|   bindings.length = 0 |   bindings.length = 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //https://github.com/RubyLouvre/Anot/issues/636
 |  | ||||||
| var mergeTextNodes = |  | ||||||
|   IEVersion && window.MutationObserver |  | ||||||
|     ? function(elem) { |  | ||||||
|         var node = elem.firstChild, |  | ||||||
|           text |  | ||||||
|         while (node) { |  | ||||||
|           var aaa = node.nextSibling |  | ||||||
|           if (node.nodeType === 3) { |  | ||||||
|             if (text) { |  | ||||||
|               text.nodeValue += node.nodeValue |  | ||||||
|               elem.removeChild(node) |  | ||||||
|             } else { |  | ||||||
|               text = node |  | ||||||
|             } |  | ||||||
|           } else { |  | ||||||
|             text = null |  | ||||||
|           } |  | ||||||
|           node = aaa |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     : 0 |  | ||||||
| var roneTime = /^\s*::/ | var roneTime = /^\s*::/ | ||||||
| var rmsAttr = /:(\w+)-?(.*)/ | var rmsAttr = /:(\w+)-?(.*)|@(.*)/ | ||||||
| 
 | 
 | ||||||
| var events = oneObject( | var events = oneObject( | ||||||
|   'animationend,blur,change,input,click,dblclick,focus,keydown,keypress,keyup,mousedown,mouseenter,mouseleave,mousemove,mouseout,mouseover,mouseup,scan,scroll,submit' |   'animationend,blur,change,input,click,dblclick,focus,keydown,keypress,keyup,mousedown,mouseenter,mouseleave,mousemove,mouseout,mouseover,mouseup,scan,scroll,submit' | ||||||
|  | @ -93,45 +63,7 @@ function bindingSorter(a, b) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var rnoCollect = /^(:\S+|data-\S+|on[a-z]+|style|class)$/ | var rnoCollect = /^(:\S+|data-\S+|on[a-z]+|style|class)$/ | ||||||
| var ronattr = '__fn__' |  | ||||||
| var specifiedVars = [':disabled', ':loading', ':value'] |  | ||||||
| var filterTypes = ['html', 'text', 'attr', 'data'] | var filterTypes = ['html', 'text', 'attr', 'data'] | ||||||
| function getOptionsFromTag(elem, vmodels) { |  | ||||||
|   var attributes = aslice.call(elem.attributes, 0) |  | ||||||
|   var ret = {} |  | ||||||
|   var vm = vmodels[0] || {} |  | ||||||
| 
 |  | ||||||
|   for (var i = 0, attr; (attr = attributes[i++]); ) { |  | ||||||
|     var name = attr.name |  | ||||||
|     if ( |  | ||||||
|       (attr.specified && !rnoCollect.test(name)) || |  | ||||||
|       specifiedVars.includes(name) |  | ||||||
|     ) { |  | ||||||
|       elem.removeAttribute(name) |  | ||||||
|       if (name.indexOf(ronattr) === 0) { |  | ||||||
|         name = attr.value.slice(6) |  | ||||||
|         ret[name] = elem[attr.value] |  | ||||||
|         delete elem[attr.value] |  | ||||||
|       } else { |  | ||||||
|         var camelizeName = camelize(name) |  | ||||||
|         if (camelizeName.indexOf('@') === 0) { |  | ||||||
|           camelizeName = camelizeName.slice(1) |  | ||||||
|           attr.value = attr.value.replace(/\(.*\)$/, '') |  | ||||||
|           if (vm.$id.slice(0, 10) === 'proxy-each') { |  | ||||||
|             vm = vm.$up |  | ||||||
|           } |  | ||||||
|           var fn = parseVmValue(vm, attr.value) |  | ||||||
|           if (fn && typeof fn === 'function') { |  | ||||||
|             ret[camelizeName] = fn.bind(vm) |  | ||||||
|           } |  | ||||||
|         } else { |  | ||||||
|           ret[camelizeName] = parseData(attr.value) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return ret |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function scanAttr(elem, vmodels, match) { | function scanAttr(elem, vmodels, match) { | ||||||
|   var scanNode = true |   var scanNode = true | ||||||
|  | @ -151,9 +83,10 @@ function scanAttr(elem, vmodels, match) { | ||||||
|           //如果是以指定前缀命名的
 |           //如果是以指定前缀命名的
 | ||||||
|           var type = match[1] |           var type = match[1] | ||||||
|           var param = match[2] || '' |           var param = match[2] || '' | ||||||
|  |           var eparam = match[3] || '' // 事件绑定的简写
 | ||||||
|           var value = attr.value |           var value = attr.value | ||||||
|           if (events[type]) { |           if (events[type] || events[eparam]) { | ||||||
|             param = type |             param = type || eparam | ||||||
|             type = 'on' |             type = 'on' | ||||||
|           } |           } | ||||||
|           if (directives[type]) { |           if (directives[type]) { | ||||||
|  | @ -171,6 +104,7 @@ function scanAttr(elem, vmodels, match) { | ||||||
|                 (directives[type].priority || type.charCodeAt(0) * 10) + |                 (directives[type].priority || type.charCodeAt(0) * 10) + | ||||||
|                 (Number(param.replace(/\D/g, '')) || 0) |                 (Number(param.replace(/\D/g, '')) || 0) | ||||||
|             } |             } | ||||||
|  |             // 如果指令允许使用过滤器
 | ||||||
|             if (filterTypes.includes(type)) { |             if (filterTypes.includes(type)) { | ||||||
|               var filters = getToken(value).filters |               var filters = getToken(value).filters | ||||||
|               binding.expr = binding.expr.replace(filters, '') |               binding.expr = binding.expr.replace(filters, '') | ||||||
|  | @ -211,12 +145,7 @@ function scanAttr(elem, vmodels, match) { | ||||||
|       executeBindings(bindings, vmodels) |       executeBindings(bindings, vmodels) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if ( |   if (scanNode && !stopScan[elem.tagName]) { | ||||||
|     scanNode && |  | ||||||
|     !stopScan[elem.tagName] && |  | ||||||
|     (isWidget(elem) ? elem.msResolved : 1) |  | ||||||
|   ) { |  | ||||||
|     mergeTextNodes && mergeTextNodes(elem) |  | ||||||
|     scanNodeList(elem, vmodels) //扫描子孙元素
 |     scanNodeList(elem, vmodels) //扫描子孙元素
 | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | @ -239,33 +168,11 @@ function scanNodeArray(nodes, vmodels) { | ||||||
|     switch (node.nodeType) { |     switch (node.nodeType) { | ||||||
|       case 1: |       case 1: | ||||||
|         var elem = node |         var elem = node | ||||||
|         if ( |         if (elem.parentNode && elem.parentNode.nodeType === 1) { | ||||||
|           !elem.msResolved && |           // 非组件才检查 ref属性
 | ||||||
|           elem.parentNode && |           var ref = isRef(elem) | ||||||
|           elem.parentNode.nodeType === 1 |           if (ref && vmodels.length) { | ||||||
|         ) { |             vmodels[0].$refs[ref] = elem | ||||||
|           var widget = isWidget(elem) |  | ||||||
| 
 |  | ||||||
|           if (widget) { |  | ||||||
|             elem.setAttribute('is-widget', '') |  | ||||||
|             elem.removeAttribute(':if') |  | ||||||
|             elem.removeAttribute(':if-loop') |  | ||||||
|             componentQueue.push({ |  | ||||||
|               element: elem, |  | ||||||
|               vmodels: vmodels, |  | ||||||
|               name: widget |  | ||||||
|             }) |  | ||||||
|             if (Anot.components[widget]) { |  | ||||||
|               // log(widget, Anot.components)
 |  | ||||||
|               //确保所有:attr-name扫描完再处理
 |  | ||||||
|               _delay_component(widget) |  | ||||||
|             } |  | ||||||
|           } else { |  | ||||||
|             // 非组件才检查 ref属性
 |  | ||||||
|             var ref = isRef(elem) |  | ||||||
|             if (ref && vmodels.length) { |  | ||||||
|               vmodels[0].$refs[ref] = elem |  | ||||||
|             } |  | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,351 +0,0 @@ | ||||||
| var componentQueue = [] |  | ||||||
| var widgetList = [] |  | ||||||
| var componentHooks = { |  | ||||||
|   __init__: noop, |  | ||||||
|   componentWillMount: noop, |  | ||||||
|   componentDidMount: noop, |  | ||||||
|   childComponentDidMount: noop, |  | ||||||
|   componentWillUnmount: noop, |  | ||||||
|   render: function() { |  | ||||||
|     return null |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function parseSlot(collections, vms) { |  | ||||||
|   var arr = aslice.call(collections, 0) |  | ||||||
|   var obj = { __extra__: [] } |  | ||||||
|   arr.forEach(function(elem) { |  | ||||||
|     switch (elem.nodeType) { |  | ||||||
|       case 1: |  | ||||||
|         var isSlotTag = elem.tagName === 'SLOT' |  | ||||||
|         var slotKey = null |  | ||||||
|         var isSlotAttr = elem.getAttribute('slot') |  | ||||||
| 
 |  | ||||||
|         if (isSlotTag) { |  | ||||||
|           slotKey = elem.name || elem.getAttribute('name') |  | ||||||
|         } else if (isSlotAttr) { |  | ||||||
|           slotKey = isSlotAttr |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (slotKey) { |  | ||||||
|           obj[slotKey] = obj[slotKey] || [] |  | ||||||
|           elem.removeAttribute('slot') |  | ||||||
|           if (isSlotTag) { |  | ||||||
|             obj[slotKey].push(elem.innerHTML) |  | ||||||
|           } else { |  | ||||||
|             obj[slotKey].push(elem.outerHTML) |  | ||||||
|           } |  | ||||||
|         } else { |  | ||||||
|           var txt = elem.outerHTML |  | ||||||
|           if (isWidget(elem) || /:[\w-]*=".*"/.test(txt)) { |  | ||||||
|             break |  | ||||||
|           } |  | ||||||
|           if (rexpr.test(txt)) { |  | ||||||
|             var expr = normalizeExpr(txt) |  | ||||||
|             txt = parseExpr(expr, vms, {}).apply(0, vms) |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           obj.__extra__.push(txt) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         break |  | ||||||
|       case 3: |  | ||||||
|         var txt = elem.textContent.trim() |  | ||||||
|         if (txt) { |  | ||||||
|           obj.__extra__.push(txt) |  | ||||||
|         } |  | ||||||
|         break |  | ||||||
|       default: |  | ||||||
|         break |  | ||||||
|     } |  | ||||||
|     elem.parentNode.removeChild(elem) |  | ||||||
|   }) |  | ||||||
|   return obj |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function parseVmValue(vm, key, val) { |  | ||||||
|   if (arguments.length === 2) { |  | ||||||
|     var oval = Function('o', 'return o.' + key)(vm) |  | ||||||
|     if (oval && typeof oval === 'object') { |  | ||||||
|       try { |  | ||||||
|         return oval.$model |  | ||||||
|       } catch (err) {} |  | ||||||
|     } |  | ||||||
|     return oval |  | ||||||
|   } else if (arguments.length === 3) { |  | ||||||
|     Function('o', 'v', 'return o.' + key + ' = v')(vm, val) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Anot.components = {} |  | ||||||
| Anot.component = function(name, opts) { |  | ||||||
|   if (opts) { |  | ||||||
|     Anot.components[name] = Anot.mix({}, componentHooks, opts) |  | ||||||
|   } |  | ||||||
|   for (var i = 0, obj; (obj = componentQueue[i]); i++) { |  | ||||||
|     if (name === obj.name) { |  | ||||||
|       componentQueue.splice(i, 1) |  | ||||||
|       i-- |  | ||||||
|       // (obj, Anot.components[name], obj.element, obj.name)
 |  | ||||||
|       ;(function(host, hooks, elem, widget) { |  | ||||||
|         //如果elem已从Document里移除,直接返回
 |  | ||||||
|         if (!Anot.contains(DOC, elem) || elem.msResolved) { |  | ||||||
|           Anot.Array.remove(componentQueue, host) |  | ||||||
|           return |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         var dependencies = 1 |  | ||||||
| 
 |  | ||||||
|         //===========收集各种配置=======
 |  | ||||||
|         if (elem.getAttribute(':attr-uuid')) { |  | ||||||
|           //如果还没有解析完,就延迟一下 #1155
 |  | ||||||
|           return |  | ||||||
|         } |  | ||||||
|         hooks.watch = hooks.watch || {} |  | ||||||
|         var parentVm = host.vmodels.concat().pop() |  | ||||||
|         var state = {} |  | ||||||
|         var props = getOptionsFromTag(elem, host.vmodels) |  | ||||||
|         var $id = props.uuid || generateID(widget) |  | ||||||
|         var slots = { __extra__: [] } |  | ||||||
| 
 |  | ||||||
|         // 对象组件的子父vm关系, 只存最顶层的$components对象中,
 |  | ||||||
|         while (parentVm.$up && parentVm.$up.__WIDGET__ === name) { |  | ||||||
|           parentVm = parentVm.$up |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (elem.childNodes.length) { |  | ||||||
|           slots = parseSlot(elem.childNodes, host.vmodels) |  | ||||||
|         } |  | ||||||
|         var txtContent = slots.__extra__.join('') |  | ||||||
|         delete slots.__extra__ |  | ||||||
|         elem.text = function() { |  | ||||||
|           return txtContent |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (props.hasOwnProperty(':disabled')) { |  | ||||||
|           var disabledKey = props[':disabled'] |  | ||||||
|           var disabledKeyReverse = false |  | ||||||
|           if (disabledKey.indexOf('!') === 0) { |  | ||||||
|             disabledKey = disabledKey.slice(1) |  | ||||||
|             disabledKeyReverse = true |  | ||||||
|           } |  | ||||||
|           state.disabled = parseVmValue(parentVm, disabledKey) |  | ||||||
|           if (disabledKeyReverse) { |  | ||||||
|             state.disabled = !state.disabled |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           parentVm.$watch(disabledKey, function(val) { |  | ||||||
|             if (disabledKeyReverse) { |  | ||||||
|               val = !val |  | ||||||
|             } |  | ||||||
|             Anot.vmodels[$id].disabled = val |  | ||||||
|           }) |  | ||||||
| 
 |  | ||||||
|           delete props[':disabled'] |  | ||||||
|         } |  | ||||||
|         if (props.hasOwnProperty(':loading')) { |  | ||||||
|           var loadingKey = props[':loading'] |  | ||||||
|           var loadingKeyReverse = false |  | ||||||
|           if (loadingKey.indexOf('!') === 0) { |  | ||||||
|             loadingKey = loadingKey.slice(1) |  | ||||||
|             loadingKeyReverse = true |  | ||||||
|           } |  | ||||||
|           state.loading = parseVmValue(parentVm, loadingKey) |  | ||||||
|           if (loadingKeyReverse) { |  | ||||||
|             state.loading = !state.loading |  | ||||||
|           } |  | ||||||
|           parentVm.$watch(loadingKey, function(val) { |  | ||||||
|             if (loadingKeyReverse) { |  | ||||||
|               val = !val |  | ||||||
|             } |  | ||||||
|             Anot.vmodels[$id].loading = val |  | ||||||
|           }) |  | ||||||
|           delete props[':loading'] |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // :value可实现双向同步值
 |  | ||||||
|         if (props.hasOwnProperty(':value')) { |  | ||||||
|           var valueKey = props[':value'] |  | ||||||
|           var valueWatcher = function() { |  | ||||||
|             var val = parseVmValue(parentVm, valueKey) |  | ||||||
|             Anot.vmodels[$id].value = val |  | ||||||
|           } |  | ||||||
|           var childValueWatcher = function() { |  | ||||||
|             var val = this.value |  | ||||||
|             if (val && typeof val === 'object') { |  | ||||||
|               val = val.$model |  | ||||||
|             } |  | ||||||
|             parseVmValue(parentVm, valueKey, val) |  | ||||||
|           } |  | ||||||
|           state.value = parseVmValue(parentVm, valueKey) |  | ||||||
| 
 |  | ||||||
|           if (hooks.watch.value) { |  | ||||||
|             hooks.watch.value = [hooks.watch.value] |  | ||||||
|           } else { |  | ||||||
|             hooks.watch.value = [] |  | ||||||
|           } |  | ||||||
|           if (hooks.watch['value.length']) { |  | ||||||
|             hooks.watch['value.length'] = [hooks.watch['value.length']] |  | ||||||
|           } else { |  | ||||||
|             hooks.watch['value.length'] = [] |  | ||||||
|           } |  | ||||||
|           if (hooks.watch['value.*']) { |  | ||||||
|             hooks.watch['value.*'] = [hooks.watch['value.*']] |  | ||||||
|           } else { |  | ||||||
|             hooks.watch['value.*'] = [] |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           parentVm.$watch(valueKey, valueWatcher) |  | ||||||
|           if (Array.isArray(state.value)) { |  | ||||||
|             parentVm.$watch(valueKey + '.*', valueWatcher) |  | ||||||
|             parentVm.$watch(valueKey + '.length', valueWatcher) |  | ||||||
|             hooks.watch['value.*'].push(childValueWatcher) |  | ||||||
|             hooks.watch['value.length'].push(childValueWatcher) |  | ||||||
|           } else { |  | ||||||
|             hooks.watch.value.push(childValueWatcher) |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           delete props[':value'] |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         delete props.uuid |  | ||||||
|         delete props.name |  | ||||||
|         delete props.isWidget |  | ||||||
| 
 |  | ||||||
|         hooks.props = hooks.props || {} |  | ||||||
|         hooks.state = hooks.state || {} |  | ||||||
| 
 |  | ||||||
|         Object.assign(hooks.props, props) |  | ||||||
|         Object.assign(hooks.state, state) |  | ||||||
| 
 |  | ||||||
|         var __READY__ = false |  | ||||||
| 
 |  | ||||||
|         hooks.__init__.call(elem, hooks.props, hooks.state, function next() { |  | ||||||
|           __READY__ = true |  | ||||||
| 
 |  | ||||||
|           delete elem.text |  | ||||||
|         }) |  | ||||||
| 
 |  | ||||||
|         if (!__READY__) { |  | ||||||
|           return |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         hooks.$id = $id |  | ||||||
| 
 |  | ||||||
|         //==========构建VM=========
 |  | ||||||
|         var { |  | ||||||
|           componentWillMount, |  | ||||||
|           componentDidMount, |  | ||||||
|           childComponentDidMount, |  | ||||||
|           componentWillUnmount, |  | ||||||
|           render |  | ||||||
|         } = hooks |  | ||||||
| 
 |  | ||||||
|         delete hooks.__init__ |  | ||||||
|         delete hooks.componentWillMount |  | ||||||
|         delete hooks.componentDidMount |  | ||||||
|         delete hooks.childComponentDidMount |  | ||||||
|         delete hooks.componentWillUnmount |  | ||||||
| 
 |  | ||||||
|         var vmodel = Anot(hooks) |  | ||||||
|         Anot.vmodels[vmodel.$id] = vmodel |  | ||||||
|         hideProperty(vmodel, '__WIDGET__', name) |  | ||||||
|         hideProperty(vmodel, '$recycle', function() { |  | ||||||
|           for (var i in this.$events) { |  | ||||||
|             var ev = this.$events[i] || [] |  | ||||||
|             var len = ev.length |  | ||||||
|             while (len--) { |  | ||||||
|               if (ev[len].type === null || ev[len].type === 'user-watcher') { |  | ||||||
|                 ev.splice(len, 1) |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }) |  | ||||||
|         delete vmodel.$mounted |  | ||||||
| 
 |  | ||||||
|         // 对象组件的子父vm关系, 只存最顶层的$components对象中,
 |  | ||||||
|         // 而子vm, 无论向下多少级, 他们的$up对象也只存最顶层的组件vm
 |  | ||||||
|         parentVm.$components.push(vmodel) |  | ||||||
|         if (parentVm.__WIDGET__ === name) { |  | ||||||
|           vmodel.$up = parentVm |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         elem.msResolved = 1 //防止二进扫描此元素
 |  | ||||||
| 
 |  | ||||||
|         componentWillMount.call(vmodel) |  | ||||||
| 
 |  | ||||||
|         Anot.clearHTML(elem) |  | ||||||
|         var html = render.call(vmodel, slots) || '' |  | ||||||
| 
 |  | ||||||
|         html = html.replace(/<\w+[^>]*>/g, function(m, s) { |  | ||||||
|           return m.replace(/[\n\t\s]{1,}/g, ' ') |  | ||||||
|         }) |  | ||||||
| 
 |  | ||||||
|         elem.innerHTML = html |  | ||||||
| 
 |  | ||||||
|         hideProperty(vmodel, '$elem', elem) |  | ||||||
|         elem.__VM__ = vmodel |  | ||||||
| 
 |  | ||||||
|         Anot.fireDom(elem, 'datasetchanged', { |  | ||||||
|           vm: vmodel, |  | ||||||
|           childReady: 1 |  | ||||||
|         }) |  | ||||||
| 
 |  | ||||||
|         var children = 0 |  | ||||||
|         var removeFn = Anot.bind(elem, 'datasetchanged', function(ev) { |  | ||||||
|           if (ev.childReady) { |  | ||||||
|             dependencies += ev.childReady |  | ||||||
|             if (vmodel.$id !== ev.vm.$id) { |  | ||||||
|               if (ev.childReady === -1) { |  | ||||||
|                 children++ |  | ||||||
|                 childComponentDidMount.call(vmodel, ev.vm) |  | ||||||
|               } |  | ||||||
|               ev.stopPropagation() |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|           if (dependencies === 0) { |  | ||||||
|             var timer = setTimeout(function() { |  | ||||||
|               clearTimeout(timer) |  | ||||||
|               elem.removeAttribute('is-widget') |  | ||||||
|               componentDidMount.call(vmodel) |  | ||||||
|             }, children ? Math.max(children * 17, 100) : 17) |  | ||||||
| 
 |  | ||||||
|             Anot.unbind(elem, 'datasetchanged', removeFn) |  | ||||||
|             //==================
 |  | ||||||
|             host.rollback = function() { |  | ||||||
|               try { |  | ||||||
|                 componentWillUnmount.call(vmodel) |  | ||||||
|               } catch (e) {} |  | ||||||
|               parentVm.$recycle && parentVm.$recycle() |  | ||||||
|               Anot.Array.remove(parentVm.$components, vmodel) |  | ||||||
|               delete Anot.vmodels[vmodel.$id] |  | ||||||
|             } |  | ||||||
|             injectDisposeQueue(host, widgetList) |  | ||||||
|             if (window.chrome) { |  | ||||||
|               elem.addEventListener('DOMNodeRemovedFromDocument', function() { |  | ||||||
|                 setTimeout(rejectDisposeQueue) |  | ||||||
|               }) |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }) |  | ||||||
| 
 |  | ||||||
|         scanTag(elem, [vmodel]) |  | ||||||
| 
 |  | ||||||
|         if (!elem.childNodes.length) { |  | ||||||
|           Anot.fireDom(elem, 'datasetchanged', { |  | ||||||
|             vm: vmodel, |  | ||||||
|             childReady: -1 |  | ||||||
|           }) |  | ||||||
|         } else { |  | ||||||
|           var id2 = setTimeout(function() { |  | ||||||
|             clearTimeout(id2) |  | ||||||
|             Anot.fireDom(elem, 'datasetchanged', { |  | ||||||
|               vm: vmodel, |  | ||||||
|               childReady: -1 |  | ||||||
|             }) |  | ||||||
|           }, 17) |  | ||||||
|         } |  | ||||||
|       })(obj, toJson(Anot.components[name]), obj.element, obj.name) // jshint ignore:line
 |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -9,25 +9,6 @@ bools.replace(rword, function(name) { | ||||||
|   boolMap[name.toLowerCase()] = name |   boolMap[name.toLowerCase()] = name | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| var propMap = { |  | ||||||
|   //属性名映射
 |  | ||||||
|   'accept-charset': 'acceptCharset', |  | ||||||
|   char: 'ch', |  | ||||||
|   charoff: 'chOff', |  | ||||||
|   class: 'className', |  | ||||||
|   for: 'htmlFor', |  | ||||||
|   'http-equiv': 'httpEquiv' |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| var anomaly = [ |  | ||||||
|   'accessKey,bgColor,cellPadding,cellSpacing,codeBase,codeType,colSpan', |  | ||||||
|   'dateTime,defaultValue,frameBorder,longDesc,maxLength,marginWidth,marginHeight', |  | ||||||
|   'rowSpan,tabIndex,useMap,vSpace,valueType,vAlign' |  | ||||||
| ].join(',') |  | ||||||
| anomaly.replace(rword, function(name) { |  | ||||||
|   propMap[name.toLowerCase()] = name |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| var attrDir = Anot.directive('attr', { | var attrDir = Anot.directive('attr', { | ||||||
|   init: function(binding) { |   init: function(binding) { | ||||||
|     //{{aaa}} --> aaa
 |     //{{aaa}} --> aaa
 | ||||||
|  | @ -46,8 +27,9 @@ var attrDir = Anot.directive('attr', { | ||||||
|         'data-loaded', |         'data-loaded', | ||||||
|         binding.vmodels |         binding.vmodels | ||||||
|       ) |       ) | ||||||
|       var outer = (binding.includeReplace = !!Anot(elem).data('includeReplace')) |       // 是否直接替换当前容器
 | ||||||
|       if (Anot(elem).data('cache')) { |       var outer = (binding.includeReplace = elem.hasAttribute('replace')) | ||||||
|  |       if (elem.hasAttribute('cache')) { | ||||||
|         binding.templateCache = {} |         binding.templateCache = {} | ||||||
|       } |       } | ||||||
|       binding.start = DOC.createComment(':include') |       binding.start = DOC.createComment(':include') | ||||||
|  | @ -66,17 +48,16 @@ var attrDir = Anot.directive('attr', { | ||||||
|   update: function(val) { |   update: function(val) { | ||||||
|     var elem = this.element |     var elem = this.element | ||||||
|     var obj = {} |     var obj = {} | ||||||
|     var vm = this.vmodels[0] |  | ||||||
| 
 | 
 | ||||||
|     val = toJson(val) |     val = toJson(val) | ||||||
| 
 | 
 | ||||||
|     if (this.param) { |     if (this.param) { | ||||||
|       if (typeof val === 'object' && val !== null) { |       if (val && typeof val === 'object') { | ||||||
|         if (Array.isArray(val)) { |         if (Array.isArray(val)) { | ||||||
|           obj[this.param] = val |           obj[this.param] = val | ||||||
|         } else { |         } else { | ||||||
|           if (Date.isDate(val)) { |           if (Date.isDate(val)) { | ||||||
|             obj[this.param] = val.toUTCString() |             obj[this.param] = val.toISOString() | ||||||
|           } else { |           } else { | ||||||
|             obj[this.param] = val |             obj[this.param] = val | ||||||
|           } |           } | ||||||
|  | @ -85,10 +66,12 @@ var attrDir = Anot.directive('attr', { | ||||||
|         obj[this.param] = val |         obj[this.param] = val | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       if (!val || typeof val !== 'object' || Array.isArray(val)) { |       if ( | ||||||
|         return |         !val || | ||||||
|       } |         typeof val !== 'object' || | ||||||
|       if (Date.isDate(val)) { |         Array.isArray(val) || | ||||||
|  |         Date.isDate(val) | ||||||
|  |       ) { | ||||||
|         return |         return | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  | @ -97,71 +80,38 @@ var attrDir = Anot.directive('attr', { | ||||||
| 
 | 
 | ||||||
|     for (var i in obj) { |     for (var i in obj) { | ||||||
|       if (i === 'style') { |       if (i === 'style') { | ||||||
|         console.error('设置style样式, 请改用 :css指令') |         elem.style.cssText = obj[i] | ||||||
|         continue |         continue | ||||||
|       } |       } | ||||||
|       // 通过属性设置回调,必须以@符号开头
 |  | ||||||
|       if (i.indexOf('@') === 0) { |  | ||||||
|         if (typeof obj[i] !== 'function') { |  | ||||||
|           continue |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       if (i === 'href' || i === 'src') { |       if (i === 'href' || i === 'src') { | ||||||
|         //处理IE67自动转义的问题
 |  | ||||||
|         if (!root.hasAttribute) obj[i] = obj[i].replace(/&/g, '&') |  | ||||||
| 
 |  | ||||||
|         elem[i] = obj[i] |         elem[i] = obj[i] | ||||||
| 
 |  | ||||||
|         //chrome v37- 下embed标签动态设置的src,无法发起请求
 |  | ||||||
|         if (window.chrome && elem.tagName === 'EMBED') { |  | ||||||
|           var _parent = elem.parentNode |  | ||||||
|           var com = DOC.createComment(':src') |  | ||||||
|           _parent.replaceChild(com, elem) |  | ||||||
|           _parent.replaceChild(elem, com) |  | ||||||
|         } |  | ||||||
|       } else { |       } else { | ||||||
|         var k = i |  | ||||||
|         //古董IE下,部分属性名字要进行映射
 |  | ||||||
|         if (!W3C && propMap[k]) { |  | ||||||
|           k = propMap[k] |  | ||||||
|         } |  | ||||||
|         if (obj[i] === false || obj[i] === null || obj[i] === undefined) { |         if (obj[i] === false || obj[i] === null || obj[i] === undefined) { | ||||||
|           obj[i] = '' |           obj[i] = '' | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (typeof elem[boolMap[k]] === 'boolean') { |         if (typeof elem[boolMap[i]] === 'boolean') { | ||||||
|           //布尔属性必须使用el.xxx = true|false方式设值
 |           //布尔属性必须使用el.xxx = true|false方式设值
 | ||||||
|           elem[boolMap[k]] = !!obj[i] |           obj[i] = !!obj[i] | ||||||
|  |           elem[boolMap[i]] = obj[i] | ||||||
| 
 | 
 | ||||||
|           //如果为false, IE全系列下相当于setAttribute(xxx, ''),会影响到样式,需要进一步处理
 |  | ||||||
|           if (!obj[i]) { |           if (!obj[i]) { | ||||||
|             obj[i] = !!obj[i] |             elem.removeAttribute(boolMap[i]) | ||||||
|           } |  | ||||||
|           if (obj[i] === false) { |  | ||||||
|             elem.removeAttribute(k) |  | ||||||
|             continue |             continue | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         //SVG只能使用setAttribute(xxx, yyy), VML只能使用elem.xxx = yyy ,HTML的固有属性必须elem.xxx = yyy
 |         //SVG只能使用setAttribute(xxx, yyy), VML只能使用elem.xxx = yyy ,HTML的固有属性必须elem.xxx = yyy
 | ||||||
|         var isInnate = rsvg.test(elem) |         var isInnate = rsvg.test(elem) ? false : i in elem.cloneNode(false) | ||||||
|           ? false |  | ||||||
|           : DOC.namespaces && isVML(elem) |  | ||||||
|             ? true |  | ||||||
|             : k in elem.cloneNode(false) |  | ||||||
|         if (isInnate) { |         if (isInnate) { | ||||||
|           elem[k] = obj[i] |           elem[i] = obj[i] | ||||||
|         } else { |         } else { | ||||||
|           if (typeof obj[i] === 'object') { |           if (typeof obj[i] === 'object') { | ||||||
|             obj[i] = Date.isDate(obj[i]) |             obj[i] = Date.isDate(obj[i]) | ||||||
|               ? obj[i].toUTCString() |               ? obj[i].toISOString() | ||||||
|               : JSON.stringify(obj[i]) |               : JSON.stringify(obj[i]) | ||||||
|           } else if (typeof obj[i] === 'function') { |  | ||||||
|             k = ronattr + camelize(k.slice(1)) |  | ||||||
|             elem[k] = obj[i].bind(vm) |  | ||||||
|             obj[i] = k |  | ||||||
|           } |           } | ||||||
|           elem.setAttribute(k, obj[i]) |           elem.setAttribute(i, obj[i]) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1,25 +1,11 @@ | ||||||
| //类名定义, :class="xx:yy"  :class="{xx: yy}" :class="xx" :class="{{xx}}"
 | //类名定义  :class="{xx: yy}" :class="xx"
 | ||||||
| Anot.directive('class', { | Anot.directive('class', { | ||||||
|   init: function(binding) { |   init: function(binding) { | ||||||
|     binding.expr = binding.expr.replace(/\n/g, '  ').replace(/\s{2,}/g, '  ') |     binding.expr = binding.expr.replace(/\n/g, ' ').replace(/\s+/g, ' ') | ||||||
|     var expr = [] |  | ||||||
|     if (!/^\{.*\}$/.test(binding.expr)) { |  | ||||||
|       expr = binding.expr.split(':') |  | ||||||
|       expr[1] = (expr[1] && expr[1].trim()) || 'true' |  | ||||||
|       var arr = expr[0].split(/\s+/) |  | ||||||
|       binding.expr = |  | ||||||
|         '{' + |  | ||||||
|         arr |  | ||||||
|           .map(function(it) { |  | ||||||
|             return it + ': ' + expr[1] |  | ||||||
|           }) |  | ||||||
|           .join(', ') + |  | ||||||
|         '}' |  | ||||||
|     } else if (/^\{\{.*\}\}$/.test(binding.expr)) { |  | ||||||
|       binding.expr = binding.expr.slice(2, -2) |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (binding.type === 'hover' || binding.type === 'active') { |     if (binding.type === 'hover' || binding.type === 'active') { | ||||||
|  |       var expr = new Function('return ' + binding.expr)() | ||||||
|  | 
 | ||||||
|       //确保只绑定一次
 |       //确保只绑定一次
 | ||||||
|       if (!binding.hasBindEvent) { |       if (!binding.hasBindEvent) { | ||||||
|         var elem = binding.element |         var elem = binding.element | ||||||
|  | @ -32,16 +18,16 @@ Anot.directive('class', { | ||||||
|           activate = 'mousedown' |           activate = 'mousedown' | ||||||
|           abandon = 'mouseup' |           abandon = 'mouseup' | ||||||
|           var fn0 = $elem.bind('mouseleave', function() { |           var fn0 = $elem.bind('mouseleave', function() { | ||||||
|             $elem.removeClass(expr[0]) |             $elem.removeClass(expr) | ||||||
|           }) |           }) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       var fn1 = $elem.bind(activate, function() { |       var fn1 = $elem.bind(activate, function() { | ||||||
|         $elem.addClass(expr[0]) |         $elem.addClass(expr) | ||||||
|       }) |       }) | ||||||
|       var fn2 = $elem.bind(abandon, function() { |       var fn2 = $elem.bind(abandon, function() { | ||||||
|         $elem.removeClass(expr[0]) |         $elem.removeClass(expr) | ||||||
|       }) |       }) | ||||||
|       binding.rollback = function() { |       binding.rollback = function() { | ||||||
|         $elem.unbind('mouseleave', fn0) |         $elem.unbind('mouseleave', fn0) | ||||||
|  | @ -73,9 +59,8 @@ Anot.directive('class', { | ||||||
|       obj = obj.$model |       obj = obj.$model | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     var $elem = Anot(this.element) |  | ||||||
|     for (var i in obj) { |     for (var i in obj) { | ||||||
|       $elem.toggleClass(i, !!obj[i]) |       this.element.classList.toggle(i, !!obj[i]) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | @ -4,22 +4,22 @@ Anot.directive('css', { | ||||||
|   init: directives.attr.init, |   init: directives.attr.init, | ||||||
|   update: function(val) { |   update: function(val) { | ||||||
|     var $elem = Anot(this.element) |     var $elem = Anot(this.element) | ||||||
|     if (!this.param) { |     if (this.param) { | ||||||
|       var obj = val |  | ||||||
|       try { |  | ||||||
|         if (typeof val === 'object') { |  | ||||||
|           if (!Anot.isPlainObject(val)) obj = val.$model |  | ||||||
|         } else { |  | ||||||
|           obj = new Function('return ' + val)() |  | ||||||
|         } |  | ||||||
|         for (var i in obj) { |  | ||||||
|           $elem.css(i, obj[i]) |  | ||||||
|         } |  | ||||||
|       } catch (err) { |  | ||||||
|         log('样式格式错误 %c %s="%s"', 'color:#f00', this.name, this.expr) |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       $elem.css(this.param, val) |       $elem.css(this.param, val) | ||||||
|  |     } else { | ||||||
|  |       if (typeof val !== 'object') { | ||||||
|  |         return log( | ||||||
|  |           ':css指令格式错误 %c %s="%s"', | ||||||
|  |           'color:#f00', | ||||||
|  |           this.name, | ||||||
|  |           this.expr | ||||||
|  |         ) | ||||||
|  |       } | ||||||
|  |       var obj = val | ||||||
|  |       if (!Anot.isPlainObject(obj)) { | ||||||
|  |         obj = val.$model | ||||||
|  |       } | ||||||
|  |       $elem.css(obj) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | @ -3,17 +3,25 @@ Anot.directive('data', { | ||||||
|   priority: 100, |   priority: 100, | ||||||
|   init: directives.attr.init, |   init: directives.attr.init, | ||||||
|   update: function(val) { |   update: function(val) { | ||||||
|     var obj = val |     var $el = Anot(this.element) | ||||||
|     if (typeof obj === 'object' && obj !== null) { |     if (this.param) { | ||||||
|       if (!Anot.isPlainObject(obj)) obj = val.$model |       $el.data(this.param, val) | ||||||
| 
 |  | ||||||
|       for (var i in obj) { |  | ||||||
|         this.element.setAttribute('data-' + i, obj[i]) |  | ||||||
|       } |  | ||||||
|     } else { |     } else { | ||||||
|       if (!this.param) return |       if (typeof val !== 'object') { | ||||||
| 
 |         return log( | ||||||
|       this.element.setAttribute('data-' + this.param, obj) |           ':data指令格式错误 %c %s="%s"', | ||||||
|  |           'color:#f00', | ||||||
|  |           this.name, | ||||||
|  |           this.expr | ||||||
|  |         ) | ||||||
|  |       } | ||||||
|  |       var obj = val | ||||||
|  |       if (!Anot.isPlainObject(obj)) { | ||||||
|  |         obj = val.$model | ||||||
|  |       } | ||||||
|  |       for (var i in obj) { | ||||||
|  |         $el.data(i, obj[i]) | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
|  |  | ||||||
							
								
								
									
										129
									
								
								src/20-:rule.js
								
								
								
								
							
							
						
						
									
										129
									
								
								src/20-:rule.js
								
								
								
								
							|  | @ -1,129 +0,0 @@ | ||||||
| /*------ 表单验证 -------*/ |  | ||||||
| var __rules = {} |  | ||||||
| Anot.validate = function(key, cb) { |  | ||||||
|   if (!__rules[key]) { |  | ||||||
|     throw new Error('validate [' + key + '] not exists.') |  | ||||||
|   } |  | ||||||
|   if (typeof cb === 'function') { |  | ||||||
|     __rules[key].event = cb |  | ||||||
|   } |  | ||||||
|   var result = __rules[key].result |  | ||||||
|   for (var k in result) { |  | ||||||
|     if (!result[k].passed) { |  | ||||||
|       return result[k] |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return true |  | ||||||
| } |  | ||||||
| Anot.directive('rule', { |  | ||||||
|   priority: 2010, |  | ||||||
|   init: function(binding) { |  | ||||||
|     if (binding.param && !__rules[binding.param]) { |  | ||||||
|       __rules[binding.param] = { |  | ||||||
|         event: noop, |  | ||||||
|         result: {} |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     binding.target = __rules[binding.param] |  | ||||||
|   }, |  | ||||||
|   update: function(opt) { |  | ||||||
|     var _this = this |  | ||||||
|     var elem = this.element |  | ||||||
|     if (!['INPUT', 'TEXTAREA'].includes(elem.nodeName)) { |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
|     if (elem.msBinded) { |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
|     if (this.target) { |  | ||||||
|       this.target.result[elem.expr] = { key: elem.expr } |  | ||||||
|     } |  | ||||||
|     var target = this.target |  | ||||||
| 
 |  | ||||||
|     // 0: 验证通过
 |  | ||||||
|     // 10001: 不能为空
 |  | ||||||
|     // 10002: 必须为合法数字
 |  | ||||||
|     // 10003: Email格式错误
 |  | ||||||
|     // 10004: 手机格式错误
 |  | ||||||
|     // 10005: 必须为纯中文
 |  | ||||||
|     // 10006: 格式匹配错误(正则)
 |  | ||||||
|     // 10011: 输入值超过指定最大长度
 |  | ||||||
|     // 10012: 输入值短于指定最小长度
 |  | ||||||
|     // 10021: 输入值大于指定最大数值
 |  | ||||||
|     // 10022: 输入值小于指定最小数值
 |  | ||||||
|     // 10031: 与指定的表单的值不一致
 |  | ||||||
|     function checked(ev) { |  | ||||||
|       var val = elem.value |  | ||||||
|       var code = 0 |  | ||||||
| 
 |  | ||||||
|       if (opt.require && (val === '' || val === null)) { |  | ||||||
|         code = 10001 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.isNumeric) { |  | ||||||
|         code = !isFinite(val) ? 10002 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.isEmail) |  | ||||||
|         code = !/^[\w\.\-]+@\w+([\.\-]\w+)*\.\w+$/.test(val) ? 10003 : 0 |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.isPhone) { |  | ||||||
|         code = !/^1[34578]\d{9}$/.test(val) ? 10004 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.isCN) { |  | ||||||
|         code = !/^[\u4e00-\u9fa5]+$/.test(val) ? 10005 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.exp) { |  | ||||||
|         code = !opt.exp.test(val) ? 10006 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.maxLen) { |  | ||||||
|         code = val.length > opt.maxLen ? 10011 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.minLen) { |  | ||||||
|         code = val.length < opt.minLen ? 10012 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.hasOwnProperty('max')) { |  | ||||||
|         code = val > opt.max ? 10021 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.hasOwnProperty('min')) { |  | ||||||
|         code = val < opt.min ? 10022 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (code === 0 && opt.eq) { |  | ||||||
|         var eqVal = parseVmValue(_this.vmodels[0], opt.eq) |  | ||||||
|         code = val !== eqVal ? 10031 : 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       target.result[elem.expr].code = code |  | ||||||
|       target.result[elem.expr].passed = opt.require |  | ||||||
|         ? code === 0 |  | ||||||
|         : val |  | ||||||
|           ? code === 0 |  | ||||||
|           : true |  | ||||||
| 
 |  | ||||||
|       var passed = true |  | ||||||
|       for (var k in target.result) { |  | ||||||
|         if (!target.result[k].passed) { |  | ||||||
|           passed = false |  | ||||||
|           target.event(target.result[k]) |  | ||||||
|           break |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       if (passed) { |  | ||||||
|         target.event(true) |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     Anot(elem).bind('blur', checked) |  | ||||||
|     this.rollback = function() { |  | ||||||
|       Anot(elem).unbind('blur', checked) |  | ||||||
|     } |  | ||||||
|     elem.msBinded = true |  | ||||||
|     checked() |  | ||||||
|   } |  | ||||||
| }) |  | ||||||
|  | @ -35,12 +35,12 @@ var duplexBinding = Anot.directive('duplex', { | ||||||
|         elem.tagName === 'SELECT' |         elem.tagName === 'SELECT' | ||||||
|           ? 'select' |           ? 'select' | ||||||
|           : elem.type === 'checkbox' |           : elem.type === 'checkbox' | ||||||
|             ? 'checkbox' |           ? 'checkbox' | ||||||
|             : elem.type === 'radio' |           : elem.type === 'radio' | ||||||
|               ? 'radio' |           ? 'radio' | ||||||
|               : /^change/.test(elem.getAttribute('data-event')) |           : /^change/.test(elem.getAttribute('data-event')) | ||||||
|                 ? 'change' |           ? 'change' | ||||||
|                 : 'input' |           : 'input' | ||||||
|     } |     } | ||||||
|     elem.expr = binding.expr |     elem.expr = binding.expr | ||||||
|     //===================绑定事件======================
 |     //===================绑定事件======================
 | ||||||
|  | @ -72,7 +72,11 @@ var duplexBinding = Anot.directive('duplex', { | ||||||
|         return |         return | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       var lastValue = binding.pipe(val, binding, 'get') |       var lastValue = binding.pipe( | ||||||
|  |         val, | ||||||
|  |         binding, | ||||||
|  |         'get' | ||||||
|  |       ) | ||||||
|       binding.oldValue = val |       binding.oldValue = val | ||||||
|       binding.setter(lastValue) |       binding.setter(lastValue) | ||||||
| 
 | 
 | ||||||
|  | @ -82,7 +86,11 @@ var duplexBinding = Anot.directive('duplex', { | ||||||
|     switch (binding.xtype) { |     switch (binding.xtype) { | ||||||
|       case 'radio': |       case 'radio': | ||||||
|         bound('click', function() { |         bound('click', function() { | ||||||
|           var lastValue = binding.pipe(elem.value, binding, 'get') |           var lastValue = binding.pipe( | ||||||
|  |             elem.value, | ||||||
|  |             binding, | ||||||
|  |             'get' | ||||||
|  |           ) | ||||||
|           binding.setter(lastValue) |           binding.setter(lastValue) | ||||||
|           callback.call(elem, lastValue) |           callback.call(elem, lastValue) | ||||||
|         }) |         }) | ||||||
|  | @ -95,7 +103,11 @@ var duplexBinding = Anot.directive('duplex', { | ||||||
|             log(':duplex应用于checkbox上要对应一个数组') |             log(':duplex应用于checkbox上要对应一个数组') | ||||||
|             array = [array] |             array = [array] | ||||||
|           } |           } | ||||||
|           var val = binding.pipe(elem.value, binding, 'get') |           var val = binding.pipe( | ||||||
|  |             elem.value, | ||||||
|  |             binding, | ||||||
|  |             'get' | ||||||
|  |           ) | ||||||
|           Anot.Array[method](array, val) |           Anot.Array[method](array, val) | ||||||
|           callback.call(elem, array) |           callback.call(elem, array) | ||||||
|         }) |         }) | ||||||
|  | @ -106,21 +118,27 @@ var duplexBinding = Anot.directive('duplex', { | ||||||
|       case 'input': |       case 'input': | ||||||
|         bound('input', updateVModel) |         bound('input', updateVModel) | ||||||
|         bound('keyup', updateVModel) |         bound('keyup', updateVModel) | ||||||
|         if (!IEVersion) { |         bound('compositionstart', compositionStart) | ||||||
|           bound('compositionstart', compositionStart) |         bound('compositionend', compositionEnd) | ||||||
|           bound('compositionend', compositionEnd) |         bound('DOMAutoComplete', updateVModel) | ||||||
|           bound('DOMAutoComplete', updateVModel) |  | ||||||
|         } |  | ||||||
|         break |         break | ||||||
|       case 'select': |       case 'select': | ||||||
|         bound('change', function() { |         bound('change', function() { | ||||||
|           var val = Anot(elem).val() //字符串或字符串数组
 |           var val = Anot(elem).val() //字符串或字符串数组
 | ||||||
|           if (Array.isArray(val)) { |           if (Array.isArray(val)) { | ||||||
|             val = val.map(function(v) { |             val = val.map(function(v) { | ||||||
|               return binding.pipe(v, binding, 'get') |               return binding.pipe( | ||||||
|  |                 v, | ||||||
|  |                 binding, | ||||||
|  |                 'get' | ||||||
|  |               ) | ||||||
|             }) |             }) | ||||||
|           } else { |           } else { | ||||||
|             val = binding.pipe(val, binding, 'get') |             val = binding.pipe( | ||||||
|  |               val, | ||||||
|  |               binding, | ||||||
|  |               'get' | ||||||
|  |             ) | ||||||
|           } |           } | ||||||
|           if (val + '' !== binding.oldValue) { |           if (val + '' !== binding.oldValue) { | ||||||
|             try { |             try { | ||||||
|  | @ -176,7 +194,11 @@ var duplexBinding = Anot.directive('duplex', { | ||||||
|         elem.value = value |         elem.value = value | ||||||
|         break |         break | ||||||
|       case 'change': |       case 'change': | ||||||
|         curValue = this.pipe(value, this, 'set') //fix #673
 |         curValue = this.pipe( | ||||||
|  |           value, | ||||||
|  |           this, | ||||||
|  |           'set' | ||||||
|  |         ) //fix #673
 | ||||||
|         if (curValue !== this.oldValue) { |         if (curValue !== this.oldValue) { | ||||||
|           var fixCaret = false |           var fixCaret = false | ||||||
|           if (elem.msFocus) { |           if (elem.msFocus) { | ||||||
|  | @ -201,7 +223,11 @@ var duplexBinding = Anot.directive('duplex', { | ||||||
|         break |         break | ||||||
|       case 'checkbox': |       case 'checkbox': | ||||||
|         var array = [].concat(value) //强制转换为数组
 |         var array = [].concat(value) //强制转换为数组
 | ||||||
|         curValue = this.pipe(elem.value, this, 'get') |         curValue = this.pipe( | ||||||
|  |           elem.value, | ||||||
|  |           this, | ||||||
|  |           'get' | ||||||
|  |         ) | ||||||
|         elem.checked = array.indexOf(curValue) > -1 |         elem.checked = array.indexOf(curValue) > -1 | ||||||
|         break |         break | ||||||
|       case 'select': |       case 'select': | ||||||
|  |  | ||||||
|  | @ -3,13 +3,18 @@ Anot.directive('if', { | ||||||
|   update: function(val) { |   update: function(val) { | ||||||
|     var binding = this |     var binding = this | ||||||
|     var elem = this.element |     var elem = this.element | ||||||
|     var stamp = (binding.stamp = +new Date()) |     var stamp = (binding.stamp = Date.now()) | ||||||
|     var par |     var par | ||||||
|     var after = function() { |     var after = function() { | ||||||
|       if (stamp !== binding.stamp) return |       if (stamp !== binding.stamp) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|       binding.recoverNode = null |       binding.recoverNode = null | ||||||
|     } |     } | ||||||
|     if (binding.recoverNode) binding.recoverNode() // 还原现场,有移动节点的都需要还原现场
 |     if (binding.recoverNode) { | ||||||
|  |       binding.recoverNode() // 还原现场,有移动节点的都需要还原现场
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     try { |     try { | ||||||
|       if (!elem.parentNode) return |       if (!elem.parentNode) return | ||||||
|       par = elem.parentNode |       par = elem.parentNode | ||||||
|  |  | ||||||
|  | @ -1,6 +1,3 @@ | ||||||
| var getXHR = function() { |  | ||||||
|   return new window.XMLHttpRequest() // jshint ignore:line
 |  | ||||||
| } |  | ||||||
| //将所有远程加载的模板,以字符串形式存放到这里
 | //将所有远程加载的模板,以字符串形式存放到这里
 | ||||||
| var templatePool = (Anot.templateCache = {}) | var templatePool = (Anot.templateCache = {}) | ||||||
| 
 | 
 | ||||||
|  | @ -26,24 +23,30 @@ function nodesToFrag(nodes) { | ||||||
| Anot.directive('include', { | Anot.directive('include', { | ||||||
|   init: directives.attr.init, |   init: directives.attr.init, | ||||||
|   update: function(val) { |   update: function(val) { | ||||||
|  |     if (!val) { | ||||||
|  |       return | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     var binding = this |     var binding = this | ||||||
|     var elem = this.element |     var elem = this.element | ||||||
|     var vmodels = binding.vmodels |     var vmodels = binding.vmodels | ||||||
|     var rendered = binding.includeRendered |     var loaded = binding.includeLoaded // 加载完的回调
 | ||||||
|  |     var rendered = binding.includeRendered // 渲染完的回调
 | ||||||
|     var effectClass = binding.effectName && binding.effectClass // 是否开启动画
 |     var effectClass = binding.effectName && binding.effectClass // 是否开启动画
 | ||||||
|     var templateCache = binding.templateCache // 是否data-include-cache
 |     var templateCache = binding.templateCache // 是否开启 缓存
 | ||||||
|     var outer = binding.includeReplace // 是否data-include-replace
 |     var outer = binding.includeReplace // 是否替换容器
 | ||||||
|     var loaded = binding.includeLoaded |  | ||||||
|     var target = outer ? elem.parentNode : elem |     var target = outer ? elem.parentNode : elem | ||||||
|     var _ele = binding._element // data-include-replace binding.element === binding.end
 |     var _ele = binding._element // replace binding.element === binding.end
 | ||||||
| 
 | 
 | ||||||
|     binding.recoverNodes = binding.recoverNodes || Anot.noop |     binding.recoverNodes = binding.recoverNodes || Anot.noop | ||||||
| 
 | 
 | ||||||
|     var scanTemplate = function(text) { |     var scanTemplate = function(text) { | ||||||
|       var _stamp = (binding._stamp = +new Date()) // 过滤掉频繁操作
 |       var _stamp = (binding._stamp = Date.now()) // 过滤掉频繁操作
 | ||||||
|       if (loaded) { |       if (loaded) { | ||||||
|         var newText = loaded.apply(target, [text].concat(vmodels)) |         var newText = loaded.apply(target, [text].concat(vmodels)) | ||||||
|         if (typeof newText === 'string') text = newText |         if (typeof newText === 'string') { | ||||||
|  |           text = newText | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|       if (rendered) { |       if (rendered) { | ||||||
|         checkScan( |         checkScan( | ||||||
|  | @ -104,7 +107,7 @@ Anot.directive('include', { | ||||||
|       if (outer && effectClass) { |       if (outer && effectClass) { | ||||||
|         enterEl = _ele |         enterEl = _ele | ||||||
|         enterEl.innerHTML = '' // 清空
 |         enterEl.innerHTML = '' // 清空
 | ||||||
|         enterEl.setAttribute(':skip', 'true') |         enterEl.setAttribute('skip', '') | ||||||
|         target.insertBefore(enterEl, binding.end.nextSibling) // 插入到bingding.end之后避免被错误的移动
 |         target.insertBefore(enterEl, binding.end.nextSibling) // 插入到bingding.end之后避免被错误的移动
 | ||||||
|         before = function() { |         before = function() { | ||||||
|           enterEl.insertBefore(fragment, null) // 插入节点
 |           enterEl.insertBefore(fragment, null) // 插入节点
 | ||||||
|  | @ -133,51 +136,33 @@ Anot.directive('include', { | ||||||
|       Anot.effect.apply(enterEl, 'enter', before, after) |       Anot.effect.apply(enterEl, 'enter', before, after) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!val) return |     if (templatePool[val]) { | ||||||
| 
 |       Anot.nextTick(function() { | ||||||
|     var el = val |         scanTemplate(templatePool[val]) | ||||||
| 
 |       }) | ||||||
|     if (typeof el === 'object') { |  | ||||||
|       if (el.nodeType !== 1) return log('include 不支持非DOM对象') |  | ||||||
|     } else { |     } else { | ||||||
|       el = DOC.getElementById(val) |       fetch(val, { | ||||||
|       if (!el) { |         method: 'get', | ||||||
|         if (typeof templatePool[val] === 'string') { |         headers: { | ||||||
|           Anot.nextTick(function() { |           'X-Requested-With': 'XMLHttpRequest' | ||||||
|             scanTemplate(templatePool[val]) |  | ||||||
|           }) |  | ||||||
|         } else if (Array.isArray(templatePool[val])) { |  | ||||||
|           //#805 防止在循环绑定中发出许多相同的请求
 |  | ||||||
|           templatePool[val].push(scanTemplate) |  | ||||||
|         } else { |  | ||||||
|           var xhr = getXHR() |  | ||||||
|           xhr.onload = function() { |  | ||||||
|             if (xhr.status !== 200) |  | ||||||
|               return log('获取网络资源出错, httpError[' + xhr.status + ']') |  | ||||||
| 
 |  | ||||||
|             var text = xhr.responseText |  | ||||||
|             for (var f = 0, fn; (fn = templatePool[val][f++]); ) { |  | ||||||
|               fn(text) |  | ||||||
|             } |  | ||||||
|             templatePool[val] = text |  | ||||||
|           } |  | ||||||
|           xhr.onerror = function() { |  | ||||||
|             log(':include load [' + val + '] error') |  | ||||||
|           } |  | ||||||
|           templatePool[val] = [scanTemplate] |  | ||||||
|           xhr.open('GET', val, true) |  | ||||||
|           if ('withCredentials' in xhr) { |  | ||||||
|             xhr.withCredentials = true |  | ||||||
|           } |  | ||||||
|           xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest') |  | ||||||
|           xhr.send(null) |  | ||||||
|         } |         } | ||||||
|         return |       }) | ||||||
|       } |         .then(res => { | ||||||
|  |           if (res.status >= 200 && res.status < 300) { | ||||||
|  |             return res.text() | ||||||
|  |           } else { | ||||||
|  |             return Promise.reject( | ||||||
|  |               `获取网络资源出错, ${res.status} (${res.statusText})` | ||||||
|  |             ) | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |         .then(text => { | ||||||
|  |           templatePool[val] = text | ||||||
|  |           scanTemplate(text) | ||||||
|  |         }) | ||||||
|  |         .catch(err => { | ||||||
|  |           log(':include load [' + val + '] error\n%c%s', 'color:#f30', err) | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     Anot.nextTick(function() { |  | ||||||
|       scanTemplate(el.value || el.innerText || el.innerHTML) |  | ||||||
|     }) |  | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ function parseDisplay(nodeName, val) { | ||||||
|   if (!parseDisplay[key]) { |   if (!parseDisplay[key]) { | ||||||
|     var node = DOC.createElement(nodeName) |     var node = DOC.createElement(nodeName) | ||||||
|     root.appendChild(node) |     root.appendChild(node) | ||||||
|     if (W3C) { | 
 | ||||||
|       val = getComputedStyle(node, null).display |     val = getComputedStyle(node, null).display | ||||||
|     } else { | 
 | ||||||
|       val = node.currentStyle.display |  | ||||||
|     } |  | ||||||
|     root.removeChild(node) |     root.removeChild(node) | ||||||
|     parseDisplay[key] = val |     parseDisplay[key] = val | ||||||
|   } |   } | ||||||
|  | @ -27,7 +25,7 @@ Anot.directive('visible', { | ||||||
|       stamp |       stamp | ||||||
|     var noEffect = !this.effectName |     var noEffect = !this.effectName | ||||||
|     if (!this.stamp) { |     if (!this.stamp) { | ||||||
|       stamp = this.stamp = +new Date() |       stamp = this.stamp = Date.now() | ||||||
|       if (val) { |       if (val) { | ||||||
|         elem.style.display = binding.display || '' |         elem.style.display = binding.display || '' | ||||||
|         if (Anot(elem).css('display') === 'none') { |         if (Anot(elem).css('display') === 'none') { | ||||||
|  |  | ||||||
|  | @ -88,7 +88,7 @@ var filters = (Anot.filters = { | ||||||
|   //    <a href="jav  ascript:alert('XSS');">IE67chrome</a>
 |   //    <a href="jav  ascript:alert('XSS');">IE67chrome</a>
 | ||||||
|   //    <a href="jav	ascript:alert('XSS');">IE67chrome</a>
 |   //    <a href="jav	ascript:alert('XSS');">IE67chrome</a>
 | ||||||
|   //    <a href="jav
ascript:alert('XSS');">IE67chrome</a>
 |   //    <a href="jav
ascript:alert('XSS');">IE67chrome</a>
 | ||||||
|   sanitize: function(str) { |   xss: function(str) { | ||||||
|     return str.replace(rscripts, '').replace(ropen, function(a, b) { |     return str.replace(rscripts, '').replace(ropen, function(a, b) { | ||||||
|       var match = a.toLowerCase().match(/<(\w+)\s/) |       var match = a.toLowerCase().match(/<(\w+)\s/) | ||||||
|       if (match) { |       if (match) { | ||||||
|  | @ -127,25 +127,20 @@ var filters = (Anot.filters = { | ||||||
|   }, |   }, | ||||||
|   number: numberFormat, |   number: numberFormat, | ||||||
|   //日期格式化,类似php的date函数,
 |   //日期格式化,类似php的date函数,
 | ||||||
|   date: function(stamp, str, second) { |   date: function(stamp, str) { | ||||||
|     second = second === undefined ? false : true |     var oDate = stamp | ||||||
|     var oDate | 
 | ||||||
|     if (!Date.isDate(stamp)) { |     if (!Date.isDate(oDate)) { | ||||||
|       if (!/[^\d]/.test(stamp)) { |       var tmp = +oDate | ||||||
|         stamp -= 0 |       if (tmp === tmp) { | ||||||
|         if (second) { |         oDate = tmp | ||||||
|           stamp *= 1000 |  | ||||||
|         } |  | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       oDate = new Date(stamp) |       oDate = new Date(oDate) | ||||||
|       if (oDate + '' === 'Invalid Date') { |       if (oDate.toString() === 'Invalid Date') { | ||||||
|         return 'Invalid Date' |         return 'Invalid Date' | ||||||
|       } |       } | ||||||
|     } else { |  | ||||||
|       oDate = stamp |  | ||||||
|     } |     } | ||||||
|     return oDate.format(str) |     return oDate.format(str) | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
| 
 |  | ||||||
|  |  | ||||||
		Reference in New Issue
	
	 宇天
						宇天