avalon-rails 1.4.1.1.20150404164109 → 1.4.6.0.20150915133100
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.
- checksums.yaml +13 -5
- data/lib/avalon-rails/version.rb +1 -1
- data/vendor/assets/javascripts/avalon.js +2066 -1877
- data/vendor/assets/javascripts/avalon.min.js +3 -3
- data/vendor/assets/javascripts/avalon.mobile.js +1653 -1535
- data/vendor/assets/javascripts/avalon.mobile.min.js +3 -3
- data/vendor/assets/javascripts/avalon.mobile.old.js +2030 -1928
- data/vendor/assets/javascripts/avalon.mobile.shim.js +1660 -1548
- data/vendor/assets/javascripts/avalon.modern.js +1481 -1276
- data/vendor/assets/javascripts/avalon.modern.min.js +2 -2
- data/vendor/assets/javascripts/avalon.modern.shim.js +1488 -1289
- data/vendor/assets/javascripts/avalon.shim.js +1863 -1684
- metadata +7 -7
@@ -5,7 +5,7 @@
|
|
5
5
|
http://weibo.com/jslouvre/
|
6
6
|
|
7
7
|
Released under the MIT license
|
8
|
-
avalon.shim.js(无加载器版本) 1.
|
8
|
+
avalon.shim.js(无加载器版本) 1.46 built in 2015.9.11
|
9
9
|
support IE6+ and other browsers
|
10
10
|
==================================================*/
|
11
11
|
(function(global, factory) {
|
@@ -67,10 +67,10 @@ var aslice = ap.slice
|
|
67
67
|
var Registry = {} //将函数曝光到此对象上,方便访问器收集依赖
|
68
68
|
var W3C = window.dispatchEvent
|
69
69
|
var root = DOC.documentElement
|
70
|
-
var
|
70
|
+
var avalonFragment = DOC.createDocumentFragment()
|
71
71
|
var cinerator = DOC.createElement("div")
|
72
72
|
var class2type = {}
|
73
|
-
"Boolean Number String Function Array Date RegExp Object Error".replace(rword, function(name) {
|
73
|
+
"Boolean Number String Function Array Date RegExp Object Error".replace(rword, function (name) {
|
74
74
|
class2type["[object " + name + "]"] = name.toLowerCase()
|
75
75
|
})
|
76
76
|
|
@@ -92,30 +92,35 @@ function oneObject(array, val) {
|
|
92
92
|
}
|
93
93
|
|
94
94
|
//生成UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
|
95
|
-
var generateID = function(prefix) {
|
95
|
+
var generateID = function (prefix) {
|
96
96
|
prefix = prefix || "avalon"
|
97
|
-
return (
|
97
|
+
return String(Math.random() + Math.random()).replace(/\d\.\d{4}/, prefix)
|
98
98
|
}
|
99
99
|
function IE() {
|
100
100
|
if (window.VBArray) {
|
101
101
|
var mode = document.documentMode
|
102
102
|
return mode ? mode : window.XMLHttpRequest ? 7 : 6
|
103
103
|
} else {
|
104
|
-
return
|
104
|
+
return NaN
|
105
105
|
}
|
106
106
|
}
|
107
107
|
var IEVersion = IE()
|
108
108
|
|
109
|
-
avalon = function(el) { //创建jQuery式的无new 实例化结构
|
109
|
+
avalon = function (el) { //创建jQuery式的无new 实例化结构
|
110
110
|
return new avalon.init(el)
|
111
111
|
}
|
112
112
|
|
113
|
+
avalon.profile = function () {
|
114
|
+
if (window.console && avalon.config.profile) {
|
115
|
+
Function.apply.call(console.log, console, arguments)
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
113
119
|
/*视浏览器情况采用最快的异步回调*/
|
114
|
-
avalon.nextTick = new function() {// jshint ignore:line
|
120
|
+
avalon.nextTick = new function () {// jshint ignore:line
|
115
121
|
var tickImmediate = window.setImmediate
|
116
122
|
var tickObserver = window.MutationObserver
|
117
|
-
|
118
|
-
if (tickImmediate) {
|
123
|
+
if (tickImmediate) {//IE10 \11 edage
|
119
124
|
return tickImmediate.bind(window)
|
120
125
|
}
|
121
126
|
|
@@ -128,43 +133,43 @@ avalon.nextTick = new function() {// jshint ignore:line
|
|
128
133
|
queue = queue.slice(n)
|
129
134
|
}
|
130
135
|
|
131
|
-
if (tickObserver) {
|
136
|
+
if (tickObserver) {// 支持MutationObserver
|
132
137
|
var node = document.createTextNode("avalon")
|
133
138
|
new tickObserver(callback).observe(node, {characterData: true})// jshint ignore:line
|
134
|
-
return function(fn) {
|
139
|
+
return function (fn) {
|
135
140
|
queue.push(fn)
|
136
141
|
node.data = Math.random()
|
137
142
|
}
|
138
143
|
}
|
139
144
|
|
140
|
-
if (
|
141
|
-
|
142
|
-
var source = e.source
|
143
|
-
if ((source === window || source === null) && e.data === "process-tick") {
|
144
|
-
e.stopPropagation()
|
145
|
-
callback()
|
146
|
-
}
|
147
|
-
})
|
148
|
-
|
149
|
-
return function(fn) {
|
145
|
+
if (window.VBArray) {
|
146
|
+
return function (fn) {
|
150
147
|
queue.push(fn)
|
151
|
-
|
148
|
+
var node = DOC.createElement("script")
|
149
|
+
node.onreadystatechange = function () {
|
150
|
+
callback() //在interactive阶段就触发
|
151
|
+
node.onreadystatechange = null
|
152
|
+
head.removeChild(node)
|
153
|
+
node = null
|
154
|
+
}
|
155
|
+
head.appendChild(node)
|
152
156
|
}
|
153
157
|
}
|
154
158
|
|
155
|
-
|
156
|
-
|
159
|
+
|
160
|
+
return function (fn) {
|
161
|
+
setTimeout(fn, 4)
|
157
162
|
}
|
158
163
|
}// jshint ignore:line
|
159
164
|
/*********************************************************************
|
160
165
|
* avalon的静态方法定义区 *
|
161
166
|
**********************************************************************/
|
162
|
-
avalon.init = function(el) {
|
167
|
+
avalon.init = function (el) {
|
163
168
|
this[0] = this.element = el
|
164
169
|
}
|
165
170
|
avalon.fn = avalon.prototype = avalon.init.prototype
|
166
171
|
|
167
|
-
avalon.type = function(obj) { //取得目标的类型
|
172
|
+
avalon.type = function (obj) { //取得目标的类型
|
168
173
|
if (obj == null) {
|
169
174
|
return String(obj)
|
170
175
|
}
|
@@ -174,18 +179,18 @@ avalon.type = function(obj) { //取得目标的类型
|
|
174
179
|
typeof obj
|
175
180
|
}
|
176
181
|
|
177
|
-
var isFunction = typeof alert === "object" ? function(fn) {
|
182
|
+
var isFunction = typeof alert === "object" ? function (fn) {
|
178
183
|
try {
|
179
184
|
return /^\s*\bfunction\b/.test(fn + "")
|
180
185
|
} catch (e) {
|
181
186
|
return false
|
182
187
|
}
|
183
|
-
} : function(fn) {
|
188
|
+
} : function (fn) {
|
184
189
|
return serialize.call(fn) === "[object Function]"
|
185
190
|
}
|
186
191
|
avalon.isFunction = isFunction
|
187
192
|
|
188
|
-
avalon.isWindow = function(obj) {
|
193
|
+
avalon.isWindow = function (obj) {
|
189
194
|
if (!obj)
|
190
195
|
return false
|
191
196
|
// 利用IE678 window == document为true,document == window竟然为false的神奇特性
|
@@ -205,7 +210,7 @@ for (enu in avalon({})) {
|
|
205
210
|
}
|
206
211
|
var enumerateBUG = enu !== "0" //IE6下为true, 其他为false
|
207
212
|
/*判定是否是一个朴素的javascript对象(Object),不是DOM对象,不是BOM对象,不是自定义类的实例*/
|
208
|
-
avalon.isPlainObject = function(obj, key) {
|
213
|
+
avalon.isPlainObject = function (obj, key) {
|
209
214
|
if (!obj || avalon.type(obj) !== "object" || obj.nodeType || avalon.isWindow(obj)) {
|
210
215
|
return false;
|
211
216
|
}
|
@@ -226,13 +231,13 @@ avalon.isPlainObject = function(obj, key) {
|
|
226
231
|
return key === void 0 || ohasOwn.call(obj, key)
|
227
232
|
}
|
228
233
|
if (rnative.test(Object.getPrototypeOf)) {
|
229
|
-
avalon.isPlainObject = function(obj) {
|
234
|
+
avalon.isPlainObject = function (obj) {
|
230
235
|
// 简单的 typeof obj === "object"检测,会致使用isPlainObject(window)在opera下通不过
|
231
236
|
return serialize.call(obj) === "[object Object]" && Object.getPrototypeOf(obj) === oproto
|
232
237
|
}
|
233
238
|
}
|
234
239
|
//与jQuery.extend方法,可用于浅拷贝,深拷贝
|
235
|
-
avalon.mix = avalon.fn.mix = function() {
|
240
|
+
avalon.mix = avalon.fn.mix = function () {
|
236
241
|
var options, name, src, copy, copyIsArray, clone,
|
237
242
|
target = arguments[0] || {},
|
238
243
|
i = 1,
|
@@ -299,12 +304,12 @@ function _number(a, len) { //用于模拟slice, splice的效果
|
|
299
304
|
avalon.mix({
|
300
305
|
rword: rword,
|
301
306
|
subscribers: subscribers,
|
302
|
-
version: 1.
|
307
|
+
version: 1.46,
|
303
308
|
ui: {},
|
304
309
|
log: log,
|
305
|
-
slice: W3C ? function(nodes, start, end) {
|
310
|
+
slice: W3C ? function (nodes, start, end) {
|
306
311
|
return aslice.call(nodes, start, end)
|
307
|
-
} : function(nodes, start, end) {
|
312
|
+
} : function (nodes, start, end) {
|
308
313
|
var ret = []
|
309
314
|
var len = nodes.length
|
310
315
|
if (end === void 0)
|
@@ -320,7 +325,7 @@ avalon.mix({
|
|
320
325
|
},
|
321
326
|
noop: noop,
|
322
327
|
/*如果不用Error对象封装一下,str在控制台下可能会乱码*/
|
323
|
-
error: function(str, e) {
|
328
|
+
error: function (str, e) {
|
324
329
|
throw (e || Error)(str)
|
325
330
|
},
|
326
331
|
/*将一个以空格或逗号隔开的字符串或数组,转换成一个键值都为1的对象*/
|
@@ -335,7 +340,7 @@ avalon.mix({
|
|
335
340
|
=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
|
336
341
|
avalon.range(0)
|
337
342
|
=> []*/
|
338
|
-
range: function(start, end, step) { // 用于生成整数数组
|
343
|
+
range: function (start, end, step) { // 用于生成整数数组
|
339
344
|
step || (step = 1)
|
340
345
|
if (end == null) {
|
341
346
|
end = start || 0
|
@@ -350,7 +355,7 @@ avalon.mix({
|
|
350
355
|
}
|
351
356
|
return result
|
352
357
|
},
|
353
|
-
eventHooks:
|
358
|
+
eventHooks: [],
|
354
359
|
/*绑定事件*/
|
355
360
|
bind: function(el, type, fn, phase) {
|
356
361
|
var hooks = avalon.eventHooks
|
@@ -389,7 +394,7 @@ avalon.mix({
|
|
389
394
|
}
|
390
395
|
},
|
391
396
|
/*读写删除元素节点的样式*/
|
392
|
-
css: function(node, name, value) {
|
397
|
+
css: function (node, name, value) {
|
393
398
|
if (node instanceof avalon) {
|
394
399
|
node = node[0]
|
395
400
|
}
|
@@ -416,7 +421,7 @@ avalon.mix({
|
|
416
421
|
}
|
417
422
|
},
|
418
423
|
/*遍历数组与对象,回调的第一个参数为索引或键名,第二个或元素或键值*/
|
419
|
-
each: function(obj, fn) {
|
424
|
+
each: function (obj, fn) {
|
420
425
|
if (obj) { //排除null, undefined
|
421
426
|
var i = 0
|
422
427
|
if (isArrayLike(obj)) {
|
@@ -434,12 +439,12 @@ avalon.mix({
|
|
434
439
|
}
|
435
440
|
},
|
436
441
|
//收集元素的data-{{prefix}}-*属性,并转换为对象
|
437
|
-
getWidgetData: function(elem, prefix) {
|
442
|
+
getWidgetData: function (elem, prefix) {
|
438
443
|
var raw = avalon(elem).data()
|
439
444
|
var result = {}
|
440
445
|
for (var i in raw) {
|
441
446
|
if (i.indexOf(prefix) === 0) {
|
442
|
-
result[i.replace(prefix, "").replace(/\w/, function(a) {
|
447
|
+
result[i.replace(prefix, "").replace(/\w/, function (a) {
|
443
448
|
return a.toLowerCase()
|
444
449
|
})] = raw[i]
|
445
450
|
}
|
@@ -448,17 +453,17 @@ avalon.mix({
|
|
448
453
|
},
|
449
454
|
Array: {
|
450
455
|
/*只有当前数组不存在此元素时只添加它*/
|
451
|
-
ensure: function(target, item) {
|
456
|
+
ensure: function (target, item) {
|
452
457
|
if (target.indexOf(item) === -1) {
|
453
458
|
return target.push(item)
|
454
459
|
}
|
455
460
|
},
|
456
461
|
/*移除数组中指定位置的元素,返回布尔表示成功与否*/
|
457
|
-
removeAt: function(target, index) {
|
462
|
+
removeAt: function (target, index) {
|
458
463
|
return !!target.splice(index, 1).length
|
459
464
|
},
|
460
465
|
/*移除数组中第一个匹配传参的那个元素,返回布尔表示成功与否*/
|
461
|
-
remove: function(target, item) {
|
466
|
+
remove: function (target, item) {
|
462
467
|
var index = target.indexOf(item)
|
463
468
|
if (~index)
|
464
469
|
return avalon.Array.removeAt(target, index)
|
@@ -534,6 +539,7 @@ var Cache = new function() {// jshint ignore:line
|
|
534
539
|
entry.newer =
|
535
540
|
entry.older =
|
536
541
|
this._keymap[entry.key] = void 0
|
542
|
+
delete this._keymap[entry.key] //#1029
|
537
543
|
}
|
538
544
|
}
|
539
545
|
p.get = function(key) {
|
@@ -593,7 +599,7 @@ var hasDontEnumBug = !({
|
|
593
599
|
dontEnumsLength = dontEnums.length;
|
594
600
|
if (!Object.keys) {
|
595
601
|
Object.keys = function (object) { //ecma262v5 15.2.3.14
|
596
|
-
var theKeys = []
|
602
|
+
var theKeys = []
|
597
603
|
var skipProto = hasProtoEnumBug && typeof object === "function"
|
598
604
|
if (typeof object === "string" || (object && object.callee)) {
|
599
605
|
for (var i = 0; i < object.length; ++i) {
|
@@ -609,7 +615,7 @@ if (!Object.keys) {
|
|
609
615
|
|
610
616
|
if (hasDontEnumBug) {
|
611
617
|
var ctor = object.constructor,
|
612
|
-
skipConstructor = ctor && ctor.prototype === object
|
618
|
+
skipConstructor = ctor && ctor.prototype === object
|
613
619
|
for (var j = 0; j < dontEnumsLength; j++) {
|
614
620
|
var dontEnum = dontEnums[j]
|
615
621
|
if (!(skipConstructor && dontEnum === "constructor") && ohasOwn.call(object, dontEnum)) {
|
@@ -785,6 +791,7 @@ if (!root.outerHTML && window.HTMLElement) { //firefox 到11时才有outerHTML
|
|
785
791
|
HTMLElement.prototype.__defineGetter__("outerHTML", outerHTML);
|
786
792
|
}
|
787
793
|
|
794
|
+
|
788
795
|
//============================= event binding =======================
|
789
796
|
var rmouseEvent = /^(?:mouse|contextmenu|drag)|click/
|
790
797
|
function fixEvent(event) {
|
@@ -887,6 +894,7 @@ if (DOC.onmousewheel === void 0) {
|
|
887
894
|
}
|
888
895
|
|
889
896
|
|
897
|
+
|
890
898
|
/*********************************************************************
|
891
899
|
* 配置系统 *
|
892
900
|
**********************************************************************/
|
@@ -924,15 +932,15 @@ var plugins = {
|
|
924
932
|
openTag = array[0]
|
925
933
|
closeTag = array[1]
|
926
934
|
if (openTag === closeTag) {
|
927
|
-
throw new SyntaxError("openTag
|
928
|
-
} else if (array + "" === "<!--,-->") {
|
929
|
-
kernel.commentInterpolate = true
|
935
|
+
throw new SyntaxError("openTag===closeTag")
|
930
936
|
} else {
|
931
937
|
var test = openTag + "test" + closeTag
|
932
938
|
cinerator.innerHTML = test
|
933
939
|
if (cinerator.innerHTML !== test && cinerator.innerHTML.indexOf("<") > -1) {
|
934
940
|
throw new SyntaxError("此定界符不合法")
|
935
941
|
}
|
942
|
+
kernel.openTag = openTag
|
943
|
+
kernel.closeTag = closeTag
|
936
944
|
cinerator.innerHTML = ""
|
937
945
|
}
|
938
946
|
var o = escapeRegExp(openTag),
|
@@ -1031,8 +1039,8 @@ var EventBus = {
|
|
1031
1039
|
}
|
1032
1040
|
//循环两个vmodel中的节点,查找匹配(向上匹配或者向下匹配)的节点并设置标识
|
1033
1041
|
/* jshint ignore:start */
|
1034
|
-
|
1035
|
-
|
1042
|
+
ap.forEach.call(eventNodes, function (node) {
|
1043
|
+
ap.forEach.call(elements, function (element) {
|
1036
1044
|
var ok = special === "down" ? element.contains(node) : //向下捕获
|
1037
1045
|
node.contains(element) //向上冒泡
|
1038
1046
|
if (ok) {
|
@@ -1046,7 +1054,7 @@ var EventBus = {
|
|
1046
1054
|
}
|
1047
1055
|
var nodes = DOC.getElementsByTagName("*") //实现节点排序
|
1048
1056
|
var alls = []
|
1049
|
-
|
1057
|
+
ap.forEach.call(nodes, function (el) {
|
1050
1058
|
if (el._avalon) {
|
1051
1059
|
alls.push(el._avalon)
|
1052
1060
|
el._avalon = ""
|
@@ -1075,7 +1083,6 @@ var EventBus = {
|
|
1075
1083
|
}
|
1076
1084
|
}
|
1077
1085
|
}
|
1078
|
-
|
1079
1086
|
/*********************************************************************
|
1080
1087
|
* modelFactory *
|
1081
1088
|
**********************************************************************/
|
@@ -1096,6 +1103,7 @@ avalon.define = function (id, factory) {
|
|
1096
1103
|
$watch: noop
|
1097
1104
|
}
|
1098
1105
|
factory(scope) //得到所有定义
|
1106
|
+
|
1099
1107
|
model = modelFactory(scope) //偷天换日,将scope换为model
|
1100
1108
|
stopRepeatAssign = true
|
1101
1109
|
factory(model)
|
@@ -1106,52 +1114,7 @@ avalon.define = function (id, factory) {
|
|
1106
1114
|
}
|
1107
1115
|
|
1108
1116
|
//一些不需要被监听的属性
|
1109
|
-
var $$skipArray = String("$id,$watch,$unwatch,$fire,$events,$model,$skipArray").match(rword)
|
1110
|
-
|
1111
|
-
function isObservable(name, value, $skipArray) {
|
1112
|
-
if (isFunction(value) || value && value.nodeType) {
|
1113
|
-
return false
|
1114
|
-
}
|
1115
|
-
if ($skipArray.indexOf(name) !== -1) {
|
1116
|
-
return false
|
1117
|
-
}
|
1118
|
-
if ($$skipArray.indexOf(name) !== -1) {
|
1119
|
-
return false
|
1120
|
-
}
|
1121
|
-
var $special = $skipArray.$special
|
1122
|
-
if (name && name.charAt(0) === "$" && !$special[name]) {
|
1123
|
-
return false
|
1124
|
-
}
|
1125
|
-
return true
|
1126
|
-
}
|
1127
|
-
//ms-with,ms-each, ms-repeat绑定生成的代理对象储存池
|
1128
|
-
var midway = {}
|
1129
|
-
function getNewValue(accessor, name, value, $vmodel) {
|
1130
|
-
switch (accessor.type) {
|
1131
|
-
case 0://计算属性
|
1132
|
-
var getter = accessor.get
|
1133
|
-
var setter = accessor.set
|
1134
|
-
if (isFunction(setter)) {
|
1135
|
-
var $events = $vmodel.$events
|
1136
|
-
var lock = $events[name]
|
1137
|
-
$events[name] = [] //清空回调,防止内部冒泡而触发多次$fire
|
1138
|
-
setter.call($vmodel, value)
|
1139
|
-
$events[name] = lock
|
1140
|
-
}
|
1141
|
-
return getter.call($vmodel) //同步$model
|
1142
|
-
case 1://监控属性
|
1143
|
-
return value
|
1144
|
-
case 2://对象属性(包括数组与哈希)
|
1145
|
-
if (value !== $vmodel.$model[name]) {
|
1146
|
-
var svmodel = accessor.svmodel = objectFactory($vmodel, name, value, accessor.valueType)
|
1147
|
-
value = svmodel.$model //同步$model
|
1148
|
-
var fn = midway[svmodel.$id]
|
1149
|
-
fn && fn() //同步视图
|
1150
|
-
}
|
1151
|
-
return value
|
1152
|
-
}
|
1153
|
-
}
|
1154
|
-
|
1117
|
+
var $$skipArray = String("$id,$watch,$unwatch,$fire,$events,$model,$skipArray,$reinitialize").match(rword)
|
1155
1118
|
var defineProperty = Object.defineProperty
|
1156
1119
|
var canHideOwn = true
|
1157
1120
|
//如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8
|
@@ -1164,11 +1127,12 @@ try {
|
|
1164
1127
|
} catch (e) {
|
1165
1128
|
canHideOwn = false
|
1166
1129
|
}
|
1130
|
+
|
1167
1131
|
function modelFactory(source, $special, $model) {
|
1168
1132
|
if (Array.isArray(source)) {
|
1169
1133
|
var arr = source.concat()
|
1170
1134
|
source.length = 0
|
1171
|
-
var collection =
|
1135
|
+
var collection = arrayFactory(source)
|
1172
1136
|
collection.pushArray(arr)
|
1173
1137
|
return collection
|
1174
1138
|
}
|
@@ -1176,146 +1140,254 @@ function modelFactory(source, $special, $model) {
|
|
1176
1140
|
if (!source || source.nodeType > 0 || (source.$id && source.$events)) {
|
1177
1141
|
return source
|
1178
1142
|
}
|
1179
|
-
|
1180
|
-
|
1181
|
-
}
|
1182
|
-
source.$skipArray.$special = $special || {} //强制要监听的属性
|
1143
|
+
var $skipArray = Array.isArray(source.$skipArray) ? source.$skipArray : []
|
1144
|
+
$skipArray.$special = $special || {} //强制要监听的属性
|
1183
1145
|
var $vmodel = {} //要返回的对象, 它在IE6-8下可能被偷龙转凤
|
1184
1146
|
$model = $model || {} //vmodels.$model属性
|
1185
1147
|
var $events = {} //vmodel.$events属性
|
1186
|
-
var
|
1187
|
-
var
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1148
|
+
var accessors = {} //监控属性
|
1149
|
+
var computed = []
|
1150
|
+
$$skipArray.forEach(function (name) {
|
1151
|
+
delete source[name]
|
1152
|
+
})
|
1153
|
+
var names = Object.keys(source)
|
1154
|
+
/* jshint ignore:start */
|
1155
|
+
names.forEach(function (name, accessor) {
|
1156
|
+
var val = source[name]
|
1157
|
+
$model[name] = val
|
1158
|
+
if (isObservable(name, val, $skipArray)) {
|
1194
1159
|
//总共产生三种accessor
|
1195
1160
|
$events[name] = []
|
1196
1161
|
var valueType = avalon.type(val)
|
1197
|
-
var accessor = function (newValue) {
|
1198
|
-
var name = accessor._name
|
1199
|
-
var $vmodel = this
|
1200
|
-
var $model = $vmodel.$model
|
1201
|
-
var oldValue = $model[name]
|
1202
|
-
var $events = $vmodel.$events
|
1203
|
-
|
1204
|
-
if (arguments.length) {
|
1205
|
-
if (stopRepeatAssign) {
|
1206
|
-
return
|
1207
|
-
}
|
1208
|
-
//计算属性与对象属性需要重新计算newValue
|
1209
|
-
if (accessor.type !== 1) {
|
1210
|
-
newValue = getNewValue(accessor, name, newValue, $vmodel)
|
1211
|
-
if (!accessor.type)
|
1212
|
-
return
|
1213
|
-
}
|
1214
|
-
if (!isEqual(oldValue, newValue)) {
|
1215
|
-
$model[name] = newValue
|
1216
|
-
notifySubscribers($events[name]) //同步视图
|
1217
|
-
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
|
1218
|
-
}
|
1219
|
-
} else {
|
1220
|
-
if (accessor.type === 0) { //type 0 计算属性 1 监控属性 2 对象属性
|
1221
|
-
//计算属性不需要收集视图刷新函数,都是由其他监控属性代劳
|
1222
|
-
newValue = accessor.get.call($vmodel)
|
1223
|
-
if (oldValue !== newValue) {
|
1224
|
-
$model[name] = newValue
|
1225
|
-
//这里不用同步视图
|
1226
|
-
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
|
1227
|
-
}
|
1228
|
-
return newValue
|
1229
|
-
} else {
|
1230
|
-
collectSubscribers($events[name]) //收集视图函数
|
1231
|
-
return accessor.svmodel || oldValue
|
1232
|
-
}
|
1233
|
-
}
|
1234
|
-
}
|
1235
1162
|
//总共产生三种accessor
|
1236
1163
|
if (valueType === "object" && isFunction(val.get) && Object.keys(val).length <= 2) {
|
1237
|
-
|
1238
|
-
accessor
|
1239
|
-
accessor.get = val.get
|
1240
|
-
accessor.type = 0
|
1241
|
-
initCallbacks.push(function () {
|
1242
|
-
var data = {
|
1243
|
-
evaluator: function () {
|
1244
|
-
data.type = Math.random(),
|
1245
|
-
data.element = null
|
1246
|
-
$model[name] = accessor.get.call($vmodel)
|
1247
|
-
},
|
1248
|
-
element: head,
|
1249
|
-
type: Math.random(),
|
1250
|
-
handler: noop,
|
1251
|
-
args: []
|
1252
|
-
}
|
1253
|
-
Registry[expose] = data
|
1254
|
-
accessor.call($vmodel)
|
1255
|
-
delete Registry[expose]
|
1256
|
-
})
|
1164
|
+
accessor = makeComputedAccessor(name, val)
|
1165
|
+
computed.push(accessor)
|
1257
1166
|
} else if (rcomplexType.test(valueType)) {
|
1258
|
-
|
1259
|
-
|
1260
|
-
accessor
|
1261
|
-
initCallbacks.push(function () {
|
1262
|
-
var svmodel = modelFactory(val, 0, $model[name])
|
1263
|
-
accessor.svmodel = svmodel
|
1264
|
-
svmodel.$events[subscribers] = $events[name]
|
1265
|
-
})
|
1167
|
+
// issue #940 解决$model层次依赖丢失 https://github.com/RubyLouvre/avalon/issues/940
|
1168
|
+
// $model[name] = {}
|
1169
|
+
accessor = makeComplexAccessor(name, val, valueType, $events[name], $model)
|
1266
1170
|
} else {
|
1267
|
-
accessor
|
1268
|
-
//第3种为监控属性,对应简单的数据类型,自变量
|
1171
|
+
accessor = makeSimpleAccessor(name, val)
|
1269
1172
|
}
|
1270
|
-
|
1271
|
-
|
1272
|
-
})(i, source[i])// jshint ignore:line
|
1273
|
-
}
|
1274
|
-
|
1275
|
-
$$skipArray.forEach(function (name) {
|
1276
|
-
delete source[name]
|
1277
|
-
delete $model[name] //这些特殊属性不应该在$model中出现
|
1173
|
+
accessors[name] = accessor
|
1174
|
+
}
|
1278
1175
|
})
|
1279
|
-
|
1280
|
-
$vmodel = defineProperties($vmodel, descriptorFactory(
|
1281
|
-
for (var
|
1282
|
-
|
1176
|
+
/* jshint ignore:end */
|
1177
|
+
$vmodel = defineProperties($vmodel, descriptorFactory(accessors), source) //生成一个空的ViewModel
|
1178
|
+
for (var i = 0; i < names.length; i++) {
|
1179
|
+
var name = names[i]
|
1180
|
+
if (!accessors[name]) {
|
1283
1181
|
$vmodel[name] = source[name]
|
1284
1182
|
}
|
1285
1183
|
}
|
1286
1184
|
//添加$id, $model, $events, $watch, $unwatch, $fire
|
1287
|
-
$vmodel
|
1288
|
-
$vmodel
|
1289
|
-
$vmodel
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1185
|
+
hideProperty($vmodel, "$id", generateID())
|
1186
|
+
hideProperty($vmodel, "$model", $model)
|
1187
|
+
hideProperty($vmodel, "$events", $events)
|
1188
|
+
/* jshint ignore:start */
|
1189
|
+
if (canHideOwn) {
|
1190
|
+
hideProperty($vmodel, "hasOwnProperty", function (name) {
|
1191
|
+
return name in $vmodel.$model
|
1192
|
+
})
|
1193
|
+
} else {
|
1194
|
+
$vmodel.hasOwnProperty = function (name) {
|
1195
|
+
return (name in $vmodel.$model) && (name !== "hasOwnProperty")
|
1294
1196
|
}
|
1295
|
-
$vmodel[i] = fn
|
1296
1197
|
}
|
1198
|
+
/* jshint ignore:end */
|
1199
|
+
for ( i in EventBus) {
|
1200
|
+
hideProperty($vmodel, i, EventBus[i].bind($vmodel))
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
$vmodel.$reinitialize = function () {
|
1204
|
+
computed.forEach(function (accessor) {
|
1205
|
+
delete accessor._value
|
1206
|
+
delete accessor.oldArgs
|
1207
|
+
accessor.digest = function () {
|
1208
|
+
accessor.call($vmodel)
|
1209
|
+
}
|
1210
|
+
dependencyDetection.begin({
|
1211
|
+
callback: function (vm, dependency) {//dependency为一个accessor
|
1212
|
+
var name = dependency._name
|
1213
|
+
if (dependency !== accessor) {
|
1214
|
+
var list = vm.$events[name]
|
1215
|
+
injectDependency(list, accessor.digest)
|
1216
|
+
}
|
1217
|
+
}
|
1218
|
+
})
|
1219
|
+
try {
|
1220
|
+
accessor.get.call($vmodel)
|
1221
|
+
} finally {
|
1222
|
+
dependencyDetection.end()
|
1223
|
+
}
|
1224
|
+
})
|
1225
|
+
}
|
1226
|
+
$vmodel.$reinitialize()
|
1227
|
+
return $vmodel
|
1228
|
+
}
|
1297
1229
|
|
1230
|
+
|
1231
|
+
function hideProperty(host, name, value) {
|
1298
1232
|
if (canHideOwn) {
|
1299
|
-
Object.defineProperty(
|
1300
|
-
value:
|
1301
|
-
|
1302
|
-
},
|
1303
|
-
writable: false,
|
1233
|
+
Object.defineProperty(host, name, {
|
1234
|
+
value: value,
|
1235
|
+
writable: true,
|
1304
1236
|
enumerable: false,
|
1305
1237
|
configurable: true
|
1306
1238
|
})
|
1307
|
-
|
1308
1239
|
} else {
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1240
|
+
host[name] = value
|
1241
|
+
}
|
1242
|
+
}
|
1243
|
+
//创建一个简单访问器
|
1244
|
+
function makeSimpleAccessor(name, value) {
|
1245
|
+
function accessor(value) {
|
1246
|
+
var oldValue = accessor._value
|
1247
|
+
if (arguments.length > 0) {
|
1248
|
+
if (!stopRepeatAssign && !isEqual(value, oldValue)) {
|
1249
|
+
accessor.updateValue(this, value)
|
1250
|
+
accessor.notify(this, value, oldValue)
|
1251
|
+
}
|
1252
|
+
return this
|
1253
|
+
} else {
|
1254
|
+
dependencyDetection.collectDependency(this, accessor)
|
1255
|
+
return oldValue
|
1312
1256
|
}
|
1313
|
-
/* jshint ignore:end */
|
1314
1257
|
}
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1258
|
+
accessorFactory(accessor, name)
|
1259
|
+
accessor._value = value
|
1260
|
+
return accessor;
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
//创建一个计算访问器
|
1264
|
+
function makeComputedAccessor(name, options) {
|
1265
|
+
function accessor(value) {//计算属性
|
1266
|
+
var oldValue = accessor._value
|
1267
|
+
var init = ("_value" in accessor)
|
1268
|
+
if (arguments.length > 0) {
|
1269
|
+
if (stopRepeatAssign) {
|
1270
|
+
return this
|
1271
|
+
}
|
1272
|
+
if (typeof accessor.set === "function") {
|
1273
|
+
if (accessor.oldArgs !== value) {
|
1274
|
+
accessor.oldArgs = value
|
1275
|
+
var $events = this.$events
|
1276
|
+
var lock = $events[name]
|
1277
|
+
$events[name] = [] //清空回调,防止内部冒泡而触发多次$fire
|
1278
|
+
accessor.set.call(this, value)
|
1279
|
+
$events[name] = lock
|
1280
|
+
value = accessor.get.call(this)
|
1281
|
+
if (value !== oldValue) {
|
1282
|
+
accessor.updateValue(this, value)
|
1283
|
+
accessor.notify(this, value, oldValue) //触发$watch回调
|
1284
|
+
}
|
1285
|
+
}
|
1286
|
+
}
|
1287
|
+
return this
|
1288
|
+
} else {
|
1289
|
+
//将依赖于自己的高层访问器或视图刷新函数(以绑定对象形式)放到自己的订阅数组中
|
1290
|
+
//将自己注入到低层访问器的订阅数组中
|
1291
|
+
value = accessor.get.call(this)
|
1292
|
+
accessor.updateValue(this, value)
|
1293
|
+
if (init && oldValue !== value) {
|
1294
|
+
accessor.notify(this, value, oldValue) //触发$watch回调
|
1295
|
+
}
|
1296
|
+
return value
|
1297
|
+
}
|
1298
|
+
}
|
1299
|
+
accessor.set = options.set
|
1300
|
+
accessor.get = options.get
|
1301
|
+
accessorFactory(accessor, name)
|
1302
|
+
return accessor
|
1303
|
+
}
|
1304
|
+
|
1305
|
+
//创建一个复杂访问器
|
1306
|
+
function makeComplexAccessor(name, initValue, valueType, list, parentModel) {
|
1307
|
+
|
1308
|
+
function accessor(value) {
|
1309
|
+
var oldValue = accessor._value
|
1310
|
+
|
1311
|
+
var son = accessor._vmodel
|
1312
|
+
if (arguments.length > 0) {
|
1313
|
+
if (stopRepeatAssign) {
|
1314
|
+
return this
|
1315
|
+
}
|
1316
|
+
if (valueType === "array") {
|
1317
|
+
var a = son, b = value,
|
1318
|
+
an = a.length,
|
1319
|
+
bn = b.length
|
1320
|
+
a.$lock = true
|
1321
|
+
if (an > bn) {
|
1322
|
+
a.splice(bn, an - bn)
|
1323
|
+
} else if (bn > an) {
|
1324
|
+
a.push.apply(a, b.slice(an))
|
1325
|
+
}
|
1326
|
+
var n = Math.min(an, bn)
|
1327
|
+
for (var i = 0; i < n; i++) {
|
1328
|
+
a.set(i, b[i])
|
1329
|
+
}
|
1330
|
+
delete a.$lock
|
1331
|
+
a._fire("set")
|
1332
|
+
} else if (valueType === "object") {
|
1333
|
+
var observes = this.$events[name] || []
|
1334
|
+
var newObject = avalon.mix(true, {}, value)
|
1335
|
+
for(i in son ){
|
1336
|
+
if(son.hasOwnProperty(i) && ohasOwn.call(newObject,i)){
|
1337
|
+
son[i] = newObject[i]
|
1338
|
+
}
|
1339
|
+
}
|
1340
|
+
son = accessor._vmodel = modelFactory(value)
|
1341
|
+
son.$events[subscribers] = observes
|
1342
|
+
if (observes.length) {
|
1343
|
+
observes.forEach(function (data) {
|
1344
|
+
if (!data.type) {
|
1345
|
+
return //数据未准备好时忽略更新
|
1346
|
+
}
|
1347
|
+
if (data.rollback) {
|
1348
|
+
data.rollback() //还原 ms-with ms-on
|
1349
|
+
}
|
1350
|
+
bindingHandlers[data.type](data, data.vmodels)
|
1351
|
+
})
|
1352
|
+
}
|
1353
|
+
}
|
1354
|
+
accessor.updateValue(this, son.$model)
|
1355
|
+
accessor.notify(this, this._value, oldValue)
|
1356
|
+
return this
|
1357
|
+
} else {
|
1358
|
+
dependencyDetection.collectDependency(this, accessor)
|
1359
|
+
return son
|
1360
|
+
}
|
1361
|
+
}
|
1362
|
+
accessorFactory(accessor, name)
|
1363
|
+
if (Array.isArray(initValue)) {
|
1364
|
+
parentModel[name] = initValue
|
1365
|
+
} else {
|
1366
|
+
parentModel[name] = parentModel[name] || {}
|
1367
|
+
}
|
1368
|
+
var son = accessor._vmodel = modelFactory(initValue, 0, parentModel[name])
|
1369
|
+
son.$events[subscribers] = list
|
1370
|
+
return accessor
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
function globalUpdateValue(vmodel, value) {
|
1374
|
+
vmodel.$model[this._name] = this._value = value
|
1375
|
+
}
|
1376
|
+
|
1377
|
+
function globalNotify(vmodel, value, oldValue) {
|
1378
|
+
var name = this._name
|
1379
|
+
var array = vmodel.$events[name] //刷新值
|
1380
|
+
if (array) {
|
1381
|
+
fireDependencies(array) //同步视图
|
1382
|
+
EventBus.$fire.call(vmodel, name, value, oldValue) //触发$watch回调
|
1383
|
+
}
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
function accessorFactory(accessor, name) {
|
1387
|
+
accessor._name = name
|
1388
|
+
//同时更新_value与model
|
1389
|
+
accessor.updateValue = globalUpdateValue
|
1390
|
+
accessor.notify = globalNotify
|
1319
1391
|
}
|
1320
1392
|
|
1321
1393
|
//比较两个值是否相等
|
@@ -1329,12 +1401,29 @@ var isEqual = Object.is || function (v1, v2) {
|
|
1329
1401
|
}
|
1330
1402
|
}
|
1331
1403
|
|
1332
|
-
function
|
1333
|
-
if (
|
1334
|
-
|
1404
|
+
function isObservable(name, value, $skipArray) {
|
1405
|
+
if (isFunction(value) || value && value.nodeType) {
|
1406
|
+
return false
|
1407
|
+
}
|
1408
|
+
if ($skipArray.indexOf(name) !== -1) {
|
1409
|
+
return false
|
1410
|
+
}
|
1411
|
+
var $special = $skipArray.$special
|
1412
|
+
if (name && name.charAt(0) === "$" && !$special[name]) {
|
1413
|
+
return false
|
1335
1414
|
}
|
1415
|
+
return true
|
1416
|
+
}
|
1417
|
+
function keysVM(obj) {
|
1418
|
+
var arr = Object.keys(obj.$model ? obj.$model: obj)
|
1419
|
+
for (var i = 0; i < $$skipArray.length; i++) {
|
1420
|
+
var index = arr.indexOf($$skipArray[i])
|
1421
|
+
if (index !== -1) {
|
1422
|
+
arr.splice(index, 1)
|
1423
|
+
}
|
1424
|
+
}
|
1425
|
+
return arr
|
1336
1426
|
}
|
1337
|
-
|
1338
1427
|
var descriptorFactory = W3C ? function (obj) {
|
1339
1428
|
var descriptors = {}
|
1340
1429
|
for (var i in obj) {
|
@@ -1350,47 +1439,6 @@ var descriptorFactory = W3C ? function (obj) {
|
|
1350
1439
|
return a
|
1351
1440
|
}
|
1352
1441
|
|
1353
|
-
|
1354
|
-
|
1355
|
-
//应用于第2种accessor
|
1356
|
-
function objectFactory(parent, name, value, valueType) {
|
1357
|
-
//a为原来的VM, b为新数组或新对象
|
1358
|
-
var son = parent[name]
|
1359
|
-
if (valueType === "array") {
|
1360
|
-
if (!Array.isArray(value) || son === value) {
|
1361
|
-
return son //fix https://github.com/RubyLouvre/avalon/issues/261
|
1362
|
-
}
|
1363
|
-
son._.$unwatch()
|
1364
|
-
son.clear()
|
1365
|
-
son._.$watch()
|
1366
|
-
son.pushArray(value.concat())
|
1367
|
-
return son
|
1368
|
-
} else {
|
1369
|
-
var iterators = parent.$events[name]
|
1370
|
-
var pool = son.$events.$withProxyPool
|
1371
|
-
if (pool) {
|
1372
|
-
recycleProxies(pool, "with")
|
1373
|
-
son.$events.$withProxyPool = null
|
1374
|
-
}
|
1375
|
-
var ret = modelFactory(value)
|
1376
|
-
ret.$events[subscribers] = iterators
|
1377
|
-
midway[ret.$id] = function (data) {
|
1378
|
-
while (data = iterators.shift()) {
|
1379
|
-
(function (el) {
|
1380
|
-
avalon.nextTick(function () {
|
1381
|
-
var type = el.type
|
1382
|
-
if (type && bindingHandlers[type]) { //#753
|
1383
|
-
el.rollback && el.rollback() //还原 ms-with ms-on
|
1384
|
-
bindingHandlers[type](el, el.vmodels)
|
1385
|
-
}
|
1386
|
-
})
|
1387
|
-
})(data) // jshint ignore:line
|
1388
|
-
}
|
1389
|
-
delete midway[ret.$id]
|
1390
|
-
}
|
1391
|
-
return ret
|
1392
|
-
}
|
1393
|
-
}
|
1394
1442
|
//===================修复浏览器对Object.defineProperties的支持=================
|
1395
1443
|
if (!canHideOwn) {
|
1396
1444
|
if ("__defineGetter__" in avalon) {
|
@@ -1416,28 +1464,11 @@ if (!canHideOwn) {
|
|
1416
1464
|
}
|
1417
1465
|
}
|
1418
1466
|
if (IEVersion) {
|
1419
|
-
|
1467
|
+
var VBClassPool = {}
|
1468
|
+
window.execScript([// jshint ignore:line
|
1420
1469
|
"Function parseVB(code)",
|
1421
1470
|
"\tExecuteGlobal(code)",
|
1422
|
-
"End Function"
|
1423
|
-
"Dim VBClassBodies",
|
1424
|
-
"Set VBClassBodies=CreateObject(\"Scripting.Dictionary\")",
|
1425
|
-
"Function findOrDefineVBClass(name,body)",
|
1426
|
-
"\tDim found",
|
1427
|
-
"\tfound=\"\"",
|
1428
|
-
"\tFor Each key in VBClassBodies",
|
1429
|
-
"\t\tIf body=VBClassBodies.Item(key) Then",
|
1430
|
-
"\t\t\tfound=key",
|
1431
|
-
"\t\t\tExit For",
|
1432
|
-
"\t\tEnd If",
|
1433
|
-
"\tnext",
|
1434
|
-
"\tIf found=\"\" Then",
|
1435
|
-
"\t\tparseVB(\"Class \" + name + body)",
|
1436
|
-
"\t\tVBClassBodies.Add name, body",
|
1437
|
-
"\t\tfound=name",
|
1438
|
-
"\tEnd If",
|
1439
|
-
"\tfindOrDefineVBClass=found",
|
1440
|
-
"End Function"
|
1471
|
+
"End Function" //转换一段文本为VB代码
|
1441
1472
|
].join("\n"), "VBScript")
|
1442
1473
|
function VBMediator(instance, accessors, name, value) {// jshint ignore:line
|
1443
1474
|
var accessor = accessors[name]
|
@@ -1448,12 +1479,12 @@ if (!canHideOwn) {
|
|
1448
1479
|
}
|
1449
1480
|
}
|
1450
1481
|
defineProperties = function (name, accessors, properties) {
|
1451
|
-
|
1452
|
-
|
1482
|
+
// jshint ignore:line
|
1483
|
+
var buffer = []
|
1453
1484
|
buffer.push(
|
1454
1485
|
"\r\n\tPrivate [__data__], [__proxy__]",
|
1455
|
-
"\tPublic Default Function [__const__](d, p)",
|
1456
|
-
"\t\tSet [__data__] = d: set [__proxy__] = p",
|
1486
|
+
"\tPublic Default Function [__const__](d"+expose+", p"+expose+")",
|
1487
|
+
"\t\tSet [__data__] = d"+expose+": set [__proxy__] = p"+expose,
|
1457
1488
|
"\t\tSet [__const__] = Me", //链式调用
|
1458
1489
|
"\tEnd Function")
|
1459
1490
|
//添加普通属性,因为VBScript对象不能像JS那样随意增删属性,必须在这里预先定义好
|
@@ -1490,9 +1521,11 @@ if (!canHideOwn) {
|
|
1490
1521
|
}
|
1491
1522
|
|
1492
1523
|
buffer.push("End Class")
|
1493
|
-
var
|
1494
|
-
|
1495
|
-
if (
|
1524
|
+
var body = buffer.join("\r\n")
|
1525
|
+
var className =VBClassPool[body]
|
1526
|
+
if (!className) {
|
1527
|
+
className = generateID("VBClass")
|
1528
|
+
window.parseVB("Class " + className + body)
|
1496
1529
|
window.parseVB([
|
1497
1530
|
"Function " + className + "Factory(a, b)", //创建实例并传入两个关键的参数
|
1498
1531
|
"\tDim o",
|
@@ -1500,8 +1533,9 @@ if (!canHideOwn) {
|
|
1500
1533
|
"\tSet " + className + "Factory = o",
|
1501
1534
|
"End Function"
|
1502
1535
|
].join("\r\n"))
|
1536
|
+
VBClassPool[body] = className
|
1503
1537
|
}
|
1504
|
-
var ret = window[
|
1538
|
+
var ret = window[className + "Factory"](accessors, VBMediator) //得到其产品
|
1505
1539
|
return ret //得到其产品
|
1506
1540
|
}
|
1507
1541
|
}
|
@@ -1511,7 +1545,7 @@ if (!canHideOwn) {
|
|
1511
1545
|
* 监控数组(与ms-each, ms-repeat配合使用) *
|
1512
1546
|
**********************************************************************/
|
1513
1547
|
|
1514
|
-
function
|
1548
|
+
function arrayFactory(model) {
|
1515
1549
|
var array = []
|
1516
1550
|
array.$id = generateID()
|
1517
1551
|
array.$model = model //数据模型
|
@@ -1526,7 +1560,7 @@ function Collection(model) {
|
|
1526
1560
|
for (var i in EventBus) {
|
1527
1561
|
array[i] = EventBus[i]
|
1528
1562
|
}
|
1529
|
-
avalon.mix(array,
|
1563
|
+
avalon.mix(array, arrayPrototype)
|
1530
1564
|
return array
|
1531
1565
|
}
|
1532
1566
|
|
@@ -1534,7 +1568,7 @@ function mutateArray(method, pos, n, index, method2, pos2, n2) {
|
|
1534
1568
|
var oldLen = this.length, loop = 2
|
1535
1569
|
while (--loop) {
|
1536
1570
|
switch (method) {
|
1537
|
-
|
1571
|
+
case "add":
|
1538
1572
|
/* jshint ignore:start */
|
1539
1573
|
var array = this.$model.slice(pos, pos + n).map(function (el) {
|
1540
1574
|
if (rcomplexType.test(avalon.type(el))) {
|
@@ -1568,10 +1602,10 @@ function mutateArray(method, pos, n, index, method2, pos2, n2) {
|
|
1568
1602
|
}
|
1569
1603
|
|
1570
1604
|
var _splice = ap.splice
|
1571
|
-
var
|
1605
|
+
var arrayPrototype = {
|
1572
1606
|
_splice: _splice,
|
1573
1607
|
_fire: function (method, a, b) {
|
1574
|
-
|
1608
|
+
fireDependencies(this.$events[subscribers], method, a, b)
|
1575
1609
|
},
|
1576
1610
|
size: function () { //取得数组长度,这个函数可以同步视图,length不能
|
1577
1611
|
return this._.length
|
@@ -1657,11 +1691,13 @@ var CollectionPrototype = {
|
|
1657
1691
|
},
|
1658
1692
|
removeAll: function (all) { //移除N个元素
|
1659
1693
|
if (Array.isArray(all)) {
|
1660
|
-
all.forEach(function (el) {
|
1661
|
-
this.remove(el)
|
1662
|
-
}, this)
|
1663
|
-
} else if (typeof all === "function") {
|
1664
1694
|
for (var i = this.length - 1; i >= 0; i--) {
|
1695
|
+
if (all.indexOf(this[i]) !== -1) {
|
1696
|
+
this.removeAt(i)
|
1697
|
+
}
|
1698
|
+
}
|
1699
|
+
} else if (typeof all === "function") {
|
1700
|
+
for ( i = this.length - 1; i >= 0; i--) {
|
1665
1701
|
var el = this[i]
|
1666
1702
|
if (all(el, i)) {
|
1667
1703
|
this.removeAt(i)
|
@@ -1678,7 +1714,7 @@ var CollectionPrototype = {
|
|
1678
1714
|
return this
|
1679
1715
|
},
|
1680
1716
|
set: function (index, val) {
|
1681
|
-
if (index
|
1717
|
+
if (index < this.length && index > -1) {
|
1682
1718
|
var valueType = avalon.type(val)
|
1683
1719
|
if (val && val.$model) {
|
1684
1720
|
val = val.$model
|
@@ -1701,6 +1737,15 @@ var CollectionPrototype = {
|
|
1701
1737
|
return this
|
1702
1738
|
}
|
1703
1739
|
}
|
1740
|
+
//相当于原来bindingExecutors.repeat 的index分支
|
1741
|
+
function resetIndex(array, pos) {
|
1742
|
+
var last = array.length - 1
|
1743
|
+
for (var el; el = array[pos]; pos++) {
|
1744
|
+
el.$index = pos
|
1745
|
+
el.$first = pos === 0
|
1746
|
+
el.$last = pos === last
|
1747
|
+
}
|
1748
|
+
}
|
1704
1749
|
|
1705
1750
|
function sortByIndex(array, indexes) {
|
1706
1751
|
var map = {};
|
@@ -1717,7 +1762,7 @@ function sortByIndex(array, indexes) {
|
|
1717
1762
|
}
|
1718
1763
|
|
1719
1764
|
"sort,reverse".replace(rword, function (method) {
|
1720
|
-
|
1765
|
+
arrayPrototype[method] = function () {
|
1721
1766
|
var newArray = this.$model//这是要排序的新数组
|
1722
1767
|
var oldArray = newArray.concat() //保持原来状态的旧数组
|
1723
1768
|
var mask = Math.random()
|
@@ -1738,28 +1783,57 @@ function sortByIndex(array, indexes) {
|
|
1738
1783
|
}
|
1739
1784
|
if (hasSort) {
|
1740
1785
|
sortByIndex(this, indexes)
|
1786
|
+
// sortByIndex(this.$proxy, indexes)
|
1741
1787
|
this._fire("move", indexes)
|
1742
|
-
|
1788
|
+
this._fire("index", 0)
|
1743
1789
|
}
|
1744
1790
|
return this
|
1745
1791
|
}
|
1746
1792
|
})
|
1747
1793
|
|
1794
|
+
|
1748
1795
|
/*********************************************************************
|
1749
1796
|
* 依赖调度系统 *
|
1750
1797
|
**********************************************************************/
|
1798
|
+
//检测两个对象间的依赖关系
|
1799
|
+
var dependencyDetection = (function () {
|
1800
|
+
var outerFrames = []
|
1801
|
+
var currentFrame
|
1802
|
+
return {
|
1803
|
+
begin: function (accessorObject) {
|
1804
|
+
//accessorObject为一个拥有callback的对象
|
1805
|
+
outerFrames.push(currentFrame)
|
1806
|
+
currentFrame = accessorObject
|
1807
|
+
},
|
1808
|
+
end: function () {
|
1809
|
+
currentFrame = outerFrames.pop()
|
1810
|
+
},
|
1811
|
+
collectDependency: function (vmodel, accessor) {
|
1812
|
+
if (currentFrame) {
|
1813
|
+
//被dependencyDetection.begin调用
|
1814
|
+
currentFrame.callback(vmodel, accessor);
|
1815
|
+
}
|
1816
|
+
}
|
1817
|
+
};
|
1818
|
+
})()
|
1819
|
+
//将绑定对象注入到其依赖项的订阅数组中
|
1751
1820
|
var ronduplex = /^(duplex|on)$/
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1821
|
+
avalon.injectBinding = function (data) {
|
1822
|
+
var valueFn = data.evaluator
|
1823
|
+
if (valueFn) { //如果是求值函数
|
1824
|
+
dependencyDetection.begin({
|
1825
|
+
callback: function (vmodel, dependency) {
|
1826
|
+
injectDependency(vmodel.$events[dependency._name], data)
|
1827
|
+
}
|
1828
|
+
})
|
1758
1829
|
try {
|
1759
|
-
var
|
1760
|
-
|
1830
|
+
var value = ronduplex.test(data.type) ? data : valueFn.apply(0, data.args)
|
1831
|
+
if(value === void 0){
|
1832
|
+
delete data.evaluator
|
1833
|
+
}
|
1834
|
+
data.handler(value, data.element, data)
|
1761
1835
|
} catch (e) {
|
1762
|
-
|
1836
|
+
log("warning:exception throwed in [avalon.injectBinding] " , e)
|
1763
1837
|
delete data.evaluator
|
1764
1838
|
var node = data.element
|
1765
1839
|
if (node.nodeType === 3) {
|
@@ -1767,126 +1841,160 @@ function registerSubscriber(data) {
|
|
1767
1841
|
if (kernel.commentInterpolate) {
|
1768
1842
|
parent.replaceChild(DOC.createComment(data.value), node)
|
1769
1843
|
} else {
|
1770
|
-
node.data = openTag + data.value + closeTag
|
1844
|
+
node.data = openTag + (data.oneTime ? "::" : "") + data.value + closeTag
|
1771
1845
|
}
|
1772
1846
|
}
|
1847
|
+
} finally {
|
1848
|
+
dependencyDetection.end()
|
1773
1849
|
}
|
1774
1850
|
}
|
1775
|
-
avalon.openComputedCollect = false
|
1776
|
-
delete Registry[expose]
|
1777
1851
|
}
|
1778
1852
|
|
1779
|
-
|
1780
|
-
|
1781
|
-
if (
|
1782
|
-
|
1853
|
+
//将依赖项(比它高层的访问器或构建视图刷新函数的绑定对象)注入到订阅者数组
|
1854
|
+
function injectDependency(list, data) {
|
1855
|
+
if (data.oneTime)
|
1856
|
+
return
|
1857
|
+
if (list && avalon.Array.ensure(list, data) && data.element) {
|
1858
|
+
injectDisposeQueue(data, list)
|
1859
|
+
if (new Date() - beginTime > 444 ) {
|
1860
|
+
rejectDisposeQueue()
|
1861
|
+
}
|
1783
1862
|
}
|
1784
1863
|
}
|
1785
1864
|
|
1786
|
-
|
1787
|
-
function
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1865
|
+
//通知依赖于这个访问器的订阅者更新自身
|
1866
|
+
function fireDependencies(list) {
|
1867
|
+
if (list && list.length) {
|
1868
|
+
if (new Date() - beginTime > 444 && typeof list[0] === "object") {
|
1869
|
+
rejectDisposeQueue()
|
1870
|
+
}
|
1871
|
+
var args = aslice.call(arguments, 1)
|
1872
|
+
for (var i = list.length, fn; fn = list[--i]; ) {
|
1873
|
+
var el = fn.element
|
1874
|
+
if (el && el.parentNode) {
|
1875
|
+
try {
|
1876
|
+
var valueFn = fn.evaluator
|
1877
|
+
if (fn.$repeat) {
|
1878
|
+
fn.handler.apply(fn, args) //处理监控数组的方法
|
1879
|
+
}else if("$repeat" in fn || !valueFn ){//如果没有eval,先eval
|
1880
|
+
bindingHandlers[fn.type](fn, fn.vmodels)
|
1881
|
+
} else if (fn.type !== "on") { //事件绑定只能由用户触发,不能由程序触发
|
1882
|
+
var value = valueFn.apply(0, fn.args || [])
|
1883
|
+
fn.handler(value, el, fn)
|
1884
|
+
}
|
1885
|
+
} catch (e) {
|
1886
|
+
console.log(e)
|
1887
|
+
}
|
1888
|
+
}
|
1889
|
+
}
|
1798
1890
|
}
|
1799
1891
|
}
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1892
|
+
/*********************************************************************
|
1893
|
+
* 定时GC回收机制 *
|
1894
|
+
**********************************************************************/
|
1895
|
+
var disposeCount = 0
|
1896
|
+
var disposeQueue = avalon.$$subscribers = []
|
1897
|
+
var beginTime = new Date()
|
1898
|
+
var oldInfo = {}
|
1899
|
+
//var uuid2Node = {}
|
1900
|
+
function getUid(elem, makeID) { //IE9+,标准浏览器
|
1901
|
+
if (!elem.uuid && !makeID) {
|
1902
|
+
elem.uuid = ++disposeCount
|
1806
1903
|
}
|
1904
|
+
return elem.uuid
|
1807
1905
|
}
|
1808
1906
|
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1907
|
+
//添加到回收列队中
|
1908
|
+
function injectDisposeQueue(data, list) {
|
1909
|
+
var elem = data.element
|
1910
|
+
if (!data.uuid) {
|
1911
|
+
if (elem.nodeType !== 1) {
|
1912
|
+
data.uuid = data.type + (data.pos || 0) + "-" + getUid(elem.parentNode)
|
1913
|
+
} else {
|
1914
|
+
data.uuid = data.name + "-" + getUid(elem)
|
1813
1915
|
}
|
1814
|
-
} catch (e) {
|
1815
|
-
return true
|
1816
1916
|
}
|
1817
|
-
|
1818
|
-
|
1917
|
+
var lists = data.lists || (data.lists = [])
|
1918
|
+
avalon.Array.ensure(lists, list)
|
1919
|
+
list.$uuid = list.$uuid || generateID()
|
1920
|
+
if (!disposeQueue[data.uuid]) {
|
1921
|
+
disposeQueue[data.uuid] = 1
|
1922
|
+
disposeQueue.push(data)
|
1923
|
+
}
|
1819
1924
|
}
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
var i =
|
1925
|
+
|
1926
|
+
function rejectDisposeQueue(data) {
|
1927
|
+
if (avalon.optimize)
|
1928
|
+
return
|
1929
|
+
var i = disposeQueue.length
|
1825
1930
|
var n = i
|
1826
|
-
var
|
1827
|
-
var
|
1828
|
-
var types = []
|
1931
|
+
var allTypes = []
|
1932
|
+
var iffishTypes = {}
|
1829
1933
|
var newInfo = {}
|
1830
|
-
|
1831
|
-
while (
|
1832
|
-
var data = obj.data
|
1934
|
+
//对页面上所有绑定对象进行分门别类, 只检测个数发生变化的类型
|
1935
|
+
while (data = disposeQueue[--i]) {
|
1833
1936
|
var type = data.type
|
1834
1937
|
if (newInfo[type]) {
|
1835
1938
|
newInfo[type]++
|
1836
1939
|
} else {
|
1837
1940
|
newInfo[type] = 1
|
1838
|
-
|
1941
|
+
allTypes.push(type)
|
1839
1942
|
}
|
1840
1943
|
}
|
1841
1944
|
var diff = false
|
1842
|
-
|
1945
|
+
allTypes.forEach(function (type) {
|
1843
1946
|
if (oldInfo[type] !== newInfo[type]) {
|
1844
|
-
|
1947
|
+
iffishTypes[type] = 1
|
1845
1948
|
diff = true
|
1846
1949
|
}
|
1847
1950
|
})
|
1848
1951
|
i = n
|
1849
|
-
//avalon.log("需要检测的个数 " + i)
|
1850
1952
|
if (diff) {
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
if (data.element === void 0)
|
1953
|
+
while (data = disposeQueue[--i]) {
|
1954
|
+
if (data.element === null) {
|
1955
|
+
disposeQueue.splice(i, 1)
|
1855
1956
|
continue
|
1856
|
-
|
1857
|
-
|
1858
|
-
|
1859
|
-
delete
|
1860
|
-
|
1861
|
-
|
1957
|
+
}
|
1958
|
+
if (iffishTypes[data.type] && shouldDispose(data.element)) { //如果它没有在DOM树
|
1959
|
+
disposeQueue.splice(i, 1)
|
1960
|
+
delete disposeQueue[data.uuid]
|
1961
|
+
//delete uuid2Node[data.element.uuid]
|
1962
|
+
var lists = data.lists
|
1963
|
+
for (var k = 0, list; list = lists[k++]; ) {
|
1964
|
+
avalon.Array.remove(lists, list)
|
1965
|
+
avalon.Array.remove(list, data)
|
1966
|
+
}
|
1862
1967
|
disposeData(data)
|
1863
|
-
obj.data = obj.list = null
|
1864
1968
|
}
|
1865
1969
|
}
|
1866
1970
|
}
|
1867
1971
|
oldInfo = newInfo
|
1868
|
-
// avalon.log("已经移除的个数 " + k)
|
1869
1972
|
beginTime = new Date()
|
1870
1973
|
}
|
1871
1974
|
|
1872
|
-
function
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1975
|
+
function disposeData(data) {
|
1976
|
+
delete disposeQueue[data.uuid] // 先清除,不然无法回收了
|
1977
|
+
data.element = null
|
1978
|
+
data.rollback && data.rollback()
|
1979
|
+
for (var key in data) {
|
1980
|
+
data[key] = null
|
1981
|
+
}
|
1982
|
+
}
|
1983
|
+
|
1984
|
+
function shouldDispose(el) {
|
1985
|
+
try {//IE下,如果文本节点脱离DOM树,访问parentNode会报错
|
1986
|
+
var fireError = el.parentNode.nodeType
|
1987
|
+
} catch (e) {
|
1988
|
+
return true
|
1989
|
+
}
|
1990
|
+
if (el.ifRemove) {
|
1991
|
+
// 如果节点被放到ifGroup,才移除
|
1992
|
+
if (!root.contains(el.ifRemove) && (ifGroup === el.parentNode)) {
|
1993
|
+
el.parentNode && el.parentNode.removeChild(el)
|
1994
|
+
return true
|
1888
1995
|
}
|
1889
1996
|
}
|
1997
|
+
return el.msRetain ? 0 : (el.nodeType === 1 ? !root.contains(el) : !avalon.contains(root, el))
|
1890
1998
|
}
|
1891
1999
|
|
1892
2000
|
/************************************************************************
|
@@ -1920,7 +2028,7 @@ var rnest = /<(?:tb|td|tf|th|tr|col|opt|leg|cap|area)/ //需要处理套嵌关
|
|
1920
2028
|
var script = DOC.createElement("script")
|
1921
2029
|
var rhtml = /<|&#?\w+;/
|
1922
2030
|
avalon.parseHTML = function (html) {
|
1923
|
-
var fragment =
|
2031
|
+
var fragment = avalonFragment.cloneNode(false)
|
1924
2032
|
if (typeof html !== "string") {
|
1925
2033
|
return fragment
|
1926
2034
|
}
|
@@ -2022,879 +2130,506 @@ avalon.clearHTML = function (node) {
|
|
2022
2130
|
}
|
2023
2131
|
|
2024
2132
|
/*********************************************************************
|
2025
|
-
*
|
2133
|
+
* avalon的原型方法定义区 *
|
2026
2134
|
**********************************************************************/
|
2027
2135
|
|
2028
|
-
|
2029
|
-
|
2030
|
-
|
2031
|
-
scanTag(elem, vmodels)
|
2136
|
+
function hyphen(target) {
|
2137
|
+
//转换为连字符线风格
|
2138
|
+
return target.replace(/([a-z\d])([A-Z]+)/g, "$1-$2").toLowerCase()
|
2032
2139
|
}
|
2033
2140
|
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
callback()
|
2043
|
-
} else {
|
2044
|
-
checkScan(elem, callback, currHTML)
|
2045
|
-
}
|
2141
|
+
function camelize(target) {
|
2142
|
+
//提前判断,提高getStyle等的效率
|
2143
|
+
if (!target || target.indexOf("-") < 0 && target.indexOf("_") < 0) {
|
2144
|
+
return target
|
2145
|
+
}
|
2146
|
+
//转换为驼峰风格
|
2147
|
+
return target.replace(/[-_][^-_]/g, function(match) {
|
2148
|
+
return match.charAt(1).toUpperCase()
|
2046
2149
|
})
|
2047
2150
|
}
|
2048
2151
|
|
2049
|
-
|
2050
|
-
function
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
}
|
2152
|
+
var fakeClassListMethods = {
|
2153
|
+
_toString: function() {
|
2154
|
+
var node = this.node
|
2155
|
+
var cls = node.className
|
2156
|
+
var str = typeof cls === "string" ? cls : cls.baseVal
|
2157
|
+
return str.split(/\s+/).join(" ")
|
2158
|
+
},
|
2159
|
+
_contains: function(cls) {
|
2160
|
+
return (" " + this + " ").indexOf(" " + cls + " ") > -1
|
2161
|
+
},
|
2162
|
+
_add: function(cls) {
|
2163
|
+
if (!this.contains(cls)) {
|
2164
|
+
this._set(this + " " + cls)
|
2063
2165
|
}
|
2064
|
-
}
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
if (
|
2072
|
-
//
|
2073
|
-
|
2166
|
+
},
|
2167
|
+
_remove: function(cls) {
|
2168
|
+
this._set((" " + this + " ").replace(" " + cls + " ", " "))
|
2169
|
+
},
|
2170
|
+
__set: function(cls) {
|
2171
|
+
cls = cls.trim()
|
2172
|
+
var node = this.node
|
2173
|
+
if (rsvg.test(node)) {
|
2174
|
+
//SVG元素的className是一个对象 SVGAnimatedString { baseVal="", animVal=""},只能通过set/getAttribute操作
|
2175
|
+
node.setAttribute("class", cls)
|
2176
|
+
} else {
|
2177
|
+
node.className = cls
|
2074
2178
|
}
|
2075
|
-
}
|
2076
|
-
bindings.length = 0
|
2179
|
+
} //toggle存在版本差异,因此不使用它
|
2077
2180
|
}
|
2078
2181
|
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
text.nodeValue += node.nodeValue
|
2087
|
-
elem.removeChild(node)
|
2088
|
-
} else {
|
2089
|
-
text = node
|
2182
|
+
function fakeClassList(node) {
|
2183
|
+
if (!("classList" in node)) {
|
2184
|
+
node.classList = {
|
2185
|
+
node: node
|
2186
|
+
}
|
2187
|
+
for (var k in fakeClassListMethods) {
|
2188
|
+
node.classList[k.slice(1)] = fakeClassListMethods[k]
|
2090
2189
|
}
|
2091
|
-
} else {
|
2092
|
-
text = null
|
2093
2190
|
}
|
2094
|
-
node
|
2191
|
+
return node.classList
|
2095
2192
|
}
|
2096
|
-
} : 0
|
2097
|
-
|
2098
|
-
var rmsAttr = /ms-(\w+)-?(.*)/
|
2099
|
-
var priorityMap = {
|
2100
|
-
"if": 10,
|
2101
|
-
"repeat": 90,
|
2102
|
-
"data": 100,
|
2103
|
-
"widget": 110,
|
2104
|
-
"each": 1400,
|
2105
|
-
"with": 1500,
|
2106
|
-
"duplex": 2000,
|
2107
|
-
"on": 3000
|
2108
|
-
}
|
2109
2193
|
|
2110
|
-
var events = oneObject("animationend,blur,change,input,click,dblclick,focus,keydown,keypress,keyup,mousedown,mouseenter,mouseleave,mousemove,mouseout,mouseover,mouseup,scan,scroll,submit")
|
2111
|
-
var obsoleteAttrs = oneObject("value,title,alt,checked,selected,disabled,readonly,enabled")
|
2112
|
-
function bindingSorter(a, b) {
|
2113
|
-
return a.priority - b.priority
|
2114
|
-
}
|
2115
2194
|
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2136
|
-
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
2149
|
-
|
2150
|
-
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
2157
|
-
|
2158
|
-
|
2159
|
-
|
2160
|
-
|
2161
|
-
|
2162
|
-
|
2163
|
-
|
2164
|
-
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
}
|
2170
|
-
if (vmodels.length) {
|
2171
|
-
bindings.push(binding)
|
2172
|
-
if (type === "widget") {
|
2173
|
-
elem.msData = elem.msData || msData
|
2195
|
+
"add,remove".replace(rword, function(method) {
|
2196
|
+
avalon.fn[method + "Class"] = function(cls) {
|
2197
|
+
var el = this[0]
|
2198
|
+
//https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/26
|
2199
|
+
if (cls && typeof cls === "string" && el && el.nodeType === 1) {
|
2200
|
+
cls.replace(/\S+/g, function(c) {
|
2201
|
+
fakeClassList(el)[method](c)
|
2202
|
+
})
|
2203
|
+
}
|
2204
|
+
return this
|
2205
|
+
}
|
2206
|
+
})
|
2207
|
+
avalon.fn.mix({
|
2208
|
+
hasClass: function(cls) {
|
2209
|
+
var el = this[0] || {}
|
2210
|
+
return el.nodeType === 1 && fakeClassList(el).contains(cls)
|
2211
|
+
},
|
2212
|
+
toggleClass: function(value, stateVal) {
|
2213
|
+
var className, i = 0
|
2214
|
+
var classNames = String(value).split(/\s+/)
|
2215
|
+
var isBool = typeof stateVal === "boolean"
|
2216
|
+
while ((className = classNames[i++])) {
|
2217
|
+
var state = isBool ? stateVal : !this.hasClass(className)
|
2218
|
+
this[state ? "addClass" : "removeClass"](className)
|
2219
|
+
}
|
2220
|
+
return this
|
2221
|
+
},
|
2222
|
+
attr: function(name, value) {
|
2223
|
+
if (arguments.length === 2) {
|
2224
|
+
this[0].setAttribute(name, value)
|
2225
|
+
return this
|
2226
|
+
} else {
|
2227
|
+
return this[0].getAttribute(name)
|
2228
|
+
}
|
2229
|
+
},
|
2230
|
+
data: function(name, value) {
|
2231
|
+
name = "data-" + hyphen(name || "")
|
2232
|
+
switch (arguments.length) {
|
2233
|
+
case 2:
|
2234
|
+
this.attr(name, value)
|
2235
|
+
return this
|
2236
|
+
case 1:
|
2237
|
+
var val = this.attr(name)
|
2238
|
+
return parseData(val)
|
2239
|
+
case 0:
|
2240
|
+
var ret = {}
|
2241
|
+
ap.forEach.call(this[0].attributes, function(attr) {
|
2242
|
+
if (attr) {
|
2243
|
+
name = attr.name
|
2244
|
+
if (!name.indexOf("data-")) {
|
2245
|
+
name = camelize(name.slice(5))
|
2246
|
+
ret[name] = parseData(attr.value)
|
2247
|
+
}
|
2174
2248
|
}
|
2175
|
-
}
|
2249
|
+
})
|
2250
|
+
return ret
|
2251
|
+
}
|
2252
|
+
},
|
2253
|
+
removeData: function(name) {
|
2254
|
+
name = "data-" + hyphen(name)
|
2255
|
+
this[0].removeAttribute(name)
|
2256
|
+
return this
|
2257
|
+
},
|
2258
|
+
css: function(name, value) {
|
2259
|
+
if (avalon.isPlainObject(name)) {
|
2260
|
+
for (var i in name) {
|
2261
|
+
avalon.css(this, i, name[i])
|
2176
2262
|
}
|
2263
|
+
} else {
|
2264
|
+
var ret = avalon.css(this, name, value)
|
2177
2265
|
}
|
2266
|
+
return ret !== void 0 ? ret : this
|
2267
|
+
},
|
2268
|
+
position: function() {
|
2269
|
+
var offsetParent, offset,
|
2270
|
+
elem = this[0],
|
2271
|
+
parentOffset = {
|
2272
|
+
top: 0,
|
2273
|
+
left: 0
|
2274
|
+
}
|
2275
|
+
if (!elem) {
|
2276
|
+
return
|
2277
|
+
}
|
2278
|
+
if (this.css("position") === "fixed") {
|
2279
|
+
offset = elem.getBoundingClientRect()
|
2280
|
+
} else {
|
2281
|
+
offsetParent = this.offsetParent() //得到真正的offsetParent
|
2282
|
+
offset = this.offset() // 得到正确的offsetParent
|
2283
|
+
if (offsetParent[0].tagName !== "HTML") {
|
2284
|
+
parentOffset = offsetParent.offset()
|
2285
|
+
}
|
2286
|
+
parentOffset.top += avalon.css(offsetParent[0], "borderTopWidth", true)
|
2287
|
+
parentOffset.left += avalon.css(offsetParent[0], "borderLeftWidth", true)
|
2288
|
+
|
2289
|
+
// Subtract offsetParent scroll positions
|
2290
|
+
parentOffset.top -= offsetParent.scrollTop()
|
2291
|
+
parentOffset.left -= offsetParent.scrollLeft()
|
2292
|
+
}
|
2293
|
+
return {
|
2294
|
+
top: offset.top - parentOffset.top - avalon.css(elem, "marginTop", true),
|
2295
|
+
left: offset.left - parentOffset.left - avalon.css(elem, "marginLeft", true)
|
2296
|
+
}
|
2297
|
+
},
|
2298
|
+
offsetParent: function() {
|
2299
|
+
var offsetParent = this[0].offsetParent
|
2300
|
+
while (offsetParent && avalon.css(offsetParent, "position") === "static") {
|
2301
|
+
offsetParent = offsetParent.offsetParent;
|
2302
|
+
}
|
2303
|
+
return avalon(offsetParent || root)
|
2304
|
+
},
|
2305
|
+
bind: function(type, fn, phase) {
|
2306
|
+
if (this[0]) { //此方法不会链
|
2307
|
+
return avalon.bind(this[0], type, fn, phase)
|
2308
|
+
}
|
2309
|
+
},
|
2310
|
+
unbind: function(type, fn, phase) {
|
2311
|
+
if (this[0]) {
|
2312
|
+
avalon.unbind(this[0], type, fn, phase)
|
2313
|
+
}
|
2314
|
+
return this
|
2315
|
+
},
|
2316
|
+
val: function(value) {
|
2317
|
+
var node = this[0]
|
2318
|
+
if (node && node.nodeType === 1) {
|
2319
|
+
var get = arguments.length === 0
|
2320
|
+
var access = get ? ":get" : ":set"
|
2321
|
+
var fn = valHooks[getValType(node) + access]
|
2322
|
+
if (fn) {
|
2323
|
+
var val = fn(node, value)
|
2324
|
+
} else if (get) {
|
2325
|
+
return (node.value || "").replace(/\r/g, "")
|
2326
|
+
} else {
|
2327
|
+
node.value = value
|
2328
|
+
}
|
2329
|
+
}
|
2330
|
+
return get ? val : this
|
2178
2331
|
}
|
2332
|
+
})
|
2333
|
+
|
2334
|
+
function parseData(data) {
|
2335
|
+
try {
|
2336
|
+
if (typeof data === "object")
|
2337
|
+
return data
|
2338
|
+
data = data === "true" ? true :
|
2339
|
+
data === "false" ? false :
|
2340
|
+
data === "null" ? null : +data + "" === data ? +data : rbrace.test(data) ? avalon.parseJSON(data) : data
|
2341
|
+
} catch (e) {}
|
2342
|
+
return data
|
2179
2343
|
}
|
2180
|
-
|
2181
|
-
|
2182
|
-
|
2183
|
-
|
2184
|
-
|
2185
|
-
|
2186
|
-
|
2187
|
-
|
2188
|
-
|
2189
|
-
|
2190
|
-
|
2191
|
-
|
2192
|
-
|
2193
|
-
|
2194
|
-
return executeBindings(bindings.slice(0, i + 1), vmodels)
|
2195
|
-
} else if (scanNode) {
|
2196
|
-
scanNode = !rnoscanNodeBinding.test(type)
|
2344
|
+
var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
|
2345
|
+
rvalidchars = /^[\],:{}\s]*$/,
|
2346
|
+
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
|
2347
|
+
rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
|
2348
|
+
rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g
|
2349
|
+
avalon.parseJSON = window.JSON ? JSON.parse : function(data) {
|
2350
|
+
if (typeof data === "string") {
|
2351
|
+
data = data.trim();
|
2352
|
+
if (data) {
|
2353
|
+
if (rvalidchars.test(data.replace(rvalidescape, "@")
|
2354
|
+
.replace(rvalidtokens, "]")
|
2355
|
+
.replace(rvalidbraces, ""))) {
|
2356
|
+
return (new Function("return " + data))() // jshint ignore:line
|
2357
|
+
}
|
2197
2358
|
}
|
2359
|
+
avalon.error("Invalid JSON: " + data)
|
2198
2360
|
}
|
2199
|
-
|
2200
|
-
if (scanNode && !stopScan[elem.tagName] && rbind.test(elem.innerHTML.replace(rlt, "<").replace(rgt, ">"))) {
|
2201
|
-
mergeTextNodes && mergeTextNodes(elem)
|
2202
|
-
scanNodeList(elem, vmodels) //扫描子孙元素
|
2203
|
-
}
|
2361
|
+
return data
|
2204
2362
|
}
|
2205
2363
|
|
2206
|
-
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
// avalon.log(el.outerHTML)
|
2222
|
-
// }
|
2223
|
-
// }
|
2224
|
-
//依次输出<SECTION>, </SECTION>
|
2225
|
-
var getAttributes = function (elem) {
|
2226
|
-
var html = elem.outerHTML
|
2227
|
-
//处理IE6-8解析HTML5新标签的情况,及<br>等半闭合标签outerHTML为空的情况
|
2228
|
-
if (html.slice(0, 2) === "</" || !html.trim()) {
|
2229
|
-
return []
|
2230
|
-
}
|
2231
|
-
var str = html.match(rtag)[0]
|
2232
|
-
var attributes = [],
|
2233
|
-
match,
|
2234
|
-
k, v
|
2235
|
-
var ret = cacheAttrs.get(str)
|
2236
|
-
if (ret) {
|
2237
|
-
return ret
|
2238
|
-
}
|
2239
|
-
while (k = rattrs.exec(str)) {
|
2240
|
-
v = k[2]
|
2241
|
-
if (v) {
|
2242
|
-
v = (rquote.test(v) ? v.slice(1, -1) : v).replace(ramp, "&")
|
2243
|
-
}
|
2244
|
-
var name = k[1].toLowerCase()
|
2245
|
-
match = name.match(rmsAttr)
|
2246
|
-
var binding = {
|
2247
|
-
name: name,
|
2248
|
-
specified: true,
|
2249
|
-
value: v || ""
|
2364
|
+
//生成avalon.fn.scrollLeft, avalon.fn.scrollTop方法
|
2365
|
+
avalon.each({
|
2366
|
+
scrollLeft: "pageXOffset",
|
2367
|
+
scrollTop: "pageYOffset"
|
2368
|
+
}, function(method, prop) {
|
2369
|
+
avalon.fn[method] = function(val) {
|
2370
|
+
var node = this[0] || {}, win = getWindow(node),
|
2371
|
+
top = method === "scrollTop"
|
2372
|
+
if (!arguments.length) {
|
2373
|
+
return win ? (prop in win) ? win[prop] : root[method] : node[method]
|
2374
|
+
} else {
|
2375
|
+
if (win) {
|
2376
|
+
win.scrollTo(!top ? val : avalon(win).scrollLeft(), top ? val : avalon(win).scrollTop())
|
2377
|
+
} else {
|
2378
|
+
node[method] = val
|
2250
2379
|
}
|
2251
|
-
attributes.push(binding)
|
2252
2380
|
}
|
2253
|
-
return cacheAttrs.put(str, attributes)
|
2254
2381
|
}
|
2255
|
-
}
|
2382
|
+
})
|
2256
2383
|
|
2257
|
-
function
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2384
|
+
function getWindow(node) {
|
2385
|
+
return node.window && node.document ? node : node.nodeType === 9 ? node.defaultView || node.parentWindow : false;
|
2386
|
+
}
|
2387
|
+
//=============================css相关=======================
|
2388
|
+
var cssHooks = avalon.cssHooks = {}
|
2389
|
+
var prefixes = ["", "-webkit-", "-o-", "-moz-", "-ms-"]
|
2390
|
+
var cssMap = {
|
2391
|
+
"float": W3C ? "cssFloat" : "styleFloat"
|
2264
2392
|
}
|
2393
|
+
avalon.cssNumber = oneObject("animationIterationCount,columnCount,order,flex,flexGrow,flexShrink,fillOpacity,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom")
|
2265
2394
|
|
2266
|
-
function
|
2267
|
-
|
2268
|
-
|
2395
|
+
avalon.cssName = function(name, host, camelCase) {
|
2396
|
+
if (cssMap[name]) {
|
2397
|
+
return cssMap[name]
|
2269
2398
|
}
|
2270
|
-
|
2271
|
-
|
2272
|
-
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2276
|
-
} else if (kernel.commentInterpolate && nodeType === 8 && !rexpr.test(node.nodeValue)) {
|
2277
|
-
scanText(node, vmodels) //扫描注释节点
|
2399
|
+
host = host || root.style
|
2400
|
+
for (var i = 0, n = prefixes.length; i < n; i++) {
|
2401
|
+
camelCase = camelize(prefixes[i] + name)
|
2402
|
+
if (camelCase in host) {
|
2403
|
+
return (cssMap[name] = camelCase)
|
2404
|
+
}
|
2278
2405
|
}
|
2406
|
+
return null
|
2279
2407
|
}
|
2280
|
-
function
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
//#360 在旧式IE中 Object标签在引入Flash等资源时,可能出现没有getAttributeNode,innerHTML的情形
|
2285
|
-
if (!elem.getAttributeNode) {
|
2286
|
-
return log("warning " + elem.tagName + " no getAttributeNode method")
|
2287
|
-
}
|
2288
|
-
var b = elem.getAttributeNode("ms-important")
|
2289
|
-
var c = elem.getAttributeNode("ms-controller")
|
2290
|
-
if (typeof a === "string") {
|
2291
|
-
return
|
2292
|
-
} else if (node = b || c) {
|
2293
|
-
var newVmodel = avalon.vmodels[node.value]
|
2294
|
-
if (!newVmodel) {
|
2295
|
-
return
|
2296
|
-
}
|
2297
|
-
//ms-important不包含父VM,ms-controller相反
|
2298
|
-
vmodels = node === b ? [newVmodel] : [newVmodel].concat(vmodels)
|
2299
|
-
var name = node.name
|
2300
|
-
elem.removeAttribute(name) //removeAttributeNode不会刷新[ms-controller]样式规则
|
2301
|
-
avalon(elem).removeClass(name)
|
2302
|
-
createSignalTower(elem, newVmodel)
|
2303
|
-
}
|
2304
|
-
scanAttr(elem, vmodels) //扫描特性节点
|
2408
|
+
cssHooks["@:set"] = function(node, name, value) {
|
2409
|
+
try { //node.style.width = NaN;node.style.width = "xxxxxxx";node.style.width = undefine 在旧式IE下会抛异常
|
2410
|
+
node.style[name] = value
|
2411
|
+
} catch (e) {}
|
2305
2412
|
}
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
rstringLiteral = /(['"])(\\\1|.)+?\1/g
|
2311
|
-
function getToken(value) {
|
2312
|
-
if (value.indexOf("|") > 0) {
|
2313
|
-
var scapegoat = value.replace( rstringLiteral, function(_){
|
2314
|
-
return Array(_.length+1).join("1")// jshint ignore:line
|
2315
|
-
})
|
2316
|
-
var index = scapegoat.replace(r11a, "\u1122\u3344").indexOf("|") //干掉所有短路或
|
2317
|
-
if (index > -1) {
|
2318
|
-
return {
|
2319
|
-
filters: value.slice(index),
|
2320
|
-
value: value.slice(0, index),
|
2321
|
-
expr: true
|
2322
|
-
}
|
2413
|
+
if (window.getComputedStyle) {
|
2414
|
+
cssHooks["@:get"] = function(node, name) {
|
2415
|
+
if (!node || !node.style) {
|
2416
|
+
throw new Error("getComputedStyle要求传入一个节点 " + node)
|
2323
2417
|
}
|
2418
|
+
var ret, styles = getComputedStyle(node, null)
|
2419
|
+
if (styles) {
|
2420
|
+
ret = name === "filter" ? styles.getPropertyValue(name) : styles[name]
|
2421
|
+
if (ret === "") {
|
2422
|
+
ret = node.style[name] //其他浏览器需要我们手动取内联样式
|
2423
|
+
}
|
2424
|
+
}
|
2425
|
+
return ret
|
2324
2426
|
}
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2328
|
-
expr: true
|
2427
|
+
cssHooks["opacity:get"] = function(node) {
|
2428
|
+
var ret = cssHooks["@:get"](node, "opacity")
|
2429
|
+
return ret === "" ? "1" : ret
|
2329
2430
|
}
|
2330
|
-
}
|
2331
|
-
|
2332
|
-
|
2333
|
-
var
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2431
|
+
} else {
|
2432
|
+
var rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i
|
2433
|
+
var rposition = /^(top|right|bottom|left)$/
|
2434
|
+
var ralpha = /alpha\([^)]*\)/i
|
2435
|
+
var ie8 = !! window.XDomainRequest
|
2436
|
+
var salpha = "DXImageTransform.Microsoft.Alpha"
|
2437
|
+
var border = {
|
2438
|
+
thin: ie8 ? '1px' : '2px',
|
2439
|
+
medium: ie8 ? '3px' : '4px',
|
2440
|
+
thick: ie8 ? '5px' : '6px'
|
2441
|
+
}
|
2442
|
+
cssHooks["@:get"] = function(node, name) {
|
2443
|
+
//取得精确值,不过它有可能是带em,pc,mm,pt,%等单位
|
2444
|
+
var currentStyle = node.currentStyle
|
2445
|
+
var ret = currentStyle[name]
|
2446
|
+
if ((rnumnonpx.test(ret) && !rposition.test(ret))) {
|
2447
|
+
//①,保存原有的style.left, runtimeStyle.left,
|
2448
|
+
var style = node.style,
|
2449
|
+
left = style.left,
|
2450
|
+
rsLeft = node.runtimeStyle.left
|
2451
|
+
//②由于③处的style.left = xxx会影响到currentStyle.left,
|
2452
|
+
//因此把它currentStyle.left放到runtimeStyle.left,
|
2453
|
+
//runtimeStyle.left拥有最高优先级,不会style.left影响
|
2454
|
+
node.runtimeStyle.left = currentStyle.left
|
2455
|
+
//③将精确值赋给到style.left,然后通过IE的另一个私有属性 style.pixelLeft
|
2456
|
+
//得到单位为px的结果;fontSize的分支见http://bugs.jquery.com/ticket/760
|
2457
|
+
style.left = name === 'fontSize' ? '1em' : (ret || 0)
|
2458
|
+
ret = style.pixelLeft + "px"
|
2459
|
+
//④还原 style.left,runtimeStyle.left
|
2460
|
+
style.left = left
|
2461
|
+
node.runtimeStyle.left = rsLeft
|
2353
2462
|
}
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2463
|
+
if (ret === "medium") {
|
2464
|
+
name = name.replace("Width", "Style")
|
2465
|
+
//border width 默认值为medium,即使其为0"
|
2466
|
+
if (currentStyle[name] === "none") {
|
2467
|
+
ret = "0px"
|
2468
|
+
}
|
2357
2469
|
}
|
2358
|
-
|
2359
|
-
} while (1)
|
2360
|
-
value = str.slice(start)
|
2361
|
-
if (value) { //}} 右边的文本
|
2362
|
-
tokens.push({
|
2363
|
-
value: value,
|
2364
|
-
expr: false,
|
2365
|
-
filters: ""
|
2366
|
-
})
|
2367
|
-
}
|
2368
|
-
return tokens
|
2369
|
-
}
|
2370
|
-
|
2371
|
-
function scanText(textNode, vmodels) {
|
2372
|
-
var bindings = []
|
2373
|
-
if (textNode.nodeType === 8) {
|
2374
|
-
var token = getToken(textNode.nodeValue)
|
2375
|
-
var tokens = [token]
|
2376
|
-
} else {
|
2377
|
-
tokens = scanExpr(textNode.data)
|
2470
|
+
return ret === "" ? "auto" : border[ret] || ret
|
2378
2471
|
}
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
}
|
2392
|
-
hyperspace.appendChild(node)
|
2472
|
+
cssHooks["opacity:set"] = function(node, name, value) {
|
2473
|
+
var style = node.style
|
2474
|
+
var opacity = isFinite(value) && value <= 1 ? "alpha(opacity=" + value * 100 + ")" : ""
|
2475
|
+
var filter = style.filter || "";
|
2476
|
+
style.zoom = 1
|
2477
|
+
//不能使用以下方式设置透明度
|
2478
|
+
//node.filters.alpha.opacity = value * 100
|
2479
|
+
style.filter = (ralpha.test(filter) ?
|
2480
|
+
filter.replace(ralpha, opacity) :
|
2481
|
+
filter + " " + opacity).trim()
|
2482
|
+
if (!style.filter) {
|
2483
|
+
style.removeAttribute("filter")
|
2393
2484
|
}
|
2394
|
-
textNode.parentNode.replaceChild(hyperspace, textNode)
|
2395
|
-
if (bindings.length)
|
2396
|
-
executeBindings(bindings, vmodels)
|
2397
2485
|
}
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
function hyphen(target) {
|
2405
|
-
//转换为连字符线风格
|
2406
|
-
return target.replace(/([a-z\d])([A-Z]+)/g, "$1-$2").toLowerCase()
|
2407
|
-
}
|
2408
|
-
|
2409
|
-
function camelize(target) {
|
2410
|
-
//转换为驼峰风格
|
2411
|
-
if (target.indexOf("-") < 0 && target.indexOf("_") < 0) {
|
2412
|
-
return target //提前判断,提高getStyle等的效率
|
2486
|
+
cssHooks["opacity:get"] = function(node) {
|
2487
|
+
//这是最快的获取IE透明值的方式,不需要动用正则了!
|
2488
|
+
var alpha = node.filters.alpha || node.filters[salpha],
|
2489
|
+
op = alpha && alpha.enabled ? alpha.opacity : 100
|
2490
|
+
return (op / 100) + "" //确保返回的是字符串
|
2413
2491
|
}
|
2414
|
-
return target.replace(/[-_][^-_]/g, function(match) {
|
2415
|
-
return match.charAt(1).toUpperCase()
|
2416
|
-
})
|
2417
|
-
}
|
2418
|
-
|
2419
|
-
var fakeClassListMethods = {
|
2420
|
-
_toString: function() {
|
2421
|
-
var node = this.node
|
2422
|
-
var cls = node.className
|
2423
|
-
var str = typeof cls === "string" ? cls : cls.baseVal
|
2424
|
-
return str.split(/\s+/).join(" ")
|
2425
|
-
},
|
2426
|
-
_contains: function(cls) {
|
2427
|
-
return (" " + this + " ").indexOf(" " + cls + " ") > -1
|
2428
|
-
},
|
2429
|
-
_add: function(cls) {
|
2430
|
-
if (!this.contains(cls)) {
|
2431
|
-
this._set(this + " " + cls)
|
2432
|
-
}
|
2433
|
-
},
|
2434
|
-
_remove: function(cls) {
|
2435
|
-
this._set((" " + this + " ").replace(" " + cls + " ", " "))
|
2436
|
-
},
|
2437
|
-
__set: function(cls) {
|
2438
|
-
cls = cls.trim()
|
2439
|
-
var node = this.node
|
2440
|
-
if (rsvg.test(node)) {
|
2441
|
-
//SVG元素的className是一个对象 SVGAnimatedString { baseVal="", animVal=""},只能通过set/getAttribute操作
|
2442
|
-
node.setAttribute("class", cls)
|
2443
|
-
} else {
|
2444
|
-
node.className = cls
|
2445
|
-
}
|
2446
|
-
} //toggle存在版本差异,因此不使用它
|
2447
2492
|
}
|
2448
2493
|
|
2449
|
-
function
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
for (var k in fakeClassListMethods) {
|
2455
|
-
node.classList[k.slice(1)] = fakeClassListMethods[k]
|
2456
|
-
}
|
2494
|
+
"top,left".replace(rword, function(name) {
|
2495
|
+
cssHooks[name + ":get"] = function(node) {
|
2496
|
+
var computed = cssHooks["@:get"](node, name)
|
2497
|
+
return /px$/.test(computed) ? computed :
|
2498
|
+
avalon(node).position()[name] + "px"
|
2457
2499
|
}
|
2458
|
-
|
2500
|
+
})
|
2501
|
+
|
2502
|
+
var cssShow = {
|
2503
|
+
position: "absolute",
|
2504
|
+
visibility: "hidden",
|
2505
|
+
display: "block"
|
2459
2506
|
}
|
2460
2507
|
|
2508
|
+
var rdisplayswap = /^(none|table(?!-c[ea]).+)/
|
2461
2509
|
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
2468
|
-
|
2469
|
-
|
2510
|
+
function showHidden(node, array) {
|
2511
|
+
//http://www.cnblogs.com/rubylouvre/archive/2012/10/27/2742529.html
|
2512
|
+
if (node.offsetWidth <= 0) { //opera.offsetWidth可能小于0
|
2513
|
+
if (rdisplayswap.test(cssHooks["@:get"](node, "display"))) {
|
2514
|
+
var obj = {
|
2515
|
+
node: node
|
2516
|
+
}
|
2517
|
+
for (var name in cssShow) {
|
2518
|
+
obj[name] = node.style[name]
|
2519
|
+
node.style[name] = cssShow[name]
|
2520
|
+
}
|
2521
|
+
array.push(obj)
|
2522
|
+
}
|
2523
|
+
var parent = node.parentNode
|
2524
|
+
if (parent && parent.nodeType === 1) {
|
2525
|
+
showHidden(parent, array)
|
2526
|
+
}
|
2470
2527
|
}
|
2471
|
-
return this
|
2472
2528
|
}
|
2473
|
-
|
2474
|
-
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2478
|
-
|
2479
|
-
|
2480
|
-
|
2481
|
-
|
2482
|
-
|
2483
|
-
|
2484
|
-
|
2485
|
-
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
return this[0].getAttribute(name)
|
2495
|
-
}
|
2496
|
-
},
|
2497
|
-
data: function(name, value) {
|
2498
|
-
name = "data-" + hyphen(name || "")
|
2499
|
-
switch (arguments.length) {
|
2500
|
-
case 2:
|
2501
|
-
this.attr(name, value)
|
2502
|
-
return this
|
2503
|
-
case 1:
|
2504
|
-
var val = this.attr(name)
|
2505
|
-
return parseData(val)
|
2506
|
-
case 0:
|
2507
|
-
var ret = {}
|
2508
|
-
ap.forEach.call(this[0].attributes, function(attr) {
|
2509
|
-
if (attr) {
|
2510
|
-
name = attr.name
|
2511
|
-
if (!name.indexOf("data-")) {
|
2512
|
-
name = camelize(name.slice(5))
|
2513
|
-
ret[name] = parseData(attr.value)
|
2514
|
-
}
|
2515
|
-
}
|
2516
|
-
})
|
2529
|
+
"Width,Height".replace(rword, function(name) { //fix 481
|
2530
|
+
var method = name.toLowerCase(),
|
2531
|
+
clientProp = "client" + name,
|
2532
|
+
scrollProp = "scroll" + name,
|
2533
|
+
offsetProp = "offset" + name
|
2534
|
+
cssHooks[method + ":get"] = function(node, which, override) {
|
2535
|
+
var boxSizing = -4
|
2536
|
+
if (typeof override === "number") {
|
2537
|
+
boxSizing = override
|
2538
|
+
}
|
2539
|
+
which = name === "Width" ? ["Left", "Right"] : ["Top", "Bottom"]
|
2540
|
+
var ret = node[offsetProp] // border-box 0
|
2541
|
+
if (boxSizing === 2) { // margin-box 2
|
2542
|
+
return ret + avalon.css(node, "margin" + which[0], true) + avalon.css(node, "margin" + which[1], true)
|
2543
|
+
}
|
2544
|
+
if (boxSizing < 0) { // padding-box -2
|
2545
|
+
ret = ret - avalon.css(node, "border" + which[0] + "Width", true) - avalon.css(node, "border" + which[1] + "Width", true)
|
2546
|
+
}
|
2547
|
+
if (boxSizing === -4) { // content-box -4
|
2548
|
+
ret = ret - avalon.css(node, "padding" + which[0], true) - avalon.css(node, "padding" + which[1], true)
|
2549
|
+
}
|
2517
2550
|
return ret
|
2518
|
-
}
|
2519
|
-
},
|
2520
|
-
removeData: function(name) {
|
2521
|
-
name = "data-" + hyphen(name)
|
2522
|
-
this[0].removeAttribute(name)
|
2523
|
-
return this
|
2524
|
-
},
|
2525
|
-
css: function(name, value) {
|
2526
|
-
if (avalon.isPlainObject(name)) {
|
2527
|
-
for (var i in name) {
|
2528
|
-
avalon.css(this, i, name[i])
|
2529
2551
|
}
|
2530
|
-
|
2531
|
-
var
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
left: 0
|
2552
|
+
cssHooks[method + "&get"] = function(node) {
|
2553
|
+
var hidden = [];
|
2554
|
+
showHidden(node, hidden);
|
2555
|
+
var val = cssHooks[method + ":get"](node)
|
2556
|
+
for (var i = 0, obj; obj = hidden[i++];) {
|
2557
|
+
node = obj.node
|
2558
|
+
for (var n in obj) {
|
2559
|
+
if (typeof obj[n] === "string") {
|
2560
|
+
node.style[n] = obj[n]
|
2561
|
+
}
|
2541
2562
|
}
|
2542
|
-
if (!elem) {
|
2543
|
-
return
|
2544
|
-
}
|
2545
|
-
if (this.css("position") === "fixed") {
|
2546
|
-
offset = elem.getBoundingClientRect()
|
2547
|
-
} else {
|
2548
|
-
offsetParent = this.offsetParent() //得到真正的offsetParent
|
2549
|
-
offset = this.offset() // 得到正确的offsetParent
|
2550
|
-
if (offsetParent[0].tagName !== "HTML") {
|
2551
|
-
parentOffset = offsetParent.offset()
|
2552
2563
|
}
|
2553
|
-
|
2554
|
-
parentOffset.left += avalon.css(offsetParent[0], "borderLeftWidth", true)
|
2564
|
+
return val;
|
2555
2565
|
}
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2566
|
+
avalon.fn[method] = function(value) { //会忽视其display
|
2567
|
+
var node = this[0]
|
2568
|
+
if (arguments.length === 0) {
|
2569
|
+
if (node.setTimeout) { //取得窗口尺寸,IE9后可以用node.innerWidth /innerHeight代替
|
2570
|
+
return node["inner" + name] || node.document.documentElement[clientProp]
|
2571
|
+
}
|
2572
|
+
if (node.nodeType === 9) { //取得页面尺寸
|
2573
|
+
var doc = node.documentElement
|
2574
|
+
//FF chrome html.scrollHeight< body.scrollHeight
|
2575
|
+
//IE 标准模式 : html.scrollHeight> body.scrollHeight
|
2576
|
+
//IE 怪异模式 : html.scrollHeight 最大等于可视窗口多一点?
|
2577
|
+
return Math.max(node.body[scrollProp], doc[scrollProp], node.body[offsetProp], doc[offsetProp], doc[clientProp])
|
2578
|
+
}
|
2579
|
+
return cssHooks[method + "&get"](node)
|
2580
|
+
} else {
|
2581
|
+
return this.css(method, value)
|
2582
|
+
}
|
2565
2583
|
}
|
2566
|
-
|
2567
|
-
|
2568
|
-
bind: function(type, fn, phase) {
|
2569
|
-
if (this[0]) { //此方法不会链
|
2570
|
-
return avalon.bind(this[0], type, fn, phase)
|
2584
|
+
avalon.fn["inner" + name] = function() {
|
2585
|
+
return cssHooks[method + ":get"](this[0], void 0, -2)
|
2571
2586
|
}
|
2572
|
-
|
2573
|
-
|
2574
|
-
if (this[0]) {
|
2575
|
-
avalon.unbind(this[0], type, fn, phase)
|
2587
|
+
avalon.fn["outer" + name] = function(includeMargin) {
|
2588
|
+
return cssHooks[method + ":get"](this[0], void 0, includeMargin === true ? 2 : 0)
|
2576
2589
|
}
|
2577
|
-
|
2578
|
-
|
2579
|
-
|
2580
|
-
var node = this[0]
|
2581
|
-
if (node && node.nodeType === 1) {
|
2582
|
-
var get = arguments.length === 0
|
2583
|
-
var access = get ? ":get" : ":set"
|
2584
|
-
var fn = valHooks[getValType(node) + access]
|
2585
|
-
if (fn) {
|
2586
|
-
var val = fn(node, value)
|
2587
|
-
} else if (get) {
|
2588
|
-
return (node.value || "").replace(/\r/g, "")
|
2589
|
-
} else {
|
2590
|
-
node.value = value
|
2591
|
-
}
|
2592
|
-
}
|
2593
|
-
return get ? val : this
|
2594
|
-
}
|
2595
|
-
})
|
2596
|
-
|
2597
|
-
function parseData(data) {
|
2598
|
-
try {
|
2599
|
-
if (typeof data === "object")
|
2600
|
-
return data
|
2601
|
-
data = data === "true" ? true :
|
2602
|
-
data === "false" ? false :
|
2603
|
-
data === "null" ? null : +data + "" === data ? +data : rbrace.test(data) ? avalon.parseJSON(data) : data
|
2604
|
-
} catch (e) {
|
2605
|
-
}
|
2606
|
-
return data
|
2607
|
-
}
|
2608
|
-
var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
|
2609
|
-
rvalidchars = /^[\],:{}\s]*$/,
|
2610
|
-
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
|
2611
|
-
rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
|
2612
|
-
rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g
|
2613
|
-
avalon.parseJSON = window.JSON ? JSON.parse : function(data) {
|
2614
|
-
if (typeof data === "string") {
|
2615
|
-
data = data.trim();
|
2616
|
-
if (data) {
|
2617
|
-
if (rvalidchars.test(data.replace(rvalidescape, "@")
|
2618
|
-
.replace(rvalidtokens, "]")
|
2619
|
-
.replace(rvalidbraces, ""))) {
|
2620
|
-
return (new Function("return " + data))()// jshint ignore:line
|
2621
|
-
}
|
2622
|
-
}
|
2623
|
-
avalon.error("Invalid JSON: " + data)
|
2624
|
-
}
|
2625
|
-
return data
|
2626
|
-
}
|
2627
|
-
|
2628
|
-
//生成avalon.fn.scrollLeft, avalon.fn.scrollTop方法
|
2629
|
-
avalon.each({
|
2630
|
-
scrollLeft: "pageXOffset",
|
2631
|
-
scrollTop: "pageYOffset"
|
2632
|
-
}, function(method, prop) {
|
2633
|
-
avalon.fn[method] = function(val) {
|
2634
|
-
var node = this[0] || {}, win = getWindow(node),
|
2635
|
-
top = method === "scrollTop"
|
2636
|
-
if (!arguments.length) {
|
2637
|
-
return win ? (prop in win) ? win[prop] : root[method] : node[method]
|
2638
|
-
} else {
|
2639
|
-
if (win) {
|
2640
|
-
win.scrollTo(!top ? val : avalon(win).scrollLeft(), top ? val : avalon(win).scrollTop())
|
2641
|
-
} else {
|
2642
|
-
node[method] = val
|
2643
|
-
}
|
2644
|
-
}
|
2645
|
-
}
|
2646
|
-
})
|
2647
|
-
|
2648
|
-
function getWindow(node) {
|
2649
|
-
return node.window && node.document ? node : node.nodeType === 9 ? node.defaultView || node.parentWindow : false;
|
2650
|
-
}
|
2651
|
-
//=============================css相关=======================
|
2652
|
-
var cssHooks = avalon.cssHooks = {}
|
2653
|
-
var prefixes = ["", "-webkit-", "-o-", "-moz-", "-ms-"]
|
2654
|
-
var cssMap = {
|
2655
|
-
"float": W3C ? "cssFloat" : "styleFloat"
|
2656
|
-
}
|
2657
|
-
avalon.cssNumber = oneObject("columnCount,order,fillOpacity,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom")
|
2658
|
-
|
2659
|
-
avalon.cssName = function(name, host, camelCase) {
|
2660
|
-
if (cssMap[name]) {
|
2661
|
-
return cssMap[name]
|
2662
|
-
}
|
2663
|
-
host = host || root.style
|
2664
|
-
for (var i = 0, n = prefixes.length; i < n; i++) {
|
2665
|
-
camelCase = camelize(prefixes[i] + name)
|
2666
|
-
if (camelCase in host) {
|
2667
|
-
return (cssMap[name] = camelCase)
|
2668
|
-
}
|
2669
|
-
}
|
2670
|
-
return null
|
2671
|
-
}
|
2672
|
-
cssHooks["@:set"] = function(node, name, value) {
|
2673
|
-
try { //node.style.width = NaN;node.style.width = "xxxxxxx";node.style.width = undefine 在旧式IE下会抛异常
|
2674
|
-
node.style[name] = value
|
2675
|
-
} catch (e) {
|
2676
|
-
}
|
2677
|
-
}
|
2678
|
-
if (window.getComputedStyle) {
|
2679
|
-
cssHooks["@:get"] = function(node, name) {
|
2680
|
-
if (!node || !node.style) {
|
2681
|
-
throw new Error("getComputedStyle要求传入一个节点 " + node)
|
2682
|
-
}
|
2683
|
-
var ret, styles = getComputedStyle(node, null)
|
2684
|
-
if (styles) {
|
2685
|
-
ret = name === "filter" ? styles.getPropertyValue(name) : styles[name]
|
2686
|
-
if (ret === "") {
|
2687
|
-
ret = node.style[name] //其他浏览器需要我们手动取内联样式
|
2688
|
-
}
|
2689
|
-
}
|
2690
|
-
return ret
|
2691
|
-
}
|
2692
|
-
cssHooks["opacity:get"] = function(node) {
|
2693
|
-
var ret = cssHooks["@:get"](node, "opacity")
|
2694
|
-
return ret === "" ? "1" : ret
|
2695
|
-
}
|
2696
|
-
} else {
|
2697
|
-
var rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i
|
2698
|
-
var rposition = /^(top|right|bottom|left)$/
|
2699
|
-
var ralpha = /alpha\([^)]*\)/i
|
2700
|
-
var ie8 = !!window.XDomainRequest
|
2701
|
-
var salpha = "DXImageTransform.Microsoft.Alpha"
|
2702
|
-
var border = {
|
2703
|
-
thin: ie8 ? '1px' : '2px',
|
2704
|
-
medium: ie8 ? '3px' : '4px',
|
2705
|
-
thick: ie8 ? '5px' : '6px'
|
2706
|
-
}
|
2707
|
-
cssHooks["@:get"] = function(node, name) {
|
2708
|
-
//取得精确值,不过它有可能是带em,pc,mm,pt,%等单位
|
2709
|
-
var currentStyle = node.currentStyle
|
2710
|
-
var ret = currentStyle[name]
|
2711
|
-
if ((rnumnonpx.test(ret) && !rposition.test(ret))) {
|
2712
|
-
//①,保存原有的style.left, runtimeStyle.left,
|
2713
|
-
var style = node.style,
|
2714
|
-
left = style.left,
|
2715
|
-
rsLeft = node.runtimeStyle.left
|
2716
|
-
//②由于③处的style.left = xxx会影响到currentStyle.left,
|
2717
|
-
//因此把它currentStyle.left放到runtimeStyle.left,
|
2718
|
-
//runtimeStyle.left拥有最高优先级,不会style.left影响
|
2719
|
-
node.runtimeStyle.left = currentStyle.left
|
2720
|
-
//③将精确值赋给到style.left,然后通过IE的另一个私有属性 style.pixelLeft
|
2721
|
-
//得到单位为px的结果;fontSize的分支见http://bugs.jquery.com/ticket/760
|
2722
|
-
style.left = name === 'fontSize' ? '1em' : (ret || 0)
|
2723
|
-
ret = style.pixelLeft + "px"
|
2724
|
-
//④还原 style.left,runtimeStyle.left
|
2725
|
-
style.left = left
|
2726
|
-
node.runtimeStyle.left = rsLeft
|
2727
|
-
}
|
2728
|
-
if (ret === "medium") {
|
2729
|
-
name = name.replace("Width", "Style")
|
2730
|
-
//border width 默认值为medium,即使其为0"
|
2731
|
-
if (currentStyle[name] === "none") {
|
2732
|
-
ret = "0px"
|
2733
|
-
}
|
2734
|
-
}
|
2735
|
-
return ret === "" ? "auto" : border[ret] || ret
|
2736
|
-
}
|
2737
|
-
cssHooks["opacity:set"] = function(node, name, value) {
|
2738
|
-
var style = node.style
|
2739
|
-
var opacity = isFinite(value) && value <= 1 ? "alpha(opacity=" + value * 100 + ")" : ""
|
2740
|
-
var filter = style.filter || "";
|
2741
|
-
style.zoom = 1
|
2742
|
-
//不能使用以下方式设置透明度
|
2743
|
-
//node.filters.alpha.opacity = value * 100
|
2744
|
-
style.filter = (ralpha.test(filter) ?
|
2745
|
-
filter.replace(ralpha, opacity) :
|
2746
|
-
filter + " " + opacity).trim()
|
2747
|
-
if (!style.filter) {
|
2748
|
-
style.removeAttribute("filter")
|
2749
|
-
}
|
2750
|
-
}
|
2751
|
-
cssHooks["opacity:get"] = function(node) {
|
2752
|
-
//这是最快的获取IE透明值的方式,不需要动用正则了!
|
2753
|
-
var alpha = node.filters.alpha || node.filters[salpha],
|
2754
|
-
op = alpha && alpha.enabled ? alpha.opacity : 100
|
2755
|
-
return (op / 100) + "" //确保返回的是字符串
|
2756
|
-
}
|
2757
|
-
}
|
2758
|
-
|
2759
|
-
"top,left".replace(rword, function(name) {
|
2760
|
-
cssHooks[name + ":get"] = function(node) {
|
2761
|
-
var computed = cssHooks["@:get"](node, name)
|
2762
|
-
return /px$/.test(computed) ? computed :
|
2763
|
-
avalon(node).position()[name] + "px"
|
2764
|
-
}
|
2765
|
-
})
|
2766
|
-
|
2767
|
-
var cssShow = {
|
2768
|
-
position: "absolute",
|
2769
|
-
visibility: "hidden",
|
2770
|
-
display: "block"
|
2771
|
-
}
|
2772
|
-
|
2773
|
-
var rdisplayswap = /^(none|table(?!-c[ea]).+)/
|
2774
|
-
|
2775
|
-
function showHidden(node, array) {
|
2776
|
-
//http://www.cnblogs.com/rubylouvre/archive/2012/10/27/2742529.html
|
2777
|
-
if (node.offsetWidth <= 0) { //opera.offsetWidth可能小于0
|
2778
|
-
if (rdisplayswap.test(cssHooks["@:get"](node, "display"))) {
|
2779
|
-
var obj = {
|
2780
|
-
node: node
|
2781
|
-
}
|
2782
|
-
for (var name in cssShow) {
|
2783
|
-
obj[name] = node.style[name]
|
2784
|
-
node.style[name] = cssShow[name]
|
2785
|
-
}
|
2786
|
-
array.push(obj)
|
2787
|
-
}
|
2788
|
-
var parent = node.parentNode
|
2789
|
-
if (parent && parent.nodeType === 1) {
|
2790
|
-
showHidden(parent, array)
|
2791
|
-
}
|
2792
|
-
}
|
2793
|
-
}
|
2794
|
-
"Width,Height".replace(rword, function(name) { //fix 481
|
2795
|
-
var method = name.toLowerCase(),
|
2796
|
-
clientProp = "client" + name,
|
2797
|
-
scrollProp = "scroll" + name,
|
2798
|
-
offsetProp = "offset" + name
|
2799
|
-
cssHooks[method + ":get"] = function(node, which, override) {
|
2800
|
-
var boxSizing = -4
|
2801
|
-
if (typeof override === "number") {
|
2802
|
-
boxSizing = override
|
2803
|
-
}
|
2804
|
-
which = name === "Width" ? ["Left", "Right"] : ["Top", "Bottom"]
|
2805
|
-
var ret = node[offsetProp] // border-box 0
|
2806
|
-
if (boxSizing === 2) { // margin-box 2
|
2807
|
-
return ret + avalon.css(node, "margin" + which[0], true) + avalon.css(node, "margin" + which[1], true)
|
2808
|
-
}
|
2809
|
-
if (boxSizing < 0) { // padding-box -2
|
2810
|
-
ret = ret - avalon.css(node, "border" + which[0] + "Width", true) - avalon.css(node, "border" + which[1] + "Width", true)
|
2811
|
-
}
|
2812
|
-
if (boxSizing === -4) { // content-box -4
|
2813
|
-
ret = ret - avalon.css(node, "padding" + which[0], true) - avalon.css(node, "padding" + which[1], true)
|
2814
|
-
}
|
2815
|
-
return ret
|
2816
|
-
}
|
2817
|
-
cssHooks[method + "&get"] = function(node) {
|
2818
|
-
var hidden = [];
|
2819
|
-
showHidden(node, hidden);
|
2820
|
-
var val = cssHooks[method + ":get"](node)
|
2821
|
-
for (var i = 0, obj; obj = hidden[i++]; ) {
|
2822
|
-
node = obj.node
|
2823
|
-
for (var n in obj) {
|
2824
|
-
if (typeof obj[n] === "string") {
|
2825
|
-
node.style[n] = obj[n]
|
2826
|
-
}
|
2827
|
-
}
|
2828
|
-
}
|
2829
|
-
return val;
|
2830
|
-
}
|
2831
|
-
avalon.fn[method] = function(value) { //会忽视其display
|
2832
|
-
var node = this[0]
|
2833
|
-
if (arguments.length === 0) {
|
2834
|
-
if (node.setTimeout) { //取得窗口尺寸,IE9后可以用node.innerWidth /innerHeight代替
|
2835
|
-
return node["inner" + name] || node.document.documentElement[clientProp]
|
2836
|
-
}
|
2837
|
-
if (node.nodeType === 9) { //取得页面尺寸
|
2838
|
-
var doc = node.documentElement
|
2839
|
-
//FF chrome html.scrollHeight< body.scrollHeight
|
2840
|
-
//IE 标准模式 : html.scrollHeight> body.scrollHeight
|
2841
|
-
//IE 怪异模式 : html.scrollHeight 最大等于可视窗口多一点?
|
2842
|
-
return Math.max(node.body[scrollProp], doc[scrollProp], node.body[offsetProp], doc[offsetProp], doc[clientProp])
|
2843
|
-
}
|
2844
|
-
return cssHooks[method + "&get"](node)
|
2845
|
-
} else {
|
2846
|
-
return this.css(method, value)
|
2847
|
-
}
|
2848
|
-
}
|
2849
|
-
avalon.fn["inner" + name] = function() {
|
2850
|
-
return cssHooks[method + ":get"](this[0], void 0, -2)
|
2851
|
-
}
|
2852
|
-
avalon.fn["outer" + name] = function(includeMargin) {
|
2853
|
-
return cssHooks[method + ":get"](this[0], void 0, includeMargin === true ? 2 : 0)
|
2854
|
-
}
|
2855
|
-
})
|
2856
|
-
avalon.fn.offset = function() { //取得距离页面左右角的坐标
|
2857
|
-
var node = this[0],
|
2590
|
+
})
|
2591
|
+
avalon.fn.offset = function() { //取得距离页面左右角的坐标
|
2592
|
+
var node = this[0],
|
2858
2593
|
box = {
|
2859
2594
|
left: 0,
|
2860
2595
|
top: 0
|
2861
2596
|
}
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2597
|
+
if (!node || !node.tagName || !node.ownerDocument) {
|
2598
|
+
return box
|
2599
|
+
}
|
2600
|
+
var doc = node.ownerDocument,
|
2866
2601
|
body = doc.body,
|
2867
2602
|
root = doc.documentElement,
|
2868
2603
|
win = doc.defaultView || doc.parentWindow
|
2869
|
-
|
2870
|
-
|
2871
|
-
|
2872
|
-
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
2876
|
-
|
2877
|
-
|
2878
|
-
|
2879
|
-
|
2604
|
+
if (!avalon.contains(root, node)) {
|
2605
|
+
return box
|
2606
|
+
}
|
2607
|
+
//http://hkom.blog1.fc2.com/?mode=m&no=750 body的偏移量是不包含margin的
|
2608
|
+
//我们可以通过getBoundingClientRect来获得元素相对于client的rect.
|
2609
|
+
//http://msdn.microsoft.com/en-us/library/ms536433.aspx
|
2610
|
+
if (node.getBoundingClientRect) {
|
2611
|
+
box = node.getBoundingClientRect() // BlackBerry 5, iOS 3 (original iPhone)
|
2612
|
+
}
|
2613
|
+
//chrome/IE6: body.scrollTop, firefox/other: root.scrollTop
|
2614
|
+
var clientTop = root.clientTop || body.clientTop,
|
2880
2615
|
clientLeft = root.clientLeft || body.clientLeft,
|
2881
2616
|
scrollTop = Math.max(win.pageYOffset || 0, root.scrollTop, body.scrollTop),
|
2882
2617
|
scrollLeft = Math.max(win.pageXOffset || 0, root.scrollLeft, body.scrollLeft)
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2618
|
+
// 把滚动距离加到left,top中去。
|
2619
|
+
// IE一些版本中会自动为HTML元素加上2px的border,我们需要去掉它
|
2620
|
+
// http://msdn.microsoft.com/en-us/library/ms533564(VS.85).aspx
|
2621
|
+
return {
|
2622
|
+
top: box.top + scrollTop - clientTop,
|
2623
|
+
left: box.left + scrollLeft - clientLeft
|
2624
|
+
}
|
2889
2625
|
}
|
2890
|
-
}
|
2891
2626
|
|
2892
|
-
//==================================val相关============================
|
2627
|
+
//==================================val相关============================
|
2893
2628
|
|
2894
|
-
function getValType(
|
2895
|
-
|
2896
|
-
|
2897
|
-
}
|
2629
|
+
function getValType(elem) {
|
2630
|
+
var ret = elem.tagName.toLowerCase()
|
2631
|
+
return ret === "input" && /checkbox|radio/.test(elem.type) ? "checked" : ret
|
2632
|
+
}
|
2898
2633
|
var roption = /^<option(?:\s+\w+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s+value[\s=]/i
|
2899
2634
|
var valHooks = {
|
2900
2635
|
"option:get": IEVersion ? function(node) {
|
@@ -2906,12 +2641,12 @@ var valHooks = {
|
|
2906
2641
|
},
|
2907
2642
|
"select:get": function(node, value) {
|
2908
2643
|
var option, options = node.options,
|
2909
|
-
|
2910
|
-
|
2911
|
-
|
2912
|
-
|
2913
|
-
|
2914
|
-
|
2644
|
+
index = node.selectedIndex,
|
2645
|
+
getter = valHooks["option:get"],
|
2646
|
+
one = node.type === "select-one" || index < 0,
|
2647
|
+
values = one ? null : [],
|
2648
|
+
max = one ? index + 1 : options.length,
|
2649
|
+
i = index < 0 ? max : one ? index : 0
|
2915
2650
|
for (; i < max; i++) {
|
2916
2651
|
option = options[i]
|
2917
2652
|
//旧式IE在reset后不会改变selected,需要改用i === index判定
|
@@ -2931,7 +2666,7 @@ var valHooks = {
|
|
2931
2666
|
"select:set": function(node, values, optionSet) {
|
2932
2667
|
values = [].concat(values) //强制转换为数组
|
2933
2668
|
var getter = valHooks["option:get"]
|
2934
|
-
for (var i = 0, el; el = node.options[i++];
|
2669
|
+
for (var i = 0, el; el = node.options[i++];) {
|
2935
2670
|
if ((el.selected = values.indexOf(getter(el)) > -1)) {
|
2936
2671
|
optionSet = true
|
2937
2672
|
}
|
@@ -2976,10 +2711,10 @@ var rsplit = /[^\w$]+/g
|
|
2976
2711
|
var rkeywords = new RegExp(["\\b" + keywords.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g')
|
2977
2712
|
var rnumber = /\b\d[^,]*/g
|
2978
2713
|
var rcomma = /^,+|,+$/g
|
2979
|
-
var
|
2714
|
+
var variablePool = new Cache(512)
|
2980
2715
|
var getVariables = function (code) {
|
2981
2716
|
var key = "," + code.trim()
|
2982
|
-
var ret =
|
2717
|
+
var ret = variablePool.get(key)
|
2983
2718
|
if (ret) {
|
2984
2719
|
return ret
|
2985
2720
|
}
|
@@ -2990,7 +2725,7 @@ var getVariables = function (code) {
|
|
2990
2725
|
.replace(rnumber, "")
|
2991
2726
|
.replace(rcomma, "")
|
2992
2727
|
.split(/^$|,+/)
|
2993
|
-
return
|
2728
|
+
return variablePool.put(key, uniqSet(match))
|
2994
2729
|
}
|
2995
2730
|
/*添加赋值语句*/
|
2996
2731
|
|
@@ -3023,7 +2758,7 @@ function uniqSet(array) {
|
|
3023
2758
|
return ret
|
3024
2759
|
}
|
3025
2760
|
//缓存求值函数,以便多次利用
|
3026
|
-
var
|
2761
|
+
var evaluatorPool = new Cache(128)
|
3027
2762
|
//取得求值函数及其传参
|
3028
2763
|
var rduplex = /\w\[.*\]|\w\.\w/
|
3029
2764
|
var rproxy = /(\$proxy\$[a-z]+)\d+$/
|
@@ -3047,7 +2782,7 @@ function parseFilter(val, filters) {
|
|
3047
2782
|
.replace(rthimLeftParentheses, function () {
|
3048
2783
|
return '",'
|
3049
2784
|
}) + "]"
|
3050
|
-
return "return
|
2785
|
+
return "return this.filters.$filter(" + val + ", " + filters + ")"
|
3051
2786
|
}
|
3052
2787
|
|
3053
2788
|
function parseExpr(code, scopes, data) {
|
@@ -3079,9 +2814,11 @@ function parseExpr(code, scopes, data) {
|
|
3079
2814
|
//https://github.com/RubyLouvre/avalon/issues/583
|
3080
2815
|
data.vars.forEach(function (v) {
|
3081
2816
|
var reg = new RegExp("\\b" + v + "(?:\\.\\w+|\\[\\w+\\])+", "ig")
|
3082
|
-
code = code.replace(reg, function (_) {
|
2817
|
+
code = code.replace(reg, function (_, cap) {
|
3083
2818
|
var c = _.charAt(v.length)
|
3084
|
-
var r = IEVersion ? code.slice(arguments[1] + _.length) : RegExp.rightContext
|
2819
|
+
//var r = IEVersion ? code.slice(arguments[1] + _.length) : RegExp.rightContext
|
2820
|
+
//https://github.com/RubyLouvre/avalon/issues/966
|
2821
|
+
var r = code.slice(cap + _.length)
|
3085
2822
|
var method = /^\s*\(/.test(r)
|
3086
2823
|
if (c === "." || c === "[" || method) {//比如v为aa,我们只匹配aa.bb,aa[cc],不匹配aaa.xxx
|
3087
2824
|
var name = "var" + String(Math.random()).replace(/^0\./, "")
|
@@ -3106,7 +2843,8 @@ function parseExpr(code, scopes, data) {
|
|
3106
2843
|
//---------------args----------------
|
3107
2844
|
data.args = args
|
3108
2845
|
//---------------cache----------------
|
3109
|
-
|
2846
|
+
delete data.vars
|
2847
|
+
var fn = evaluatorPool.get(exprId) //直接从缓存,免得重复生成
|
3110
2848
|
if (fn) {
|
3111
2849
|
data.evaluator = fn
|
3112
2850
|
return
|
@@ -3121,6 +2859,16 @@ function parseExpr(code, scopes, data) {
|
|
3121
2859
|
}
|
3122
2860
|
code = "\nvar ret" + expose + " = " + code + ";\r\n"
|
3123
2861
|
code += parseFilter("ret" + expose, filters)
|
2862
|
+
try {
|
2863
|
+
fn = Function.apply(noop, names.concat("'use strict';\n" + prefix + code))
|
2864
|
+
data.evaluator = evaluatorPool.put(exprId, function() {
|
2865
|
+
return fn.apply(avalon, arguments)//确保可以在编译代码中使用this获取avalon对象
|
2866
|
+
})
|
2867
|
+
} catch (e) {
|
2868
|
+
log("debug: parse error," + e.message)
|
2869
|
+
}
|
2870
|
+
vars = assigns = names = null //释放内存
|
2871
|
+
return
|
3124
2872
|
} else if (dataType === "duplex") { //双工绑定
|
3125
2873
|
var _body = "'use strict';\nreturn function(vvv){\n\t" +
|
3126
2874
|
prefix +
|
@@ -3130,10 +2878,11 @@ function parseExpr(code, scopes, data) {
|
|
3130
2878
|
"= vvv;\n} "
|
3131
2879
|
try {
|
3132
2880
|
fn = Function.apply(noop, names.concat(_body))
|
3133
|
-
data.evaluator =
|
2881
|
+
data.evaluator = evaluatorPool.put(exprId, fn)
|
3134
2882
|
} catch (e) {
|
3135
2883
|
log("debug: parse error," + e.message)
|
3136
2884
|
}
|
2885
|
+
vars = assigns = names = null //释放内存
|
3137
2886
|
return
|
3138
2887
|
} else if (dataType === "on") { //事件绑定
|
3139
2888
|
if (code.indexOf("(") === -1) {
|
@@ -3152,37 +2901,430 @@ function parseExpr(code, scopes, data) {
|
|
3152
2901
|
}
|
3153
2902
|
try {
|
3154
2903
|
fn = Function.apply(noop, names.concat("'use strict';\n" + prefix + code))
|
3155
|
-
data.evaluator =
|
2904
|
+
data.evaluator = evaluatorPool.put(exprId, fn)
|
3156
2905
|
} catch (e) {
|
3157
2906
|
log("debug: parse error," + e.message)
|
3158
|
-
} finally {
|
3159
|
-
vars = assigns = names = null //释放内存
|
3160
2907
|
}
|
2908
|
+
vars = assigns = names = null //释放内存
|
3161
2909
|
}
|
3162
|
-
|
3163
|
-
|
3164
|
-
|
3165
|
-
|
3166
|
-
|
3167
|
-
|
3168
|
-
|
2910
|
+
function stringifyExpr(code) {
|
2911
|
+
var hasExpr = rexpr.test(code) //比如ms-class="width{{w}}"的情况
|
2912
|
+
if (hasExpr) {
|
2913
|
+
var array = scanExpr(code)
|
2914
|
+
if (array.length === 1) {
|
2915
|
+
return array[0].value
|
2916
|
+
}
|
2917
|
+
return array.map(function (el) {
|
3169
2918
|
return el.expr ? "(" + el.value + ")" : quote(el.value)
|
3170
2919
|
}).join(" + ")
|
2920
|
+
} else {
|
2921
|
+
return code
|
3171
2922
|
}
|
2923
|
+
}
|
2924
|
+
//parseExpr的智能引用代理
|
2925
|
+
|
2926
|
+
function parseExprProxy(code, scopes, data, noRegister) {
|
2927
|
+
code = code || "" //code 可能未定义
|
3172
2928
|
parseExpr(code, scopes, data)
|
3173
|
-
if (data.evaluator && !
|
2929
|
+
if (data.evaluator && !noRegister) {
|
3174
2930
|
data.handler = bindingExecutors[data.handlerName || data.type]
|
3175
2931
|
//方便调试
|
3176
2932
|
//这里非常重要,我们通过判定视图刷新函数的element是否在DOM树决定
|
3177
2933
|
//将它移出订阅者列表
|
3178
|
-
|
2934
|
+
avalon.injectBinding(data)
|
2935
|
+
}
|
2936
|
+
}
|
2937
|
+
avalon.parseExprProxy = parseExprProxy
|
2938
|
+
/*********************************************************************
|
2939
|
+
* 扫描系统 *
|
2940
|
+
**********************************************************************/
|
2941
|
+
|
2942
|
+
avalon.scan = function(elem, vmodel) {
|
2943
|
+
elem = elem || root
|
2944
|
+
var vmodels = vmodel ? [].concat(vmodel) : []
|
2945
|
+
scanTag(elem, vmodels)
|
2946
|
+
}
|
2947
|
+
|
2948
|
+
//http://www.w3.org/TR/html5/syntax.html#void-elements
|
2949
|
+
var stopScan = oneObject("area,base,basefont,br,col,command,embed,hr,img,input,link,meta,param,source,track,wbr,noscript,script,style,textarea".toUpperCase())
|
2950
|
+
|
2951
|
+
function checkScan(elem, callback, innerHTML) {
|
2952
|
+
var id = setTimeout(function() {
|
2953
|
+
var currHTML = elem.innerHTML
|
2954
|
+
clearTimeout(id)
|
2955
|
+
if (currHTML === innerHTML) {
|
2956
|
+
callback()
|
2957
|
+
} else {
|
2958
|
+
checkScan(elem, callback, currHTML)
|
2959
|
+
}
|
2960
|
+
})
|
2961
|
+
}
|
2962
|
+
|
2963
|
+
|
2964
|
+
function createSignalTower(elem, vmodel) {
|
2965
|
+
var id = elem.getAttribute("avalonctrl") || vmodel.$id
|
2966
|
+
elem.setAttribute("avalonctrl", id)
|
2967
|
+
vmodel.$events.expr = elem.tagName + '[avalonctrl="' + id + '"]'
|
2968
|
+
}
|
2969
|
+
|
2970
|
+
var getBindingCallback = function(elem, name, vmodels) {
|
2971
|
+
var callback = elem.getAttribute(name)
|
2972
|
+
if (callback) {
|
2973
|
+
for (var i = 0, vm; vm = vmodels[i++]; ) {
|
2974
|
+
if (vm.hasOwnProperty(callback) && typeof vm[callback] === "function") {
|
2975
|
+
return vm[callback]
|
2976
|
+
}
|
2977
|
+
}
|
2978
|
+
}
|
2979
|
+
}
|
2980
|
+
|
2981
|
+
function executeBindings(bindings, vmodels) {
|
2982
|
+
for (var i = 0, data; data = bindings[i++]; ) {
|
2983
|
+
data.vmodels = vmodels
|
2984
|
+
bindingHandlers[data.type](data, vmodels)
|
2985
|
+
if (data.evaluator && data.element && data.element.nodeType === 1) { //移除数据绑定,防止被二次解析
|
2986
|
+
//chrome使用removeAttributeNode移除不存在的特性节点时会报错 https://github.com/RubyLouvre/avalon/issues/99
|
2987
|
+
data.element.removeAttribute(data.name)
|
2988
|
+
}
|
2989
|
+
}
|
2990
|
+
bindings.length = 0
|
2991
|
+
}
|
2992
|
+
|
2993
|
+
//https://github.com/RubyLouvre/avalon/issues/636
|
2994
|
+
var mergeTextNodes = IEVersion && window.MutationObserver ? function (elem) {
|
2995
|
+
var node = elem.firstChild, text
|
2996
|
+
while (node) {
|
2997
|
+
var aaa = node.nextSibling
|
2998
|
+
if (node.nodeType === 3) {
|
2999
|
+
if (text) {
|
3000
|
+
text.nodeValue += node.nodeValue
|
3001
|
+
elem.removeChild(node)
|
3002
|
+
} else {
|
3003
|
+
text = node
|
3004
|
+
}
|
3005
|
+
} else {
|
3006
|
+
text = null
|
3007
|
+
}
|
3008
|
+
node = aaa
|
3009
|
+
}
|
3010
|
+
} : 0
|
3011
|
+
var roneTime = /^\s*::/
|
3012
|
+
var rmsAttr = /ms-(\w+)-?(.*)/
|
3013
|
+
var priorityMap = {
|
3014
|
+
"if": 10,
|
3015
|
+
"repeat": 90,
|
3016
|
+
"data": 100,
|
3017
|
+
"widget": 110,
|
3018
|
+
"each": 1400,
|
3019
|
+
"with": 1500,
|
3020
|
+
"duplex": 2000,
|
3021
|
+
"on": 3000
|
3022
|
+
}
|
3023
|
+
|
3024
|
+
var events = oneObject("animationend,blur,change,input,click,dblclick,focus,keydown,keypress,keyup,mousedown,mouseenter,mouseleave,mousemove,mouseout,mouseover,mouseup,scan,scroll,submit")
|
3025
|
+
var obsoleteAttrs = oneObject("value,title,alt,checked,selected,disabled,readonly,enabled")
|
3026
|
+
function bindingSorter(a, b) {
|
3027
|
+
return a.priority - b.priority
|
3028
|
+
}
|
3029
|
+
|
3030
|
+
function scanAttr(elem, vmodels, match) {
|
3031
|
+
var scanNode = true
|
3032
|
+
if (vmodels.length) {
|
3033
|
+
var attributes = getAttributes ? getAttributes(elem) : elem.attributes
|
3034
|
+
var bindings = []
|
3035
|
+
var fixAttrs = []
|
3036
|
+
var msData = {}
|
3037
|
+
var uniq = {}
|
3038
|
+
for (var i = 0, attr; attr = attributes[i++]; ) {
|
3039
|
+
if (attr.specified) {
|
3040
|
+
if (match = attr.name.match(rmsAttr)) {
|
3041
|
+
//如果是以指定前缀命名的
|
3042
|
+
var type = match[1]
|
3043
|
+
var param = match[2] || ""
|
3044
|
+
var value = attr.value
|
3045
|
+
var name = attr.name
|
3046
|
+
if (uniq[name]) {//IE8下ms-repeat,ms-with BUG
|
3047
|
+
continue
|
3048
|
+
}
|
3049
|
+
uniq[name] = 1
|
3050
|
+
if (events[type]) {
|
3051
|
+
param = type
|
3052
|
+
type = "on"
|
3053
|
+
} else if (obsoleteAttrs[type]) {
|
3054
|
+
if (type === "enabled") {//吃掉ms-enabled绑定,用ms-disabled代替
|
3055
|
+
log("warning!ms-enabled或ms-attr-enabled已经被废弃")
|
3056
|
+
type = "disabled"
|
3057
|
+
value = "!(" + value + ")"
|
3058
|
+
}
|
3059
|
+
param = type
|
3060
|
+
type = "attr"
|
3061
|
+
name = "ms-" + type + "-" + param
|
3062
|
+
fixAttrs.push([attr.name, name, value])
|
3063
|
+
}
|
3064
|
+
msData[name] = value
|
3065
|
+
if (typeof bindingHandlers[type] === "function") {
|
3066
|
+
var newValue = value.replace(roneTime, "")
|
3067
|
+
var oneTime = value !== newValue
|
3068
|
+
var binding = {
|
3069
|
+
type: type,
|
3070
|
+
param: param,
|
3071
|
+
element: elem,
|
3072
|
+
name: name,
|
3073
|
+
value: newValue,
|
3074
|
+
oneTime: oneTime,
|
3075
|
+
uuid: name + "-" + getUid(elem),
|
3076
|
+
//chrome与firefox下Number(param)得到的值不一样 #855
|
3077
|
+
priority: (priorityMap[type] || type.charCodeAt(0) * 10) + (Number(param.replace(/\D/g, "")) || 0)
|
3078
|
+
}
|
3079
|
+
if (type === "html" || type === "text") {
|
3080
|
+
var token = getToken(value)
|
3081
|
+
avalon.mix(binding, token)
|
3082
|
+
binding.filters = binding.filters.replace(rhasHtml, function () {
|
3083
|
+
binding.type = "html"
|
3084
|
+
binding.group = 1
|
3085
|
+
return ""
|
3086
|
+
})// jshint ignore:line
|
3087
|
+
} else if (type === "duplex") {
|
3088
|
+
var hasDuplex = name
|
3089
|
+
} else if (name === "ms-if-loop") {
|
3090
|
+
binding.priority += 100
|
3091
|
+
}
|
3092
|
+
bindings.push(binding)
|
3093
|
+
if (type === "widget") {
|
3094
|
+
elem.msData = elem.msData || msData
|
3095
|
+
}
|
3096
|
+
}
|
3097
|
+
}
|
3098
|
+
}
|
3099
|
+
}
|
3100
|
+
if (bindings.length) {
|
3101
|
+
bindings.sort(bindingSorter)
|
3102
|
+
fixAttrs.forEach(function (arr) {
|
3103
|
+
log("warning!请改用" + arr[1] + "代替" + arr[0] + "!")
|
3104
|
+
elem.removeAttribute(arr[0])
|
3105
|
+
elem.setAttribute(arr[1], arr[2])
|
3106
|
+
})
|
3107
|
+
//http://bugs.jquery.com/ticket/7071
|
3108
|
+
//在IE下对VML读取type属性,会让此元素所有属性都变成<Failed>
|
3109
|
+
if (hasDuplex && msData["ms-attr-value"] && !elem.scopeName && elem.type === "text") {
|
3110
|
+
log("warning!一个控件不能同时定义ms-attr-value与" + hasDuplex)
|
3111
|
+
}
|
3112
|
+
for (i = 0; binding = bindings[i]; i++) {
|
3113
|
+
type = binding.type
|
3114
|
+
if (rnoscanAttrBinding.test(type)) {
|
3115
|
+
return executeBindings(bindings.slice(0, i + 1), vmodels)
|
3116
|
+
} else if (scanNode) {
|
3117
|
+
scanNode = !rnoscanNodeBinding.test(type)
|
3118
|
+
}
|
3119
|
+
}
|
3120
|
+
executeBindings(bindings, vmodels)
|
3121
|
+
}
|
3122
|
+
}
|
3123
|
+
if (scanNode && !stopScan[elem.tagName] && rbind.test(elem.innerHTML.replace(rlt, "<").replace(rgt, ">"))) {
|
3124
|
+
mergeTextNodes && mergeTextNodes(elem)
|
3125
|
+
scanNodeList(elem, vmodels) //扫描子孙元素
|
3126
|
+
}
|
3127
|
+
}
|
3128
|
+
var rnoscanAttrBinding = /^if|widget|repeat$/
|
3129
|
+
var rnoscanNodeBinding = /^each|with|html|include$/
|
3130
|
+
//IE67下,在循环绑定中,一个节点如果是通过cloneNode得到,自定义属性的specified为false,无法进入里面的分支,
|
3131
|
+
//但如果我们去掉scanAttr中的attr.specified检测,一个元素会有80+个特性节点(因为它不区分固有属性与自定义属性),很容易卡死页面
|
3132
|
+
if (!W3C) {
|
3133
|
+
var attrPool = new Cache(512)
|
3134
|
+
var rattrs = /\s+(ms-[^=\s]+)(?:=("[^"]*"|'[^']*'|[^\s>]+))?/g,
|
3135
|
+
rquote = /^['"]/,
|
3136
|
+
rtag = /<\w+\b(?:(["'])[^"]*?(\1)|[^>])*>/i,
|
3137
|
+
ramp = /&/g
|
3138
|
+
//IE6-8解析HTML5新标签,会将它分解两个元素节点与一个文本节点
|
3139
|
+
//<body><section>ddd</section></body>
|
3140
|
+
// window.onload = function() {
|
3141
|
+
// var body = document.body
|
3142
|
+
// for (var i = 0, el; el = body.children[i++]; ) {
|
3143
|
+
// avalon.log(el.outerHTML)
|
3144
|
+
// }
|
3145
|
+
// }
|
3146
|
+
//依次输出<SECTION>, </SECTION>
|
3147
|
+
var getAttributes = function (elem) {
|
3148
|
+
var html = elem.outerHTML
|
3149
|
+
//处理IE6-8解析HTML5新标签的情况,及<br>等半闭合标签outerHTML为空的情况
|
3150
|
+
if (html.slice(0, 2) === "</" || !html.trim()) {
|
3151
|
+
return []
|
3152
|
+
}
|
3153
|
+
var str = html.match(rtag)[0]
|
3154
|
+
var attributes = [],
|
3155
|
+
match,
|
3156
|
+
k, v
|
3157
|
+
var ret = attrPool.get(str)
|
3158
|
+
if (ret) {
|
3159
|
+
return ret
|
3160
|
+
}
|
3161
|
+
while (k = rattrs.exec(str)) {
|
3162
|
+
v = k[2]
|
3163
|
+
if (v) {
|
3164
|
+
v = (rquote.test(v) ? v.slice(1, -1) : v).replace(ramp, "&")
|
3165
|
+
}
|
3166
|
+
var name = k[1].toLowerCase()
|
3167
|
+
match = name.match(rmsAttr)
|
3168
|
+
var binding = {
|
3169
|
+
name: name,
|
3170
|
+
specified: true,
|
3171
|
+
value: v || ""
|
3172
|
+
}
|
3173
|
+
attributes.push(binding)
|
3174
|
+
}
|
3175
|
+
return attrPool.put(str, attributes)
|
3176
|
+
}
|
3177
|
+
}
|
3178
|
+
|
3179
|
+
function scanNodeList(parent, vmodels) {
|
3180
|
+
var nodes = avalon.slice(parent.childNodes)
|
3181
|
+
scanNodeArray(nodes, vmodels)
|
3182
|
+
}
|
3183
|
+
|
3184
|
+
function scanNodeArray(nodes, vmodels) {
|
3185
|
+
for (var i = 0, node; node = nodes[i++];) {
|
3186
|
+
switch (node.nodeType) {
|
3187
|
+
case 1:
|
3188
|
+
scanTag(node, vmodels) //扫描元素节点
|
3189
|
+
if (node.msCallback) {
|
3190
|
+
node.msCallback()
|
3191
|
+
node.msCallback = void 0
|
3192
|
+
}
|
3193
|
+
break
|
3194
|
+
case 3:
|
3195
|
+
if(rexpr.test(node.nodeValue)){
|
3196
|
+
scanText(node, vmodels, i) //扫描文本节点
|
3197
|
+
}
|
3198
|
+
break
|
3199
|
+
}
|
3200
|
+
}
|
3201
|
+
}
|
3202
|
+
|
3203
|
+
|
3204
|
+
function scanTag(elem, vmodels, node) {
|
3205
|
+
//扫描顺序 ms-skip(0) --> ms-important(1) --> ms-controller(2) --> ms-if(10) --> ms-repeat(100)
|
3206
|
+
//--> ms-if-loop(110) --> ms-attr(970) ...--> ms-each(1400)-->ms-with(1500)--〉ms-duplex(2000)垫后
|
3207
|
+
var a = elem.getAttribute("ms-skip")
|
3208
|
+
//#360 在旧式IE中 Object标签在引入Flash等资源时,可能出现没有getAttributeNode,innerHTML的情形
|
3209
|
+
if (!elem.getAttributeNode) {
|
3210
|
+
return log("warning " + elem.tagName + " no getAttributeNode method")
|
3211
|
+
}
|
3212
|
+
var b = elem.getAttributeNode("ms-important")
|
3213
|
+
var c = elem.getAttributeNode("ms-controller")
|
3214
|
+
if (typeof a === "string") {
|
3215
|
+
return
|
3216
|
+
} else if (node = b || c) {
|
3217
|
+
var newVmodel = avalon.vmodels[node.value]
|
3218
|
+
if (!newVmodel) {
|
3219
|
+
return
|
3220
|
+
}
|
3221
|
+
//ms-important不包含父VM,ms-controller相反
|
3222
|
+
vmodels = node === b ? [newVmodel] : [newVmodel].concat(vmodels)
|
3223
|
+
var name = node.name
|
3224
|
+
elem.removeAttribute(name) //removeAttributeNode不会刷新[ms-controller]样式规则
|
3225
|
+
avalon(elem).removeClass(name)
|
3226
|
+
createSignalTower(elem, newVmodel)
|
3227
|
+
}
|
3228
|
+
scanAttr(elem, vmodels) //扫描特性节点
|
3229
|
+
}
|
3230
|
+
var rhasHtml = /\|\s*html(?:\b|$)/,
|
3231
|
+
r11a = /\|\|/g,
|
3232
|
+
rlt = /</g,
|
3233
|
+
rgt = />/g,
|
3234
|
+
rstringLiteral = /(['"])(\\\1|.)+?\1/g
|
3235
|
+
function getToken(value) {
|
3236
|
+
if (value.indexOf("|") > 0) {
|
3237
|
+
var scapegoat = value.replace(rstringLiteral, function (_) {
|
3238
|
+
return Array(_.length + 1).join("1")// jshint ignore:line
|
3239
|
+
})
|
3240
|
+
var index = scapegoat.replace(r11a, "\u1122\u3344").indexOf("|") //干掉所有短路或
|
3241
|
+
if (index > -1) {
|
3242
|
+
return {
|
3243
|
+
filters: value.slice(index),
|
3244
|
+
value: value.slice(0, index),
|
3245
|
+
expr: true
|
3246
|
+
}
|
3247
|
+
}
|
3248
|
+
}
|
3249
|
+
return {
|
3250
|
+
value: value,
|
3251
|
+
filters: "",
|
3252
|
+
expr: true
|
3253
|
+
}
|
3254
|
+
}
|
3255
|
+
|
3256
|
+
function scanExpr(str) {
|
3257
|
+
var tokens = [],
|
3258
|
+
value, start = 0,
|
3259
|
+
stop
|
3260
|
+
do {
|
3261
|
+
stop = str.indexOf(openTag, start)
|
3262
|
+
if (stop === -1) {
|
3263
|
+
break
|
3264
|
+
}
|
3265
|
+
value = str.slice(start, stop)
|
3266
|
+
if (value) { // {{ 左边的文本
|
3267
|
+
tokens.push({
|
3268
|
+
value: value,
|
3269
|
+
filters: "",
|
3270
|
+
expr: false
|
3271
|
+
})
|
3272
|
+
}
|
3273
|
+
start = stop + openTag.length
|
3274
|
+
stop = str.indexOf(closeTag, start)
|
3275
|
+
if (stop === -1) {
|
3276
|
+
break
|
3277
|
+
}
|
3278
|
+
value = str.slice(start, stop)
|
3279
|
+
if (value) { //处理{{ }}插值表达式
|
3280
|
+
tokens.push(getToken(value, start))
|
3281
|
+
}
|
3282
|
+
start = stop + closeTag.length
|
3283
|
+
} while (1)
|
3284
|
+
value = str.slice(start)
|
3285
|
+
if (value) { //}} 右边的文本
|
3286
|
+
tokens.push({
|
3287
|
+
value: value,
|
3288
|
+
expr: false,
|
3289
|
+
filters: ""
|
3290
|
+
})
|
3291
|
+
}
|
3292
|
+
return tokens
|
3293
|
+
}
|
3294
|
+
|
3295
|
+
function scanText(textNode, vmodels, index) {
|
3296
|
+
var bindings = []
|
3297
|
+
tokens = scanExpr(textNode.data)
|
3298
|
+
if (tokens.length) {
|
3299
|
+
for (var i = 0; token = tokens[i++]; ) {
|
3300
|
+
var node = DOC.createTextNode(token.value) //将文本转换为文本节点,并替换原来的文本节点
|
3301
|
+
if (token.expr) {
|
3302
|
+
token.value = token.value.replace(roneTime, function () {
|
3303
|
+
token.oneTime = true
|
3304
|
+
return ""
|
3305
|
+
})// jshint ignore:line
|
3306
|
+
token.type = "text"
|
3307
|
+
token.element = node
|
3308
|
+
token.filters = token.filters.replace(rhasHtml, function (a, b,c) {
|
3309
|
+
token.type = "html"
|
3310
|
+
return ""
|
3311
|
+
})// jshint ignore:line
|
3312
|
+
token.pos = index * 1000 + i
|
3313
|
+
bindings.push(token) //收集带有插值表达式的文本
|
3314
|
+
}
|
3315
|
+
avalonFragment.appendChild(node)
|
3316
|
+
}
|
3317
|
+
textNode.parentNode.replaceChild(avalonFragment, textNode)
|
3318
|
+
if (bindings.length)
|
3319
|
+
executeBindings(bindings, vmodels)
|
3179
3320
|
}
|
3180
3321
|
}
|
3181
|
-
|
3322
|
+
|
3182
3323
|
var bools = ["autofocus,autoplay,async,allowTransparency,checked,controls",
|
3183
3324
|
"declare,disabled,defer,defaultChecked,defaultSelected",
|
3184
3325
|
"contentEditable,isMap,loop,multiple,noHref,noResize,noShade",
|
3185
|
-
"open,readOnly,selected"
|
3326
|
+
"open,readOnly,selected"
|
3327
|
+
].join(",")
|
3186
3328
|
var boolMap = {}
|
3187
3329
|
bools.replace(rword, function (name) {
|
3188
3330
|
boolMap[name.toLowerCase()] = name
|
@@ -3199,7 +3341,8 @@ var propMap = {//属性名映射
|
|
3199
3341
|
|
3200
3342
|
var anomaly = ["accessKey,bgColor,cellPadding,cellSpacing,codeBase,codeType,colSpan",
|
3201
3343
|
"dateTime,defaultValue,frameBorder,longDesc,maxLength,marginWidth,marginHeight",
|
3202
|
-
"rowSpan,tabIndex,useMap,vSpace,valueType,vAlign"
|
3344
|
+
"rowSpan,tabIndex,useMap,vSpace,valueType,vAlign"
|
3345
|
+
].join(",")
|
3203
3346
|
anomaly.replace(rword, function (name) {
|
3204
3347
|
propMap[name.toLowerCase()] = name
|
3205
3348
|
})
|
@@ -3208,21 +3351,13 @@ var rnoscripts = /<noscript.*?>(?:[\s\S]+?)<\/noscript>/img
|
|
3208
3351
|
var rnoscriptText = /<noscript.*?>([\s\S]+?)<\/noscript>/im
|
3209
3352
|
|
3210
3353
|
var getXHR = function () {
|
3211
|
-
return new (window.XMLHttpRequest || ActiveXObject)("Microsoft.XMLHTTP")// jshint ignore:line
|
3354
|
+
return new (window.XMLHttpRequest || ActiveXObject)("Microsoft.XMLHTTP") // jshint ignore:line
|
3212
3355
|
}
|
3213
3356
|
|
3214
|
-
var
|
3357
|
+
var templatePool = avalon.templateCache = {}
|
3215
3358
|
|
3216
3359
|
bindingHandlers.attr = function (data, vmodels) {
|
3217
|
-
var
|
3218
|
-
simple = true
|
3219
|
-
if (text.indexOf(openTag) > -1 && text.indexOf(closeTag) > 2) {
|
3220
|
-
simple = false
|
3221
|
-
if (rexpr.test(text) && RegExp.rightContext === "" && RegExp.leftContext === "") {
|
3222
|
-
simple = true
|
3223
|
-
text = RegExp.$1
|
3224
|
-
}
|
3225
|
-
}
|
3360
|
+
var value = stringifyExpr(data.value.trim())
|
3226
3361
|
if (data.type === "include") {
|
3227
3362
|
var elem = data.element
|
3228
3363
|
data.includeRendered = getBindingCallback(elem, "data-include-rendered", vmodels)
|
@@ -3243,7 +3378,7 @@ bindingHandlers.attr = function (data, vmodels) {
|
|
3243
3378
|
}
|
3244
3379
|
}
|
3245
3380
|
data.handlerName = "attr" //handleName用于处理多种绑定共用同一种bindingExecutor的情况
|
3246
|
-
parseExprProxy(
|
3381
|
+
parseExprProxy(value, vmodels, data)
|
3247
3382
|
}
|
3248
3383
|
|
3249
3384
|
bindingExecutors.attr = function (val, elem, data) {
|
@@ -3252,28 +3387,29 @@ bindingExecutors.attr = function (val, elem, data) {
|
|
3252
3387
|
if (method === "css") {
|
3253
3388
|
avalon(elem).css(attrName, val)
|
3254
3389
|
} else if (method === "attr") {
|
3390
|
+
|
3255
3391
|
// ms-attr-class="xxx" vm.xxx="aaa bbb ccc"将元素的className设置为aaa bbb ccc
|
3256
3392
|
// ms-attr-class="xxx" vm.xxx=false 清空元素的所有类名
|
3257
3393
|
// ms-attr-name="yyy" vm.yyy="ooo" 为元素设置name属性
|
3258
|
-
if (boolMap[attrName]) {
|
3259
|
-
var bool = boolMap[attrName]
|
3260
|
-
if (typeof elem[bool] === "boolean") {
|
3261
|
-
// IE6-11不支持动态设置fieldset的disabled属性,IE11下样式是生效了,但无法阻止用户对其底下的input元素进行设值……
|
3262
|
-
return elem[bool] = !!val
|
3263
|
-
}
|
3264
|
-
}
|
3265
3394
|
var toRemove = (val === false) || (val === null) || (val === void 0)
|
3266
3395
|
|
3267
3396
|
if (!W3C && propMap[attrName]) { //旧式IE下需要进行名字映射
|
3268
3397
|
attrName = propMap[attrName]
|
3269
3398
|
}
|
3399
|
+
var bool = boolMap[attrName]
|
3400
|
+
if (typeof elem[bool] === "boolean") {
|
3401
|
+
elem[bool] = !!val //布尔属性必须使用el.xxx = true|false方式设值
|
3402
|
+
if (!val) { //如果为false, IE全系列下相当于setAttribute(xxx,''),会影响到样式,需要进一步处理
|
3403
|
+
toRemove = true
|
3404
|
+
}
|
3405
|
+
}
|
3270
3406
|
if (toRemove) {
|
3271
3407
|
return elem.removeAttribute(attrName)
|
3272
3408
|
}
|
3273
3409
|
//SVG只能使用setAttribute(xxx, yyy), VML只能使用elem.xxx = yyy ,HTML的固有属性必须elem.xxx = yyy
|
3274
3410
|
var isInnate = rsvg.test(elem) ? false : (DOC.namespaces && isVML(elem)) ? true : attrName in elem.cloneNode(false)
|
3275
3411
|
if (isInnate) {
|
3276
|
-
elem[attrName] = val
|
3412
|
+
elem[attrName] = val + ""
|
3277
3413
|
} else {
|
3278
3414
|
elem.setAttribute(attrName, val)
|
3279
3415
|
}
|
@@ -3285,7 +3421,9 @@ bindingExecutors.attr = function (val, elem, data) {
|
|
3285
3421
|
var target = replace ? elem.parentNode : elem
|
3286
3422
|
var scanTemplate = function (text) {
|
3287
3423
|
if (loaded) {
|
3288
|
-
|
3424
|
+
var newText = loaded.apply(target, [text].concat(vmodels))
|
3425
|
+
if (typeof newText === "string")
|
3426
|
+
text = newText
|
3289
3427
|
}
|
3290
3428
|
if (rendered) {
|
3291
3429
|
checkScan(target, function () {
|
@@ -3318,20 +3456,27 @@ bindingExecutors.attr = function (val, elem, data) {
|
|
3318
3456
|
}
|
3319
3457
|
|
3320
3458
|
if (data.param === "src") {
|
3321
|
-
if (
|
3459
|
+
if (typeof templatePool[val] === "string") {
|
3322
3460
|
avalon.nextTick(function () {
|
3323
|
-
scanTemplate(
|
3461
|
+
scanTemplate(templatePool[val])
|
3324
3462
|
})
|
3463
|
+
} else if (Array.isArray(templatePool[val])) { //#805 防止在循环绑定中发出许多相同的请求
|
3464
|
+
templatePool[val].push(scanTemplate)
|
3325
3465
|
} else {
|
3326
3466
|
var xhr = getXHR()
|
3327
3467
|
xhr.onreadystatechange = function () {
|
3328
3468
|
if (xhr.readyState === 4) {
|
3329
3469
|
var s = xhr.status
|
3330
3470
|
if (s >= 200 && s < 300 || s === 304 || s === 1223) {
|
3331
|
-
|
3471
|
+
var text = xhr.responseText
|
3472
|
+
for (var f = 0, fn; fn = templatePool[val][f++]; ) {
|
3473
|
+
fn(text)
|
3474
|
+
}
|
3475
|
+
templatePool[val] = text
|
3332
3476
|
}
|
3333
3477
|
}
|
3334
3478
|
}
|
3479
|
+
templatePool[val] = [scanTemplate]
|
3335
3480
|
xhr.open("GET", val, true)
|
3336
3481
|
if ("withCredentials" in xhr) {
|
3337
3482
|
xhr.withCredentials = true
|
@@ -3382,13 +3527,14 @@ bindingExecutors.attr = function (val, elem, data) {
|
|
3382
3527
|
function getTemplateNodes(data, id, text) {
|
3383
3528
|
var div = data.templateCache && data.templateCache[id]
|
3384
3529
|
if (div) {
|
3385
|
-
var dom = DOC.createDocumentFragment(),
|
3530
|
+
var dom = DOC.createDocumentFragment(),
|
3531
|
+
firstChild
|
3386
3532
|
while (firstChild = div.firstChild) {
|
3387
3533
|
dom.appendChild(firstChild)
|
3388
3534
|
}
|
3389
3535
|
return dom
|
3390
3536
|
}
|
3391
|
-
return
|
3537
|
+
return avalon.parseHTML(text)
|
3392
3538
|
}
|
3393
3539
|
|
3394
3540
|
//这几个指令都可以使用插值表达式,如ms-src="aaa/{{b}}/{{c}}.html"
|
@@ -3397,92 +3543,85 @@ function getTemplateNodes(data, id, text) {
|
|
3397
3543
|
})
|
3398
3544
|
//根据VM的属性值或表达式的值切换类名,ms-class="xxx yyy zzz:flag"
|
3399
3545
|
//http://www.cnblogs.com/rubylouvre/archive/2012/12/17/2818540.html
|
3400
|
-
bindingHandlers["class"] = function(
|
3401
|
-
var oldStyle =
|
3402
|
-
text =
|
3546
|
+
bindingHandlers["class"] = function (binding, vmodels) {
|
3547
|
+
var oldStyle = binding.param,
|
3548
|
+
text = binding.value,
|
3403
3549
|
rightExpr
|
3404
|
-
|
3550
|
+
binding.handlerName = "class"
|
3405
3551
|
if (!oldStyle || isFinite(oldStyle)) {
|
3406
|
-
|
3407
|
-
var
|
3552
|
+
binding.param = "" //去掉数字
|
3553
|
+
var colonIndex = text.replace(rexprg, function (a) {
|
3408
3554
|
return a.replace(/./g, "0")
|
3409
|
-
|
3410
|
-
})
|
3411
|
-
var colonIndex = noExpr.indexOf(":") //取得第一个冒号的位置
|
3555
|
+
}).indexOf(":") //取得第一个冒号的位置
|
3412
3556
|
if (colonIndex === -1) { // 比如 ms-class="aaa bbb ccc" 的情况
|
3413
3557
|
var className = text
|
3414
|
-
|
3558
|
+
rightExpr = true
|
3559
|
+
} else { // 比如 ms-class-1="ui-state-active:checked" 的情况
|
3415
3560
|
className = text.slice(0, colonIndex)
|
3416
3561
|
rightExpr = text.slice(colonIndex + 1)
|
3417
|
-
parseExpr(rightExpr, vmodels, data) //决定是添加还是删除
|
3418
|
-
if (!data.evaluator) {
|
3419
|
-
log("debug: ms-class '" + (rightExpr || "").trim() + "' 不存在于VM中")
|
3420
|
-
return false
|
3421
|
-
} else {
|
3422
|
-
data._evaluator = data.evaluator
|
3423
|
-
data._args = data.args
|
3424
|
-
}
|
3425
3562
|
}
|
3426
|
-
|
3427
|
-
|
3428
|
-
|
3563
|
+
if (!rexpr.test(text)) {
|
3564
|
+
className = quote(className)
|
3565
|
+
} else {
|
3566
|
+
className = stringifyExpr(className)
|
3429
3567
|
}
|
3430
|
-
|
3568
|
+
binding.expr = "[" + className + "," + rightExpr + "]"
|
3431
3569
|
} else {
|
3432
|
-
|
3433
|
-
|
3570
|
+
binding.expr = '[' + quote(oldStyle) + "," + text + "]"
|
3571
|
+
binding.oldStyle = oldStyle
|
3572
|
+
}
|
3573
|
+
var method = binding.type
|
3574
|
+
if (method === "hover" || method === "active") { //确保只绑定一次
|
3575
|
+
if (!binding.hasBindEvent) {
|
3576
|
+
var elem = binding.element
|
3577
|
+
var $elem = avalon(elem)
|
3578
|
+
var activate = "mouseenter" //在移出移入时切换类名
|
3579
|
+
var abandon = "mouseleave"
|
3580
|
+
if (method === "active") { //在聚焦失焦中切换类名
|
3581
|
+
elem.tabIndex = elem.tabIndex || -1
|
3582
|
+
activate = "mousedown"
|
3583
|
+
abandon = "mouseup"
|
3584
|
+
var fn0 = $elem.bind("mouseleave", function () {
|
3585
|
+
binding.toggleClass && $elem.removeClass(binding.newClass)
|
3586
|
+
})
|
3587
|
+
}
|
3588
|
+
}
|
3589
|
+
|
3590
|
+
var fn1 = $elem.bind(activate, function () {
|
3591
|
+
binding.toggleClass && $elem.addClass(binding.newClass)
|
3592
|
+
})
|
3593
|
+
var fn2 = $elem.bind(abandon, function () {
|
3594
|
+
binding.toggleClass && $elem.removeClass(binding.newClass)
|
3595
|
+
})
|
3596
|
+
binding.rollback = function () {
|
3597
|
+
$elem.unbind("mouseleave", fn0)
|
3598
|
+
$elem.unbind(activate, fn1)
|
3599
|
+
$elem.unbind(abandon, fn2)
|
3600
|
+
}
|
3601
|
+
binding.hasBindEvent = true
|
3434
3602
|
}
|
3603
|
+
parseExprProxy(binding.expr, vmodels, binding)
|
3435
3604
|
}
|
3436
3605
|
|
3437
|
-
bindingExecutors
|
3438
|
-
var $elem = avalon(elem)
|
3439
|
-
|
3440
|
-
|
3441
|
-
|
3442
|
-
|
3443
|
-
|
3444
|
-
|
3445
|
-
|
3446
|
-
if (
|
3447
|
-
$elem.
|
3448
|
-
}
|
3449
|
-
|
3450
|
-
switch (method) {
|
3451
|
-
case "class":
|
3452
|
-
$elem.toggleClass(data.newClass, data.toggleClass)
|
3453
|
-
break
|
3454
|
-
case "hover":
|
3455
|
-
case "active":
|
3456
|
-
if (!data.hasBindEvent) { //确保只绑定一次
|
3457
|
-
var activate = "mouseenter" //在移出移入时切换类名
|
3458
|
-
var abandon = "mouseleave"
|
3459
|
-
if (method === "active") { //在聚焦失焦中切换类名
|
3460
|
-
elem.tabIndex = elem.tabIndex || -1
|
3461
|
-
activate = "mousedown"
|
3462
|
-
abandon = "mouseup"
|
3463
|
-
var fn0 = $elem.bind("mouseleave", function() {
|
3464
|
-
data.toggleClass && $elem.removeClass(data.newClass)
|
3465
|
-
})
|
3466
|
-
}
|
3467
|
-
var fn1 = $elem.bind(activate, function() {
|
3468
|
-
data.toggleClass && $elem.addClass(data.newClass)
|
3469
|
-
})
|
3470
|
-
var fn2 = $elem.bind(abandon, function() {
|
3471
|
-
data.toggleClass && $elem.removeClass(data.newClass)
|
3472
|
-
})
|
3473
|
-
data.rollback = function() {
|
3474
|
-
$elem.unbind("mouseleave", fn0)
|
3475
|
-
$elem.unbind(activate, fn1)
|
3476
|
-
$elem.unbind(abandon, fn2)
|
3477
|
-
}
|
3478
|
-
data.hasBindEvent = true
|
3479
|
-
}
|
3480
|
-
break;
|
3606
|
+
bindingExecutors["class"] = function (arr, elem, binding) {
|
3607
|
+
var $elem = avalon(elem)
|
3608
|
+
binding.newClass = arr[0]
|
3609
|
+
binding.toggleClass = !!arr[1]
|
3610
|
+
if (binding.oldClass && binding.newClass !== binding.oldClass) {
|
3611
|
+
$elem.removeClass(binding.oldClass)
|
3612
|
+
}
|
3613
|
+
binding.oldClass = binding.newClass
|
3614
|
+
if (binding.type === "class") {
|
3615
|
+
if (binding.oldStyle) {
|
3616
|
+
$elem.toggleClass(binding.oldStyle, !!arr[1])
|
3617
|
+
} else {
|
3618
|
+
$elem.toggleClass(binding.newClass, binding.toggleClass)
|
3481
3619
|
}
|
3482
3620
|
}
|
3621
|
+
|
3483
3622
|
}
|
3484
3623
|
|
3485
|
-
"hover,active".replace(rword, function(method) {
|
3624
|
+
"hover,active".replace(rword, function (method) {
|
3486
3625
|
bindingHandlers[method] = bindingHandlers["class"]
|
3487
3626
|
})
|
3488
3627
|
//ms-controller绑定已经在scanTag 方法中实现
|
@@ -3491,21 +3630,20 @@ bindingExecutors ["class"] = function(val, elem, data) {
|
|
3491
3630
|
|
3492
3631
|
// bindingHandlers.data 定义在if.js
|
3493
3632
|
bindingExecutors.data = function(val, elem, data) {
|
3494
|
-
|
3495
|
-
|
3496
|
-
|
3497
|
-
|
3498
|
-
|
3499
|
-
|
3633
|
+
var key = "data-" + data.param
|
3634
|
+
if (val && typeof val === "object") {
|
3635
|
+
elem[key] = val
|
3636
|
+
} else {
|
3637
|
+
elem.setAttribute(key, String(val))
|
3638
|
+
}
|
3500
3639
|
}
|
3501
|
-
|
3502
3640
|
//双工绑定
|
3503
|
-
var duplexBinding = bindingHandlers.duplex = function
|
3641
|
+
var duplexBinding = bindingHandlers.duplex = function(data, vmodels) {
|
3504
3642
|
var elem = data.element,
|
3505
|
-
|
3506
|
-
|
3643
|
+
hasCast
|
3644
|
+
parseExprProxy(data.value, vmodels, data, 1)
|
3507
3645
|
|
3508
|
-
|
3646
|
+
data.changed = getBindingCallback(elem, "data-duplex-changed", vmodels) || noop
|
3509
3647
|
if (data.evaluator && data.args) {
|
3510
3648
|
var params = []
|
3511
3649
|
var casting = oneObject("string,number,boolean,checked")
|
@@ -3515,7 +3653,7 @@ var duplexBinding = bindingHandlers.duplex = function (data, vmodels) {
|
|
3515
3653
|
if (elem.msData) {
|
3516
3654
|
elem.msData["ms-duplex"] = data.value
|
3517
3655
|
}
|
3518
|
-
data.param.replace(/\w+/g, function
|
3656
|
+
data.param.replace(/\w+/g, function(name) {
|
3519
3657
|
if (/^(checkbox|radio)$/.test(elem.type) && /^(radio|checked)$/.test(name)) {
|
3520
3658
|
if (name === "radio")
|
3521
3659
|
log("ms-duplex-radio已经更名为ms-duplex-checked")
|
@@ -3538,14 +3676,14 @@ var duplexBinding = bindingHandlers.duplex = function (data, vmodels) {
|
|
3538
3676
|
params.push("string")
|
3539
3677
|
}
|
3540
3678
|
data.param = params.join("-")
|
3541
|
-
data.bound = function
|
3679
|
+
data.bound = function(type, callback) {
|
3542
3680
|
if (elem.addEventListener) {
|
3543
3681
|
elem.addEventListener(type, callback, false)
|
3544
3682
|
} else {
|
3545
3683
|
elem.attachEvent("on" + type, callback)
|
3546
3684
|
}
|
3547
3685
|
var old = data.rollback
|
3548
|
-
data.rollback = function
|
3686
|
+
data.rollback = function() {
|
3549
3687
|
elem.avalonSetter = null
|
3550
3688
|
avalon.unbind(elem, type, callback)
|
3551
3689
|
old && old()
|
@@ -3562,29 +3700,30 @@ var duplexBinding = bindingHandlers.duplex = function (data, vmodels) {
|
|
3562
3700
|
}
|
3563
3701
|
}
|
3564
3702
|
//不存在 bindingExecutors.duplex
|
3565
|
-
|
3566
|
-
|
3567
|
-
|
3703
|
+
|
3704
|
+
function fixNull(val) {
|
3705
|
+
return val == null ? "" : val
|
3706
|
+
}
|
3568
3707
|
avalon.duplexHooks = {
|
3569
3708
|
checked: {
|
3570
|
-
get: function
|
3709
|
+
get: function(val, data) {
|
3571
3710
|
return !data.element.oldValue
|
3572
3711
|
}
|
3573
3712
|
},
|
3574
3713
|
string: {
|
3575
|
-
get: function
|
3714
|
+
get: function(val) { //同步到VM
|
3576
3715
|
return val
|
3577
3716
|
},
|
3578
3717
|
set: fixNull
|
3579
3718
|
},
|
3580
3719
|
"boolean": {
|
3581
|
-
get: function
|
3720
|
+
get: function(val) {
|
3582
3721
|
return val === "true"
|
3583
3722
|
},
|
3584
3723
|
set: fixNull
|
3585
3724
|
},
|
3586
3725
|
number: {
|
3587
|
-
get: function
|
3726
|
+
get: function(val, data) {
|
3588
3727
|
var number = parseFloat(val)
|
3589
3728
|
if (-val === -number) {
|
3590
3729
|
return number
|
@@ -3604,7 +3743,7 @@ avalon.duplexHooks = {
|
|
3604
3743
|
}
|
3605
3744
|
|
3606
3745
|
function pipe(val, data, action, e) {
|
3607
|
-
data.param.replace(/\w+/g, function
|
3746
|
+
data.param.replace(/\w+/g, function(name) {
|
3608
3747
|
var hook = avalon.duplexHooks[name]
|
3609
3748
|
if (hook && typeof hook[action] === "function") {
|
3610
3749
|
val = hook[action](val, data)
|
@@ -3615,44 +3754,41 @@ function pipe(val, data, action, e) {
|
|
3615
3754
|
|
3616
3755
|
var TimerID, ribbon = []
|
3617
3756
|
|
3618
|
-
avalon.tick = function
|
3619
|
-
|
3620
|
-
|
3757
|
+
avalon.tick = function(fn) {
|
3758
|
+
if (ribbon.push(fn) === 1) {
|
3759
|
+
TimerID = setInterval(ticker, 60)
|
3760
|
+
}
|
3621
3761
|
}
|
3622
|
-
}
|
3623
3762
|
|
3624
|
-
function ticker() {
|
3625
|
-
|
3626
|
-
|
3627
|
-
|
3628
|
-
|
3763
|
+
function ticker() {
|
3764
|
+
for (var n = ribbon.length - 1; n >= 0; n--) {
|
3765
|
+
var el = ribbon[n]
|
3766
|
+
if (el() === false) {
|
3767
|
+
ribbon.splice(n, 1)
|
3768
|
+
}
|
3769
|
+
}
|
3770
|
+
if (!ribbon.length) {
|
3771
|
+
clearInterval(TimerID)
|
3629
3772
|
}
|
3630
3773
|
}
|
3631
|
-
if (!ribbon.length) {
|
3632
|
-
clearInterval(TimerID)
|
3633
|
-
}
|
3634
|
-
}
|
3635
3774
|
|
3636
3775
|
var watchValueInTimer = noop
|
3637
3776
|
var rmsinput = /text|password|hidden/
|
3638
|
-
new function
|
3639
|
-
try {//#272 IE9-IE11, firefox
|
3777
|
+
new function() { // jshint ignore:line
|
3778
|
+
try { //#272 IE9-IE11, firefox
|
3640
3779
|
var setters = {}
|
3641
3780
|
var aproto = HTMLInputElement.prototype
|
3642
3781
|
var bproto = HTMLTextAreaElement.prototype
|
3643
|
-
function newSetter(value) {// jshint ignore:line
|
3644
|
-
if (avalon.contains(root, this)) {
|
3782
|
+
function newSetter(value) { // jshint ignore:line
|
3645
3783
|
setters[this.tagName].call(this, value)
|
3646
|
-
if (
|
3647
|
-
return
|
3648
|
-
if (!this.msFocus && this.avalonSetter) {
|
3784
|
+
if (rmsinput.test(this.type) && !this.msFocus && this.avalonSetter) {
|
3649
3785
|
this.avalonSetter()
|
3650
3786
|
}
|
3651
|
-
}
|
3652
3787
|
}
|
3653
3788
|
var inputProto = HTMLInputElement.prototype
|
3654
3789
|
Object.getOwnPropertyNames(inputProto) //故意引发IE6-8等浏览器报错
|
3655
3790
|
setters["INPUT"] = Object.getOwnPropertyDescriptor(aproto, "value").set
|
3791
|
+
|
3656
3792
|
Object.defineProperty(aproto, "value", {
|
3657
3793
|
set: newSetter
|
3658
3794
|
})
|
@@ -3661,12 +3797,14 @@ new function () {// jshint ignore:line
|
|
3661
3797
|
set: newSetter
|
3662
3798
|
})
|
3663
3799
|
} catch (e) {
|
3800
|
+
//在chrome 43中 ms-duplex终于不需要使用定时器实现双向绑定了
|
3801
|
+
// http://updates.html5rocks.com/2015/04/DOM-attributes-now-on-the-prototype
|
3802
|
+
// https://docs.google.com/document/d/1jwA8mtClwxI-QJuHT7872Z0pxpZz8PBkf2bGAbsUtqs/edit?pli=1
|
3664
3803
|
watchValueInTimer = avalon.tick
|
3665
3804
|
}
|
3666
|
-
}// jshint ignore:line
|
3667
|
-
|
3805
|
+
} // jshint ignore:line
|
3668
3806
|
if (IEVersion) {
|
3669
|
-
avalon.bind(DOC, "selectionchange", function
|
3807
|
+
avalon.bind(DOC, "selectionchange", function(e) {
|
3670
3808
|
var el = DOC.activeElement
|
3671
3809
|
if (el && typeof el.avalonSetter === "function") {
|
3672
3810
|
el.avalonSetter()
|
@@ -3675,61 +3813,56 @@ if (IEVersion) {
|
|
3675
3813
|
}
|
3676
3814
|
|
3677
3815
|
//处理radio, checkbox, text, textarea, password
|
3678
|
-
duplexBinding.INPUT = function
|
3816
|
+
duplexBinding.INPUT = function(element, evaluator, data) {
|
3679
3817
|
var $type = element.type,
|
3680
|
-
|
3681
|
-
|
3682
|
-
|
3818
|
+
bound = data.bound,
|
3819
|
+
$elem = avalon(element),
|
3820
|
+
composing = false
|
3683
3821
|
|
3684
|
-
|
3685
|
-
|
3686
|
-
|
3822
|
+
function callback(value) {
|
3823
|
+
data.changed.call(this, value, data)
|
3824
|
+
}
|
3687
3825
|
|
3688
|
-
|
3689
|
-
|
3690
|
-
|
3826
|
+
function compositionStart() {
|
3827
|
+
composing = true
|
3828
|
+
}
|
3691
3829
|
|
3692
|
-
|
3693
|
-
|
3694
|
-
|
3695
|
-
|
3696
|
-
var updateVModel = function
|
3697
|
-
|
3830
|
+
function compositionEnd() {
|
3831
|
+
composing = false
|
3832
|
+
}
|
3833
|
+
//当value变化时改变model的值
|
3834
|
+
var updateVModel = function() {
|
3835
|
+
var val = element.value //防止递归调用形成死循环
|
3836
|
+
if (composing || val === element.oldValue) //处理中文输入法在minlengh下引发的BUG
|
3698
3837
|
return
|
3699
|
-
var val = element.oldValue = element.value //防止递归调用形成死循环
|
3700
3838
|
var lastValue = data.pipe(val, data, "get")
|
3701
|
-
if ($elem.data("
|
3839
|
+
if ($elem.data("duplexObserve") !== false) {
|
3702
3840
|
evaluator(lastValue)
|
3703
3841
|
callback.call(element, lastValue)
|
3704
|
-
if ($elem.data("duplex-focus")) {
|
3705
|
-
avalon.nextTick(function () {
|
3706
|
-
element.focus()
|
3707
|
-
})
|
3708
|
-
}
|
3709
3842
|
}
|
3710
3843
|
}
|
3711
3844
|
//当model变化时,它就会改变value的值
|
3712
|
-
data.handler = function
|
3713
|
-
var val = data.pipe(evaluator(), data, "set") +
|
3845
|
+
data.handler = function() {
|
3846
|
+
var val = data.pipe(evaluator(), data, "set") +"" //fix #673
|
3714
3847
|
if (val !== element.oldValue) {
|
3715
|
-
element.value = val
|
3848
|
+
element.value = element.oldValue = val
|
3716
3849
|
}
|
3717
3850
|
}
|
3718
3851
|
if (data.isChecked || $type === "radio") {
|
3719
3852
|
var IE6 = IEVersion === 6
|
3720
|
-
updateVModel = function
|
3721
|
-
if ($elem.data("
|
3853
|
+
updateVModel = function() {
|
3854
|
+
if ($elem.data("duplexObserve") !== false) {
|
3722
3855
|
var lastValue = data.pipe(element.value, data, "get")
|
3723
3856
|
evaluator(lastValue)
|
3724
3857
|
callback.call(element, lastValue)
|
3725
3858
|
}
|
3726
3859
|
}
|
3727
|
-
data.handler = function
|
3860
|
+
data.handler = function() {
|
3728
3861
|
var val = evaluator()
|
3729
|
-
var checked = data.isChecked ? !!val : val + "" === element.value
|
3862
|
+
var checked = data.isChecked ? !! val : val + "" === element.value
|
3730
3863
|
element.oldValue = checked
|
3731
3864
|
if (IE6) {
|
3732
|
-
setTimeout(function
|
3865
|
+
setTimeout(function() {
|
3733
3866
|
//IE8 checkbox, radio是使用defaultChecked控制选中状态,
|
3734
3867
|
//并且要先设置defaultChecked后设置checked
|
3735
3868
|
//并且必须设置延迟
|
@@ -3742,22 +3875,24 @@ duplexBinding.INPUT = function (element, evaluator, data) {
|
|
3742
3875
|
}
|
3743
3876
|
bound("click", updateVModel)
|
3744
3877
|
} else if ($type === "checkbox") {
|
3745
|
-
updateVModel = function
|
3746
|
-
if ($elem.data("
|
3878
|
+
updateVModel = function() {
|
3879
|
+
if ($elem.data("duplexObserve") !== false) {
|
3747
3880
|
var method = element.checked ? "ensure" : "remove"
|
3748
3881
|
var array = evaluator()
|
3749
3882
|
if (!Array.isArray(array)) {
|
3750
3883
|
log("ms-duplex应用于checkbox上要对应一个数组")
|
3751
3884
|
array = [array]
|
3752
3885
|
}
|
3753
|
-
|
3886
|
+
var val = data.pipe(element.value, data, "get")
|
3887
|
+
avalon.Array[method](array, val)
|
3754
3888
|
callback.call(element, array)
|
3755
3889
|
}
|
3756
3890
|
}
|
3757
3891
|
|
3758
|
-
data.handler = function
|
3892
|
+
data.handler = function() {
|
3759
3893
|
var array = [].concat(evaluator()) //强制转换为数组
|
3760
|
-
|
3894
|
+
var val = data.pipe(element.value, data, "get")
|
3895
|
+
element.checked = array.indexOf(val) > -1
|
3761
3896
|
}
|
3762
3897
|
bound(W3C ? "change" : "click", updateVModel)
|
3763
3898
|
} else {
|
@@ -3765,12 +3900,13 @@ duplexBinding.INPUT = function (element, evaluator, data) {
|
|
3765
3900
|
if (element.attributes["data-event"]) {
|
3766
3901
|
log("data-event指令已经废弃,请改用data-duplex-event")
|
3767
3902
|
}
|
3768
|
-
|
3769
|
-
|
3903
|
+
|
3904
|
+
function delay(e) { // jshint ignore:line
|
3905
|
+
setTimeout(function() {
|
3770
3906
|
updateVModel(e)
|
3771
3907
|
})
|
3772
3908
|
}
|
3773
|
-
events.replace(rword, function
|
3909
|
+
events.replace(rword, function(name) {
|
3774
3910
|
switch (name) {
|
3775
3911
|
case "input":
|
3776
3912
|
if (!IEVersion) { // W3C
|
@@ -3782,9 +3918,9 @@ duplexBinding.INPUT = function (element, evaluator, data) {
|
|
3782
3918
|
} else { //onpropertychange事件无法区分是程序触发还是用户触发
|
3783
3919
|
// IE下通过selectionchange事件监听IE9+点击input右边的X的清空行为,及粘贴,剪切,删除行为
|
3784
3920
|
if (IEVersion > 8) {
|
3785
|
-
bound("input", updateVModel)//IE9使用propertychange无法监听中文输入改动
|
3921
|
+
bound("input", updateVModel) //IE9使用propertychange无法监听中文输入改动
|
3786
3922
|
} else {
|
3787
|
-
bound("propertychange", function
|
3923
|
+
bound("propertychange", function(e) { //IE6-8下第一次修改时不会触发,需要使用keydown或selectionchange修正
|
3788
3924
|
if (e.propertyName === "value") {
|
3789
3925
|
updateVModel()
|
3790
3926
|
}
|
@@ -3800,15 +3936,15 @@ duplexBinding.INPUT = function (element, evaluator, data) {
|
|
3800
3936
|
break
|
3801
3937
|
}
|
3802
3938
|
})
|
3803
|
-
bound("focus", function
|
3939
|
+
bound("focus", function() {
|
3804
3940
|
element.msFocus = true
|
3805
3941
|
})
|
3806
|
-
bound("blur", function
|
3942
|
+
bound("blur", function() {
|
3807
3943
|
element.msFocus = false
|
3808
3944
|
})
|
3809
3945
|
|
3810
3946
|
if (rmsinput.test($type)) {
|
3811
|
-
watchValueInTimer(function
|
3947
|
+
watchValueInTimer(function() {
|
3812
3948
|
if (root.contains(element)) {
|
3813
3949
|
if (!element.msFocus && element.oldValue !== element.value) {
|
3814
3950
|
updateVModel()
|
@@ -3819,34 +3955,33 @@ duplexBinding.INPUT = function (element, evaluator, data) {
|
|
3819
3955
|
})
|
3820
3956
|
}
|
3821
3957
|
|
3822
|
-
element.avalonSetter = updateVModel//#765
|
3958
|
+
element.avalonSetter = updateVModel //#765
|
3823
3959
|
}
|
3824
3960
|
|
3825
3961
|
element.oldValue = element.value
|
3826
|
-
|
3962
|
+
avalon.injectBinding(data)
|
3827
3963
|
callback.call(element, element.value)
|
3828
3964
|
}
|
3829
3965
|
duplexBinding.TEXTAREA = duplexBinding.INPUT
|
3830
|
-
|
3831
|
-
|
3832
3966
|
duplexBinding.SELECT = function(element, evaluator, data) {
|
3833
3967
|
var $elem = avalon(element)
|
3834
|
-
|
3835
|
-
|
3836
|
-
|
3837
|
-
|
3838
|
-
|
3839
|
-
|
3840
|
-
|
3841
|
-
|
3842
|
-
|
3843
|
-
|
3844
|
-
|
3845
|
-
|
3968
|
+
|
3969
|
+
function updateVModel() {
|
3970
|
+
if ($elem.data("duplexObserve") !== false) {
|
3971
|
+
var val = $elem.val() //字符串或字符串数组
|
3972
|
+
if (Array.isArray(val)) {
|
3973
|
+
val = val.map(function(v) {
|
3974
|
+
return data.pipe(v, data, "get")
|
3975
|
+
})
|
3976
|
+
} else {
|
3977
|
+
val = data.pipe(val, data, "get")
|
3978
|
+
}
|
3979
|
+
if (val + "" !== element.oldValue) {
|
3980
|
+
evaluator(val)
|
3981
|
+
}
|
3982
|
+
data.changed.call(element, val, data)
|
3846
3983
|
}
|
3847
|
-
data.changed.call(element, val, data)
|
3848
3984
|
}
|
3849
|
-
}
|
3850
3985
|
data.handler = function() {
|
3851
3986
|
var val = evaluator()
|
3852
3987
|
val = val && val.$model || val
|
@@ -3867,74 +4002,77 @@ duplexBinding.SELECT = function(element, evaluator, data) {
|
|
3867
4002
|
}
|
3868
4003
|
}
|
3869
4004
|
data.bound("change", updateVModel)
|
3870
|
-
|
3871
|
-
|
4005
|
+
element.msCallback = function() {
|
4006
|
+
avalon.injectBinding(data)
|
3872
4007
|
data.changed.call(element, evaluator(), data)
|
3873
|
-
}
|
4008
|
+
}
|
3874
4009
|
}
|
3875
|
-
|
3876
|
-
|
3877
4010
|
// bindingHandlers.html 定义在if.js
|
3878
|
-
bindingExecutors.html = function(val, elem, data) {
|
3879
|
-
|
3880
|
-
var isHtmlFilter = "group" in data
|
4011
|
+
bindingExecutors.html = function (val, elem, data) {
|
4012
|
+
var isHtmlFilter = elem.nodeType !== 1
|
3881
4013
|
var parent = isHtmlFilter ? elem.parentNode : elem
|
3882
4014
|
if (!parent)
|
3883
4015
|
return
|
3884
|
-
|
3885
|
-
|
4016
|
+
val = val == null ? "" : val
|
4017
|
+
if (data.oldText !== val) {
|
4018
|
+
data.oldText = val
|
4019
|
+
} else {
|
4020
|
+
return
|
4021
|
+
}
|
4022
|
+
if (elem.nodeType === 3) {
|
4023
|
+
var signature = generateID("html")
|
4024
|
+
parent.insertBefore(DOC.createComment(signature), elem)
|
4025
|
+
data.element = DOC.createComment(signature + ":end")
|
4026
|
+
parent.replaceChild(data.element, elem)
|
4027
|
+
elem = data.element
|
4028
|
+
}
|
4029
|
+
if (typeof val !== "object") {//string, number, boolean
|
4030
|
+
var fragment = avalon.parseHTML(String(val))
|
4031
|
+
} else if (val.nodeType === 11) { //将val转换为文档碎片
|
4032
|
+
fragment = val
|
3886
4033
|
} else if (val.nodeType === 1 || val.item) {
|
3887
|
-
var nodes = val.nodeType === 1 ? val.childNodes : val.item
|
3888
|
-
fragment =
|
4034
|
+
var nodes = val.nodeType === 1 ? val.childNodes : val.item
|
4035
|
+
fragment = avalonFragment.cloneNode(true)
|
3889
4036
|
while (nodes[0]) {
|
3890
4037
|
fragment.appendChild(nodes[0])
|
3891
4038
|
}
|
3892
|
-
} else {
|
3893
|
-
fragment = avalon.parseHTML(val)
|
3894
4039
|
}
|
4040
|
+
|
4041
|
+
nodes = avalon.slice(fragment.childNodes)
|
3895
4042
|
//插入占位符, 如果是过滤器,需要有节制地移除指定的数量,如果是html指令,直接清空
|
3896
|
-
var comment = DOC.createComment("ms-html")
|
3897
4043
|
if (isHtmlFilter) {
|
3898
|
-
|
3899
|
-
|
3900
|
-
|
3901
|
-
|
3902
|
-
|
4044
|
+
var endValue = elem.nodeValue.slice(0, -4)
|
4045
|
+
while (true) {
|
4046
|
+
var node = elem.previousSibling
|
4047
|
+
if (!node || node.nodeType === 8 && node.nodeValue === endValue) {
|
4048
|
+
break
|
4049
|
+
} else {
|
3903
4050
|
parent.removeChild(node)
|
3904
|
-
i++
|
3905
4051
|
}
|
3906
4052
|
}
|
3907
|
-
parent.
|
3908
|
-
data.element = comment //防止被CG
|
4053
|
+
parent.insertBefore(fragment, elem)
|
3909
4054
|
} else {
|
3910
|
-
avalon.clearHTML(
|
3911
|
-
}
|
3912
|
-
if (isHtmlFilter) {
|
3913
|
-
data.group = fragment.childNodes.length || 1
|
3914
|
-
}
|
3915
|
-
nodes = avalon.slice(fragment.childNodes)
|
3916
|
-
if (nodes[0]) {
|
3917
|
-
if (comment.parentNode)
|
3918
|
-
comment.parentNode.replaceChild(fragment, comment)
|
3919
|
-
if (isHtmlFilter) {
|
3920
|
-
data.element = nodes[0]
|
3921
|
-
}
|
4055
|
+
avalon.clearHTML(elem).appendChild(fragment)
|
3922
4056
|
}
|
3923
4057
|
scanNodeArray(nodes, data.vmodels)
|
3924
4058
|
}
|
3925
|
-
|
3926
4059
|
bindingHandlers["if"] =
|
3927
|
-
|
3928
|
-
|
3929
|
-
|
3930
|
-
|
3931
|
-
|
3932
|
-
|
4060
|
+
bindingHandlers.data =
|
4061
|
+
bindingHandlers.text =
|
4062
|
+
bindingHandlers.html =
|
4063
|
+
function(data, vmodels) {
|
4064
|
+
parseExprProxy(data.value, vmodels, data)
|
4065
|
+
}
|
3933
4066
|
|
3934
4067
|
bindingExecutors["if"] = function(val, elem, data) {
|
4068
|
+
try {
|
4069
|
+
if(!elem.parentNode) return
|
4070
|
+
} catch(e) {return}
|
3935
4071
|
if (val) { //插回DOM树
|
3936
4072
|
if (elem.nodeType === 8) {
|
3937
4073
|
elem.parentNode.replaceChild(data.template, elem)
|
4074
|
+
elem.ifRemove = null
|
4075
|
+
// animate.enter(data.template, elem.parentNode)
|
3938
4076
|
elem = data.element = data.template //这时可能为null
|
3939
4077
|
}
|
3940
4078
|
if (elem.getAttribute(data.name)) {
|
@@ -3946,6 +4084,8 @@ bindingExecutors["if"] = function(val, elem, data) {
|
|
3946
4084
|
if (elem.nodeType === 1) {
|
3947
4085
|
var node = data.element = DOC.createComment("ms-if")
|
3948
4086
|
elem.parentNode.replaceChild(node, elem)
|
4087
|
+
elem.ifRemove = node
|
4088
|
+
// animate.leave(elem, node.parentNode, node)
|
3949
4089
|
data.template = elem //元素节点
|
3950
4090
|
ifGroup.appendChild(elem)
|
3951
4091
|
data.rollback = function() {
|
@@ -3956,8 +4096,6 @@ bindingExecutors["if"] = function(val, elem, data) {
|
|
3956
4096
|
}
|
3957
4097
|
}
|
3958
4098
|
}
|
3959
|
-
|
3960
|
-
|
3961
4099
|
//ms-important绑定已经在scanTag 方法中实现
|
3962
4100
|
//ms-include绑定已由ms-attr绑定实现
|
3963
4101
|
|
@@ -4001,11 +4139,9 @@ bindingExecutors.on = function(callback, elem, data) {
|
|
4001
4139
|
}
|
4002
4140
|
}
|
4003
4141
|
}
|
4004
|
-
|
4005
|
-
|
4006
|
-
bindingHandlers.repeat = function(data, vmodels) {
|
4142
|
+
bindingHandlers.repeat = function (data, vmodels) {
|
4007
4143
|
var type = data.type
|
4008
|
-
parseExprProxy(data.value, vmodels, data,
|
4144
|
+
parseExprProxy(data.value, vmodels, data, 1)
|
4009
4145
|
data.proxies = []
|
4010
4146
|
var freturn = false
|
4011
4147
|
try {
|
@@ -4014,11 +4150,12 @@ bindingHandlers.repeat = function(data, vmodels) {
|
|
4014
4150
|
if (xtype !== "object" && xtype !== "array") {
|
4015
4151
|
freturn = true
|
4016
4152
|
avalon.log("warning:" + data.value + "只能是对象或数组")
|
4153
|
+
} else {
|
4154
|
+
data.xtype = xtype
|
4017
4155
|
}
|
4018
4156
|
} catch (e) {
|
4019
4157
|
freturn = true
|
4020
4158
|
}
|
4021
|
-
|
4022
4159
|
var arr = data.value.split(".") || []
|
4023
4160
|
if (arr.length > 1) {
|
4024
4161
|
arr.pop()
|
@@ -4032,41 +4169,43 @@ bindingHandlers.repeat = function(data, vmodels) {
|
|
4032
4169
|
}
|
4033
4170
|
}
|
4034
4171
|
}
|
4172
|
+
|
4035
4173
|
var elem = data.element
|
4036
|
-
elem.
|
4037
|
-
|
4038
|
-
|
4039
|
-
|
4040
|
-
|
4041
|
-
|
4042
|
-
|
4043
|
-
|
4044
|
-
|
4045
|
-
|
4046
|
-
|
4047
|
-
|
4048
|
-
|
4049
|
-
|
4050
|
-
|
4051
|
-
|
4052
|
-
|
4053
|
-
|
4054
|
-
|
4055
|
-
|
4056
|
-
|
4057
|
-
|
4058
|
-
|
4059
|
-
|
4060
|
-
|
4061
|
-
|
4062
|
-
|
4063
|
-
|
4064
|
-
|
4174
|
+
if (elem.nodeType === 1) {
|
4175
|
+
elem.removeAttribute(data.name)
|
4176
|
+
data.sortedCallback = getBindingCallback(elem, "data-with-sorted", vmodels)
|
4177
|
+
data.renderedCallback = getBindingCallback(elem, "data-" + type + "-rendered", vmodels)
|
4178
|
+
var signature = generateID(type)
|
4179
|
+
var start = DOC.createComment(signature)
|
4180
|
+
var end = DOC.createComment(signature + ":end")
|
4181
|
+
data.signature = signature
|
4182
|
+
data.template = avalonFragment.cloneNode(false)
|
4183
|
+
if (type === "repeat") {
|
4184
|
+
var parent = elem.parentNode
|
4185
|
+
parent.replaceChild(end, elem)
|
4186
|
+
parent.insertBefore(start, end)
|
4187
|
+
data.template.appendChild(elem)
|
4188
|
+
} else {
|
4189
|
+
while (elem.firstChild) {
|
4190
|
+
data.template.appendChild(elem.firstChild)
|
4191
|
+
}
|
4192
|
+
elem.appendChild(start)
|
4193
|
+
elem.appendChild(end)
|
4194
|
+
}
|
4195
|
+
data.element = end
|
4196
|
+
data.handler = bindingExecutors.repeat
|
4197
|
+
data.rollback = function () {
|
4198
|
+
var elem = data.element
|
4199
|
+
if (!elem)
|
4200
|
+
return
|
4201
|
+
data.handler("clear")
|
4202
|
+
}
|
4065
4203
|
}
|
4204
|
+
|
4066
4205
|
if (freturn) {
|
4067
4206
|
return
|
4068
4207
|
}
|
4069
|
-
|
4208
|
+
|
4070
4209
|
data.$outer = {}
|
4071
4210
|
var check0 = "$key"
|
4072
4211
|
var check1 = "$val"
|
@@ -4074,6 +4213,7 @@ bindingHandlers.repeat = function(data, vmodels) {
|
|
4074
4213
|
check0 = "$first"
|
4075
4214
|
check1 = "$last"
|
4076
4215
|
}
|
4216
|
+
|
4077
4217
|
for (i = 0; v = vmodels[i++]; ) {
|
4078
4218
|
if (v.hasOwnProperty(check0) && v.hasOwnProperty(check1)) {
|
4079
4219
|
data.$outer = v
|
@@ -4082,81 +4222,101 @@ bindingHandlers.repeat = function(data, vmodels) {
|
|
4082
4222
|
}
|
4083
4223
|
var $events = $repeat.$events
|
4084
4224
|
var $list = ($events || {})[subscribers]
|
4085
|
-
|
4086
|
-
addSubscribers(data, $list)
|
4087
|
-
}
|
4225
|
+
injectDependency($list, data)
|
4088
4226
|
if (xtype === "object") {
|
4089
|
-
data
|
4090
|
-
var pool = !$events ? {} : $events.$withProxyPool || ($events.$withProxyPool = {})
|
4091
|
-
data.handler("append", $repeat, pool)
|
4227
|
+
data.handler("append")
|
4092
4228
|
} else if ($repeat.length) {
|
4093
4229
|
data.handler("add", 0, $repeat.length)
|
4094
4230
|
}
|
4095
4231
|
}
|
4096
4232
|
|
4097
|
-
bindingExecutors.repeat = function(method, pos, el) {
|
4233
|
+
bindingExecutors.repeat = function (method, pos, el) {
|
4234
|
+
var data = this
|
4235
|
+
if (!method && data.xtype) {
|
4236
|
+
var old = data.$repeat
|
4237
|
+
var neo = data.evaluator.apply(0, data.args || [])
|
4238
|
+
|
4239
|
+
if (data.xtype === "array") {
|
4240
|
+
if (old.length === neo.length) {
|
4241
|
+
return
|
4242
|
+
}
|
4243
|
+
method = "add"
|
4244
|
+
pos = 0
|
4245
|
+
data.$repeat = neo
|
4246
|
+
el = neo.length
|
4247
|
+
} else {
|
4248
|
+
if (keysVM(old).join(";;") === keysVM(neo).join(";;")) {
|
4249
|
+
return
|
4250
|
+
}
|
4251
|
+
method = "append"
|
4252
|
+
data.$repeat = neo
|
4253
|
+
}
|
4254
|
+
}
|
4098
4255
|
if (method) {
|
4099
|
-
var
|
4256
|
+
var start, fragment
|
4100
4257
|
var end = data.element
|
4258
|
+
var comments = getComments(data)
|
4101
4259
|
var parent = end.parentNode
|
4102
4260
|
var proxies = data.proxies
|
4103
|
-
var transation =
|
4261
|
+
var transation = avalonFragment.cloneNode(false)
|
4104
4262
|
switch (method) {
|
4105
|
-
case "add": //在pos位置后添加el数组(pos
|
4263
|
+
case "add": //在pos位置后添加el数组(pos为插入位置,el为要插入的个数)
|
4106
4264
|
var n = pos + el
|
4107
|
-
var
|
4108
|
-
var last = array.length - 1
|
4109
|
-
var fragments = [], fragment
|
4110
|
-
var start = locateNode(data, pos)
|
4265
|
+
var fragments = []
|
4111
4266
|
for (var i = pos; i < n; i++) {
|
4112
4267
|
var proxy = eachProxyAgent(i, data)
|
4113
4268
|
proxies.splice(i, 0, proxy)
|
4114
4269
|
shimController(data, transation, proxy, fragments)
|
4115
4270
|
}
|
4116
|
-
parent.insertBefore(transation,
|
4271
|
+
parent.insertBefore(transation, comments[pos] || end)
|
4117
4272
|
for (i = 0; fragment = fragments[i++]; ) {
|
4118
4273
|
scanNodeArray(fragment.nodes, fragment.vmodels)
|
4119
4274
|
fragment.nodes = fragment.vmodels = null
|
4120
4275
|
}
|
4276
|
+
|
4121
4277
|
break
|
4122
4278
|
case "del": //将pos后的el个元素删掉(pos, el都是数字)
|
4123
|
-
|
4124
|
-
end = locateNode(data, pos + el)
|
4125
|
-
sweepNodes(start, end)
|
4279
|
+
sweepNodes(comments[pos], comments[pos + el] || end)
|
4126
4280
|
var removed = proxies.splice(pos, el)
|
4127
4281
|
recycleProxies(removed, "each")
|
4128
4282
|
break
|
4129
4283
|
case "clear":
|
4130
|
-
|
4131
|
-
if (
|
4132
|
-
start = check.$stamp || check
|
4284
|
+
start = comments[0]
|
4285
|
+
if (start) {
|
4133
4286
|
sweepNodes(start, end)
|
4287
|
+
if (data.xtype === "object") {
|
4288
|
+
parent.insertBefore(start, end)
|
4289
|
+
}else{
|
4290
|
+
recycleProxies(proxies, "each")
|
4291
|
+
}
|
4134
4292
|
}
|
4135
|
-
recycleProxies(proxies, "each")
|
4136
4293
|
break
|
4137
4294
|
case "move":
|
4138
|
-
start =
|
4139
|
-
|
4140
|
-
|
4141
|
-
|
4142
|
-
|
4143
|
-
|
4144
|
-
|
4145
|
-
|
4146
|
-
|
4147
|
-
|
4148
|
-
|
4149
|
-
|
4150
|
-
|
4151
|
-
|
4152
|
-
|
4153
|
-
|
4295
|
+
start = comments[0]
|
4296
|
+
if (start) {
|
4297
|
+
var signature = start.nodeValue
|
4298
|
+
var rooms = []
|
4299
|
+
var room = [],
|
4300
|
+
node
|
4301
|
+
sweepNodes(start, end, function () {
|
4302
|
+
room.unshift(this)
|
4303
|
+
if (this.nodeValue === signature) {
|
4304
|
+
rooms.unshift(room)
|
4305
|
+
room = []
|
4306
|
+
}
|
4307
|
+
})
|
4308
|
+
sortByIndex(rooms, pos)
|
4309
|
+
sortByIndex(proxies, pos)
|
4310
|
+
while (room = rooms.shift()) {
|
4311
|
+
while (node = room.shift()) {
|
4312
|
+
transation.appendChild(node)
|
4313
|
+
}
|
4154
4314
|
}
|
4315
|
+
parent.insertBefore(transation, end)
|
4155
4316
|
}
|
4156
|
-
parent.insertBefore(transation, end)
|
4157
4317
|
break
|
4158
4318
|
case "index": //将proxies中的第pos个起的所有元素重新索引
|
4159
|
-
last = proxies.length - 1
|
4319
|
+
var last = proxies.length - 1
|
4160
4320
|
for (; el = proxies[pos]; pos++) {
|
4161
4321
|
el.$index = pos
|
4162
4322
|
el.$first = pos === 0
|
@@ -4166,15 +4326,23 @@ bindingExecutors.repeat = function(method, pos, el) {
|
|
4166
4326
|
case "set": //将proxies中的第pos个元素的VM设置为el(pos为数字,el任意)
|
4167
4327
|
proxy = proxies[pos]
|
4168
4328
|
if (proxy) {
|
4169
|
-
|
4329
|
+
fireDependencies(proxy.$events[data.param || "el"])
|
4170
4330
|
}
|
4171
|
-
|
4172
|
-
case "append":
|
4173
|
-
var
|
4331
|
+
break
|
4332
|
+
case "append":
|
4333
|
+
var object = data.$repeat //原来第2参数, 被循环对象
|
4334
|
+
var pool = Array.isArray(proxies) ||!proxies ? {}: proxies //代理对象组成的hash
|
4335
|
+
data.proxies = pool
|
4174
4336
|
var keys = []
|
4175
4337
|
fragments = []
|
4176
|
-
for (var key in
|
4177
|
-
if (
|
4338
|
+
for (var key in pool) {
|
4339
|
+
if (!object.hasOwnProperty(key)) {
|
4340
|
+
proxyRecycler(pool[key], withProxyPool) //去掉之前的代理VM
|
4341
|
+
delete(pool[key])
|
4342
|
+
}
|
4343
|
+
}
|
4344
|
+
for (key in object) { //得到所有键名
|
4345
|
+
if (object.hasOwnProperty(key) && key !== "hasOwnProperty") {
|
4178
4346
|
keys.push(key)
|
4179
4347
|
}
|
4180
4348
|
}
|
@@ -4186,14 +4354,11 @@ bindingExecutors.repeat = function(method, pos, el) {
|
|
4186
4354
|
}
|
4187
4355
|
for (i = 0; key = keys[i++]; ) {
|
4188
4356
|
if (key !== "hasOwnProperty") {
|
4189
|
-
|
4190
|
-
pool[key] = withProxyAgent(key, data)
|
4191
|
-
}
|
4357
|
+
pool[key] = withProxyAgent(pool[key], key, data)
|
4192
4358
|
shimController(data, transation, pool[key], fragments)
|
4193
4359
|
}
|
4194
4360
|
}
|
4195
|
-
|
4196
|
-
parent.insertBefore(comment, end)
|
4361
|
+
|
4197
4362
|
parent.insertBefore(transation, end)
|
4198
4363
|
for (i = 0; fragment = fragments[i++]; ) {
|
4199
4364
|
scanNodeArray(fragment.nodes, fragment.vmodels)
|
@@ -4201,29 +4366,26 @@ bindingExecutors.repeat = function(method, pos, el) {
|
|
4201
4366
|
}
|
4202
4367
|
break
|
4203
4368
|
}
|
4369
|
+
if (!data.$repeat || data.$repeat.hasOwnProperty("$lock")) //IE6-8 VBScript对象会报错, 有时候data.$repeat不存在
|
4370
|
+
return
|
4204
4371
|
if (method === "clear")
|
4205
4372
|
method = "del"
|
4206
4373
|
var callback = data.renderedCallback || noop,
|
4207
4374
|
args = arguments
|
4208
|
-
|
4209
|
-
|
4210
|
-
|
4211
|
-
|
4212
|
-
}
|
4213
|
-
}, NaN)
|
4375
|
+
if (parent.oldValue && parent.tagName === "SELECT") { //fix #503
|
4376
|
+
avalon(parent).val(parent.oldValue.split(","))
|
4377
|
+
}
|
4378
|
+
callback.apply(parent, args)
|
4214
4379
|
}
|
4215
4380
|
}
|
4216
|
-
|
4217
|
-
"with,each".replace(rword, function(name) {
|
4381
|
+
"with,each".replace(rword, function (name) {
|
4218
4382
|
bindingHandlers[name] = bindingHandlers.repeat
|
4219
4383
|
})
|
4220
4384
|
|
4221
4385
|
function shimController(data, transation, proxy, fragments) {
|
4222
4386
|
var content = data.template.cloneNode(true)
|
4223
4387
|
var nodes = avalon.slice(content.childNodes)
|
4224
|
-
|
4225
|
-
content.insertBefore(proxy.$stamp, content.firstChild)
|
4226
|
-
}
|
4388
|
+
content.insertBefore(DOC.createComment(data.signature), content.firstChild)
|
4227
4389
|
transation.appendChild(content)
|
4228
4390
|
var nv = [proxy].concat(data.vmodels)
|
4229
4391
|
var fragment = {
|
@@ -4233,11 +4395,21 @@ function shimController(data, transation, proxy, fragments) {
|
|
4233
4395
|
fragments.push(fragment)
|
4234
4396
|
}
|
4235
4397
|
|
4236
|
-
function
|
4237
|
-
var
|
4238
|
-
|
4398
|
+
function getComments(data) {
|
4399
|
+
var ret = []
|
4400
|
+
var nodes = data.element.parentNode.childNodes
|
4401
|
+
for (var i = 0, node; node = nodes[i++]; ) {
|
4402
|
+
if (node.nodeValue === data.signature) {
|
4403
|
+
ret.push(node)
|
4404
|
+
} else if (node.nodeValue === data.signature + ":end") {
|
4405
|
+
break
|
4406
|
+
}
|
4407
|
+
}
|
4408
|
+
return ret
|
4239
4409
|
}
|
4240
4410
|
|
4411
|
+
|
4412
|
+
//移除掉start与end之间的节点(保留end)
|
4241
4413
|
function sweepNodes(start, end, callback) {
|
4242
4414
|
while (true) {
|
4243
4415
|
var node = end.previousSibling
|
@@ -4254,24 +4426,89 @@ function sweepNodes(start, end, callback) {
|
|
4254
4426
|
// 为ms-each,ms-with, ms-repeat会创建一个代理VM,
|
4255
4427
|
// 通过它们保持一个下上文,让用户能调用$index,$first,$last,$remove,$key,$val,$outer等属性与方法
|
4256
4428
|
// 所有代理VM的产生,消费,收集,存放通过xxxProxyFactory,xxxProxyAgent, recycleProxies,xxxProxyPool实现
|
4257
|
-
var eachProxyPool = []
|
4258
4429
|
var withProxyPool = []
|
4430
|
+
function withProxyFactory() {
|
4431
|
+
var proxy = modelFactory({
|
4432
|
+
$key: "",
|
4433
|
+
$outer: {},
|
4434
|
+
$host: {},
|
4435
|
+
$val: {
|
4436
|
+
get: function () {
|
4437
|
+
return this.$host[this.$key]
|
4438
|
+
},
|
4439
|
+
set: function (val) {
|
4440
|
+
this.$host[this.$key] = val
|
4441
|
+
}
|
4442
|
+
}
|
4443
|
+
}, {
|
4444
|
+
$val: 1
|
4445
|
+
})
|
4446
|
+
proxy.$id = generateID("$proxy$with")
|
4447
|
+
return proxy
|
4448
|
+
}
|
4449
|
+
|
4450
|
+
function withProxyAgent(proxy, key, data) {
|
4451
|
+
proxy = proxy || withProxyPool.pop()
|
4452
|
+
if (!proxy) {
|
4453
|
+
proxy = withProxyFactory()
|
4454
|
+
} else {
|
4455
|
+
proxy.$reinitialize()
|
4456
|
+
}
|
4457
|
+
var host = data.$repeat
|
4458
|
+
proxy.$key = key
|
4459
|
+
|
4460
|
+
proxy.$host = host
|
4461
|
+
proxy.$outer = data.$outer
|
4462
|
+
if (host.$events) {
|
4463
|
+
proxy.$events.$val = host.$events[key]
|
4464
|
+
} else {
|
4465
|
+
proxy.$events = {}
|
4466
|
+
}
|
4467
|
+
return proxy
|
4468
|
+
}
|
4469
|
+
|
4470
|
+
|
4471
|
+
function recycleProxies(proxies) {
|
4472
|
+
eachProxyRecycler(proxies)
|
4473
|
+
}
|
4474
|
+
function eachProxyRecycler(proxies) {
|
4475
|
+
proxies.forEach(function (proxy) {
|
4476
|
+
proxyRecycler(proxy, eachProxyPool)
|
4477
|
+
})
|
4478
|
+
proxies.length = 0
|
4479
|
+
}
|
4480
|
+
|
4481
|
+
|
4482
|
+
var eachProxyPool = []
|
4259
4483
|
function eachProxyFactory(name) {
|
4260
4484
|
var source = {
|
4261
4485
|
$host: [],
|
4262
4486
|
$outer: {},
|
4263
|
-
$stamp: 1,
|
4264
4487
|
$index: 0,
|
4265
4488
|
$first: false,
|
4266
4489
|
$last: false,
|
4267
4490
|
$remove: avalon.noop
|
4268
4491
|
}
|
4269
4492
|
source[name] = {
|
4270
|
-
get: function() {
|
4271
|
-
|
4493
|
+
get: function () {
|
4494
|
+
var e = this.$events
|
4495
|
+
var array = e.$index
|
4496
|
+
e.$index = e[name] //#817 通过$index为el收集依赖
|
4497
|
+
try {
|
4498
|
+
return this.$host[this.$index]
|
4499
|
+
} finally {
|
4500
|
+
e.$index = array
|
4501
|
+
}
|
4272
4502
|
},
|
4273
|
-
set: function(val) {
|
4274
|
-
|
4503
|
+
set: function (val) {
|
4504
|
+
try {
|
4505
|
+
var e = this.$events
|
4506
|
+
var array = e.$index
|
4507
|
+
e.$index = []
|
4508
|
+
this.$host.set(this.$index, val)
|
4509
|
+
} finally {
|
4510
|
+
e.$index = array
|
4511
|
+
}
|
4275
4512
|
}
|
4276
4513
|
}
|
4277
4514
|
var second = {
|
@@ -4280,14 +4517,13 @@ function eachProxyFactory(name) {
|
|
4280
4517
|
$index: 1
|
4281
4518
|
}
|
4282
4519
|
var proxy = modelFactory(source, second)
|
4283
|
-
var e = proxy.$events
|
4284
|
-
e[name] = e.$first = e.$last = e.$index
|
4285
4520
|
proxy.$id = generateID("$proxy$each")
|
4286
4521
|
return proxy
|
4287
4522
|
}
|
4288
4523
|
|
4289
4524
|
function eachProxyAgent(index, data) {
|
4290
|
-
var param = data.param || "el",
|
4525
|
+
var param = data.param || "el",
|
4526
|
+
proxy
|
4291
4527
|
for (var i = 0, n = eachProxyPool.length; i < n; i++) {
|
4292
4528
|
var candidate = eachProxyPool[i]
|
4293
4529
|
if (candidate && candidate.hasOwnProperty(param)) {
|
@@ -4305,76 +4541,30 @@ function eachProxyAgent(index, data) {
|
|
4305
4541
|
proxy.$last = index === last
|
4306
4542
|
proxy.$host = host
|
4307
4543
|
proxy.$outer = data.$outer
|
4308
|
-
proxy.$
|
4309
|
-
proxy.$remove = function() {
|
4544
|
+
proxy.$remove = function () {
|
4310
4545
|
return host.removeAt(proxy.$index)
|
4311
4546
|
}
|
4312
4547
|
return proxy
|
4313
4548
|
}
|
4314
4549
|
|
4315
|
-
function withProxyFactory() {
|
4316
|
-
var proxy = modelFactory({
|
4317
|
-
$key: "",
|
4318
|
-
$outer: {},
|
4319
|
-
$host: {},
|
4320
|
-
$val: {
|
4321
|
-
get: function() {
|
4322
|
-
return this.$host[this.$key]
|
4323
|
-
},
|
4324
|
-
set: function(val) {
|
4325
|
-
this.$host[this.$key] = val
|
4326
|
-
}
|
4327
|
-
}
|
4328
|
-
}, {
|
4329
|
-
$val: 1
|
4330
|
-
})
|
4331
|
-
proxy.$id = generateID("$proxy$with")
|
4332
|
-
return proxy
|
4333
|
-
}
|
4334
4550
|
|
4335
|
-
function
|
4336
|
-
var
|
4337
|
-
|
4338
|
-
|
4551
|
+
function proxyRecycler(proxy, proxyPool) {
|
4552
|
+
for (var i in proxy.$events) {
|
4553
|
+
var arr = proxy.$events[i]
|
4554
|
+
if (Array.isArray(arr)) {
|
4555
|
+
arr.forEach(function (data) {
|
4556
|
+
if (typeof data === "object")
|
4557
|
+
disposeData(data)
|
4558
|
+
})// jshint ignore:line
|
4559
|
+
arr.length = 0
|
4560
|
+
}
|
4339
4561
|
}
|
4340
|
-
|
4341
|
-
proxy
|
4342
|
-
|
4343
|
-
proxy.$outer = data.$outer
|
4344
|
-
if (host.$events) {
|
4345
|
-
proxy.$events.$val = host.$events[key]
|
4346
|
-
} else {
|
4347
|
-
proxy.$events = {}
|
4562
|
+
proxy.$host = proxy.$outer = {}
|
4563
|
+
if (proxyPool.unshift(proxy) > kernel.maxRepeatSize) {
|
4564
|
+
proxyPool.pop()
|
4348
4565
|
}
|
4349
|
-
return proxy
|
4350
|
-
}
|
4351
|
-
|
4352
|
-
function recycleProxies(proxies, type) {
|
4353
|
-
var proxyPool = type === "each" ? eachProxyPool : withProxyPool
|
4354
|
-
avalon.each(proxies, function(key, proxy) {
|
4355
|
-
if (proxy.$events) {
|
4356
|
-
for (var i in proxy.$events) {
|
4357
|
-
if (Array.isArray(proxy.$events[i])) {
|
4358
|
-
proxy.$events[i].forEach(function(data) {
|
4359
|
-
if (typeof data === "object")
|
4360
|
-
disposeData(data)
|
4361
|
-
})// jshint ignore:line
|
4362
|
-
proxy.$events[i].length = 0
|
4363
|
-
}
|
4364
|
-
}
|
4365
|
-
proxy.$host = proxy.$outer = {}
|
4366
|
-
if (proxyPool.unshift(proxy) > kernel.maxRepeatSize) {
|
4367
|
-
proxyPool.pop()
|
4368
|
-
}
|
4369
|
-
}
|
4370
|
-
})
|
4371
|
-
if (type === "each")
|
4372
|
-
proxies.length = 0
|
4373
4566
|
}
|
4374
4567
|
|
4375
|
-
|
4376
|
-
|
4377
|
-
|
4378
4568
|
/*********************************************************************
|
4379
4569
|
* 各种指令 *
|
4380
4570
|
**********************************************************************/
|
@@ -4385,8 +4575,7 @@ bindingExecutors.text = function(val, elem) {
|
|
4385
4575
|
if (elem.nodeType === 3) { //绑定在文本节点上
|
4386
4576
|
try { //IE对游离于DOM树外的节点赋值会报错
|
4387
4577
|
elem.data = val
|
4388
|
-
} catch (e) {
|
4389
|
-
}
|
4578
|
+
} catch (e) {}
|
4390
4579
|
} else { //绑定在特性节点上
|
4391
4580
|
if ("textContent" in elem) {
|
4392
4581
|
elem.textContent = val
|
@@ -4395,8 +4584,6 @@ bindingExecutors.text = function(val, elem) {
|
|
4395
4584
|
}
|
4396
4585
|
}
|
4397
4586
|
}
|
4398
|
-
|
4399
|
-
|
4400
4587
|
function parseDisplay(nodeName, val) {
|
4401
4588
|
//用于取得此类标签的默认display值
|
4402
4589
|
var key = "_" + nodeName
|
@@ -4416,42 +4603,33 @@ function parseDisplay(nodeName, val) {
|
|
4416
4603
|
|
4417
4604
|
avalon.parseDisplay = parseDisplay
|
4418
4605
|
|
4419
|
-
bindingHandlers.visible = function(data, vmodels) {
|
4420
|
-
var elem = avalon(data.element)
|
4421
|
-
var display = elem.css("display")
|
4422
|
-
if (display === "none") {
|
4423
|
-
var style = elem[0].style
|
4424
|
-
var has = /visibility/i.test(style.cssText)
|
4425
|
-
var visible = elem.css("visibility")
|
4426
|
-
style.display = ""
|
4427
|
-
style.visibility = "hidden"
|
4428
|
-
display = elem.css("display")
|
4429
|
-
if (display === "none") {
|
4430
|
-
display = parseDisplay(elem[0].nodeName)
|
4431
|
-
}
|
4432
|
-
style.visibility = has ? visible : ""
|
4433
|
-
}
|
4434
|
-
data.display = display
|
4606
|
+
bindingHandlers.visible = function (data, vmodels) {
|
4435
4607
|
parseExprProxy(data.value, vmodels, data)
|
4436
4608
|
}
|
4437
4609
|
|
4438
|
-
bindingExecutors.visible = function(val, elem,
|
4439
|
-
|
4610
|
+
bindingExecutors.visible = function (val, elem, binding) {
|
4611
|
+
if (val) {
|
4612
|
+
elem.style.display = binding.display || ""
|
4613
|
+
if (avalon(elem).css("display") === "none") {
|
4614
|
+
elem.style.display = binding.display = parseDisplay(elem.nodeName)
|
4615
|
+
}
|
4616
|
+
} else {
|
4617
|
+
elem.style.display = "none"
|
4618
|
+
}
|
4440
4619
|
}
|
4441
|
-
|
4442
4620
|
bindingHandlers.widget = function(data, vmodels) {
|
4443
4621
|
var args = data.value.match(rword)
|
4444
4622
|
var elem = data.element
|
4445
4623
|
var widget = args[0]
|
4446
4624
|
var id = args[1]
|
4447
|
-
if (!id || id === "$") {//没有定义或为$时,取组件名+随机数
|
4625
|
+
if (!id || id === "$") { //没有定义或为$时,取组件名+随机数
|
4448
4626
|
id = generateID(widget)
|
4449
4627
|
}
|
4450
|
-
var optName = args[2] || widget//没有定义,取组件名
|
4628
|
+
var optName = args[2] || widget //没有定义,取组件名
|
4451
4629
|
var constructor = avalon.ui[widget]
|
4452
4630
|
if (typeof constructor === "function") { //ms-widget="tabs,tabsAAA,optname"
|
4453
4631
|
vmodels = elem.vmodels || vmodels
|
4454
|
-
for (var i = 0, v; v = vmodels[i++];
|
4632
|
+
for (var i = 0, v; v = vmodels[i++];) {
|
4455
4633
|
if (v.hasOwnProperty(optName) && typeof v[optName] === "object") {
|
4456
4634
|
var vmOptions = v[optName]
|
4457
4635
|
vmOptions = vmOptions.$model || vmOptions
|
@@ -4461,6 +4639,7 @@ bindingHandlers.widget = function(data, vmodels) {
|
|
4461
4639
|
if (vmOptions) {
|
4462
4640
|
var wid = vmOptions[widget + "Id"]
|
4463
4641
|
if (typeof wid === "string") {
|
4642
|
+
log("warning!不再支持" + widget + "Id")
|
4464
4643
|
id = wid
|
4465
4644
|
}
|
4466
4645
|
}
|
@@ -4476,27 +4655,26 @@ bindingHandlers.widget = function(data, vmodels) {
|
|
4476
4655
|
if (vmodel.$id) {
|
4477
4656
|
avalon.vmodels[id] = vmodel
|
4478
4657
|
createSignalTower(elem, vmodel)
|
4479
|
-
|
4658
|
+
try {
|
4480
4659
|
vmodel.$init(function() {
|
4481
4660
|
avalon.scan(elem, [vmodel].concat(vmodels))
|
4482
4661
|
if (typeof options.onInit === "function") {
|
4483
4662
|
options.onInit.call(elem, vmodel, options, vmodels)
|
4484
4663
|
}
|
4485
4664
|
})
|
4486
|
-
}
|
4665
|
+
} catch (e) {}
|
4487
4666
|
data.rollback = function() {
|
4488
4667
|
try {
|
4489
|
-
vmodel.widgetElement = null
|
4490
4668
|
vmodel.$remove()
|
4491
|
-
|
4492
|
-
}
|
4669
|
+
vmodel.widgetElement = null // 放到$remove后边
|
4670
|
+
} catch (e) {}
|
4493
4671
|
elem.msData = {}
|
4494
4672
|
delete avalon.vmodels[vmodel.$id]
|
4495
4673
|
}
|
4496
|
-
|
4674
|
+
injectDisposeQueue(data, widgetList)
|
4497
4675
|
if (window.chrome) {
|
4498
4676
|
elem.addEventListener("DOMNodeRemovedFromDocument", function() {
|
4499
|
-
setTimeout(
|
4677
|
+
setTimeout(rejectDisposeQueue)
|
4500
4678
|
})
|
4501
4679
|
}
|
4502
4680
|
} else {
|
@@ -4566,7 +4744,7 @@ var filters = avalon.filters = {
|
|
4566
4744
|
truncate: function(str, length, truncation) {
|
4567
4745
|
//length,新字符串长度,truncation,新字符串的结尾的字段,返回新字符串
|
4568
4746
|
length = length || 30
|
4569
|
-
truncation = truncation ===
|
4747
|
+
truncation = typeof truncation === "string" ? truncation : "..."
|
4570
4748
|
return str.length > length ? str.slice(0, length - truncation.length) + truncation : String(str)
|
4571
4749
|
},
|
4572
4750
|
$filter: function(val) {
|
@@ -4859,33 +5037,33 @@ new function() {// jshint ignore:line
|
|
4859
5037
|
/*********************************************************************
|
4860
5038
|
* END *
|
4861
5039
|
**********************************************************************/
|
4862
|
-
new function() {
|
5040
|
+
new function () {
|
4863
5041
|
avalon.config({
|
4864
5042
|
loader: false
|
4865
5043
|
})
|
4866
|
-
var fns = [],
|
5044
|
+
var fns = [], loaded = DOC.readyState === "complete", fn
|
4867
5045
|
function flush(f) {
|
4868
5046
|
loaded = 1
|
4869
5047
|
while (f = fns.shift())
|
4870
5048
|
f()
|
4871
5049
|
}
|
4872
|
-
|
4873
|
-
|
4874
|
-
|
5050
|
+
|
5051
|
+
avalon.bind(DOC, "DOMContentLoaded", fn = function () {
|
5052
|
+
avalon.unbind(DOC, "DOMContentLoaded", fn)
|
5053
|
+
flush()
|
5054
|
+
})
|
5055
|
+
|
5056
|
+
var id = setInterval(function () {
|
5057
|
+
if (document.readyState === "complete" && document.body) {
|
5058
|
+
clearInterval(id)
|
4875
5059
|
flush()
|
4876
|
-
}
|
4877
|
-
}
|
4878
|
-
|
4879
|
-
|
4880
|
-
clearInterval(id)
|
4881
|
-
flush()
|
4882
|
-
}
|
4883
|
-
}, 50)
|
4884
|
-
}
|
4885
|
-
avalon.ready = function(fn) {
|
5060
|
+
}
|
5061
|
+
}, 50)
|
5062
|
+
|
5063
|
+
avalon.ready = function (fn) {
|
4886
5064
|
loaded ? fn(avalon) : fns.push(fn)
|
4887
5065
|
}
|
4888
|
-
avalon.ready(function() {
|
5066
|
+
avalon.ready(function () {
|
4889
5067
|
avalon.scan(DOC.body)
|
4890
5068
|
})
|
4891
5069
|
}
|
@@ -4921,6 +5099,7 @@ new function() {
|
|
4921
5099
|
if (noGlobal === void 0) {
|
4922
5100
|
window.avalon = avalon
|
4923
5101
|
}
|
5102
|
+
|
4924
5103
|
return avalon
|
4925
5104
|
|
4926
5105
|
}));
|