avalon-rails 1.3.9.1 → 1.3.9.1.20150212184918

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }));