avalon-rails 1.3.9.1 → 1.3.9.1.20150212184918

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,8 +5,7 @@
5
5
  http://weibo.com/jslouvre/
6
6
 
7
7
  Released under the MIT license
8
- avalon.shim.js(去掉加载器与domReady) 1.391 build in 2015.1.31
9
- ___
8
+ avalon.shim.js(无加载器版本) 1.391 built in 2015.2.12
10
9
  support IE6+ and other browsers
11
10
  ==================================================*/
12
11
  (function(global, factory) {
@@ -34,13 +33,14 @@ ___
34
33
  /*********************************************************************
35
34
  * 全局变量及方法 *
36
35
  **********************************************************************/
37
- var expose = new Date - 0
36
+ var expose = new Date() - 0
38
37
  //http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function
39
38
  var DOC = window.document
40
39
  var head = DOC.getElementsByTagName("head")[0] //HEAD元素
41
40
  var ifGroup = head.insertBefore(document.createElement("avalon"), head.firstChild) //避免IE6 base标签BUG
42
41
  ifGroup.innerHTML = "X<style id='avalonStyle'>.avalonHide{ display: none!important }</style>"
43
42
  ifGroup.setAttribute("ms-skip", "1")
43
+ ifGroup.className = "avalonHide"
44
44
  var rnative = /\[native code\]/ //判定是否原生函数
45
45
  function log() {
46
46
  if (window.console && avalon.config.debug) {
@@ -143,7 +143,7 @@ var isFunction = typeof alert === "object" ? function(fn) {
143
143
  return false
144
144
  }
145
145
  } : function(fn) {
146
- return serialize.call(fn) == "[object Function]"
146
+ return serialize.call(fn) === "[object Function]"
147
147
  }
148
148
  avalon.isFunction = isFunction
149
149
 
@@ -305,7 +305,7 @@ avalon.mix({
305
305
  }
306
306
  var index = -1,
307
307
  length = Math.max(0, Math.ceil((end - start) / step)),
308
- result = Array(length)
308
+ result = new Array(length)
309
309
  while (++index < length) {
310
310
  result[index] = start
311
311
  start += step
@@ -352,10 +352,10 @@ avalon.mix({
352
352
  if (node instanceof avalon) {
353
353
  node = node[0]
354
354
  }
355
- var prop = /[_-]/.test(name) ? camelize(name) : name
355
+ var prop = /[_-]/.test(name) ? camelize(name) : name, fn
356
356
  name = avalon.cssName(prop) || prop
357
357
  if (value === void 0 || typeof value === "boolean") { //获取样式
358
- var fn = cssHooks[prop + ":get"] || cssHooks["@:get"]
358
+ fn = cssHooks[prop + ":get"] || cssHooks["@:get"]
359
359
  if (name === "background") {
360
360
  name = "backgroundColor"
361
361
  }
@@ -446,7 +446,7 @@ function isArrayLike(obj) {
446
446
  }
447
447
  return true
448
448
  } catch (e) { //IE的NodeList直接抛错
449
- return !obj.eval //IE6-8 window
449
+ return !obj.window //IE6-8 window
450
450
  }
451
451
  }
452
452
  return false
@@ -691,7 +691,7 @@ function fixEvent(event) {
691
691
  ret.wheelDeltaY = ret.wheelDelta
692
692
  ret.wheelDeltaX = 0
693
693
  }
694
- ret.timeStamp = new Date - 0
694
+ ret.timeStamp = new Date() - 0
695
695
  ret.originalEvent = event
696
696
  ret.preventDefault = function() { //阻止默认行为
697
697
  event.returnValue = false
@@ -873,7 +873,7 @@ var EventBus = {
873
873
  return this
874
874
  },
875
875
  $fire: function(type) {
876
- var special
876
+ var special, i, v, callback
877
877
  if (/^(\w+)!(\S+)$/.test(type)) {
878
878
  special = RegExp.$1
879
879
  type = RegExp.$2
@@ -882,8 +882,8 @@ var EventBus = {
882
882
  var args = aslice.call(arguments, 1)
883
883
  var detail = [type].concat(args)
884
884
  if (special === "all") {
885
- for (var i in avalon.vmodels) {
886
- var v = avalon.vmodels[i]
885
+ for (i in avalon.vmodels) {
886
+ v = avalon.vmodels[i]
887
887
  if (v !== this) {
888
888
  v.$fire.apply(v, detail)
889
889
  }
@@ -892,8 +892,8 @@ var EventBus = {
892
892
  var elements = events.expr ? findNodes(events.expr) : []
893
893
  if (elements.length === 0)
894
894
  return
895
- for (var i in avalon.vmodels) {
896
- var v = avalon.vmodels[i]
895
+ for (i in avalon.vmodels) {
896
+ v = avalon.vmodels[i]
897
897
  if (v !== this) {
898
898
  if (v.$events.expr) {
899
899
  var eventNodes = findNodes(v.$events.expr)
@@ -926,19 +926,19 @@ var EventBus = {
926
926
  if (special === "up") {
927
927
  alls.reverse()
928
928
  }
929
- for (var i = 0, el; el = alls[i++]; ) {
930
- if (el.$fire.apply(el, detail) === false) {
929
+ for (i = 0; callback = alls[i++]; ) {
930
+ if (callback.$fire.apply(callback, detail) === false) {
931
931
  break
932
932
  }
933
933
  }
934
934
  } else {
935
935
  var callbacks = events[type] || []
936
936
  var all = events.$all || []
937
- for (var i = 0, callback; callback = callbacks[i++]; ) {
937
+ for (i = 0; callback = callbacks[i++]; ) {
938
938
  if (isFunction(callback))
939
939
  callback.apply(this, args)
940
940
  }
941
- for (var i = 0, callback; callback = all[i++]; ) {
941
+ for (i = 0; callback = all[i++]; ) {
942
942
  if (isFunction(callback))
943
943
  callback.apply(this, arguments)
944
944
  }
@@ -1116,7 +1116,7 @@ function modelFactory(source, $special, $model) {
1116
1116
  } else {
1117
1117
  if (accessor.type === 0) { //type 0 计算属性 1 监控属性 2 对象属性
1118
1118
  //计算属性不需要收集视图刷新函数,都是由其他监控属性代劳
1119
- var newValue = accessor.get.call($vmodel)
1119
+ newValue = accessor.get.call($vmodel)
1120
1120
  if (oldValue !== newValue) {
1121
1121
  $model[name] = newValue
1122
1122
  //这里不用同步视图
@@ -1148,12 +1148,12 @@ function modelFactory(source, $special, $model) {
1148
1148
  initCallbacks.push(function() {
1149
1149
  var data = {
1150
1150
  evaluator: function() {
1151
- data.type = new Date - 0
1151
+ data.type = Math.random(),
1152
1152
  data.element = null
1153
1153
  $model[name] = accessor.get.call($vmodel)
1154
1154
  },
1155
1155
  element: head,
1156
- type: new Date - 0,
1156
+ type: Math.random(),
1157
1157
  handler: noop,
1158
1158
  args: []
1159
1159
  }
@@ -1194,7 +1194,7 @@ function modelFactory(source, $special, $model) {
1194
1194
  $vmodel.$id = generateID()
1195
1195
  $vmodel.$model = $model
1196
1196
  $vmodel.$events = $events
1197
- for (var i in EventBus) {
1197
+ for ( i in EventBus) {
1198
1198
  var fn = EventBus[i]
1199
1199
  if (!W3C) { //在IE6-8下,VB对象的方法里的this并不指向自身,需要用bind处理一下
1200
1200
  fn = fn.bind($vmodel)
@@ -1754,7 +1754,7 @@ function removeSubscribers() {
1754
1754
  if (diff) {
1755
1755
  //avalon.log("有需要移除的元素")
1756
1756
  while (obj = $$subscribers[--i]) {
1757
- var data = obj.data
1757
+ data = obj.data
1758
1758
  if (data.element === void 0)
1759
1759
  continue
1760
1760
  if (needTest[data.type] && isRemove(data.element)) { //如果它没有在DOM树
@@ -1861,7 +1861,7 @@ avalon.parseHTML = function(html) {
1861
1861
  for (i = wrap[0]; i--; wrapper = wrapper.lastChild) {
1862
1862
  }
1863
1863
  if (!W3C) { //fix IE
1864
- var els = wrapper.getElementsByTagName("br"), n = els.length
1864
+ els = wrapper.getElementsByTagName("br"), n = els.length
1865
1865
  while (el = els[--n]) {
1866
1866
  if (el.className === "msNoScope") {
1867
1867
  el.parentNode.removeChild(el)
@@ -2003,55 +2003,6 @@ function bindingSorter(a, b) {
2003
2003
  return a.priority - b.priority
2004
2004
  }
2005
2005
 
2006
- function scanTag(elem, vmodels, node) {
2007
- //扫描顺序 ms-skip(0) --> ms-important(1) --> ms-controller(2) --> ms-if(10) --> ms-repeat(100)
2008
- //--> ms-if-loop(110) --> ms-attr(970) ...--> ms-each(1400)-->ms-with(1500)--〉ms-duplex(2000)垫后
2009
- var a = elem.getAttribute("ms-skip")
2010
- //#360 在旧式IE中 Object标签在引入Flash等资源时,可能出现没有getAttributeNode,innerHTML的情形
2011
- if (!elem.getAttributeNode) {
2012
- return log("warning " + elem.tagName + " no getAttributeNode method")
2013
- }
2014
- var b = elem.getAttributeNode("ms-important")
2015
- var c = elem.getAttributeNode("ms-controller")
2016
- if (typeof a === "string") {
2017
- return
2018
- } else if (node = b || c) {
2019
- var newVmodel = avalon.vmodels[node.value]
2020
- if (!newVmodel) {
2021
- return
2022
- }
2023
- //ms-important不包含父VM,ms-controller相反
2024
- vmodels = node === b ? [newVmodel] : [newVmodel].concat(vmodels)
2025
- var name = node.name
2026
- elem.removeAttribute(name) //removeAttributeNode不会刷新[ms-controller]样式规则
2027
- avalon(elem).removeClass(name)
2028
- createSignalTower(elem, newVmodel)
2029
- }
2030
- scanAttr(elem, vmodels) //扫描特性节点
2031
- }
2032
- function scanNodeList(parent, vmodels) {
2033
- var node = parent.firstChild
2034
- while (node) {
2035
- var nextNode = node.nextSibling
2036
- scanNode(node, node.nodeType, vmodels)
2037
- node = nextNode
2038
- }
2039
- }
2040
-
2041
- function scanNodeArray(nodes, vmodels) {
2042
- for (var i = 0, node; node = nodes[i++]; ) {
2043
- scanNode(node, node.nodeType, vmodels)
2044
- }
2045
- }
2046
- function scanNode(node, nodeType, vmodels) {
2047
- if (nodeType === 1) {
2048
- scanTag(node, vmodels) //扫描元素节点
2049
- } else if (nodeType === 3 && rexpr.test(node.data)){
2050
- scanText(node, vmodels) //扫描文本节点
2051
- } else if (kernel.commentInterpolate && nodeType === 8 && !rexpr.test(node.nodeValue)) {
2052
- scanText(node, vmodels) //扫描注释节点
2053
- }
2054
- }
2055
2006
  function scanAttr(elem, vmodels) {
2056
2007
  //防止setAttribute, removeAttribute时 attributes自动被同步,导致for循环出错
2057
2008
  var attributes = getAttributes ? getAttributes(elem) : avalon.slice(elem.attributes)
@@ -2120,8 +2071,8 @@ function scanAttr(elem, vmodels) {
2120
2071
  log("warning!一个元素上不能同时定义ms-attr-checked与ms-duplex")
2121
2072
  }
2122
2073
  var scanNode = true
2123
- for (var i = 0, binding; binding = bindings[i]; i++) {
2124
- var type = binding.type
2074
+ for (i = 0; binding = bindings[i]; i++) {
2075
+ type = binding.type
2125
2076
  if (rnoscanAttrBinding.test(type)) {
2126
2077
  return executeBindings(bindings.slice(0, i + 1), vmodels)
2127
2078
  } else if (scanNode) {
@@ -2185,14 +2136,66 @@ if (!"1" [0]) {
2185
2136
  }
2186
2137
  }
2187
2138
 
2139
+ function scanNodeList(parent, vmodels) {
2140
+ var node = parent.firstChild
2141
+ while (node) {
2142
+ var nextNode = node.nextSibling
2143
+ scanNode(node, node.nodeType, vmodels)
2144
+ node = nextNode
2145
+ }
2146
+ }
2147
+
2148
+ function scanNodeArray(nodes, vmodels) {
2149
+ for (var i = 0, node; node = nodes[i++]; ) {
2150
+ scanNode(node, node.nodeType, vmodels)
2151
+ }
2152
+ }
2153
+ function scanNode(node, nodeType, vmodels) {
2154
+ if (nodeType === 1) {
2155
+ scanTag(node, vmodels) //扫描元素节点
2156
+ } else if (nodeType === 3 && rexpr.test(node.data)){
2157
+ scanText(node, vmodels) //扫描文本节点
2158
+ } else if (kernel.commentInterpolate && nodeType === 8 && !rexpr.test(node.nodeValue)) {
2159
+ scanText(node, vmodels) //扫描注释节点
2160
+ }
2161
+ }
2162
+ function scanTag(elem, vmodels, node) {
2163
+ //扫描顺序 ms-skip(0) --> ms-important(1) --> ms-controller(2) --> ms-if(10) --> ms-repeat(100)
2164
+ //--> ms-if-loop(110) --> ms-attr(970) ...--> ms-each(1400)-->ms-with(1500)--〉ms-duplex(2000)垫后
2165
+ var a = elem.getAttribute("ms-skip")
2166
+ //#360 在旧式IE中 Object标签在引入Flash等资源时,可能出现没有getAttributeNode,innerHTML的情形
2167
+ if (!elem.getAttributeNode) {
2168
+ return log("warning " + elem.tagName + " no getAttributeNode method")
2169
+ }
2170
+ var b = elem.getAttributeNode("ms-important")
2171
+ var c = elem.getAttributeNode("ms-controller")
2172
+ if (typeof a === "string") {
2173
+ return
2174
+ } else if (node = b || c) {
2175
+ var newVmodel = avalon.vmodels[node.value]
2176
+ if (!newVmodel) {
2177
+ return
2178
+ }
2179
+ //ms-important不包含父VM,ms-controller相反
2180
+ vmodels = node === b ? [newVmodel] : [newVmodel].concat(vmodels)
2181
+ var name = node.name
2182
+ elem.removeAttribute(name) //removeAttributeNode不会刷新[ms-controller]样式规则
2183
+ avalon(elem).removeClass(name)
2184
+ createSignalTower(elem, newVmodel)
2185
+ }
2186
+ scanAttr(elem, vmodels) //扫描特性节点
2187
+ }
2188
2188
  var rhasHtml = /\|\s*html\s*/,
2189
2189
  r11a = /\|\|/g,
2190
2190
  rlt = /&lt;/g,
2191
2191
  rgt = /&gt;/g
2192
-
2192
+ rstringLiteral = /(['"])(\\\1|.)+?\1/g
2193
2193
  function getToken(value) {
2194
2194
  if (value.indexOf("|") > 0) {
2195
- var index = value.replace(r11a, "\u1122\u3344").indexOf("|") //干掉所有短路或
2195
+ var scapegoat = value.replace( rstringLiteral, function(_){
2196
+ return Math.pow(10,_.length)
2197
+ })
2198
+ var index = scapegoat.replace(r11a, "\u1122\u3344").indexOf("|") //干掉所有短路或
2196
2199
  if (index > -1) {
2197
2200
  return {
2198
2201
  filters: value.slice(index),
@@ -2256,7 +2259,7 @@ function scanText(textNode, vmodels) {
2256
2259
  tokens = scanExpr(textNode.data)
2257
2260
  }
2258
2261
  if (tokens.length) {
2259
- for (var i = 0, token; token = tokens[i++]; ) {
2262
+ for (var i = 0; token = tokens[i++]; ) {
2260
2263
  var node = DOC.createTextNode(token.value) //将文本转换为文本节点,并替换原来的文本节点
2261
2264
  if (token.expr) {
2262
2265
  token.type = "text"
@@ -2295,7 +2298,7 @@ function camelize(target) {
2295
2298
  })
2296
2299
  }
2297
2300
 
2298
- var ClassListMethods = {
2301
+ var fakeClassListMethods = {
2299
2302
  _toString: function() {
2300
2303
  var node = this.node
2301
2304
  var cls = node.className
@@ -2325,13 +2328,13 @@ var ClassListMethods = {
2325
2328
  } //toggle存在版本差异,因此不使用它
2326
2329
  }
2327
2330
 
2328
- function ClassList(node) {
2331
+ function fakeClassList(node) {
2329
2332
  if (!("classList" in node)) {
2330
2333
  node.classList = {
2331
2334
  node: node
2332
2335
  }
2333
- for (var k in ClassListMethods) {
2334
- node.classList[k.slice(1)] = ClassListMethods[k]
2336
+ for (var k in fakeClassListMethods) {
2337
+ node.classList[k.slice(1)] = fakeClassListMethods[k]
2335
2338
  }
2336
2339
  }
2337
2340
  return node.classList
@@ -2344,7 +2347,7 @@ function ClassList(node) {
2344
2347
  //https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/26
2345
2348
  if (cls && typeof cls === "string" && el && el.nodeType === 1) {
2346
2349
  cls.replace(/\S+/g, function(c) {
2347
- ClassList(el)[method](c)
2350
+ fakeClassList(el)[method](c)
2348
2351
  })
2349
2352
  }
2350
2353
  return this
@@ -2353,7 +2356,7 @@ function ClassList(node) {
2353
2356
  avalon.fn.mix({
2354
2357
  hasClass: function(cls) {
2355
2358
  var el = this[0] || {}
2356
- return el.nodeType === 1 && ClassList(el).contains(cls)
2359
+ return el.nodeType === 1 && fakeClassList(el).contains(cls)
2357
2360
  },
2358
2361
  toggleClass: function(value, stateVal) {
2359
2362
  var className, i = 0
@@ -2845,14 +2848,14 @@ var keywords =
2845
2848
  // 关键字
2846
2849
  "break,case,catch,continue,debugger,default,delete,do,else,false" +
2847
2850
  ",finally,for,function,if,in,instanceof,new,null,return,switch,this" +
2848
- ",throw,true,try,typeof,var,void,while,with"
2851
+ ",throw,true,try,typeof,var,void,while,with" +
2849
2852
  // 保留字
2850
- + ",abstract,boolean,byte,char,class,const,double,enum,export,extends" +
2853
+ ",abstract,boolean,byte,char,class,const,double,enum,export,extends" +
2851
2854
  ",final,float,goto,implements,import,int,interface,long,native" +
2852
2855
  ",package,private,protected,public,short,static,super,synchronized" +
2853
- ",throws,transient,volatile"
2856
+ ",throws,transient,volatile" +
2854
2857
  // ECMA 5 - use strict
2855
- + ",arguments,let,yield" + ",undefined"
2858
+ ",arguments,let,yield" + ",undefined"
2856
2859
  var rrexpstr = /\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|[\s\t\n]*\.[\s\t\n]*[$\w\.]+/g
2857
2860
  var rsplit = /[^\w$]+/g
2858
2861
  var rkeywords = new RegExp(["\\b" + keywords.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g')
@@ -2992,7 +2995,7 @@ function parseExpr(code, scopes, data) {
2992
2995
  data.evaluator = fn
2993
2996
  return
2994
2997
  }
2995
- var prefix = assigns.join(", ")
2998
+ prefix = assigns.join(", ")
2996
2999
  if (prefix) {
2997
3000
  prefix = "var " + prefix
2998
3001
  }
@@ -3060,12 +3063,6 @@ function parseExprProxy(code, scopes, data, tokens, noregister) {
3060
3063
  }
3061
3064
  }
3062
3065
  avalon.parseExprProxy = parseExprProxy
3063
- /*********************************************************************
3064
- * 各种指令 *
3065
- **********************************************************************/
3066
- //ms-skip绑定已经在scanTag 方法中实现
3067
- //ms-controller绑定已经在scanTag 方法中实现
3068
- //ms-important绑定已经在scanTag 方法中实现
3069
3066
  var bools = "autofocus,autoplay,async,allowTransparency,checked,controls,declare,disabled,defer,defaultChecked,defaultSelected" +
3070
3067
  "contentEditable,isMap,loop,multiple,noHref,noResize,noShade,open,readOnly,selected"
3071
3068
  var boolMap = {}
@@ -3163,7 +3160,7 @@ bindingExecutors.attr = function(val, elem, data) {
3163
3160
  var loaded = data.includeLoaded
3164
3161
  var replace = data.includeReplaced
3165
3162
  var target = replace ? elem.parentNode : elem
3166
- function scanTemplate(text) {
3163
+ var scanTemplate = function(text) {
3167
3164
  if (loaded) {
3168
3165
  text = loaded.apply(target, [text].concat(vmodels))
3169
3166
  }
@@ -3213,7 +3210,7 @@ bindingExecutors.attr = function(val, elem, data) {
3213
3210
  var el = val && val.nodeType === 1 ? val : DOC.getElementById(val)
3214
3211
  if (el) {
3215
3212
  if (el.tagName === "NOSCRIPT" && !(el.innerHTML || el.fixIE78)) { //IE7-8 innerText,innerHTML都无法取得其内容,IE6能取得其innerHTML
3216
- var xhr = getXHR() //IE9-11与chrome的innerHTML会得到转义的内容,它们的innerText可以
3213
+ xhr = getXHR() //IE9-11与chrome的innerHTML会得到转义的内容,它们的innerText可以
3217
3214
  xhr.open("GET", location, false) //谢谢Nodejs 乱炖群 深圳-纯属虚构
3218
3215
  xhr.send(null)
3219
3216
  //http://bbs.csdn.net/topics/390349046?page=1#post-393492653
@@ -3251,8 +3248,6 @@ bindingExecutors.attr = function(val, elem, data) {
3251
3248
  "title,alt,src,value,css,include,href".replace(rword, function(name) {
3252
3249
  bindingHandlers[name] = bindingHandlers.attr
3253
3250
  })
3254
- //ms-include绑定已由ms-attr绑定实现
3255
-
3256
3251
  //根据VM的属性值或表达式的值切换类名,ms-class="xxx yyy zzz:flag"
3257
3252
  //http://www.cnblogs.com/rubylouvre/archive/2012/12/17/2818540.html
3258
3253
  bindingHandlers["class"] = function(data, vmodels) {
@@ -3343,6 +3338,10 @@ bindingExecutors ["class"] = function(val, elem, data) {
3343
3338
  "hover,active".replace(rword, function(method) {
3344
3339
  bindingHandlers[method] = bindingHandlers["class"]
3345
3340
  })
3341
+ //ms-controller绑定已经在scanTag 方法中实现
3342
+ //ms-css绑定已由ms-attr绑定实现
3343
+
3344
+
3346
3345
  // bindingHandlers.data 定义在if.js
3347
3346
  bindingExecutors.data = function(val, elem, data) {
3348
3347
  var key = "data-" + data.param
@@ -3353,350 +3352,95 @@ bindingExecutors.data = function(val, elem, data) {
3353
3352
  }
3354
3353
  }
3355
3354
 
3356
- // bindingHandlers.text 定义在if.js
3357
- bindingExecutors.text = function(val, elem) {
3358
- val = val == null ? "" : val //不在页面上显示undefined null
3359
- if (elem.nodeType === 3) { //绑定在文本节点上
3360
- try { //IE对游离于DOM树外的节点赋值会报错
3361
- elem.data = val
3362
- } catch (e) {
3355
+ //双工绑定
3356
+ var duplexBinding = bindingHandlers.duplex = function(data, vmodels) {
3357
+ var elem = data.element,
3358
+ hasCast
3359
+ parseExprProxy(data.value, vmodels, data, 0, 1)
3360
+
3361
+ data.changed = getBindingCallback(elem, "data-duplex-changed", vmodels) || noop
3362
+ if (data.evaluator && data.args) {
3363
+ var params = []
3364
+ var casting = oneObject("string,number,boolean,checked")
3365
+ if (elem.type === "radio" && data.param === "") {
3366
+ data.param = "checked"
3363
3367
  }
3364
- } else { //绑定在特性节点上
3365
- if ("textContent" in elem) {
3366
- elem.textContent = val
3367
- } else {
3368
- elem.innerText = val
3368
+ if (elem.msData) {
3369
+ elem.msData["ms-duplex"] = data.value
3369
3370
  }
3370
- }
3371
- }
3372
-
3373
-
3374
- // bindingHandlers.html 定义在if.js
3375
- bindingExecutors.html = function(val, elem, data) {
3376
- val = val == null ? "" : val
3377
- var isHtmlFilter = "group" in data
3378
- var parent = isHtmlFilter ? elem.parentNode : elem
3379
- if (!parent)
3380
- return
3381
- if (val.nodeType === 11) { //将val转换为文档碎片
3382
- var fragment = val
3383
- } else if (val.nodeType === 1 || val.item) {
3384
- var nodes = val.nodeType === 1 ? val.childNodes : val.item ? val : []
3385
- fragment = hyperspace.cloneNode(true)
3386
- while (nodes[0]) {
3387
- fragment.appendChild(nodes[0])
3371
+ data.param.replace(/\w+/g, function(name) {
3372
+ if (/^(checkbox|radio)$/.test(elem.type) && /^(radio|checked)$/.test(name)) {
3373
+ if (name === "radio")
3374
+ log("ms-duplex-radio已经更名为ms-duplex-checked")
3375
+ name = "checked"
3376
+ data.isChecked = true
3377
+ }
3378
+ if (name === "bool") {
3379
+ name = "boolean"
3380
+ log("ms-duplex-bool已经更名为ms-duplex-boolean")
3381
+ } else if (name === "text") {
3382
+ name = "string"
3383
+ log("ms-duplex-text已经更名为ms-duplex-string")
3384
+ }
3385
+ if (casting[name]) {
3386
+ hasCast = true
3387
+ }
3388
+ avalon.Array.ensure(params, name)
3389
+ })
3390
+ if (!hasCast) {
3391
+ params.push("string")
3388
3392
  }
3389
- } else {
3390
- fragment = avalon.parseHTML(val)
3391
- }
3392
- //插入占位符, 如果是过滤器,需要有节制地移除指定的数量,如果是html指令,直接清空
3393
- var comment = DOC.createComment("ms-html")
3394
- if (isHtmlFilter) {
3395
- parent.insertBefore(comment, elem)
3396
- var n = data.group, i = 1
3397
- while (i < n) {
3398
- var node = elem.nextSibling
3399
- if (node) {
3400
- parent.removeChild(node)
3401
- i++
3393
+ data.param = params.join("-")
3394
+ data.bound = function(type, callback) {
3395
+ if (elem.addEventListener) {
3396
+ elem.addEventListener(type, callback, false)
3397
+ } else {
3398
+ elem.attachEvent("on" + type, callback)
3399
+ }
3400
+ var old = data.rollback
3401
+ data.rollback = function() {
3402
+ elem.avalonSetter = null
3403
+ avalon.unbind(elem, type, callback)
3404
+ old && old()
3402
3405
  }
3403
3406
  }
3404
- parent.removeChild(elem)
3405
- data.element = comment //防止被CG
3406
- } else {
3407
- avalon.clearHTML(parent).appendChild(comment)
3408
- }
3409
- if (isHtmlFilter) {
3410
- data.group = fragment.childNodes.length || 1
3407
+ for (var i in avalon.vmodels) {
3408
+ var v = avalon.vmodels[i]
3409
+ v.$fire("avalon-ms-duplex-init", data)
3410
+ }
3411
+ var cpipe = data.pipe || (data.pipe = pipe)
3412
+ cpipe(null, data, "init")
3413
+ var tagName = elem.tagName
3414
+ duplexBinding[tagName] && duplexBinding[tagName](elem, data.evaluator.apply(null, data.args), data)
3411
3415
  }
3412
- var nodes = avalon.slice(fragment.childNodes)
3413
- if (nodes[0]) {
3414
- if (comment.parentNode)
3415
- comment.parentNode.replaceChild(fragment, comment)
3416
- if (isHtmlFilter) {
3417
- data.element = nodes[0]
3416
+ }
3417
+ //不存在 bindingExecutors.duplex
3418
+ function fixNull(val) {
3419
+ return val == null ? "" : val
3420
+ }
3421
+ avalon.duplexHooks = {
3422
+ checked: {
3423
+ get: function(val, data) {
3424
+ return !data.element.oldValue
3418
3425
  }
3419
- }
3420
- scanNodeArray(nodes, data.vmodels)
3421
- }
3422
-
3423
- bindingHandlers["if"] =
3424
- bindingHandlers.data =
3425
- bindingHandlers.text =
3426
- bindingHandlers.html =
3427
- function(data, vmodels) {
3428
- parseExprProxy(data.value, vmodels, data)
3429
- }
3430
-
3431
- bindingExecutors["if"] = function(val, elem, data) {
3432
- if (val) { //插回DOM树
3433
- if (elem.nodeType === 8) {
3434
- elem.parentNode.replaceChild(data.template, elem)
3435
- elem = data.element = data.template //这时可能为null
3436
- }
3437
- if (elem.getAttribute(data.name)) {
3438
- elem.removeAttribute(data.name)
3439
- scanAttr(elem, data.vmodels)
3440
- }
3441
- data.rollback = null
3442
- } else { //移出DOM树,并用注释节点占据原位置
3443
- if (elem.nodeType === 1) {
3444
- var node = data.element = DOC.createComment("ms-if")
3445
- elem.parentNode.replaceChild(node, elem)
3446
- data.template = elem //元素节点
3447
- ifGroup.appendChild(elem)
3448
- data.rollback = function() {
3449
- if (elem.parentNode === ifGroup) {
3450
- ifGroup.removeChild(elem)
3451
- }
3452
- }
3453
- }
3454
- }
3455
- }
3456
-
3457
-
3458
- function parseDisplay(nodeName, val) {
3459
- //用于取得此类标签的默认display值
3460
- var key = "_" + nodeName
3461
- if (!parseDisplay[key]) {
3462
- var node = DOC.createElement(nodeName)
3463
- root.appendChild(node)
3464
- if (W3C) {
3465
- val = getComputedStyle(node, null).display
3466
- } else {
3467
- val = node.currentStyle.display
3468
- }
3469
- root.removeChild(node)
3470
- parseDisplay[key] = val
3471
- }
3472
- return parseDisplay[key]
3473
- }
3474
-
3475
- avalon.parseDisplay = parseDisplay
3476
-
3477
- bindingHandlers.visible = function(data, vmodels) {
3478
- var elem = avalon(data.element)
3479
- var display = elem.css("display")
3480
- if (display === "none") {
3481
- var style = elem[0].style
3482
- var has = /visibility/i.test(style.cssText)
3483
- var visible = elem.css("visibility")
3484
- style.display = ""
3485
- style.visibility = "hidden"
3486
- display = elem.css("display")
3487
- if (display === "none") {
3488
- display = parseDisplay(elem[0].nodeName)
3489
- }
3490
- style.visibility = has ? visible : ""
3491
- }
3492
- data.display = display
3493
- parseExprProxy(data.value, vmodels, data)
3494
- }
3495
-
3496
- bindingExecutors.visible = function(val, elem, data) {
3497
- elem.style.display = val ? data.display : "none"
3498
- }
3499
-
3500
- var rdash = /\(([^)]*)\)/
3501
- bindingHandlers.on = function(data, vmodels) {
3502
- var value = data.value
3503
- data.type = "on"
3504
- var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
3505
- if (typeof bindingHandlers.on[eventType + "Hook"] === "function") {
3506
- bindingHandlers.on[eventType + "Hook"](data)
3507
- }
3508
- if (value.indexOf("(") > 0 && value.indexOf(")") > -1) {
3509
- var matched = (value.match(rdash) || ["", ""])[1].trim()
3510
- if (matched === "" || matched === "$event") { // aaa() aaa($event)当成aaa处理
3511
- value = value.replace(rdash, "")
3512
- }
3513
- }
3514
- parseExprProxy(value, vmodels, data)
3515
- }
3516
-
3517
- bindingExecutors.on = function(callback, elem, data) {
3518
- callback = function(e) {
3519
- var fn = data.evaluator || noop
3520
- return fn.apply(this, data.args.concat(e))
3521
- }
3522
- var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
3523
- if (eventType === "scan") {
3524
- callback.call(elem, {
3525
- type: eventType
3526
- })
3527
- } else if (typeof data.specialBind === "function") {
3528
- data.specialBind(elem, callback)
3529
- } else {
3530
- var removeFn = avalon.bind(elem, eventType, callback)
3531
- }
3532
- data.rollback = function() {
3533
- if (typeof data.specialUnbind === "function") {
3534
- data.specialUnbind()
3535
- } else {
3536
- avalon.unbind(elem, eventType, removeFn)
3537
- }
3538
- }
3539
- }
3540
-
3541
-
3542
- bindingHandlers.widget = function(data, vmodels) {
3543
- var args = data.value.match(rword)
3544
- var elem = data.element
3545
- var widget = args[0]
3546
- var id = args[1]
3547
- if (!id || id === "$") {//没有定义或为$时,取组件名+随机数
3548
- id = generateID(widget)
3549
- }
3550
- var optName = args[2] || widget//没有定义,取组件名
3551
- var constructor = avalon.ui[widget]
3552
- if (typeof constructor === "function") { //ms-widget="tabs,tabsAAA,optname"
3553
- vmodels = elem.vmodels || vmodels
3554
- for (var i = 0, v; v = vmodels[i++]; ) {
3555
- if (v.hasOwnProperty(optName) && typeof v[optName] === "object") {
3556
- var vmOptions = v[optName]
3557
- vmOptions = vmOptions.$model || vmOptions
3558
- break
3559
- }
3560
- }
3561
- if (vmOptions) {
3562
- var wid = vmOptions[widget + "Id"]
3563
- if (typeof wid === "string") {
3564
- id = wid
3565
- }
3566
- }
3567
- //抽取data-tooltip-text、data-tooltip-attr属性,组成一个配置对象
3568
- var widgetData = avalon.getWidgetData(elem, widget)
3569
- data.value = [widget, id, optName].join(",")
3570
- data[widget + "Id"] = id
3571
- data.evaluator = noop
3572
- elem.msData["ms-widget-id"] = id
3573
- var options = data[widget + "Options"] = avalon.mix({}, constructor.defaults, vmOptions || {}, widgetData)
3574
- elem.removeAttribute("ms-widget")
3575
- var vmodel = constructor(elem, data, vmodels) || {} //防止组件不返回VM
3576
- if (vmodel.$id) {
3577
- avalon.vmodels[id] = vmodel
3578
- createSignalTower(elem, vmodel)
3579
- if (vmodel.hasOwnProperty("$init")) {
3580
- vmodel.$init(function() {
3581
- avalon.scan(elem, [vmodel].concat(vmodels))
3582
- if (typeof options.onInit === "function") {
3583
- options.onInit.call(elem, vmodel, options, vmodels)
3584
- }
3585
- })
3586
- }
3587
- data.rollback = function() {
3588
- try {
3589
- vmodel.widgetElement = null
3590
- vmodel.$remove()
3591
- } catch (e) {
3592
- }
3593
- elem.msData = {}
3594
- delete avalon.vmodels[vmodel.$id]
3595
- }
3596
- addSubscribers(data, widgetList)
3597
- if (window.chrome) {
3598
- elem.addEventListener("DOMNodeRemovedFromDocument", function() {
3599
- setTimeout(removeSubscribers)
3600
- })
3601
- }
3602
- } else {
3603
- avalon.scan(elem, vmodels)
3604
- }
3605
- } else if (vmodels.length) { //如果该组件还没有加载,那么保存当前的vmodels
3606
- elem.vmodels = vmodels
3607
- }
3608
- }
3609
- var widgetList = []
3610
- //不存在 bindingExecutors.widget
3611
- //双工绑定
3612
- var duplexBinding = bindingHandlers.duplex = function(data, vmodels) {
3613
- var elem = data.element,
3614
- hasCast
3615
- parseExprProxy(data.value, vmodels, data, 0, 1)
3616
-
3617
- data.changed = getBindingCallback(elem, "data-duplex-changed", vmodels) || noop
3618
- if (data.evaluator && data.args) {
3619
- var params = []
3620
- var casting = oneObject("string,number,boolean,checked")
3621
- if (elem.type === "radio" && data.param === "") {
3622
- data.param = "checked"
3623
- }
3624
- if (elem.msData) {
3625
- elem.msData["ms-duplex"] = data.value
3626
- }
3627
- data.param.replace(/\w+/g, function(name) {
3628
- if (/^(checkbox|radio)$/.test(elem.type) && /^(radio|checked)$/.test(name)) {
3629
- if (name === "radio")
3630
- log("ms-duplex-radio已经更名为ms-duplex-checked")
3631
- name = "checked"
3632
- data.isChecked = true
3633
- }
3634
- if (name === "bool") {
3635
- name = "boolean"
3636
- log("ms-duplex-bool已经更名为ms-duplex-boolean")
3637
- } else if (name === "text") {
3638
- name = "string"
3639
- log("ms-duplex-text已经更名为ms-duplex-string")
3640
- }
3641
- if (casting[name]) {
3642
- hasCast = true
3643
- }
3644
- avalon.Array.ensure(params, name)
3645
- })
3646
- if (!hasCast) {
3647
- params.push("string")
3648
- }
3649
- data.param = params.join("-")
3650
- data.bound = function(type, callback) {
3651
- if (elem.addEventListener) {
3652
- elem.addEventListener(type, callback, false)
3653
- } else {
3654
- elem.attachEvent("on" + type, callback)
3655
- }
3656
- var old = data.rollback
3657
- data.rollback = function() {
3658
- elem.avalonSetter = null
3659
- avalon.unbind(elem, type, callback)
3660
- old && old()
3661
- }
3662
- }
3663
- for (var i in avalon.vmodels) {
3664
- var v = avalon.vmodels[i]
3665
- v.$fire("avalon-ms-duplex-init", data)
3666
- }
3667
- var cpipe = data.pipe || (data.pipe = pipe)
3668
- cpipe(null, data, "init")
3669
- var tagName = elem.tagName
3670
- duplexBinding[tagName] && duplexBinding[tagName](elem, data.evaluator.apply(null, data.args), data)
3671
- }
3672
- }
3673
- //不存在 bindingExecutors.duplex
3674
- function fixNull(val) {
3675
- return val == null ? "" : val
3676
- }
3677
- avalon.duplexHooks = {
3678
- checked: {
3679
- get: function(val, data) {
3680
- return !data.element.oldValue
3681
- }
3682
- },
3683
- string: {
3684
- get: function(val) { //同步到VM
3685
- return val
3686
- },
3687
- set: fixNull
3688
- },
3689
- "boolean": {
3690
- get: function(val) {
3691
- return val === "true"
3692
- },
3693
- set: fixNull
3694
- },
3695
- number: {
3696
- get: function(val) {
3697
- return isFinite(val) ? parseFloat(val) || 0 : val
3698
- },
3699
- set: fixNull
3426
+ },
3427
+ string: {
3428
+ get: function(val) { //同步到VM
3429
+ return val
3430
+ },
3431
+ set: fixNull
3432
+ },
3433
+ "boolean": {
3434
+ get: function(val) {
3435
+ return val === "true"
3436
+ },
3437
+ set: fixNull
3438
+ },
3439
+ number: {
3440
+ get: function(val) {
3441
+ return isFinite(val) ? parseFloat(val) || 0 : val
3442
+ },
3443
+ set: fixNull
3700
3444
  }
3701
3445
  }
3702
3446
 
@@ -3906,67 +3650,196 @@ duplexBinding.INPUT = function(element, evaluator, data) {
3906
3650
  }
3907
3651
  })
3908
3652
  }
3909
- if (/text|password/.test(element.type)) {
3910
- watchValueInTimer(function() {
3911
- if (root.contains(element)) {
3912
- if (element.value !== element.oldValue) {
3913
- updateVModel()
3653
+ if (/text|password/.test(element.type)) {
3654
+ watchValueInTimer(function() {
3655
+ if (root.contains(element)) {
3656
+ if (element.value !== element.oldValue) {
3657
+ updateVModel()
3658
+ }
3659
+ } else if (!element.msRetain) {
3660
+ return false
3661
+ }
3662
+ })
3663
+ }
3664
+ element.avalonSetter = updateVModel
3665
+ element.oldValue = element.value
3666
+ registerSubscriber(data)
3667
+ callback.call(element, element.value)
3668
+ }
3669
+ duplexBinding.TEXTAREA = duplexBinding.INPUT
3670
+
3671
+
3672
+ duplexBinding.SELECT = function(element, evaluator, data) {
3673
+ var $elem = avalon(element)
3674
+ function updateVModel() {
3675
+ if ($elem.data("duplex-observe") !== false) {
3676
+ var val = $elem.val() //字符串或字符串数组
3677
+ if (Array.isArray(val)) {
3678
+ val = val.map(function(v) {
3679
+ return data.pipe(v, data, "get")
3680
+ })
3681
+ } else {
3682
+ val = data.pipe(val, data, "get")
3683
+ }
3684
+ if (val + "" !== element.oldValue) {
3685
+ evaluator(val)
3686
+ }
3687
+ data.changed.call(element, val, data)
3688
+ }
3689
+ }
3690
+ data.handler = function() {
3691
+ var val = evaluator()
3692
+ val = val && val.$model || val
3693
+ if (Array.isArray(val)) {
3694
+ if (!element.multiple) {
3695
+ log("ms-duplex在<select multiple=true>上要求对应一个数组")
3696
+ }
3697
+ } else {
3698
+ if (element.multiple) {
3699
+ log("ms-duplex在<select multiple=false>不能对应一个数组")
3700
+ }
3701
+ }
3702
+ //必须变成字符串后才能比较
3703
+ val = Array.isArray(val) ? val.map(String) : val + ""
3704
+ if (val + "" !== element.oldValue) {
3705
+ $elem.val(val)
3706
+ element.oldValue = val + ""
3707
+ }
3708
+ }
3709
+ data.bound("change", updateVModel)
3710
+ checkScan(element, function() {
3711
+ registerSubscriber(data)
3712
+ data.changed.call(element, evaluator(), data)
3713
+ }, NaN)
3714
+ }
3715
+
3716
+
3717
+ // bindingHandlers.html 定义在if.js
3718
+ bindingExecutors.html = function(val, elem, data) {
3719
+ val = val == null ? "" : val
3720
+ var isHtmlFilter = "group" in data
3721
+ var parent = isHtmlFilter ? elem.parentNode : elem
3722
+ if (!parent)
3723
+ return
3724
+ if (val.nodeType === 11) { //将val转换为文档碎片
3725
+ var fragment = val
3726
+ } else if (val.nodeType === 1 || val.item) {
3727
+ var nodes = val.nodeType === 1 ? val.childNodes : val.item ? val : []
3728
+ fragment = hyperspace.cloneNode(true)
3729
+ while (nodes[0]) {
3730
+ fragment.appendChild(nodes[0])
3731
+ }
3732
+ } else {
3733
+ fragment = avalon.parseHTML(val)
3734
+ }
3735
+ //插入占位符, 如果是过滤器,需要有节制地移除指定的数量,如果是html指令,直接清空
3736
+ var comment = DOC.createComment("ms-html")
3737
+ if (isHtmlFilter) {
3738
+ parent.insertBefore(comment, elem)
3739
+ var n = data.group, i = 1
3740
+ while (i < n) {
3741
+ var node = elem.nextSibling
3742
+ if (node) {
3743
+ parent.removeChild(node)
3744
+ i++
3745
+ }
3746
+ }
3747
+ parent.removeChild(elem)
3748
+ data.element = comment //防止被CG
3749
+ } else {
3750
+ avalon.clearHTML(parent).appendChild(comment)
3751
+ }
3752
+ if (isHtmlFilter) {
3753
+ data.group = fragment.childNodes.length || 1
3754
+ }
3755
+ nodes = avalon.slice(fragment.childNodes)
3756
+ if (nodes[0]) {
3757
+ if (comment.parentNode)
3758
+ comment.parentNode.replaceChild(fragment, comment)
3759
+ if (isHtmlFilter) {
3760
+ data.element = nodes[0]
3761
+ }
3762
+ }
3763
+ scanNodeArray(nodes, data.vmodels)
3764
+ }
3765
+
3766
+ bindingHandlers["if"] =
3767
+ bindingHandlers.data =
3768
+ bindingHandlers.text =
3769
+ bindingHandlers.html =
3770
+ function(data, vmodels) {
3771
+ parseExprProxy(data.value, vmodels, data)
3772
+ }
3773
+
3774
+ bindingExecutors["if"] = function(val, elem, data) {
3775
+ if (val) { //插回DOM树
3776
+ if (elem.nodeType === 8) {
3777
+ elem.parentNode.replaceChild(data.template, elem)
3778
+ elem = data.element = data.template //这时可能为null
3779
+ }
3780
+ if (elem.getAttribute(data.name)) {
3781
+ elem.removeAttribute(data.name)
3782
+ scanAttr(elem, data.vmodels)
3783
+ }
3784
+ data.rollback = null
3785
+ } else { //移出DOM树,并用注释节点占据原位置
3786
+ if (elem.nodeType === 1) {
3787
+ var node = data.element = DOC.createComment("ms-if")
3788
+ elem.parentNode.replaceChild(node, elem)
3789
+ data.template = elem //元素节点
3790
+ ifGroup.appendChild(elem)
3791
+ data.rollback = function() {
3792
+ if (elem.parentNode === ifGroup) {
3793
+ ifGroup.removeChild(elem)
3914
3794
  }
3915
- } else if (!element.msRetain) {
3916
- return false
3917
3795
  }
3918
- })
3796
+ }
3919
3797
  }
3920
- element.avalonSetter = updateVModel
3921
- element.oldValue = element.value
3922
- registerSubscriber(data)
3923
- callback.call(element, element.value)
3924
3798
  }
3925
- duplexBinding.TEXTAREA = duplexBinding.INPUT
3926
3799
 
3927
3800
 
3928
- duplexBinding.SELECT = function(element, evaluator, data) {
3929
- var $elem = avalon(element)
3930
- function updateVModel() {
3931
- if ($elem.data("duplex-observe") !== false) {
3932
- var val = $elem.val() //字符串或字符串数组
3933
- if (Array.isArray(val)) {
3934
- val = val.map(function(v) {
3935
- return data.pipe(v, data, "get")
3936
- })
3937
- } else {
3938
- val = data.pipe(val, data, "get")
3939
- }
3940
- if (val + "" !== element.oldValue) {
3941
- evaluator(val)
3942
- }
3943
- data.changed.call(element, val, data)
3801
+ //ms-important绑定已经在scanTag 方法中实现
3802
+ //ms-include绑定已由ms-attr绑定实现
3803
+
3804
+ var rdash = /\(([^)]*)\)/
3805
+ bindingHandlers.on = function(data, vmodels) {
3806
+ var value = data.value
3807
+ data.type = "on"
3808
+ var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
3809
+ if (typeof bindingHandlers.on[eventType + "Hook"] === "function") {
3810
+ bindingHandlers.on[eventType + "Hook"](data)
3811
+ }
3812
+ if (value.indexOf("(") > 0 && value.indexOf(")") > -1) {
3813
+ var matched = (value.match(rdash) || ["", ""])[1].trim()
3814
+ if (matched === "" || matched === "$event") { // aaa() aaa($event)当成aaa处理
3815
+ value = value.replace(rdash, "")
3944
3816
  }
3945
3817
  }
3946
- data.handler = function() {
3947
- var val = evaluator()
3948
- val = val && val.$model || val
3949
- if (Array.isArray(val)) {
3950
- if (!element.multiple) {
3951
- log("ms-duplex在<select multiple=true>上要求对应一个数组")
3952
- }
3818
+ parseExprProxy(value, vmodels, data)
3819
+ }
3820
+
3821
+ bindingExecutors.on = function(callback, elem, data) {
3822
+ callback = function(e) {
3823
+ var fn = data.evaluator || noop
3824
+ return fn.apply(this, data.args.concat(e))
3825
+ }
3826
+ var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
3827
+ if (eventType === "scan") {
3828
+ callback.call(elem, {
3829
+ type: eventType
3830
+ })
3831
+ } else if (typeof data.specialBind === "function") {
3832
+ data.specialBind(elem, callback)
3833
+ } else {
3834
+ var removeFn = avalon.bind(elem, eventType, callback)
3835
+ }
3836
+ data.rollback = function() {
3837
+ if (typeof data.specialUnbind === "function") {
3838
+ data.specialUnbind()
3953
3839
  } else {
3954
- if (element.multiple) {
3955
- log("ms-duplex在<select multiple=false>不能对应一个数组")
3956
- }
3957
- }
3958
- //必须变成字符串后才能比较
3959
- val = Array.isArray(val) ? val.map(String) : val + ""
3960
- if (val + "" !== element.oldValue) {
3961
- $elem.val(val)
3962
- element.oldValue = val + ""
3840
+ avalon.unbind(elem, eventType, removeFn)
3963
3841
  }
3964
3842
  }
3965
- data.bound("change", updateVModel)
3966
- checkScan(element, function() {
3967
- registerSubscriber(data)
3968
- data.changed.call(element, evaluator(), data)
3969
- }, NaN)
3970
3843
  }
3971
3844
 
3972
3845
 
@@ -4042,9 +3915,9 @@ bindingHandlers.repeat = function(data, vmodels) {
4042
3915
  check0 = "$first"
4043
3916
  check1 = "$last"
4044
3917
  }
4045
- for (var i = 0, p; p = vmodels[i++]; ) {
4046
- if (p.hasOwnProperty(check0) && p.hasOwnProperty(check1)) {
4047
- data.$outer = p
3918
+ for (i = 0; v = vmodels[i++]; ) {
3919
+ if (v.hasOwnProperty(check0) && v.hasOwnProperty(check1)) {
3920
+ data.$outer = v
4048
3921
  break
4049
3922
  }
4050
3923
  }
@@ -4074,7 +3947,7 @@ bindingExecutors.repeat = function(method, pos, el) {
4074
3947
  var n = pos + el
4075
3948
  var array = data.$repeat
4076
3949
  var last = array.length - 1
4077
- var fragments = []
3950
+ var fragments = [], fragment
4078
3951
  var start = locateNode(data, pos)
4079
3952
  for (var i = pos; i < n; i++) {
4080
3953
  var proxy = eachProxyAgent(i, data)
@@ -4082,7 +3955,7 @@ bindingExecutors.repeat = function(method, pos, el) {
4082
3955
  shimController(data, transation, proxy, fragments)
4083
3956
  }
4084
3957
  parent.insertBefore(transation, start)
4085
- for (var i = 0, fragment; fragment = fragments[i++]; ) {
3958
+ for (i = 0; fragment = fragments[i++]; ) {
4086
3959
  scanNodeArray(fragment.nodes, fragment.vmodels)
4087
3960
  fragment.nodes = fragment.vmodels = null
4088
3961
  }
@@ -4124,7 +3997,7 @@ bindingExecutors.repeat = function(method, pos, el) {
4124
3997
  parent.insertBefore(transation, end)
4125
3998
  break
4126
3999
  case "index": //将proxies中的第pos个起的所有元素重新索引
4127
- var last = proxies.length - 1
4000
+ last = proxies.length - 1
4128
4001
  for (; el = proxies[pos]; pos++) {
4129
4002
  el.$index = pos
4130
4003
  el.$first = pos === 0
@@ -4132,7 +4005,7 @@ bindingExecutors.repeat = function(method, pos, el) {
4132
4005
  }
4133
4006
  return
4134
4007
  case "set": //将proxies中的第pos个元素的VM设置为el(pos为数字,el任意)
4135
- var proxy = proxies[pos]
4008
+ proxy = proxies[pos]
4136
4009
  if (proxy) {
4137
4010
  notifySubscribers(proxy.$events.$index)
4138
4011
  }
@@ -4140,7 +4013,7 @@ bindingExecutors.repeat = function(method, pos, el) {
4140
4013
  case "append": //将pos的键值对从el中取出(pos为一个普通对象,el为预先生成好的代理VM对象池)
4141
4014
  var pool = el
4142
4015
  var keys = []
4143
- var fragments = []
4016
+ fragments = []
4144
4017
  for (var key in pos) { //得到所有键名
4145
4018
  if (pos.hasOwnProperty(key) && key !== "hasOwnProperty") {
4146
4019
  keys.push(key)
@@ -4152,7 +4025,7 @@ bindingExecutors.repeat = function(method, pos, el) {
4152
4025
  keys = keys2
4153
4026
  }
4154
4027
  }
4155
- for (var i = 0, key; key = keys[i++]; ) {
4028
+ for (i = 0; key = keys[i++]; ) {
4156
4029
  if (key !== "hasOwnProperty") {
4157
4030
  if (!pool[key]) {
4158
4031
  pool[key] = withProxyAgent(key, data)
@@ -4163,7 +4036,7 @@ bindingExecutors.repeat = function(method, pos, el) {
4163
4036
  var comment = data.$stamp = data.clone
4164
4037
  parent.insertBefore(comment, end)
4165
4038
  parent.insertBefore(transation, end)
4166
- for (var i = 0, fragment; fragment = fragments[i++]; ) {
4039
+ for (i = 0; fragment = fragments[i++]; ) {
4167
4040
  scanNodeArray(fragment.nodes, fragment.vmodels)
4168
4041
  fragment.nodes = fragment.vmodels = null
4169
4042
  }
@@ -4343,6 +4216,139 @@ function recycleProxies(proxies, type) {
4343
4216
 
4344
4217
 
4345
4218
 
4219
+ /*********************************************************************
4220
+ * 各种指令 *
4221
+ **********************************************************************/
4222
+ //ms-skip绑定已经在scanTag 方法中实现
4223
+ // bindingHandlers.text 定义在if.js
4224
+ bindingExecutors.text = function(val, elem) {
4225
+ val = val == null ? "" : val //不在页面上显示undefined null
4226
+ if (elem.nodeType === 3) { //绑定在文本节点上
4227
+ try { //IE对游离于DOM树外的节点赋值会报错
4228
+ elem.data = val
4229
+ } catch (e) {
4230
+ }
4231
+ } else { //绑定在特性节点上
4232
+ if ("textContent" in elem) {
4233
+ elem.textContent = val
4234
+ } else {
4235
+ elem.innerText = val
4236
+ }
4237
+ }
4238
+ }
4239
+
4240
+
4241
+ function parseDisplay(nodeName, val) {
4242
+ //用于取得此类标签的默认display值
4243
+ var key = "_" + nodeName
4244
+ if (!parseDisplay[key]) {
4245
+ var node = DOC.createElement(nodeName)
4246
+ root.appendChild(node)
4247
+ if (W3C) {
4248
+ val = getComputedStyle(node, null).display
4249
+ } else {
4250
+ val = node.currentStyle.display
4251
+ }
4252
+ root.removeChild(node)
4253
+ parseDisplay[key] = val
4254
+ }
4255
+ return parseDisplay[key]
4256
+ }
4257
+
4258
+ avalon.parseDisplay = parseDisplay
4259
+
4260
+ bindingHandlers.visible = function(data, vmodels) {
4261
+ var elem = avalon(data.element)
4262
+ var display = elem.css("display")
4263
+ if (display === "none") {
4264
+ var style = elem[0].style
4265
+ var has = /visibility/i.test(style.cssText)
4266
+ var visible = elem.css("visibility")
4267
+ style.display = ""
4268
+ style.visibility = "hidden"
4269
+ display = elem.css("display")
4270
+ if (display === "none") {
4271
+ display = parseDisplay(elem[0].nodeName)
4272
+ }
4273
+ style.visibility = has ? visible : ""
4274
+ }
4275
+ data.display = display
4276
+ parseExprProxy(data.value, vmodels, data)
4277
+ }
4278
+
4279
+ bindingExecutors.visible = function(val, elem, data) {
4280
+ elem.style.display = val ? data.display : "none"
4281
+ }
4282
+
4283
+ bindingHandlers.widget = function(data, vmodels) {
4284
+ var args = data.value.match(rword)
4285
+ var elem = data.element
4286
+ var widget = args[0]
4287
+ var id = args[1]
4288
+ if (!id || id === "$") {//没有定义或为$时,取组件名+随机数
4289
+ id = generateID(widget)
4290
+ }
4291
+ var optName = args[2] || widget//没有定义,取组件名
4292
+ var constructor = avalon.ui[widget]
4293
+ if (typeof constructor === "function") { //ms-widget="tabs,tabsAAA,optname"
4294
+ vmodels = elem.vmodels || vmodels
4295
+ for (var i = 0, v; v = vmodels[i++]; ) {
4296
+ if (v.hasOwnProperty(optName) && typeof v[optName] === "object") {
4297
+ var vmOptions = v[optName]
4298
+ vmOptions = vmOptions.$model || vmOptions
4299
+ break
4300
+ }
4301
+ }
4302
+ if (vmOptions) {
4303
+ var wid = vmOptions[widget + "Id"]
4304
+ if (typeof wid === "string") {
4305
+ id = wid
4306
+ }
4307
+ }
4308
+ //抽取data-tooltip-text、data-tooltip-attr属性,组成一个配置对象
4309
+ var widgetData = avalon.getWidgetData(elem, widget)
4310
+ data.value = [widget, id, optName].join(",")
4311
+ data[widget + "Id"] = id
4312
+ data.evaluator = noop
4313
+ elem.msData["ms-widget-id"] = id
4314
+ var options = data[widget + "Options"] = avalon.mix({}, constructor.defaults, vmOptions || {}, widgetData)
4315
+ elem.removeAttribute("ms-widget")
4316
+ var vmodel = constructor(elem, data, vmodels) || {} //防止组件不返回VM
4317
+ if (vmodel.$id) {
4318
+ avalon.vmodels[id] = vmodel
4319
+ createSignalTower(elem, vmodel)
4320
+ if (vmodel.hasOwnProperty("$init")) {
4321
+ vmodel.$init(function() {
4322
+ avalon.scan(elem, [vmodel].concat(vmodels))
4323
+ if (typeof options.onInit === "function") {
4324
+ options.onInit.call(elem, vmodel, options, vmodels)
4325
+ }
4326
+ })
4327
+ }
4328
+ data.rollback = function() {
4329
+ try {
4330
+ vmodel.widgetElement = null
4331
+ vmodel.$remove()
4332
+ } catch (e) {
4333
+ }
4334
+ elem.msData = {}
4335
+ delete avalon.vmodels[vmodel.$id]
4336
+ }
4337
+ addSubscribers(data, widgetList)
4338
+ if (window.chrome) {
4339
+ elem.addEventListener("DOMNodeRemovedFromDocument", function() {
4340
+ setTimeout(removeSubscribers)
4341
+ })
4342
+ }
4343
+ } else {
4344
+ avalon.scan(elem, vmodels)
4345
+ }
4346
+ } else if (vmodels.length) { //如果该组件还没有加载,那么保存当前的vmodels
4347
+ elem.vmodels = vmodels
4348
+ }
4349
+ }
4350
+ var widgetList = []
4351
+ //不存在 bindingExecutors.widget
4346
4352
  /*********************************************************************
4347
4353
  * 自带过滤器 *
4348
4354
  **********************************************************************/
@@ -4567,6 +4573,7 @@ new function() {
4567
4573
  Z: timeZoneGetter
4568
4574
  }
4569
4575
  var rdateFormat = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/
4576
+ var raspnetjson = /^\/Date\((\d+)\)\/$/
4570
4577
  filters.date = function(date, format) {
4571
4578
  var locate = filters.date.locate,
4572
4579
  text = "",
@@ -4577,6 +4584,8 @@ new function() {
4577
4584
  if (typeof date === "string") {
4578
4585
  if (/^\d+$/.test(date)) {
4579
4586
  date = toInt(date)
4587
+ } else if (raspnetjson.test(date)) {
4588
+ date = +RegExp.$1
4580
4589
  } else {
4581
4590
  var trimDate = date.trim()
4582
4591
  var dateArray = [0, 0, 0, 0, 0, 0, 0]
@@ -4584,9 +4593,9 @@ new function() {
4584
4593
  //取得年月日
4585
4594
  trimDate = trimDate.replace(/^(\d+)\D(\d+)\D(\d+)/, function(_, a, b, c) {
4586
4595
  var array = c.length === 4 ? [c, a, b] : [a, b, c]
4587
- dateArray[0] = toInt(array[0]) //年
4596
+ dateArray[0] = toInt(array[0]) //年
4588
4597
  dateArray[1] = toInt(array[1]) - 1 //月
4589
- dateArray[2] = toInt(array[2])//日
4598
+ dateArray[2] = toInt(array[2]) //日
4590
4599
  return ""
4591
4600
  })
4592
4601
  var dateSetter = oDate.setFullYear
@@ -4595,10 +4604,9 @@ new function() {
4595
4604
  dateArray[3] = toInt(a) //小时
4596
4605
  dateArray[4] = toInt(b) //分钟
4597
4606
  dateArray[5] = toInt(c) //秒
4598
- if (d) {
4599
- dateArray[6] = Math.round(parseFloat("0." + d) * 1000) //毫秒
4607
+ if (d) { //毫秒
4608
+ dateArray[6] = Math.round(parseFloat("0." + d) * 1000)
4600
4609
  }
4601
- dateArray[6] = d || ""
4602
4610
  return ""
4603
4611
  })
4604
4612
  var tzHour = 0
@@ -4718,7 +4726,7 @@ new function() {
4718
4726
  }, 50)
4719
4727
  }
4720
4728
  avalon.ready = function(fn) {
4721
- loaded ? fn() : fns.push(fn)
4729
+ loaded ? fn(avalon) : fns.push(fn)
4722
4730
  }
4723
4731
  avalon.ready(function() {
4724
4732
  avalon.scan(DOC.body)
@@ -4751,11 +4759,11 @@ new function() {
4751
4759
  }
4752
4760
  return avalon
4753
4761
  }
4754
- // Expose avalon and $ identifiers, even in AMD
4762
+ // Expose avalon identifiers, even in AMD
4755
4763
  // and CommonJS for browser emulators
4756
4764
  if (noGlobal === void 0) {
4757
4765
  window.avalon = avalon
4758
4766
  }
4759
4767
  return avalon
4760
4768
 
4761
- }));
4769
+ }));