avalon-rails 1.3.9.1.20150212184918 → 1.4.1.1.20150404164109
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 +4 -4
- data/lib/avalon-rails/version.rb +1 -1
- data/vendor/assets/javascripts/avalon.js +550 -394
- data/vendor/assets/javascripts/avalon.min.js +3 -3
- data/vendor/assets/javascripts/avalon.mobile.js +701 -653
- data/vendor/assets/javascripts/avalon.mobile.min.js +3 -3
- data/vendor/assets/javascripts/avalon.mobile.old.js +5887 -0
- data/vendor/assets/javascripts/avalon.mobile.shim.js +952 -902
- data/vendor/assets/javascripts/avalon.modern.js +589 -465
- data/vendor/assets/javascripts/avalon.modern.min.js +2 -2
- data/vendor/assets/javascripts/avalon.modern.shim.js +490 -366
- data/vendor/assets/javascripts/avalon.shim.js +490 -333
- metadata +3 -2
@@ -5,8 +5,7 @@
|
|
5
5
|
http://weibo.com/jslouvre/
|
6
6
|
|
7
7
|
Released under the MIT license
|
8
|
-
avalon.mobile.shim.js
|
9
|
-
upport IE6+ and other browsers
|
8
|
+
avalon.mobile.shim.js 1.41 built in 2015.4.4
|
10
9
|
==================================================*/
|
11
10
|
(function(global, factory) {
|
12
11
|
|
@@ -46,10 +45,23 @@ function log() {
|
|
46
45
|
console.log.apply(console, arguments)
|
47
46
|
}
|
48
47
|
}
|
48
|
+
/**
|
49
|
+
* Creates a new object without a prototype. This object is useful for lookup without having to
|
50
|
+
* guard against prototypically inherited properties via hasOwnProperty.
|
51
|
+
*
|
52
|
+
* Related micro-benchmarks:
|
53
|
+
* - http://jsperf.com/object-create2
|
54
|
+
* - http://jsperf.com/proto-map-lookup/2
|
55
|
+
* - http://jsperf.com/for-in-vs-object-keys2
|
56
|
+
*/
|
57
|
+
function createMap() {
|
58
|
+
return Object.create(null)
|
59
|
+
}
|
49
60
|
|
50
61
|
var subscribers = "$" + expose
|
51
62
|
var otherRequire = window.require
|
52
63
|
var otherDefine = window.define
|
64
|
+
var innerRequire
|
53
65
|
var stopRepeatAssign = false
|
54
66
|
var rword = /[^, ]+/g //切割字符串为一个个小块,以空格或豆号分开它们,结合replace实现字符串的forEach
|
55
67
|
var rcomplexType = /^(?:object|array)$/
|
@@ -87,16 +99,6 @@ function oneObject(array, val) {
|
|
87
99
|
return result
|
88
100
|
}
|
89
101
|
|
90
|
-
function createCache(maxLength) {
|
91
|
-
var keys = []
|
92
|
-
function cache(key, value) {
|
93
|
-
if (keys.push(key) > maxLength) {
|
94
|
-
delete cache[keys.shift()]
|
95
|
-
}
|
96
|
-
return cache[key] = value;
|
97
|
-
}
|
98
|
-
return cache;
|
99
|
-
}
|
100
102
|
//生成UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
|
101
103
|
var generateID = function(prefix) {
|
102
104
|
prefix = prefix || "avalon"
|
@@ -111,13 +113,60 @@ function IE() {
|
|
111
113
|
}
|
112
114
|
}
|
113
115
|
var IEVersion = IE()
|
114
|
-
|
115
|
-
* avalon的静态方法定义区 *
|
116
|
-
**********************************************************************/
|
116
|
+
|
117
117
|
avalon = function(el) { //创建jQuery式的无new 实例化结构
|
118
118
|
return new avalon.init(el)
|
119
119
|
}
|
120
120
|
|
121
|
+
/*视浏览器情况采用最快的异步回调*/
|
122
|
+
avalon.nextTick = new function() {// jshint ignore:line
|
123
|
+
var tickImmediate = window.setImmediate
|
124
|
+
var tickObserver = window.MutationObserver
|
125
|
+
var tickPost = W3C && window.postMessage
|
126
|
+
if (tickImmediate) {
|
127
|
+
return tickImmediate.bind(window)
|
128
|
+
}
|
129
|
+
|
130
|
+
var queue = []
|
131
|
+
function callback() {
|
132
|
+
var n = queue.length
|
133
|
+
for (var i = 0; i < n; i++) {
|
134
|
+
queue[i]()
|
135
|
+
}
|
136
|
+
queue = queue.slice(n)
|
137
|
+
}
|
138
|
+
|
139
|
+
if (tickObserver) {
|
140
|
+
var node = document.createTextNode("avalon")
|
141
|
+
new tickObserver(callback).observe(node, {characterData: true})// jshint ignore:line
|
142
|
+
return function(fn) {
|
143
|
+
queue.push(fn)
|
144
|
+
node.data = Math.random()
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
if (tickPost) {
|
149
|
+
window.addEventListener("message", function(e) {
|
150
|
+
var source = e.source
|
151
|
+
if ((source === window || source === null) && e.data === "process-tick") {
|
152
|
+
e.stopPropagation()
|
153
|
+
callback()
|
154
|
+
}
|
155
|
+
})
|
156
|
+
|
157
|
+
return function(fn) {
|
158
|
+
queue.push(fn)
|
159
|
+
window.postMessage('process-tick', '*')
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
return function(fn) {
|
164
|
+
setTimeout(fn, 0)
|
165
|
+
}
|
166
|
+
}// jshint ignore:line
|
167
|
+
/*********************************************************************
|
168
|
+
* avalon的静态方法定义区 *
|
169
|
+
**********************************************************************/
|
121
170
|
avalon.init = function(el) {
|
122
171
|
this[0] = this.element = el
|
123
172
|
}
|
@@ -213,7 +262,7 @@ function _number(a, len) { //用于模拟slice, splice的效果
|
|
213
262
|
avalon.mix({
|
214
263
|
rword: rword,
|
215
264
|
subscribers: subscribers,
|
216
|
-
version: 1.
|
265
|
+
version: 1.41,
|
217
266
|
ui: {},
|
218
267
|
log: log,
|
219
268
|
slice: function(nodes, start, end) {
|
@@ -222,7 +271,7 @@ avalon.mix({
|
|
222
271
|
noop: noop,
|
223
272
|
/*如果不用Error对象封装一下,str在控制台下可能会乱码*/
|
224
273
|
error: function(str, e) {
|
225
|
-
throw new (e || Error)(str)
|
274
|
+
throw new (e || Error)(str)// jshint ignore:line
|
226
275
|
},
|
227
276
|
/*将一个以空格或逗号隔开的字符串或数组,转换成一个键值都为1的对象*/
|
228
277
|
oneObject: oneObject,
|
@@ -259,7 +308,7 @@ avalon.mix({
|
|
259
308
|
if (typeof hook === "object") {
|
260
309
|
type = hook.type
|
261
310
|
if (hook.deel) {
|
262
|
-
fn = hook.deel(el, type, fn,
|
311
|
+
fn = hook.deel(el, type, fn, phase)
|
263
312
|
}
|
264
313
|
}
|
265
314
|
if (!fn.unbind)
|
@@ -374,35 +423,107 @@ function isArrayLike(obj) {
|
|
374
423
|
}
|
375
424
|
return false
|
376
425
|
}
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
426
|
+
|
427
|
+
|
428
|
+
// https://github.com/rsms/js-lru
|
429
|
+
var Cache = new function() {// jshint ignore:line
|
430
|
+
function LRU(maxLength) {
|
431
|
+
this.size = 0
|
432
|
+
this.limit = maxLength
|
433
|
+
this.head = this.tail = void 0
|
434
|
+
this._keymap = {}
|
435
|
+
}
|
436
|
+
|
437
|
+
var p = LRU.prototype
|
438
|
+
|
439
|
+
p.put = function(key, value) {
|
440
|
+
var entry = {
|
441
|
+
key: key,
|
442
|
+
value: value
|
443
|
+
}
|
444
|
+
this._keymap[key] = entry
|
445
|
+
if (this.tail) {
|
446
|
+
this.tail.newer = entry
|
447
|
+
entry.older = this.tail
|
448
|
+
} else {
|
449
|
+
this.head = entry
|
450
|
+
}
|
451
|
+
this.tail = entry
|
452
|
+
if (this.size === this.limit) {
|
453
|
+
this.shift()
|
454
|
+
} else {
|
455
|
+
this.size++
|
456
|
+
}
|
457
|
+
return value
|
458
|
+
}
|
459
|
+
|
460
|
+
p.shift = function() {
|
461
|
+
var entry = this.head
|
462
|
+
if (entry) {
|
463
|
+
this.head = this.head.newer
|
464
|
+
this.head.older =
|
465
|
+
entry.newer =
|
466
|
+
entry.older =
|
467
|
+
this._keymap[entry.key] = void 0
|
468
|
+
}
|
469
|
+
}
|
470
|
+
p.get = function(key) {
|
471
|
+
var entry = this._keymap[key]
|
472
|
+
if (entry === void 0)
|
473
|
+
return
|
474
|
+
if (entry === this.tail) {
|
475
|
+
return entry.value
|
476
|
+
}
|
477
|
+
// HEAD--------------TAIL
|
478
|
+
// <.older .newer>
|
479
|
+
// <--- add direction --
|
480
|
+
// A B C <D> E
|
481
|
+
if (entry.newer) {
|
482
|
+
if (entry === this.head) {
|
483
|
+
this.head = entry.newer
|
484
|
+
}
|
485
|
+
entry.newer.older = entry.older // C <-- E.
|
486
|
+
}
|
487
|
+
if (entry.older) {
|
488
|
+
entry.older.newer = entry.newer // C. --> E
|
489
|
+
}
|
490
|
+
entry.newer = void 0 // D --x
|
491
|
+
entry.older = this.tail // D. --> E
|
492
|
+
if (this.tail) {
|
493
|
+
this.tail.newer = entry // E. <-- D
|
494
|
+
}
|
495
|
+
this.tail = entry
|
496
|
+
return entry.value
|
497
|
+
}
|
498
|
+
return LRU
|
499
|
+
}// jshint ignore:line
|
381
500
|
|
382
501
|
/*********************************************************************
|
383
502
|
* DOM 底层补丁 *
|
384
503
|
**********************************************************************/
|
385
|
-
|
386
|
-
|
504
|
+
//safari5+是把contains方法放在Element.prototype上而不是Node.prototype
|
505
|
+
if (!DOC.contains) {
|
506
|
+
Node.prototype.contains = function (arg) {
|
387
507
|
return !!(this.compareDocumentPosition(arg) & 16)
|
388
508
|
}
|
389
509
|
}
|
390
|
-
avalon.contains = function(root, el) {
|
510
|
+
avalon.contains = function (root, el) {
|
391
511
|
try {
|
392
512
|
while ((el = el.parentNode))
|
393
513
|
if (el === root)
|
394
|
-
return true
|
514
|
+
return true
|
395
515
|
return false
|
396
516
|
} catch (e) {
|
397
517
|
return false
|
398
518
|
}
|
399
519
|
}
|
520
|
+
|
400
521
|
if (window.SVGElement) {
|
401
522
|
var svgns = "http://www.w3.org/2000/svg"
|
402
523
|
var svg = DOC.createElementNS(svgns, "svg")
|
403
524
|
svg.innerHTML = '<circle cx="50" cy="50" r="40" fill="red" />'
|
404
525
|
if (!rsvg.test(svg.firstChild)) {// #409
|
405
|
-
|
526
|
+
/* jshint ignore:start */
|
406
527
|
function enumerateNode(node, targetNode) {
|
407
528
|
if (node && node.childNodes) {
|
408
529
|
var nodes = node.childNodes
|
@@ -411,7 +532,7 @@ if (window.SVGElement) {
|
|
411
532
|
var svg = DOC.createElementNS(svgns,
|
412
533
|
el.tagName.toLowerCase())
|
413
534
|
// copy attrs
|
414
|
-
ap.forEach.call(el.attributes, function(attr) {
|
535
|
+
ap.forEach.call(el.attributes, function (attr) {
|
415
536
|
svg.setAttribute(attr.name, attr.value)
|
416
537
|
})
|
417
538
|
// 递归处理子节点
|
@@ -421,14 +542,15 @@ if (window.SVGElement) {
|
|
421
542
|
}
|
422
543
|
}
|
423
544
|
}
|
545
|
+
/* jshint ignore:end */
|
424
546
|
Object.defineProperties(SVGElement.prototype, {
|
425
547
|
"outerHTML": {//IE9-11,firefox不支持SVG元素的innerHTML,outerHTML属性
|
426
548
|
enumerable: true,
|
427
549
|
configurable: true,
|
428
|
-
get: function() {
|
550
|
+
get: function () {
|
429
551
|
return new XMLSerializer().serializeToString(this)
|
430
552
|
},
|
431
|
-
set: function(html) {
|
553
|
+
set: function (html) {
|
432
554
|
var tagName = this.tagName.toLowerCase(),
|
433
555
|
par = this.parentNode,
|
434
556
|
frag = avalon.parseHTML(html)
|
@@ -447,13 +569,13 @@ if (window.SVGElement) {
|
|
447
569
|
"innerHTML": {
|
448
570
|
enumerable: true,
|
449
571
|
configurable: true,
|
450
|
-
get: function() {
|
572
|
+
get: function () {
|
451
573
|
var s = this.outerHTML
|
452
574
|
var ropen = new RegExp("<" + this.nodeName + '\\b(?:(["\'])[^"]*?(\\1)|[^>])*>', "i")
|
453
575
|
var rclose = new RegExp("<\/" + this.nodeName + ">$", "i")
|
454
576
|
return s.replace(ropen, "").replace(rclose, "")
|
455
577
|
},
|
456
|
-
set: function(html) {
|
578
|
+
set: function (html) {
|
457
579
|
if (avalon.clearHTML) {
|
458
580
|
avalon.clearHTML(this)
|
459
581
|
var frag = avalon.parseHTML(html)
|
@@ -465,17 +587,17 @@ if (window.SVGElement) {
|
|
465
587
|
}
|
466
588
|
}
|
467
589
|
//========================= event binding ====================
|
468
|
-
var eventHooks = avalon.eventHooks
|
590
|
+
var eventHooks = avalon.eventHooks
|
469
591
|
//针对firefox, chrome修正mouseenter, mouseleave(chrome30+)
|
470
592
|
if (!("onmouseenter" in root)) {
|
471
593
|
avalon.each({
|
472
594
|
mouseenter: "mouseover",
|
473
595
|
mouseleave: "mouseout"
|
474
|
-
}, function(origType, fixType) {
|
596
|
+
}, function (origType, fixType) {
|
475
597
|
eventHooks[origType] = {
|
476
598
|
type: fixType,
|
477
|
-
deel: function(elem, fn) {
|
478
|
-
return function(e) {
|
599
|
+
deel: function (elem, _, fn) {
|
600
|
+
return function (e) {
|
479
601
|
var t = e.relatedTarget
|
480
602
|
if (!t || (t !== elem && !(elem.compareDocumentPosition(t) & 16))) {
|
481
603
|
delete e.type
|
@@ -491,7 +613,7 @@ if (!("onmouseenter" in root)) {
|
|
491
613
|
avalon.each({
|
492
614
|
AnimationEvent: "animationend",
|
493
615
|
WebKitAnimationEvent: "webkitAnimationEnd"
|
494
|
-
}, function(construct, fixType) {
|
616
|
+
}, function (construct, fixType) {
|
495
617
|
if (window[construct] && !eventHooks.animationend) {
|
496
618
|
eventHooks.animationend = {
|
497
619
|
type: fixType
|
@@ -507,8 +629,8 @@ if (DOC.onmousewheel === void 0) {
|
|
507
629
|
chrome wheel deltaY 下100 上-100 */
|
508
630
|
eventHooks.mousewheel = {
|
509
631
|
type: "wheel",
|
510
|
-
deel: function(elem, fn) {
|
511
|
-
return function(e) {
|
632
|
+
deel: function (elem, _, fn) {
|
633
|
+
return function (e) {
|
512
634
|
e.wheelDeltaY = e.wheelDelta = e.deltaY > 0 ? -120 : 120
|
513
635
|
e.wheelDeltaX = 0
|
514
636
|
Object.defineProperty(e, "type", {
|
@@ -546,13 +668,14 @@ function escapeRegExp(target) {
|
|
546
668
|
//将字符串安全格式化为正则表达式的源码
|
547
669
|
return (target + "").replace(rregexp, "\\$&")
|
548
670
|
}
|
549
|
-
|
671
|
+
|
550
672
|
var plugins = {
|
551
|
-
loader: function(builtin) {
|
552
|
-
|
553
|
-
window.require =
|
673
|
+
loader: function (builtin) {
|
674
|
+
var flag = innerRequire && builtin
|
675
|
+
window.require = flag ? innerRequire : otherRequire
|
676
|
+
window.define = flag ? innerRequire.define : otherDefine
|
554
677
|
},
|
555
|
-
interpolate: function(array) {
|
678
|
+
interpolate: function (array) {
|
556
679
|
openTag = array[0]
|
557
680
|
closeTag = array[1]
|
558
681
|
if (openTag === closeTag) {
|
@@ -582,11 +705,15 @@ kernel.paths = {}
|
|
582
705
|
kernel.shim = {}
|
583
706
|
kernel.maxRepeatSize = 100
|
584
707
|
avalon.config = kernel
|
708
|
+
var ravalon = /(\w+)\[(avalonctrl)="(\S+)"\]/
|
709
|
+
var findNodes = function(str) {
|
710
|
+
return DOC.querySelectorAll(str)
|
711
|
+
}
|
585
712
|
/*********************************************************************
|
586
713
|
* 事件总线 *
|
587
714
|
**********************************************************************/
|
588
715
|
var EventBus = {
|
589
|
-
$watch: function(type, callback) {
|
716
|
+
$watch: function (type, callback) {
|
590
717
|
if (typeof callback === "function") {
|
591
718
|
var callbacks = this.$events[type]
|
592
719
|
if (callbacks) {
|
@@ -599,7 +726,7 @@ var EventBus = {
|
|
599
726
|
}
|
600
727
|
return this
|
601
728
|
},
|
602
|
-
$unwatch: function(type, callback) {
|
729
|
+
$unwatch: function (type, callback) {
|
603
730
|
var n = arguments.length
|
604
731
|
if (n === 0) { //让此VM的所有$watch回调无效化
|
605
732
|
this.$watch.backup = this.$events
|
@@ -617,13 +744,15 @@ var EventBus = {
|
|
617
744
|
}
|
618
745
|
return this
|
619
746
|
},
|
620
|
-
$fire: function(type) {
|
747
|
+
$fire: function (type) {
|
621
748
|
var special, i, v, callback
|
622
749
|
if (/^(\w+)!(\S+)$/.test(type)) {
|
623
750
|
special = RegExp.$1
|
624
751
|
type = RegExp.$2
|
625
752
|
}
|
626
753
|
var events = this.$events
|
754
|
+
if (!events)
|
755
|
+
return
|
627
756
|
var args = aslice.call(arguments, 1)
|
628
757
|
var detail = [type].concat(args)
|
629
758
|
if (special === "all") {
|
@@ -646,22 +775,23 @@ var EventBus = {
|
|
646
775
|
continue
|
647
776
|
}
|
648
777
|
//循环两个vmodel中的节点,查找匹配(向上匹配或者向下匹配)的节点并设置标识
|
649
|
-
|
650
|
-
|
778
|
+
/* jshint ignore:start */
|
779
|
+
Array.prototype.forEach.call(eventNodes, function (node) {
|
780
|
+
Array.prototype.forEach.call(elements, function (element) {
|
651
781
|
var ok = special === "down" ? element.contains(node) : //向下捕获
|
652
782
|
node.contains(element) //向上冒泡
|
653
|
-
|
654
783
|
if (ok) {
|
655
784
|
node._avalon = v //符合条件的加一个标识
|
656
785
|
}
|
657
786
|
});
|
658
787
|
})
|
788
|
+
/* jshint ignore:end */
|
659
789
|
}
|
660
790
|
}
|
661
791
|
}
|
662
792
|
var nodes = DOC.getElementsByTagName("*") //实现节点排序
|
663
793
|
var alls = []
|
664
|
-
Array.prototype.forEach.call(nodes, function(el) {
|
794
|
+
Array.prototype.forEach.call(nodes, function (el) {
|
665
795
|
if (el._avalon) {
|
666
796
|
alls.push(el._avalon)
|
667
797
|
el._avalon = ""
|
@@ -691,16 +821,12 @@ var EventBus = {
|
|
691
821
|
}
|
692
822
|
}
|
693
823
|
|
694
|
-
var ravalon = /(\w+)\[(avalonctrl)="(\S+)"\]/
|
695
|
-
var findNodes = function(str) {
|
696
|
-
return DOC.querySelectorAll(str)
|
697
|
-
}
|
698
824
|
/*********************************************************************
|
699
825
|
* modelFactory *
|
700
826
|
**********************************************************************/
|
701
827
|
//avalon最核心的方法的两个方法之一(另一个是avalon.scan),返回一个ViewModel(VM)
|
702
|
-
var VMODELS = avalon.vmodels =
|
703
|
-
avalon.define = function(id, factory) {
|
828
|
+
var VMODELS = avalon.vmodels = createMap() //所有vmodel都储存在这里
|
829
|
+
avalon.define = function (id, factory) {
|
704
830
|
var $id = id.$id || id
|
705
831
|
if (!$id) {
|
706
832
|
log("warning: vm必须指定$id")
|
@@ -744,7 +870,7 @@ function isObservable(name, value, $skipArray) {
|
|
744
870
|
return true
|
745
871
|
}
|
746
872
|
//ms-with,ms-each, ms-repeat绑定生成的代理对象储存池
|
747
|
-
var midway =
|
873
|
+
var midway = createMap()
|
748
874
|
function getNewValue(accessor, name, value, $vmodel) {
|
749
875
|
switch (accessor.type) {
|
750
876
|
case 0://计算属性
|
@@ -771,43 +897,29 @@ function getNewValue(accessor, name, value, $vmodel) {
|
|
771
897
|
}
|
772
898
|
}
|
773
899
|
|
774
|
-
var defineProperty = Object.defineProperty
|
775
|
-
var canHideOwn = true
|
776
|
-
//如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8
|
777
|
-
//标准浏览器使用__defineGetter__, __defineSetter__实现
|
778
|
-
try {
|
779
|
-
defineProperty({}, "_", {
|
780
|
-
value: "x"
|
781
|
-
})
|
782
|
-
var defineProperties = Object.defineProperties
|
783
|
-
} catch (e) {
|
784
|
-
canHideOwn = false
|
785
|
-
}
|
786
900
|
function modelFactory(source, $special, $model) {
|
787
901
|
if (Array.isArray(source)) {
|
788
902
|
var arr = source.concat()
|
789
903
|
source.length = 0
|
790
|
-
var collection = Collection(source)
|
904
|
+
var collection = Collection(source)// jshint ignore:line
|
791
905
|
collection.pushArray(arr)
|
792
906
|
return collection
|
793
907
|
}
|
794
|
-
|
795
|
-
|
796
|
-
}
|
797
|
-
if (source.$id && source.$events) { //fix IE6-8 createWithProxy $val: val引发的BUG
|
908
|
+
//0 null undefined || Node || VModel
|
909
|
+
if (!source || source.nodeType > 0 || (source.$id && source.$events)) {
|
798
910
|
return source
|
799
911
|
}
|
800
912
|
if (!Array.isArray(source.$skipArray)) {
|
801
913
|
source.$skipArray = []
|
802
914
|
}
|
803
|
-
source.$skipArray.$special = $special ||
|
915
|
+
source.$skipArray.$special = $special || createMap() //强制要监听的属性
|
804
916
|
var $vmodel = {} //要返回的对象, 它在IE6-8下可能被偷龙转凤
|
805
917
|
$model = $model || {} //vmodels.$model属性
|
806
|
-
var $events =
|
807
|
-
var watchedProperties =
|
918
|
+
var $events = createMap() //vmodel.$events属性
|
919
|
+
var watchedProperties = createMap() //监控属性
|
808
920
|
var initCallbacks = [] //初始化才执行的函数
|
809
921
|
for (var i in source) {
|
810
|
-
(function(name, val) {
|
922
|
+
(function (name, val) {
|
811
923
|
$model[name] = val
|
812
924
|
if (!isObservable(name, val, source.$skipArray)) {
|
813
925
|
return //过滤所有非监控属性
|
@@ -815,7 +927,7 @@ function modelFactory(source, $special, $model) {
|
|
815
927
|
//总共产生三种accessor
|
816
928
|
$events[name] = []
|
817
929
|
var valueType = avalon.type(val)
|
818
|
-
var accessor = function(newValue) {
|
930
|
+
var accessor = function (newValue) {
|
819
931
|
var name = accessor._name
|
820
932
|
var $vmodel = this
|
821
933
|
var $model = $vmodel.$model
|
@@ -834,19 +946,8 @@ function modelFactory(source, $special, $model) {
|
|
834
946
|
}
|
835
947
|
if (!isEqual(oldValue, newValue)) {
|
836
948
|
$model[name] = newValue
|
837
|
-
|
838
|
-
|
839
|
-
accessor.pedding = true
|
840
|
-
setTimeout(function() {
|
841
|
-
notifySubscribers($events[name]) //同步视图
|
842
|
-
safeFire($vmodel, name, $model[name], oldValue) //触发$watch回调
|
843
|
-
accessor.pedding = false
|
844
|
-
})
|
845
|
-
}
|
846
|
-
} else {
|
847
|
-
notifySubscribers($events[name]) //同步视图
|
848
|
-
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
|
849
|
-
}
|
949
|
+
notifySubscribers($events[name]) //同步视图
|
950
|
+
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
|
850
951
|
}
|
851
952
|
} else {
|
852
953
|
if (accessor.type === 0) { //type 0 计算属性 1 监控属性 2 对象属性
|
@@ -855,17 +956,7 @@ function modelFactory(source, $special, $model) {
|
|
855
956
|
if (oldValue !== newValue) {
|
856
957
|
$model[name] = newValue
|
857
958
|
//这里不用同步视图
|
858
|
-
|
859
|
-
if (!accessor.pedding) {
|
860
|
-
accessor.pedding = true
|
861
|
-
setTimeout(function() {
|
862
|
-
safeFire($vmodel, name, $model[name], oldValue) //触发$watch回调
|
863
|
-
accessor.pedding = false
|
864
|
-
})
|
865
|
-
}
|
866
|
-
} else {
|
867
|
-
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
|
868
|
-
}
|
959
|
+
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
|
869
960
|
}
|
870
961
|
return newValue
|
871
962
|
} else {
|
@@ -880,11 +971,11 @@ function modelFactory(source, $special, $model) {
|
|
880
971
|
accessor.set = val.set
|
881
972
|
accessor.get = val.get
|
882
973
|
accessor.type = 0
|
883
|
-
initCallbacks.push(function() {
|
974
|
+
initCallbacks.push(function () {
|
884
975
|
var data = {
|
885
|
-
evaluator: function() {
|
976
|
+
evaluator: function () {
|
886
977
|
data.type = Math.random(),
|
887
|
-
|
978
|
+
data.element = null
|
888
979
|
$model[name] = accessor.get.call($vmodel)
|
889
980
|
},
|
890
981
|
element: head,
|
@@ -900,7 +991,7 @@ function modelFactory(source, $special, $model) {
|
|
900
991
|
//第2种为对象属性,产生子VM与监控数组
|
901
992
|
accessor.type = 2
|
902
993
|
accessor.valueType = valueType
|
903
|
-
initCallbacks.push(function() {
|
994
|
+
initCallbacks.push(function () {
|
904
995
|
var svmodel = modelFactory(val, 0, $model[name])
|
905
996
|
accessor.svmodel = svmodel
|
906
997
|
svmodel.$events[subscribers] = $events[name]
|
@@ -911,15 +1002,15 @@ function modelFactory(source, $special, $model) {
|
|
911
1002
|
}
|
912
1003
|
accessor._name = name
|
913
1004
|
watchedProperties[name] = accessor
|
914
|
-
})(i, source[i])
|
1005
|
+
})(i, source[i])// jshint ignore:line
|
915
1006
|
}
|
916
1007
|
|
917
|
-
$$skipArray.forEach(function(name) {
|
1008
|
+
$$skipArray.forEach(function (name) {
|
918
1009
|
delete source[name]
|
919
1010
|
delete $model[name] //这些特殊属性不应该在$model中出现
|
920
1011
|
})
|
921
1012
|
|
922
|
-
$vmodel = defineProperties($vmodel, descriptorFactory(watchedProperties), source) //生成一个空的ViewModel
|
1013
|
+
$vmodel = Object.defineProperties($vmodel, descriptorFactory(watchedProperties), source) //生成一个空的ViewModel
|
923
1014
|
for (var name in source) {
|
924
1015
|
if (!watchedProperties[name]) {
|
925
1016
|
$vmodel[name] = source[name]
|
@@ -929,37 +1020,27 @@ function modelFactory(source, $special, $model) {
|
|
929
1020
|
$vmodel.$id = generateID()
|
930
1021
|
$vmodel.$model = $model
|
931
1022
|
$vmodel.$events = $events
|
932
|
-
for (
|
933
|
-
|
934
|
-
if (!W3C) { //在IE6-8下,VB对象的方法里的this并不指向自身,需要用bind处理一下
|
935
|
-
fn = fn.bind($vmodel)
|
936
|
-
}
|
937
|
-
$vmodel[i] = fn
|
1023
|
+
for (i in EventBus) {
|
1024
|
+
$vmodel[i] = EventBus[i]
|
938
1025
|
}
|
939
1026
|
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
})
|
1027
|
+
Object.defineProperty($vmodel, "hasOwnProperty", {
|
1028
|
+
value: function (name) {
|
1029
|
+
return name in this.$model
|
1030
|
+
},
|
1031
|
+
writable: false,
|
1032
|
+
enumerable: false,
|
1033
|
+
configurable: true
|
1034
|
+
})
|
949
1035
|
|
950
|
-
|
951
|
-
$vmodel.hasOwnProperty = function(name) {
|
952
|
-
return name in $vmodel.$model
|
953
|
-
}
|
954
|
-
}
|
955
|
-
initCallbacks.forEach(function(cb) { //收集依赖
|
1036
|
+
initCallbacks.forEach(function (cb) { //收集依赖
|
956
1037
|
cb()
|
957
1038
|
})
|
958
1039
|
return $vmodel
|
959
1040
|
}
|
960
1041
|
|
961
1042
|
//比较两个值是否相等
|
962
|
-
var isEqual = Object.is || function(v1, v2) {
|
1043
|
+
var isEqual = Object.is || function (v1, v2) {
|
963
1044
|
if (v1 === 0 && v2 === 0) {
|
964
1045
|
return 1 / v1 === 1 / v2
|
965
1046
|
} else if (v1 !== v1) {
|
@@ -975,8 +1056,8 @@ function safeFire(a, b, c, d) {
|
|
975
1056
|
}
|
976
1057
|
}
|
977
1058
|
|
978
|
-
var descriptorFactory =
|
979
|
-
var descriptors =
|
1059
|
+
var descriptorFactory = function (obj) {
|
1060
|
+
var descriptors = createMap()
|
980
1061
|
for (var i in obj) {
|
981
1062
|
descriptors[i] = {
|
982
1063
|
get: obj[i],
|
@@ -986,12 +1067,8 @@ var descriptorFactory = W3C ? function(obj) {
|
|
986
1067
|
}
|
987
1068
|
}
|
988
1069
|
return descriptors
|
989
|
-
} : function(a) {
|
990
|
-
return a
|
991
1070
|
}
|
992
1071
|
|
993
|
-
|
994
|
-
|
995
1072
|
//应用于第2种accessor
|
996
1073
|
function objectFactory(parent, name, value, valueType) {
|
997
1074
|
//a为原来的VM, b为新数组或新对象
|
@@ -1014,16 +1091,17 @@ function objectFactory(parent, name, value, valueType) {
|
|
1014
1091
|
}
|
1015
1092
|
var ret = modelFactory(value)
|
1016
1093
|
ret.$events[subscribers] = iterators
|
1017
|
-
midway[ret.$id] = function(data) {
|
1094
|
+
midway[ret.$id] = function (data) {
|
1018
1095
|
while (data = iterators.shift()) {
|
1019
|
-
(function(el) {
|
1020
|
-
avalon.nextTick(function() {
|
1021
|
-
|
1096
|
+
(function (el) {
|
1097
|
+
avalon.nextTick(function () {
|
1098
|
+
var type = el.type
|
1099
|
+
if (type && bindingHandlers[type]) { //#753
|
1022
1100
|
el.rollback && el.rollback() //还原 ms-with ms-on
|
1023
|
-
bindingHandlers[
|
1101
|
+
bindingHandlers[type](el, el.vmodels)
|
1024
1102
|
}
|
1025
1103
|
})
|
1026
|
-
})(data)
|
1104
|
+
})(data)// jshint ignore:line
|
1027
1105
|
}
|
1028
1106
|
delete midway[ret.$id]
|
1029
1107
|
}
|
@@ -1043,7 +1121,7 @@ function Collection(model) {
|
|
1043
1121
|
array._ = modelFactory({
|
1044
1122
|
length: model.length
|
1045
1123
|
})
|
1046
|
-
array._.$watch("length", function(a, b) {
|
1124
|
+
array._.$watch("length", function (a, b) {
|
1047
1125
|
array.$fire("length", a, b)
|
1048
1126
|
})
|
1049
1127
|
for (var i in EventBus) {
|
@@ -1058,13 +1136,15 @@ function mutateArray(method, pos, n, index, method2, pos2, n2) {
|
|
1058
1136
|
while (--loop) {
|
1059
1137
|
switch (method) {
|
1060
1138
|
case "add":
|
1061
|
-
|
1139
|
+
/* jshint ignore:start */
|
1140
|
+
var array = this.$model.slice(pos, pos + n).map(function (el) {
|
1062
1141
|
if (rcomplexType.test(avalon.type(el))) {
|
1063
1142
|
return el.$id ? el : modelFactory(el, 0, el)
|
1064
1143
|
} else {
|
1065
1144
|
return el
|
1066
1145
|
}
|
1067
1146
|
})
|
1147
|
+
/* jshint ignore:end */
|
1068
1148
|
_splice.apply(this, [pos, 0].concat(array))
|
1069
1149
|
this._fire("add", pos, n)
|
1070
1150
|
break
|
@@ -1091,30 +1171,30 @@ function mutateArray(method, pos, n, index, method2, pos2, n2) {
|
|
1091
1171
|
var _splice = ap.splice
|
1092
1172
|
var CollectionPrototype = {
|
1093
1173
|
_splice: _splice,
|
1094
|
-
_fire: function(method, a, b) {
|
1174
|
+
_fire: function (method, a, b) {
|
1095
1175
|
notifySubscribers(this.$events[subscribers], method, a, b)
|
1096
1176
|
},
|
1097
|
-
size: function() { //取得数组长度,这个函数可以同步视图,length不能
|
1177
|
+
size: function () { //取得数组长度,这个函数可以同步视图,length不能
|
1098
1178
|
return this._.length
|
1099
1179
|
},
|
1100
|
-
pushArray: function(array) {
|
1180
|
+
pushArray: function (array) {
|
1101
1181
|
var m = array.length, n = this.length
|
1102
1182
|
if (m) {
|
1103
1183
|
ap.push.apply(this.$model, array)
|
1104
|
-
mutateArray.call(this, "add", n, m, n)
|
1184
|
+
mutateArray.call(this, "add", n, m, Math.max(0, n - 1))
|
1105
1185
|
}
|
1106
1186
|
return m + n
|
1107
1187
|
},
|
1108
|
-
push: function() {
|
1188
|
+
push: function () {
|
1109
1189
|
//http://jsperf.com/closure-with-arguments
|
1110
1190
|
var array = []
|
1111
1191
|
var i, n = arguments.length
|
1112
1192
|
for (i = 0; i < n; i++) {
|
1113
1193
|
array[i] = arguments[i]
|
1114
1194
|
}
|
1115
|
-
return this.pushArray(
|
1195
|
+
return this.pushArray(array)
|
1116
1196
|
},
|
1117
|
-
unshift: function() {
|
1197
|
+
unshift: function () {
|
1118
1198
|
var m = arguments.length, n = this.length
|
1119
1199
|
if (m) {
|
1120
1200
|
ap.unshift.apply(this.$model, arguments)
|
@@ -1122,22 +1202,22 @@ var CollectionPrototype = {
|
|
1122
1202
|
}
|
1123
1203
|
return m + n //IE67的unshift不会返回长度
|
1124
1204
|
},
|
1125
|
-
shift: function() {
|
1205
|
+
shift: function () {
|
1126
1206
|
if (this.length) {
|
1127
1207
|
var el = this.$model.shift()
|
1128
1208
|
mutateArray.call(this, "del", 0, 1, 0)
|
1129
1209
|
return el //返回被移除的元素
|
1130
1210
|
}
|
1131
1211
|
},
|
1132
|
-
pop: function() {
|
1133
|
-
var
|
1134
|
-
if (
|
1212
|
+
pop: function () {
|
1213
|
+
var n = this.length
|
1214
|
+
if (n) {
|
1135
1215
|
var el = this.$model.pop()
|
1136
|
-
mutateArray.call(this, "del",
|
1216
|
+
mutateArray.call(this, "del", n - 1, 1, Math.max(0, n - 2))
|
1137
1217
|
return el //返回被移除的元素
|
1138
1218
|
}
|
1139
1219
|
},
|
1140
|
-
splice: function(start) {
|
1220
|
+
splice: function (start) {
|
1141
1221
|
var m = arguments.length, args = [], change
|
1142
1222
|
var removed = _splice.apply(this.$model, arguments)
|
1143
1223
|
if (removed.length) { //如果用户删掉了元素
|
@@ -1158,27 +1238,27 @@ var CollectionPrototype = {
|
|
1158
1238
|
return []
|
1159
1239
|
}
|
1160
1240
|
},
|
1161
|
-
contains: function(el) { //判定是否包含
|
1241
|
+
contains: function (el) { //判定是否包含
|
1162
1242
|
return this.indexOf(el) !== -1
|
1163
1243
|
},
|
1164
|
-
remove: function(el) { //移除第一个等于给定值的元素
|
1244
|
+
remove: function (el) { //移除第一个等于给定值的元素
|
1165
1245
|
return this.removeAt(this.indexOf(el))
|
1166
1246
|
},
|
1167
|
-
removeAt: function(index) { //移除指定索引上的元素
|
1247
|
+
removeAt: function (index) { //移除指定索引上的元素
|
1168
1248
|
if (index >= 0) {
|
1169
1249
|
this.$model.splice(index, 1)
|
1170
1250
|
return mutateArray.call(this, "del", index, 1, 0)
|
1171
1251
|
}
|
1172
1252
|
return []
|
1173
1253
|
},
|
1174
|
-
clear: function() {
|
1254
|
+
clear: function () {
|
1175
1255
|
this.$model.length = this.length = this._.length = 0 //清空数组
|
1176
1256
|
this._fire("clear", 0)
|
1177
1257
|
return this
|
1178
1258
|
},
|
1179
|
-
removeAll: function(all) { //移除N个元素
|
1259
|
+
removeAll: function (all) { //移除N个元素
|
1180
1260
|
if (Array.isArray(all)) {
|
1181
|
-
all.forEach(function(el) {
|
1261
|
+
all.forEach(function (el) {
|
1182
1262
|
this.remove(el)
|
1183
1263
|
}, this)
|
1184
1264
|
} else if (typeof all === "function") {
|
@@ -1192,13 +1272,13 @@ var CollectionPrototype = {
|
|
1192
1272
|
this.clear()
|
1193
1273
|
}
|
1194
1274
|
},
|
1195
|
-
ensure: function(el) {
|
1275
|
+
ensure: function (el) {
|
1196
1276
|
if (!this.contains(el)) { //只有不存在才push
|
1197
1277
|
this.push(el)
|
1198
1278
|
}
|
1199
1279
|
return this
|
1200
1280
|
},
|
1201
|
-
set: function(index, val) {
|
1281
|
+
set: function (index, val) {
|
1202
1282
|
if (index >= 0) {
|
1203
1283
|
var valueType = avalon.type(val)
|
1204
1284
|
if (val && val.$model) {
|
@@ -1237,8 +1317,8 @@ function sortByIndex(array, indexes) {
|
|
1237
1317
|
}
|
1238
1318
|
}
|
1239
1319
|
|
1240
|
-
"sort,reverse".replace(rword, function(method) {
|
1241
|
-
CollectionPrototype[method] = function() {
|
1320
|
+
"sort,reverse".replace(rword, function (method) {
|
1321
|
+
CollectionPrototype[method] = function () {
|
1242
1322
|
var newArray = this.$model//这是要排序的新数组
|
1243
1323
|
var oldArray = newArray.concat() //保持原来状态的旧数组
|
1244
1324
|
var mask = Math.random()
|
@@ -1414,7 +1494,7 @@ function notifySubscribers(list) { //通知依赖于这个访问器的订阅者
|
|
1414
1494
|
* HTML处理(parseHTML, innerHTML, clearHTML) *
|
1415
1495
|
**************************************************************************/
|
1416
1496
|
//parseHTML的辅助变量
|
1417
|
-
var tagHooks = new function() {
|
1497
|
+
var tagHooks = new function() {// jshint ignore:line
|
1418
1498
|
avalon.mix(this, {
|
1419
1499
|
option: DOC.createElement("select"),
|
1420
1500
|
thead: DOC.createElement("table"),
|
@@ -1429,7 +1509,7 @@ var tagHooks = new function() {
|
|
1429
1509
|
this.optgroup = this.option
|
1430
1510
|
this.tbody = this.tfoot = this.colgroup = this.caption = this.thead
|
1431
1511
|
this.th = this.td
|
1432
|
-
}
|
1512
|
+
}// jshint ignore:line
|
1433
1513
|
|
1434
1514
|
String("circle,defs,ellipse,image,line,path,polygon,polyline,rect,symbol,text,use").replace(rword, function(tag) {
|
1435
1515
|
tagHooks[tag] = tagHooks.g //处理SVG
|
@@ -1438,16 +1518,20 @@ var rtagName = /<([\w:]+)/
|
|
1438
1518
|
var rxhtml = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig
|
1439
1519
|
var scriptTypes = oneObject(["", "text/javascript", "text/ecmascript", "application/ecmascript", "application/javascript"])
|
1440
1520
|
var script = DOC.createElement("script")
|
1441
|
-
|
1521
|
+
var rhtml = /<|&#?\w+;/
|
1442
1522
|
avalon.parseHTML = function(html) {
|
1523
|
+
var fragment = hyperspace.cloneNode(false)
|
1443
1524
|
if (typeof html !== "string" ) {
|
1444
|
-
return
|
1525
|
+
return fragment
|
1526
|
+
}
|
1527
|
+
if (!rhtml.test(html)) {
|
1528
|
+
fragment.appendChild(DOC.createTextNode(html))
|
1529
|
+
return fragment
|
1445
1530
|
}
|
1446
1531
|
html = html.replace(rxhtml, "<$1></$2>").trim()
|
1447
1532
|
var tag = (rtagName.exec(html) || ["", ""])[1].toLowerCase(),
|
1448
1533
|
//取得其标签名
|
1449
1534
|
wrapper = tagHooks[tag] || tagHooks._default,
|
1450
|
-
fragment = hyperspace.cloneNode(false),
|
1451
1535
|
firstChild
|
1452
1536
|
wrapper.innerHTML = html
|
1453
1537
|
var els = wrapper.getElementsByTagName("script")
|
@@ -1457,7 +1541,7 @@ avalon.parseHTML = function(html) {
|
|
1457
1541
|
var neo = script.cloneNode(false) //FF不能省略参数
|
1458
1542
|
ap.forEach.call(el.attributes, function(attr) {
|
1459
1543
|
neo.setAttribute(attr.name, attr.value)
|
1460
|
-
})
|
1544
|
+
})// jshint ignore:line
|
1461
1545
|
neo.text = el.text
|
1462
1546
|
el.parentNode.replaceChild(neo, el)
|
1463
1547
|
}
|
@@ -1575,55 +1659,11 @@ function bindingSorter(a, b) {
|
|
1575
1659
|
return a.priority - b.priority
|
1576
1660
|
}
|
1577
1661
|
|
1578
|
-
function scanTag(elem, vmodels, node) {
|
1579
|
-
//扫描顺序 ms-skip(0) --> ms-important(1) --> ms-controller(2) --> ms-if(10) --> ms-repeat(100)
|
1580
|
-
//--> ms-if-loop(110) --> ms-attr(970) ...--> ms-each(1400)-->ms-with(1500)--〉ms-duplex(2000)垫后
|
1581
|
-
var a = elem.getAttribute("ms-skip")
|
1582
|
-
var b = elem.getAttributeNode("ms-important")
|
1583
|
-
var c = elem.getAttributeNode("ms-controller")
|
1584
|
-
if (typeof a === "string") {
|
1585
|
-
return
|
1586
|
-
} else if (node = b || c) {
|
1587
|
-
var newVmodel = avalon.vmodels[node.value]
|
1588
|
-
if (!newVmodel) {
|
1589
|
-
return
|
1590
|
-
}
|
1591
|
-
//ms-important不包含父VM,ms-controller相反
|
1592
|
-
vmodels = node === b ? [newVmodel] : [newVmodel].concat(vmodels)
|
1593
|
-
elem.removeAttribute(node.name) //removeAttributeNode不会刷新[ms-controller]样式规则
|
1594
|
-
elem.classList.remove(node.name)
|
1595
|
-
createSignalTower(elem, newVmodel)
|
1596
|
-
}
|
1597
|
-
scanAttr(elem, vmodels) //扫描特性节点
|
1598
|
-
}
|
1599
|
-
function scanNodeList(parent, vmodels) {
|
1600
|
-
var node = parent.firstChild
|
1601
|
-
while (node) {
|
1602
|
-
var nextNode = node.nextSibling
|
1603
|
-
scanNode(node, node.nodeType, vmodels)
|
1604
|
-
node = nextNode
|
1605
|
-
}
|
1606
|
-
}
|
1607
|
-
|
1608
|
-
function scanNodeArray(nodes, vmodels) {
|
1609
|
-
for (var i = 0, node; node = nodes[i++]; ) {
|
1610
|
-
scanNode(node, node.nodeType, vmodels)
|
1611
|
-
}
|
1612
|
-
}
|
1613
|
-
function scanNode(node, nodeType, vmodels) {
|
1614
|
-
if (nodeType === 1) {
|
1615
|
-
scanTag(node, vmodels) //扫描元素节点
|
1616
|
-
} else if (nodeType === 3 && rexpr.test(node.data)){
|
1617
|
-
scanText(node, vmodels) //扫描文本节点
|
1618
|
-
} else if (kernel.commentInterpolate && nodeType === 8 && !rexpr.test(node.nodeValue)) {
|
1619
|
-
scanText(node, vmodels) //扫描注释节点
|
1620
|
-
}
|
1621
|
-
}
|
1622
1662
|
function scanAttr(elem, vmodels) {
|
1623
1663
|
//防止setAttribute, removeAttribute时 attributes自动被同步,导致for循环出错
|
1624
1664
|
var attributes = elem.hasAttributes() ? avalon.slice(elem.attributes) : []
|
1625
1665
|
var bindings = [],
|
1626
|
-
msData =
|
1666
|
+
msData = createMap(),
|
1627
1667
|
match
|
1628
1668
|
for (var i = 0, attr; attr = attributes[i++]; ) {
|
1629
1669
|
if (attr.specified) {
|
@@ -1638,8 +1678,9 @@ function scanAttr(elem, vmodels) {
|
|
1638
1678
|
param = type
|
1639
1679
|
type = "on"
|
1640
1680
|
} else if (obsoleteAttrs[type]) {
|
1641
|
-
log("ms-" + type + "
|
1681
|
+
log("warning!请改用ms-attr-" + type + "代替ms-" + type + "!")
|
1642
1682
|
if (type === "enabled") {//吃掉ms-enabled绑定,用ms-disabled代替
|
1683
|
+
log("warning!ms-enabled或ms-attr-enabled已经被废弃")
|
1643
1684
|
type = "disabled"
|
1644
1685
|
value = "!(" + value + ")"
|
1645
1686
|
}
|
@@ -1663,11 +1704,11 @@ function scanAttr(elem, vmodels) {
|
|
1663
1704
|
if (type === "html" || type === "text") {
|
1664
1705
|
var token = getToken(value)
|
1665
1706
|
avalon.mix(binding, token)
|
1666
|
-
binding.filters = binding.filters.replace(rhasHtml, function() {
|
1707
|
+
binding.filters = binding.filters.replace(rhasHtml, function () {
|
1667
1708
|
binding.type = "html"
|
1668
1709
|
binding.group = 1
|
1669
1710
|
return ""
|
1670
|
-
})
|
1711
|
+
})// jshint ignore:line
|
1671
1712
|
}
|
1672
1713
|
if (name === "ms-if-loop") {
|
1673
1714
|
binding.priority += 100
|
@@ -1682,8 +1723,14 @@ function scanAttr(elem, vmodels) {
|
|
1682
1723
|
}
|
1683
1724
|
}
|
1684
1725
|
}
|
1685
|
-
|
1686
|
-
|
1726
|
+
var control = elem.type
|
1727
|
+
if (control && msData["ms-duplex"]) {
|
1728
|
+
if (msData["ms-attr-checked"] && /radio|checkbox/.test(control)) {
|
1729
|
+
log("warning!" + control + "控件不能同时定义ms-attr-checked与ms-duplex")
|
1730
|
+
}
|
1731
|
+
if (msData["ms-attr-value"] && /text|password/.test(control)) {
|
1732
|
+
log("warning!" + control + "控件不能同时定义ms-attr-value与ms-duplex")
|
1733
|
+
}
|
1687
1734
|
}
|
1688
1735
|
bindings.sort(bindingSorter)
|
1689
1736
|
var scanNode = true
|
@@ -1704,6 +1751,50 @@ function scanAttr(elem, vmodels) {
|
|
1704
1751
|
|
1705
1752
|
var rnoscanAttrBinding = /^if|widget|repeat$/
|
1706
1753
|
var rnoscanNodeBinding = /^each|with|html|include$/
|
1754
|
+
function scanNodeList(parent, vmodels) {
|
1755
|
+
var node = parent.firstChild
|
1756
|
+
while (node) {
|
1757
|
+
var nextNode = node.nextSibling
|
1758
|
+
scanNode(node, node.nodeType, vmodels)
|
1759
|
+
node = nextNode
|
1760
|
+
}
|
1761
|
+
}
|
1762
|
+
|
1763
|
+
function scanNodeArray(nodes, vmodels) {
|
1764
|
+
for (var i = 0, node; node = nodes[i++]; ) {
|
1765
|
+
scanNode(node, node.nodeType, vmodels)
|
1766
|
+
}
|
1767
|
+
}
|
1768
|
+
function scanNode(node, nodeType, vmodels) {
|
1769
|
+
if (nodeType === 1) {
|
1770
|
+
scanTag(node, vmodels) //扫描元素节点
|
1771
|
+
} else if (nodeType === 3 && rexpr.test(node.data)){
|
1772
|
+
scanText(node, vmodels) //扫描文本节点
|
1773
|
+
} else if (kernel.commentInterpolate && nodeType === 8 && !rexpr.test(node.nodeValue)) {
|
1774
|
+
scanText(node, vmodels) //扫描注释节点
|
1775
|
+
}
|
1776
|
+
}
|
1777
|
+
function scanTag(elem, vmodels, node) {
|
1778
|
+
//扫描顺序 ms-skip(0) --> ms-important(1) --> ms-controller(2) --> ms-if(10) --> ms-repeat(100)
|
1779
|
+
//--> ms-if-loop(110) --> ms-attr(970) ...--> ms-each(1400)-->ms-with(1500)--〉ms-duplex(2000)垫后
|
1780
|
+
var a = elem.getAttribute("ms-skip")
|
1781
|
+
var b = elem.getAttributeNode("ms-important")
|
1782
|
+
var c = elem.getAttributeNode("ms-controller")
|
1783
|
+
if (typeof a === "string") {
|
1784
|
+
return
|
1785
|
+
} else if (node = b || c) {
|
1786
|
+
var newVmodel = avalon.vmodels[node.value]
|
1787
|
+
if (!newVmodel) {
|
1788
|
+
return
|
1789
|
+
}
|
1790
|
+
//ms-important不包含父VM,ms-controller相反
|
1791
|
+
vmodels = node === b ? [newVmodel] : [newVmodel].concat(vmodels)
|
1792
|
+
elem.removeAttribute(node.name) //removeAttributeNode不会刷新[ms-controller]样式规则
|
1793
|
+
elem.classList.remove(node.name)
|
1794
|
+
createSignalTower(elem, newVmodel)
|
1795
|
+
}
|
1796
|
+
scanAttr(elem, vmodels) //扫描特性节点
|
1797
|
+
}
|
1707
1798
|
var rhasHtml = /\|\s*html\s*/,
|
1708
1799
|
r11a = /\|\|/g,
|
1709
1800
|
rlt = /</g,
|
@@ -1712,7 +1803,7 @@ var rhasHtml = /\|\s*html\s*/,
|
|
1712
1803
|
function getToken(value) {
|
1713
1804
|
if (value.indexOf("|") > 0) {
|
1714
1805
|
var scapegoat = value.replace( rstringLiteral, function(_){
|
1715
|
-
return
|
1806
|
+
return Array(_.length+1).join("1")// jshint ignore:line
|
1716
1807
|
})
|
1717
1808
|
var index = scapegoat.replace(r11a, "\u1122\u3344").indexOf("|") //干掉所有短路或
|
1718
1809
|
if (index > -1) {
|
@@ -1787,7 +1878,7 @@ function scanText(textNode, vmodels) {
|
|
1787
1878
|
token.type = "html"
|
1788
1879
|
token.group = 1
|
1789
1880
|
return ""
|
1790
|
-
})
|
1881
|
+
})// jshint ignore:line
|
1791
1882
|
bindings.push(token) //收集带有插值表达式的文本
|
1792
1883
|
}
|
1793
1884
|
hyperspace.appendChild(node)
|
@@ -1811,17 +1902,17 @@ function camelize(target) {
|
|
1811
1902
|
if (target.indexOf("-") < 0 && target.indexOf("_") < 0) {
|
1812
1903
|
return target //提前判断,提高getStyle等的效率
|
1813
1904
|
}
|
1814
|
-
return target.replace(/[-_][^-_]/g, function(match) {
|
1905
|
+
return target.replace(/[-_][^-_]/g, function (match) {
|
1815
1906
|
return match.charAt(1).toUpperCase()
|
1816
1907
|
})
|
1817
1908
|
}
|
1818
1909
|
|
1819
|
-
"add,remove".replace(rword, function(method) {
|
1820
|
-
avalon.fn[method + "Class"] = function(cls) {
|
1910
|
+
"add,remove".replace(rword, function (method) {
|
1911
|
+
avalon.fn[method + "Class"] = function (cls) {
|
1821
1912
|
var el = this[0]
|
1822
1913
|
//https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/26
|
1823
1914
|
if (cls && typeof cls === "string" && el && el.nodeType === 1) {
|
1824
|
-
cls.replace(/\S+/g, function(c) {
|
1915
|
+
cls.replace(/\S+/g, function (c) {
|
1825
1916
|
el.classList[method](c)
|
1826
1917
|
})
|
1827
1918
|
}
|
@@ -1830,11 +1921,11 @@ function camelize(target) {
|
|
1830
1921
|
})
|
1831
1922
|
|
1832
1923
|
avalon.fn.mix({
|
1833
|
-
hasClass: function(cls) {
|
1924
|
+
hasClass: function (cls) {
|
1834
1925
|
var el = this[0] || {} //IE10+, chrome8+, firefox3.6+, safari5.1+,opera11.5+支持classList,chrome24+,firefox26+支持classList2.0
|
1835
1926
|
return el.nodeType === 1 && el.classList.contains(cls)
|
1836
1927
|
},
|
1837
|
-
toggleClass: function(value, stateVal) {
|
1928
|
+
toggleClass: function (value, stateVal) {
|
1838
1929
|
var className, i = 0
|
1839
1930
|
var classNames = value.split(/\s+/)
|
1840
1931
|
var isBool = typeof stateVal === "boolean"
|
@@ -1844,7 +1935,7 @@ avalon.fn.mix({
|
|
1844
1935
|
}
|
1845
1936
|
return this
|
1846
1937
|
},
|
1847
|
-
attr: function(name, value) {
|
1938
|
+
attr: function (name, value) {
|
1848
1939
|
if (arguments.length === 2) {
|
1849
1940
|
this[0].setAttribute(name, value)
|
1850
1941
|
return this
|
@@ -1852,7 +1943,7 @@ avalon.fn.mix({
|
|
1852
1943
|
return this[0].getAttribute(name)
|
1853
1944
|
}
|
1854
1945
|
},
|
1855
|
-
data: function(name, value) {
|
1946
|
+
data: function (name, value) {
|
1856
1947
|
name = "data-" + hyphen(name || "")
|
1857
1948
|
switch (arguments.length) {
|
1858
1949
|
case 2:
|
@@ -1863,7 +1954,7 @@ avalon.fn.mix({
|
|
1863
1954
|
return parseData(val)
|
1864
1955
|
case 0:
|
1865
1956
|
var ret = {}
|
1866
|
-
ap.forEach.call(this[0].attributes, function(attr) {
|
1957
|
+
ap.forEach.call(this[0].attributes, function (attr) {
|
1867
1958
|
if (attr) {
|
1868
1959
|
name = attr.name
|
1869
1960
|
if (!name.indexOf("data-")) {
|
@@ -1875,12 +1966,12 @@ avalon.fn.mix({
|
|
1875
1966
|
return ret
|
1876
1967
|
}
|
1877
1968
|
},
|
1878
|
-
removeData: function(name) {
|
1969
|
+
removeData: function (name) {
|
1879
1970
|
name = "data-" + hyphen(name)
|
1880
1971
|
this[0].removeAttribute(name)
|
1881
1972
|
return this
|
1882
1973
|
},
|
1883
|
-
css: function(name, value) {
|
1974
|
+
css: function (name, value) {
|
1884
1975
|
if (avalon.isPlainObject(name)) {
|
1885
1976
|
for (var i in name) {
|
1886
1977
|
avalon.css(this, i, name[i])
|
@@ -1890,7 +1981,7 @@ avalon.fn.mix({
|
|
1890
1981
|
}
|
1891
1982
|
return ret !== void 0 ? ret : this
|
1892
1983
|
},
|
1893
|
-
position: function() {
|
1984
|
+
position: function () {
|
1894
1985
|
var offsetParent, offset,
|
1895
1986
|
elem = this[0],
|
1896
1987
|
parentOffset = {
|
@@ -1916,25 +2007,25 @@ avalon.fn.mix({
|
|
1916
2007
|
left: offset.left - parentOffset.left - avalon.css(elem, "marginLeft", true)
|
1917
2008
|
}
|
1918
2009
|
},
|
1919
|
-
offsetParent: function() {
|
2010
|
+
offsetParent: function () {
|
1920
2011
|
var offsetParent = this[0].offsetParent
|
1921
2012
|
while (offsetParent && avalon.css(offsetParent, "position") === "static") {
|
1922
2013
|
offsetParent = offsetParent.offsetParent;
|
1923
2014
|
}
|
1924
|
-
return avalon(offsetParent)
|
2015
|
+
return avalon(offsetParent || root)
|
1925
2016
|
},
|
1926
|
-
bind: function(type, fn, phase) {
|
2017
|
+
bind: function (type, fn, phase) {
|
1927
2018
|
if (this[0]) { //此方法不会链
|
1928
2019
|
return avalon.bind(this[0], type, fn, phase)
|
1929
2020
|
}
|
1930
2021
|
},
|
1931
|
-
unbind: function(type, fn, phase) {
|
2022
|
+
unbind: function (type, fn, phase) {
|
1932
2023
|
if (this[0]) {
|
1933
2024
|
avalon.unbind(this[0], type, fn, phase)
|
1934
2025
|
}
|
1935
2026
|
return this
|
1936
2027
|
},
|
1937
|
-
val: function(value) {
|
2028
|
+
val: function (value) {
|
1938
2029
|
var node = this[0]
|
1939
2030
|
if (node && node.nodeType === 1) {
|
1940
2031
|
var get = arguments.length === 0
|
@@ -1953,7 +2044,7 @@ avalon.fn.mix({
|
|
1953
2044
|
})
|
1954
2045
|
|
1955
2046
|
if (root.dataset) {
|
1956
|
-
avalon.fn.data = function(name, val) {
|
2047
|
+
avalon.fn.data = function (name, val) {
|
1957
2048
|
var dataset = this[0].dataset
|
1958
2049
|
switch (arguments.length) {
|
1959
2050
|
case 2:
|
@@ -1963,8 +2054,8 @@ if (root.dataset) {
|
|
1963
2054
|
val = dataset[name]
|
1964
2055
|
return parseData(val)
|
1965
2056
|
case 0:
|
1966
|
-
var ret =
|
1967
|
-
for (
|
2057
|
+
var ret = createMap()
|
2058
|
+
for (name in dataset) {
|
1968
2059
|
ret[name] = parseData(dataset[name])
|
1969
2060
|
}
|
1970
2061
|
return ret
|
@@ -1988,15 +2079,15 @@ function parseData(data) {
|
|
1988
2079
|
avalon.each({
|
1989
2080
|
scrollLeft: "pageXOffset",
|
1990
2081
|
scrollTop: "pageYOffset"
|
1991
|
-
}, function(method, prop) {
|
1992
|
-
avalon.fn[method] = function(val) {
|
2082
|
+
}, function (method, prop) {
|
2083
|
+
avalon.fn[method] = function (val) {
|
1993
2084
|
var node = this[0] || {}, win = getWindow(node),
|
1994
2085
|
top = method === "scrollTop"
|
1995
2086
|
if (!arguments.length) {
|
1996
2087
|
return win ? win[prop] : node[method]
|
1997
2088
|
} else {
|
1998
2089
|
if (win) {
|
1999
|
-
win.scrollTo(!top ? val :
|
2090
|
+
win.scrollTo(!top ? val : win[prop], top ? val : win[prop])
|
2000
2091
|
} else {
|
2001
2092
|
node[method] = val
|
2002
2093
|
}
|
@@ -2009,14 +2100,14 @@ function getWindow(node) {
|
|
2009
2100
|
}
|
2010
2101
|
|
2011
2102
|
//=============================css相关==================================
|
2012
|
-
var cssHooks = avalon.cssHooks =
|
2103
|
+
var cssHooks = avalon.cssHooks = createMap()
|
2013
2104
|
var prefixes = ["", "-webkit-", "-moz-", "-ms-"]//去掉opera-15的支持
|
2014
2105
|
var cssMap = {
|
2015
2106
|
"float": "cssFloat"
|
2016
2107
|
}
|
2017
2108
|
avalon.cssNumber = oneObject("columnCount,order,fillOpacity,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom")
|
2018
2109
|
|
2019
|
-
avalon.cssName = function(name, host, camelCase) {
|
2110
|
+
avalon.cssName = function (name, host, camelCase) {
|
2020
2111
|
if (cssMap[name]) {
|
2021
2112
|
return cssMap[name]
|
2022
2113
|
}
|
@@ -2029,15 +2120,15 @@ avalon.cssName = function(name, host, camelCase) {
|
|
2029
2120
|
}
|
2030
2121
|
return null
|
2031
2122
|
}
|
2032
|
-
cssHooks["@:set"] = function(node, name, value) {
|
2123
|
+
cssHooks["@:set"] = function (node, name, value) {
|
2033
2124
|
node.style[name] = value
|
2034
2125
|
}
|
2035
2126
|
|
2036
|
-
cssHooks["@:get"] = function(node, name) {
|
2127
|
+
cssHooks["@:get"] = function (node, name) {
|
2037
2128
|
if (!node || !node.style) {
|
2038
2129
|
throw new Error("getComputedStyle要求传入一个节点 " + node)
|
2039
2130
|
}
|
2040
|
-
var ret, computed = getComputedStyle(node
|
2131
|
+
var ret, computed = getComputedStyle(node)
|
2041
2132
|
if (computed) {
|
2042
2133
|
ret = name === "filter" ? computed.getPropertyValue(name) : computed[name]
|
2043
2134
|
if (ret === "") {
|
@@ -2046,13 +2137,13 @@ cssHooks["@:get"] = function(node, name) {
|
|
2046
2137
|
}
|
2047
2138
|
return ret
|
2048
2139
|
}
|
2049
|
-
cssHooks["opacity:get"] = function(node) {
|
2140
|
+
cssHooks["opacity:get"] = function (node) {
|
2050
2141
|
var ret = cssHooks["@:get"](node, "opacity")
|
2051
2142
|
return ret === "" ? "1" : ret
|
2052
2143
|
}
|
2053
2144
|
|
2054
|
-
"top,left".replace(rword, function(name) {
|
2055
|
-
cssHooks[name + ":get"] = function(node) {
|
2145
|
+
"top,left".replace(rword, function (name) {
|
2146
|
+
cssHooks[name + ":get"] = function (node) {
|
2056
2147
|
var computed = cssHooks["@:get"](node, name)
|
2057
2148
|
return /px$/.test(computed) ? computed :
|
2058
2149
|
avalon(node).position()[name] + "px"
|
@@ -2086,12 +2177,12 @@ function showHidden(node, array) {
|
|
2086
2177
|
}
|
2087
2178
|
}
|
2088
2179
|
|
2089
|
-
"Width,Height".replace(rword, function(name) {//fix 481
|
2180
|
+
"Width,Height".replace(rword, function (name) {//fix 481
|
2090
2181
|
var method = name.toLowerCase(),
|
2091
2182
|
clientProp = "client" + name,
|
2092
2183
|
scrollProp = "scroll" + name,
|
2093
2184
|
offsetProp = "offset" + name
|
2094
|
-
cssHooks[method + ":get"] = function(node, which, override) {
|
2185
|
+
cssHooks[method + ":get"] = function (node, which, override) {
|
2095
2186
|
var boxSizing = -4
|
2096
2187
|
if (typeof override === "number") {
|
2097
2188
|
boxSizing = override
|
@@ -2099,23 +2190,17 @@ function showHidden(node, array) {
|
|
2099
2190
|
which = name === "Width" ? ["Left", "Right"] : ["Top", "Bottom"]
|
2100
2191
|
var ret = node[offsetProp] // border-box 0
|
2101
2192
|
if (boxSizing === 2) { // margin-box 2
|
2102
|
-
return ret
|
2103
|
-
+ avalon.css(node, "margin" + which[0], true)
|
2104
|
-
+ avalon.css(node, "margin" + which[1], true)
|
2193
|
+
return ret + avalon.css(node, "margin" + which[0], true) + avalon.css(node, "margin" + which[1], true)
|
2105
2194
|
}
|
2106
2195
|
if (boxSizing < 0) { // padding-box -2
|
2107
|
-
ret = ret
|
2108
|
-
- avalon.css(node, "border" + which[0] + "Width", true)
|
2109
|
-
- avalon.css(node, "border" + which[1] + "Width", true)
|
2196
|
+
ret = ret - avalon.css(node, "border" + which[0] + "Width", true) - avalon.css(node, "border" + which[1] + "Width", true)
|
2110
2197
|
}
|
2111
2198
|
if (boxSizing === -4) { // content-box -4
|
2112
|
-
ret = ret
|
2113
|
-
- avalon.css(node, "padding" + which[0], true)
|
2114
|
-
- avalon.css(node, "padding" + which[1], true)
|
2199
|
+
ret = ret - avalon.css(node, "padding" + which[0], true) - avalon.css(node, "padding" + which[1], true)
|
2115
2200
|
}
|
2116
2201
|
return ret
|
2117
2202
|
}
|
2118
|
-
cssHooks[method + "&get"] = function(node) {
|
2203
|
+
cssHooks[method + "&get"] = function (node) {
|
2119
2204
|
var hidden = [];
|
2120
2205
|
showHidden(node, hidden);
|
2121
2206
|
var val = cssHooks[method + ":get"](node)
|
@@ -2129,11 +2214,11 @@ function showHidden(node, array) {
|
|
2129
2214
|
}
|
2130
2215
|
return val;
|
2131
2216
|
}
|
2132
|
-
avalon.fn[method] = function(value) { //会忽视其display
|
2217
|
+
avalon.fn[method] = function (value) { //会忽视其display
|
2133
2218
|
var node = this[0]
|
2134
2219
|
if (arguments.length === 0) {
|
2135
2220
|
if (node.setTimeout) { //取得窗口尺寸,IE9后可以用node.innerWidth /innerHeight代替
|
2136
|
-
return node["inner" + name]
|
2221
|
+
return node["inner" + name]
|
2137
2222
|
}
|
2138
2223
|
if (node.nodeType === 9) { //取得页面尺寸
|
2139
2224
|
var doc = node.documentElement
|
@@ -2147,33 +2232,33 @@ function showHidden(node, array) {
|
|
2147
2232
|
return this.css(method, value)
|
2148
2233
|
}
|
2149
2234
|
}
|
2150
|
-
avalon.fn["inner" + name] = function() {
|
2235
|
+
avalon.fn["inner" + name] = function () {
|
2151
2236
|
return cssHooks[method + ":get"](this[0], void 0, -2)
|
2152
2237
|
}
|
2153
|
-
avalon.fn["outer" + name] = function(includeMargin) {
|
2238
|
+
avalon.fn["outer" + name] = function (includeMargin) {
|
2154
2239
|
return cssHooks[method + ":get"](this[0], void 0, includeMargin === true ? 2 : 0)
|
2155
2240
|
}
|
2156
2241
|
})
|
2157
|
-
avalon.fn.offset = function() { //取得距离页面左右角的坐标
|
2158
|
-
var node = this[0]
|
2159
|
-
|
2160
|
-
|
2161
|
-
|
2162
|
-
|
2163
|
-
|
2164
|
-
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2242
|
+
avalon.fn.offset = function () { //取得距离页面左右角的坐标
|
2243
|
+
var node = this[0]
|
2244
|
+
try {
|
2245
|
+
var rect = node.getBoundingClientRect()
|
2246
|
+
// Make sure element is not hidden (display: none) or disconnected
|
2247
|
+
// https://github.com/jquery/jquery/pull/2043/files#r23981494
|
2248
|
+
if (rect.width || rect.height || node.getClientRects().length) {
|
2249
|
+
var doc = node.ownerDocument
|
2250
|
+
var root = doc.documentElement
|
2251
|
+
var win = doc.defaultView
|
2252
|
+
return {
|
2253
|
+
top: rect.top + win.pageYOffset - root.clientTop,
|
2254
|
+
left: rect.left + win.pageXOffset - root.clientLeft
|
2255
|
+
}
|
2256
|
+
}
|
2257
|
+
} catch (e) {
|
2258
|
+
return {
|
2259
|
+
left: 0,
|
2260
|
+
top: 0
|
2261
|
+
}
|
2177
2262
|
}
|
2178
2263
|
}
|
2179
2264
|
//=============================val相关=======================
|
@@ -2183,7 +2268,7 @@ function getValType(el) {
|
|
2183
2268
|
return ret === "input" && /checkbox|radio/.test(el.type) ? "checked" : ret
|
2184
2269
|
}
|
2185
2270
|
var valHooks = {
|
2186
|
-
"select:get": function(node, value) {
|
2271
|
+
"select:get": function (node, value) {
|
2187
2272
|
var option, options = node.options,
|
2188
2273
|
index = node.selectedIndex,
|
2189
2274
|
one = node.type === "select-one" || index < 0,
|
@@ -2206,7 +2291,7 @@ var valHooks = {
|
|
2206
2291
|
}
|
2207
2292
|
return values
|
2208
2293
|
},
|
2209
|
-
"select:set": function(node, values, optionSet) {
|
2294
|
+
"select:set": function (node, values, optionSet) {
|
2210
2295
|
values = [].concat(values) //强制转换为数组
|
2211
2296
|
for (var i = 0, el; el = node.options[i++]; ) {
|
2212
2297
|
if ((el.selected = values.indexOf(el.value) > -1)) {
|
@@ -2224,28 +2309,26 @@ var valHooks = {
|
|
2224
2309
|
**********************************************************************/
|
2225
2310
|
var quote = JSON.stringify
|
2226
2311
|
|
2227
|
-
var keywords =
|
2228
|
-
|
2229
|
-
|
2230
|
-
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2236
|
-
",throws,transient,volatile" +
|
2237
|
-
// ECMA 5 - use strict
|
2238
|
-
",arguments,let,yield" + ",undefined"
|
2312
|
+
var keywords = [
|
2313
|
+
"break,case,catch,continue,debugger,default,delete,do,else,false",
|
2314
|
+
"finally,for,function,if,in,instanceof,new,null,return,switch,this",
|
2315
|
+
"throw,true,try,typeof,var,void,while,with", /* 关键字*/
|
2316
|
+
"abstract,boolean,byte,char,class,const,double,enum,export,extends",
|
2317
|
+
"final,float,goto,implements,import,int,interface,long,native",
|
2318
|
+
"package,private,protected,public,short,static,super,synchronized",
|
2319
|
+
"throws,transient,volatile", /*保留字*/
|
2320
|
+
"arguments,let,yield,undefined" /* ECMA 5 - use strict*/].join(",")
|
2239
2321
|
var rrexpstr = /\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|[\s\t\n]*\.[\s\t\n]*[$\w\.]+/g
|
2240
2322
|
var rsplit = /[^\w$]+/g
|
2241
2323
|
var rkeywords = new RegExp(["\\b" + keywords.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g')
|
2242
2324
|
var rnumber = /\b\d[^,]*/g
|
2243
2325
|
var rcomma = /^,+|,+$/g
|
2244
|
-
var cacheVars =
|
2245
|
-
var getVariables = function(code) {
|
2326
|
+
var cacheVars = new Cache(512)
|
2327
|
+
var getVariables = function (code) {
|
2246
2328
|
var key = "," + code.trim()
|
2247
|
-
|
2248
|
-
|
2329
|
+
var ret = cacheVars.get(key)
|
2330
|
+
if (ret) {
|
2331
|
+
return ret
|
2249
2332
|
}
|
2250
2333
|
var match = code
|
2251
2334
|
.replace(rrexpstr, "")
|
@@ -2254,7 +2337,7 @@ var getVariables = function(code) {
|
|
2254
2337
|
.replace(rnumber, "")
|
2255
2338
|
.replace(rcomma, "")
|
2256
2339
|
.split(/^$|,+/)
|
2257
|
-
return cacheVars(key, uniqSet(match))
|
2340
|
+
return cacheVars.put(key, uniqSet(match))
|
2258
2341
|
}
|
2259
2342
|
/*添加赋值语句*/
|
2260
2343
|
|
@@ -2287,7 +2370,7 @@ function uniqSet(array) {
|
|
2287
2370
|
return ret
|
2288
2371
|
}
|
2289
2372
|
//缓存求值函数,以便多次利用
|
2290
|
-
var cacheExprs =
|
2373
|
+
var cacheExprs = new Cache(128)
|
2291
2374
|
//取得求值函数及其传参
|
2292
2375
|
var rduplex = /\w\[.*\]|\w\.\w/
|
2293
2376
|
var rproxy = /(\$proxy\$[a-z]+)\d+$/
|
@@ -2299,16 +2382,16 @@ var rthimLeftParentheses = /"\s*\(/g
|
|
2299
2382
|
function parseFilter(val, filters) {
|
2300
2383
|
filters = filters
|
2301
2384
|
.replace(rthimRightParentheses, "")//处理最后的小括号
|
2302
|
-
.replace(rthimOtherParentheses, function() {//处理其他小括号
|
2385
|
+
.replace(rthimOtherParentheses, function () {//处理其他小括号
|
2303
2386
|
return "],|"
|
2304
2387
|
})
|
2305
|
-
.replace(rquoteFilterName, function(a, b) { //处理|及它后面的过滤器的名字
|
2388
|
+
.replace(rquoteFilterName, function (a, b) { //处理|及它后面的过滤器的名字
|
2306
2389
|
return "[" + quote(b)
|
2307
2390
|
})
|
2308
|
-
.replace(rpatchBracket, function() {
|
2391
|
+
.replace(rpatchBracket, function () {
|
2309
2392
|
return '"],["'
|
2310
2393
|
})
|
2311
|
-
.replace(rthimLeftParentheses, function() {
|
2394
|
+
.replace(rthimLeftParentheses, function () {
|
2312
2395
|
return '",'
|
2313
2396
|
}) + "]"
|
2314
2397
|
return "return avalon.filters.$filter(" + val + ", " + filters + ")"
|
@@ -2317,7 +2400,7 @@ function parseFilter(val, filters) {
|
|
2317
2400
|
function parseExpr(code, scopes, data) {
|
2318
2401
|
var dataType = data.type
|
2319
2402
|
var filters = data.filters || ""
|
2320
|
-
var exprId = scopes.map(function(el) {
|
2403
|
+
var exprId = scopes.map(function (el) {
|
2321
2404
|
return String(el.$id).replace(rproxy, "$1")
|
2322
2405
|
}) + code + dataType + filters
|
2323
2406
|
var vars = getVariables(code).concat(),
|
@@ -2341,9 +2424,9 @@ function parseExpr(code, scopes, data) {
|
|
2341
2424
|
}
|
2342
2425
|
if (dataType !== "duplex" && (code.indexOf("||") > -1 || code.indexOf("&&") > -1)) {
|
2343
2426
|
//https://github.com/RubyLouvre/avalon/issues/583
|
2344
|
-
data.vars.forEach(function(v) {
|
2427
|
+
data.vars.forEach(function (v) {
|
2345
2428
|
var reg = new RegExp("\\b" + v + "(?:\\.\\w+|\\[\\w+\\])+", "ig")
|
2346
|
-
code = code.replace(reg, function(_) {
|
2429
|
+
code = code.replace(reg, function (_) {
|
2347
2430
|
var c = _.charAt(v.length)
|
2348
2431
|
var r = IEVersion ? code.slice(arguments[1] + _.length) : RegExp.rightContext
|
2349
2432
|
var method = /^\s*\(/.test(r)
|
@@ -2370,7 +2453,7 @@ function parseExpr(code, scopes, data) {
|
|
2370
2453
|
//---------------args----------------
|
2371
2454
|
data.args = args
|
2372
2455
|
//---------------cache----------------
|
2373
|
-
var fn = cacheExprs
|
2456
|
+
var fn = cacheExprs.get(exprId) //直接从缓存,免得重复生成
|
2374
2457
|
if (fn) {
|
2375
2458
|
data.evaluator = fn
|
2376
2459
|
return
|
@@ -2394,7 +2477,7 @@ function parseExpr(code, scopes, data) {
|
|
2394
2477
|
"= vvv;\n} "
|
2395
2478
|
try {
|
2396
2479
|
fn = Function.apply(noop, names.concat(_body))
|
2397
|
-
data.evaluator = cacheExprs(exprId, fn)
|
2480
|
+
data.evaluator = cacheExprs.put(exprId, fn)
|
2398
2481
|
} catch (e) {
|
2399
2482
|
log("debug: parse error," + e.message)
|
2400
2483
|
}
|
@@ -2416,11 +2499,11 @@ function parseExpr(code, scopes, data) {
|
|
2416
2499
|
}
|
2417
2500
|
try {
|
2418
2501
|
fn = Function.apply(noop, names.concat("'use strict';\n" + prefix + code))
|
2419
|
-
data.evaluator = cacheExprs(exprId, fn)
|
2502
|
+
data.evaluator = cacheExprs.put(exprId, fn)
|
2420
2503
|
} catch (e) {
|
2421
2504
|
log("debug: parse error," + e.message)
|
2422
2505
|
} finally {
|
2423
|
-
vars =
|
2506
|
+
vars = assigns = names = null //释放内存
|
2424
2507
|
}
|
2425
2508
|
}
|
2426
2509
|
|
@@ -2429,7 +2512,7 @@ function parseExpr(code, scopes, data) {
|
|
2429
2512
|
|
2430
2513
|
function parseExprProxy(code, scopes, data, tokens, noregister) {
|
2431
2514
|
if (Array.isArray(tokens)) {
|
2432
|
-
code = tokens.map(function(el) {
|
2515
|
+
code = tokens.map(function (el) {
|
2433
2516
|
return el.expr ? "(" + el.value + ")" : quote(el.value)
|
2434
2517
|
}).join(" + ")
|
2435
2518
|
}
|
@@ -2443,16 +2526,12 @@ function parseExprProxy(code, scopes, data, tokens, noregister) {
|
|
2443
2526
|
}
|
2444
2527
|
}
|
2445
2528
|
avalon.parseExprProxy = parseExprProxy
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
//ms-controller绑定已经在scanTag 方法中实现
|
2451
|
-
//ms-important绑定已经在scanTag 方法中实现
|
2452
|
-
var bools = "autofocus,autoplay,async,allowTransparency,checked,controls,declare,disabled,defer,defaultChecked,defaultSelected" +
|
2453
|
-
"contentEditable,isMap,loop,multiple,noHref,noResize,noShade,open,readOnly,selected"
|
2529
|
+
var bools = ["autofocus,autoplay,async,allowTransparency,checked,controls",
|
2530
|
+
"declare,disabled,defer,defaultChecked,defaultSelected",
|
2531
|
+
"contentEditable,isMap,loop,multiple,noHref,noResize,noShade",
|
2532
|
+
"open,readOnly,selected"].join(",")
|
2454
2533
|
var boolMap = {}
|
2455
|
-
bools.replace(rword, function(name) {
|
2534
|
+
bools.replace(rword, function (name) {
|
2456
2535
|
boolMap[name.toLowerCase()] = name
|
2457
2536
|
})
|
2458
2537
|
|
@@ -2465,21 +2544,23 @@ var propMap = {//属性名映射
|
|
2465
2544
|
"http-equiv": "httpEquiv"
|
2466
2545
|
}
|
2467
2546
|
|
2468
|
-
var anomaly = "accessKey,bgColor,cellPadding,cellSpacing,codeBase,codeType,colSpan
|
2469
|
-
|
2547
|
+
var anomaly = ["accessKey,bgColor,cellPadding,cellSpacing,codeBase,codeType,colSpan",
|
2548
|
+
"dateTime,defaultValue,frameBorder,longDesc,maxLength,marginWidth,marginHeight",
|
2549
|
+
"rowSpan,tabIndex,useMap,vSpace,valueType,vAlign"].join(",")
|
2550
|
+
anomaly.replace(rword, function (name) {
|
2470
2551
|
propMap[name.toLowerCase()] = name
|
2471
2552
|
})
|
2472
2553
|
|
2473
2554
|
var rnoscripts = /<noscript.*?>(?:[\s\S]+?)<\/noscript>/img
|
2474
2555
|
var rnoscriptText = /<noscript.*?>([\s\S]+?)<\/noscript>/im
|
2475
2556
|
|
2476
|
-
var getXHR = function() {
|
2477
|
-
return new (window.XMLHttpRequest || ActiveXObject)("Microsoft.XMLHTTP")
|
2557
|
+
var getXHR = function () {
|
2558
|
+
return new (window.XMLHttpRequest || ActiveXObject)("Microsoft.XMLHTTP")// jshint ignore:line
|
2478
2559
|
}
|
2479
2560
|
|
2480
2561
|
var cacheTmpls = avalon.templateCache = {}
|
2481
2562
|
|
2482
|
-
bindingHandlers.attr = function(data, vmodels) {
|
2563
|
+
bindingHandlers.attr = function (data, vmodels) {
|
2483
2564
|
var text = data.value.trim(),
|
2484
2565
|
simple = true
|
2485
2566
|
if (text.indexOf(openTag) > -1 && text.indexOf(closeTag) > 2) {
|
@@ -2493,7 +2574,10 @@ bindingHandlers.attr = function(data, vmodels) {
|
|
2493
2574
|
var elem = data.element
|
2494
2575
|
data.includeRendered = getBindingCallback(elem, "data-include-rendered", vmodels)
|
2495
2576
|
data.includeLoaded = getBindingCallback(elem, "data-include-loaded", vmodels)
|
2496
|
-
var outer = data.
|
2577
|
+
var outer = data.includeReplace = !!avalon(elem).data("includeReplace")
|
2578
|
+
if (avalon(elem).data("includeCache")) {
|
2579
|
+
data.templateCache = {}
|
2580
|
+
}
|
2497
2581
|
data.startInclude = DOC.createComment("ms-include")
|
2498
2582
|
data.endInclude = DOC.createComment("ms-include-end")
|
2499
2583
|
if (outer) {
|
@@ -2509,7 +2593,7 @@ bindingHandlers.attr = function(data, vmodels) {
|
|
2509
2593
|
parseExprProxy(text, vmodels, data, (simple ? 0 : scanExpr(data.value)))
|
2510
2594
|
}
|
2511
2595
|
|
2512
|
-
bindingExecutors.attr = function(val, elem, data) {
|
2596
|
+
bindingExecutors.attr = function (val, elem, data) {
|
2513
2597
|
var method = data.type,
|
2514
2598
|
attrName = data.param
|
2515
2599
|
if (method === "css") {
|
@@ -2544,38 +2628,50 @@ bindingExecutors.attr = function(val, elem, data) {
|
|
2544
2628
|
var vmodels = data.vmodels
|
2545
2629
|
var rendered = data.includeRendered
|
2546
2630
|
var loaded = data.includeLoaded
|
2547
|
-
var replace = data.
|
2631
|
+
var replace = data.includeReplace
|
2548
2632
|
var target = replace ? elem.parentNode : elem
|
2549
|
-
var scanTemplate = function(text) {
|
2633
|
+
var scanTemplate = function (text) {
|
2550
2634
|
if (loaded) {
|
2551
2635
|
text = loaded.apply(target, [text].concat(vmodels))
|
2552
2636
|
}
|
2553
2637
|
if (rendered) {
|
2554
|
-
checkScan(target, function() {
|
2638
|
+
checkScan(target, function () {
|
2555
2639
|
rendered.call(target)
|
2556
2640
|
}, NaN)
|
2557
2641
|
}
|
2642
|
+
var lastID = data.includeLastID
|
2643
|
+
if (data.templateCache && lastID && lastID !== val) {
|
2644
|
+
var lastTemplate = data.templateCache[lastID]
|
2645
|
+
if (!lastTemplate) {
|
2646
|
+
lastTemplate = data.templateCache[lastID] = DOC.createElement("div")
|
2647
|
+
ifGroup.appendChild(lastTemplate)
|
2648
|
+
}
|
2649
|
+
}
|
2650
|
+
data.includeLastID = val
|
2558
2651
|
while (true) {
|
2559
2652
|
var node = data.startInclude.nextSibling
|
2560
2653
|
if (node && node !== data.endInclude) {
|
2561
2654
|
target.removeChild(node)
|
2655
|
+
if (lastTemplate)
|
2656
|
+
lastTemplate.appendChild(node)
|
2562
2657
|
} else {
|
2563
2658
|
break
|
2564
2659
|
}
|
2565
2660
|
}
|
2566
|
-
var dom =
|
2661
|
+
var dom = getTemplateNodes(data, val, text)
|
2567
2662
|
var nodes = avalon.slice(dom.childNodes)
|
2568
2663
|
target.insertBefore(dom, data.endInclude)
|
2569
2664
|
scanNodeArray(nodes, vmodels)
|
2570
2665
|
}
|
2666
|
+
|
2571
2667
|
if (data.param === "src") {
|
2572
2668
|
if (cacheTmpls[val]) {
|
2573
|
-
avalon.nextTick(function() {
|
2669
|
+
avalon.nextTick(function () {
|
2574
2670
|
scanTemplate(cacheTmpls[val])
|
2575
2671
|
})
|
2576
2672
|
} else {
|
2577
2673
|
var xhr = getXHR()
|
2578
|
-
xhr.onreadystatechange = function() {
|
2674
|
+
xhr.onreadystatechange = function () {
|
2579
2675
|
if (xhr.readyState === 4) {
|
2580
2676
|
var s = xhr.status
|
2581
2677
|
if (s >= 200 && s < 300 || s === 304 || s === 1223) {
|
@@ -2611,7 +2707,7 @@ bindingExecutors.attr = function(val, elem, data) {
|
|
2611
2707
|
}
|
2612
2708
|
}
|
2613
2709
|
}
|
2614
|
-
avalon.nextTick(function() {
|
2710
|
+
avalon.nextTick(function () {
|
2615
2711
|
scanTemplate(el.fixIE78 || el.value || el.innerText || el.innerHTML)
|
2616
2712
|
})
|
2617
2713
|
}
|
@@ -2630,12 +2726,22 @@ bindingExecutors.attr = function(val, elem, data) {
|
|
2630
2726
|
}
|
2631
2727
|
}
|
2632
2728
|
|
2729
|
+
function getTemplateNodes(data, id, text) {
|
2730
|
+
var div = data.templateCache && data.templateCache[id]
|
2731
|
+
if (div) {
|
2732
|
+
var dom = DOC.createDocumentFragment(), firstChild
|
2733
|
+
while (firstChild = div.firstChild) {
|
2734
|
+
dom.appendChild(firstChild)
|
2735
|
+
}
|
2736
|
+
return dom
|
2737
|
+
}
|
2738
|
+
return avalon.parseHTML(text)
|
2739
|
+
}
|
2740
|
+
|
2633
2741
|
//这几个指令都可以使用插值表达式,如ms-src="aaa/{{b}}/{{c}}.html"
|
2634
|
-
"title,alt,src,value,css,include,href".replace(rword, function(name) {
|
2742
|
+
"title,alt,src,value,css,include,href".replace(rword, function (name) {
|
2635
2743
|
bindingHandlers[name] = bindingHandlers.attr
|
2636
2744
|
})
|
2637
|
-
//ms-include绑定已由ms-attr绑定实现
|
2638
|
-
|
2639
2745
|
//根据VM的属性值或表达式的值切换类名,ms-class="xxx yyy zzz:flag"
|
2640
2746
|
//http://www.cnblogs.com/rubylouvre/archive/2012/12/17/2818540.html
|
2641
2747
|
bindingHandlers["class"] = function(data, vmodels) {
|
@@ -2726,6 +2832,10 @@ bindingExecutors ["class"] = function(val, elem, data) {
|
|
2726
2832
|
"hover,active".replace(rword, function(method) {
|
2727
2833
|
bindingHandlers[method] = bindingHandlers["class"]
|
2728
2834
|
})
|
2835
|
+
//ms-controller绑定已经在scanTag 方法中实现
|
2836
|
+
//ms-css绑定已由ms-attr绑定实现
|
2837
|
+
|
2838
|
+
|
2729
2839
|
// bindingHandlers.data 定义在if.js
|
2730
2840
|
bindingExecutors.data = function(val, elem, data) {
|
2731
2841
|
var key = "data-" + data.param
|
@@ -2736,273 +2846,23 @@ bindingExecutors.data = function(val, elem, data) {
|
|
2736
2846
|
}
|
2737
2847
|
}
|
2738
2848
|
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
elem.data = val
|
2745
|
-
} catch (e) {
|
2746
|
-
}
|
2747
|
-
} else { //绑定在特性节点上
|
2748
|
-
elem.textContent = val
|
2749
|
-
}
|
2750
|
-
}
|
2849
|
+
//双工绑定
|
2850
|
+
var duplexBinding = bindingHandlers.duplex = function (data, vmodels) {
|
2851
|
+
var elem = data.element,
|
2852
|
+
hasCast
|
2853
|
+
parseExprProxy(data.value, vmodels, data, 0, 1)
|
2751
2854
|
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
return
|
2759
|
-
if (val.nodeType === 11) { //将val转换为文档碎片
|
2760
|
-
var fragment = val
|
2761
|
-
} else if (val.nodeType === 1 || val.item) {
|
2762
|
-
var nodes = val.nodeType === 1 ? val.childNodes : val.item ? val : []
|
2763
|
-
fragment = hyperspace.cloneNode(true)
|
2764
|
-
while (nodes[0]) {
|
2765
|
-
fragment.appendChild(nodes[0])
|
2766
|
-
}
|
2767
|
-
} else {
|
2768
|
-
fragment = avalon.parseHTML(val)
|
2769
|
-
}
|
2770
|
-
//插入占位符, 如果是过滤器,需要有节制地移除指定的数量,如果是html指令,直接清空
|
2771
|
-
var comment = DOC.createComment("ms-html")
|
2772
|
-
if (isHtmlFilter) {
|
2773
|
-
parent.insertBefore(comment, elem)
|
2774
|
-
var n = data.group, i = 1
|
2775
|
-
while (i < n) {
|
2776
|
-
var node = elem.nextSibling
|
2777
|
-
if (node) {
|
2778
|
-
parent.removeChild(node)
|
2779
|
-
i++
|
2780
|
-
}
|
2781
|
-
}
|
2782
|
-
parent.removeChild(elem)
|
2783
|
-
data.element = comment //防止被CG
|
2784
|
-
} else {
|
2785
|
-
avalon.clearHTML(parent).appendChild(comment)
|
2786
|
-
}
|
2787
|
-
if (isHtmlFilter) {
|
2788
|
-
data.group = fragment.childNodes.length || 1
|
2789
|
-
}
|
2790
|
-
nodes = avalon.slice(fragment.childNodes)
|
2791
|
-
if (nodes[0]) {
|
2792
|
-
if (comment.parentNode)
|
2793
|
-
comment.parentNode.replaceChild(fragment, comment)
|
2794
|
-
if (isHtmlFilter) {
|
2795
|
-
data.element = nodes[0]
|
2796
|
-
}
|
2797
|
-
}
|
2798
|
-
scanNodeArray(nodes, data.vmodels)
|
2799
|
-
}
|
2800
|
-
|
2801
|
-
bindingHandlers["if"] =
|
2802
|
-
bindingHandlers.data =
|
2803
|
-
bindingHandlers.text =
|
2804
|
-
bindingHandlers.html =
|
2805
|
-
function(data, vmodels) {
|
2806
|
-
parseExprProxy(data.value, vmodels, data)
|
2807
|
-
}
|
2808
|
-
|
2809
|
-
bindingExecutors["if"] = function(val, elem, data) {
|
2810
|
-
if (val) { //插回DOM树
|
2811
|
-
if (elem.nodeType === 8) {
|
2812
|
-
elem.parentNode.replaceChild(data.template, elem)
|
2813
|
-
elem = data.element = data.template //这时可能为null
|
2814
|
-
}
|
2815
|
-
if (elem.getAttribute(data.name)) {
|
2816
|
-
elem.removeAttribute(data.name)
|
2817
|
-
scanAttr(elem, data.vmodels)
|
2818
|
-
}
|
2819
|
-
data.rollback = null
|
2820
|
-
} else { //移出DOM树,并用注释节点占据原位置
|
2821
|
-
if (elem.nodeType === 1) {
|
2822
|
-
var node = data.element = DOC.createComment("ms-if")
|
2823
|
-
elem.parentNode.replaceChild(node, elem)
|
2824
|
-
data.template = elem //元素节点
|
2825
|
-
ifGroup.appendChild(elem)
|
2826
|
-
data.rollback = function() {
|
2827
|
-
if (elem.parentNode === ifGroup) {
|
2828
|
-
ifGroup.removeChild(elem)
|
2829
|
-
}
|
2830
|
-
}
|
2831
|
-
}
|
2832
|
-
}
|
2833
|
-
}
|
2834
|
-
|
2835
|
-
|
2836
|
-
function parseDisplay(nodeName, val) {
|
2837
|
-
//用于取得此类标签的默认display值
|
2838
|
-
var key = "_" + nodeName
|
2839
|
-
if (!parseDisplay[key]) {
|
2840
|
-
var node = DOC.createElement(nodeName)
|
2841
|
-
root.appendChild(node)
|
2842
|
-
if (W3C) {
|
2843
|
-
val = getComputedStyle(node, null).display
|
2844
|
-
} else {
|
2845
|
-
val = node.currentStyle.display
|
2846
|
-
}
|
2847
|
-
root.removeChild(node)
|
2848
|
-
parseDisplay[key] = val
|
2849
|
-
}
|
2850
|
-
return parseDisplay[key]
|
2851
|
-
}
|
2852
|
-
|
2853
|
-
avalon.parseDisplay = parseDisplay
|
2854
|
-
|
2855
|
-
bindingHandlers.visible = function(data, vmodels) {
|
2856
|
-
var elem = avalon(data.element)
|
2857
|
-
var display = elem.css("display")
|
2858
|
-
if (display === "none") {
|
2859
|
-
var style = elem[0].style
|
2860
|
-
var has = /visibility/i.test(style.cssText)
|
2861
|
-
var visible = elem.css("visibility")
|
2862
|
-
style.display = ""
|
2863
|
-
style.visibility = "hidden"
|
2864
|
-
display = elem.css("display")
|
2865
|
-
if (display === "none") {
|
2866
|
-
display = parseDisplay(elem[0].nodeName)
|
2867
|
-
}
|
2868
|
-
style.visibility = has ? visible : ""
|
2869
|
-
}
|
2870
|
-
data.display = display
|
2871
|
-
parseExprProxy(data.value, vmodels, data)
|
2872
|
-
}
|
2873
|
-
|
2874
|
-
bindingExecutors.visible = function(val, elem, data) {
|
2875
|
-
elem.style.display = val ? data.display : "none"
|
2876
|
-
}
|
2877
|
-
|
2878
|
-
var rdash = /\(([^)]*)\)/
|
2879
|
-
bindingHandlers.on = function(data, vmodels) {
|
2880
|
-
var value = data.value
|
2881
|
-
data.type = "on"
|
2882
|
-
var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
|
2883
|
-
if (typeof bindingHandlers.on[eventType + "Hook"] === "function") {
|
2884
|
-
bindingHandlers.on[eventType + "Hook"](data)
|
2885
|
-
}
|
2886
|
-
if (value.indexOf("(") > 0 && value.indexOf(")") > -1) {
|
2887
|
-
var matched = (value.match(rdash) || ["", ""])[1].trim()
|
2888
|
-
if (matched === "" || matched === "$event") { // aaa() aaa($event)当成aaa处理
|
2889
|
-
value = value.replace(rdash, "")
|
2890
|
-
}
|
2891
|
-
}
|
2892
|
-
parseExprProxy(value, vmodels, data)
|
2893
|
-
}
|
2894
|
-
|
2895
|
-
bindingExecutors.on = function(callback, elem, data) {
|
2896
|
-
callback = function(e) {
|
2897
|
-
var fn = data.evaluator || noop
|
2898
|
-
return fn.apply(this, data.args.concat(e))
|
2899
|
-
}
|
2900
|
-
var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
|
2901
|
-
if (eventType === "scan") {
|
2902
|
-
callback.call(elem, {
|
2903
|
-
type: eventType
|
2904
|
-
})
|
2905
|
-
} else if (typeof data.specialBind === "function") {
|
2906
|
-
data.specialBind(elem, callback)
|
2907
|
-
} else {
|
2908
|
-
var removeFn = avalon.bind(elem, eventType, callback)
|
2909
|
-
}
|
2910
|
-
data.rollback = function() {
|
2911
|
-
if (typeof data.specialUnbind === "function") {
|
2912
|
-
data.specialUnbind()
|
2913
|
-
} else {
|
2914
|
-
avalon.unbind(elem, eventType, removeFn)
|
2915
|
-
}
|
2916
|
-
}
|
2917
|
-
}
|
2918
|
-
|
2919
|
-
|
2920
|
-
bindingHandlers.widget = function(data, vmodels) {
|
2921
|
-
var args = data.value.match(rword)
|
2922
|
-
var elem = data.element
|
2923
|
-
var widget = args[0]
|
2924
|
-
var id = args[1]
|
2925
|
-
if (!id || id === "$") {//没有定义或为$时,取组件名+随机数
|
2926
|
-
id = generateID(widget)
|
2927
|
-
}
|
2928
|
-
var optName = args[2] || widget//没有定义,取组件名
|
2929
|
-
var constructor = avalon.ui[widget]
|
2930
|
-
if (typeof constructor === "function") { //ms-widget="tabs,tabsAAA,optname"
|
2931
|
-
vmodels = elem.vmodels || vmodels
|
2932
|
-
for (var i = 0, v; v = vmodels[i++]; ) {
|
2933
|
-
if (v.hasOwnProperty(optName) && typeof v[optName] === "object") {
|
2934
|
-
var vmOptions = v[optName]
|
2935
|
-
vmOptions = vmOptions.$model || vmOptions
|
2936
|
-
break
|
2937
|
-
}
|
2938
|
-
}
|
2939
|
-
if (vmOptions) {
|
2940
|
-
var wid = vmOptions[widget + "Id"]
|
2941
|
-
if (typeof wid === "string") {
|
2942
|
-
id = wid
|
2943
|
-
}
|
2944
|
-
}
|
2945
|
-
//抽取data-tooltip-text、data-tooltip-attr属性,组成一个配置对象
|
2946
|
-
var widgetData = avalon.getWidgetData(elem, widget)
|
2947
|
-
data.value = [widget, id, optName].join(",")
|
2948
|
-
data[widget + "Id"] = id
|
2949
|
-
data.evaluator = noop
|
2950
|
-
elem.msData["ms-widget-id"] = id
|
2951
|
-
var options = data[widget + "Options"] = avalon.mix({}, constructor.defaults, vmOptions || {}, widgetData)
|
2952
|
-
elem.removeAttribute("ms-widget")
|
2953
|
-
var vmodel = constructor(elem, data, vmodels) || {} //防止组件不返回VM
|
2954
|
-
if (vmodel.$id) {
|
2955
|
-
avalon.vmodels[id] = vmodel
|
2956
|
-
createSignalTower(elem, vmodel)
|
2957
|
-
if (vmodel.hasOwnProperty("$init")) {
|
2958
|
-
vmodel.$init(function() {
|
2959
|
-
avalon.scan(elem, [vmodel].concat(vmodels))
|
2960
|
-
if (typeof options.onInit === "function") {
|
2961
|
-
options.onInit.call(elem, vmodel, options, vmodels)
|
2962
|
-
}
|
2963
|
-
})
|
2964
|
-
}
|
2965
|
-
data.rollback = function() {
|
2966
|
-
try {
|
2967
|
-
vmodel.widgetElement = null
|
2968
|
-
vmodel.$remove()
|
2969
|
-
} catch (e) {
|
2970
|
-
}
|
2971
|
-
elem.msData = {}
|
2972
|
-
delete avalon.vmodels[vmodel.$id]
|
2973
|
-
}
|
2974
|
-
addSubscribers(data, widgetList)
|
2975
|
-
if (window.chrome) {
|
2976
|
-
elem.addEventListener("DOMNodeRemovedFromDocument", function() {
|
2977
|
-
setTimeout(removeSubscribers)
|
2978
|
-
})
|
2979
|
-
}
|
2980
|
-
} else {
|
2981
|
-
avalon.scan(elem, vmodels)
|
2982
|
-
}
|
2983
|
-
} else if (vmodels.length) { //如果该组件还没有加载,那么保存当前的vmodels
|
2984
|
-
elem.vmodels = vmodels
|
2985
|
-
}
|
2986
|
-
}
|
2987
|
-
var widgetList = []
|
2988
|
-
//不存在 bindingExecutors.widget
|
2989
|
-
//双工绑定
|
2990
|
-
var duplexBinding = bindingHandlers.duplex = function(data, vmodels) {
|
2991
|
-
var elem = data.element,
|
2992
|
-
hasCast
|
2993
|
-
parseExprProxy(data.value, vmodels, data, 0, 1)
|
2994
|
-
|
2995
|
-
data.changed = getBindingCallback(elem, "data-duplex-changed", vmodels) || noop
|
2996
|
-
if (data.evaluator && data.args) {
|
2997
|
-
var params = []
|
2998
|
-
var casting = oneObject("string,number,boolean,checked")
|
2999
|
-
if (elem.type === "radio" && data.param === "") {
|
3000
|
-
data.param = "checked"
|
2855
|
+
data.changed = getBindingCallback(elem, "data-duplex-changed", vmodels) || noop
|
2856
|
+
if (data.evaluator && data.args) {
|
2857
|
+
var params = []
|
2858
|
+
var casting = oneObject("string,number,boolean,checked")
|
2859
|
+
if (elem.type === "radio" && data.param === "") {
|
2860
|
+
data.param = "checked"
|
3001
2861
|
}
|
3002
2862
|
if (elem.msData) {
|
3003
2863
|
elem.msData["ms-duplex"] = data.value
|
3004
2864
|
}
|
3005
|
-
data.param.replace(/\w+/g, function(name) {
|
2865
|
+
data.param.replace(/\w+/g, function (name) {
|
3006
2866
|
if (/^(checkbox|radio)$/.test(elem.type) && /^(radio|checked)$/.test(name)) {
|
3007
2867
|
if (name === "radio")
|
3008
2868
|
log("ms-duplex-radio已经更名为ms-duplex-checked")
|
@@ -3025,14 +2885,14 @@ var duplexBinding = bindingHandlers.duplex = function(data, vmodels) {
|
|
3025
2885
|
params.push("string")
|
3026
2886
|
}
|
3027
2887
|
data.param = params.join("-")
|
3028
|
-
data.bound = function(type, callback) {
|
2888
|
+
data.bound = function (type, callback) {
|
3029
2889
|
if (elem.addEventListener) {
|
3030
2890
|
elem.addEventListener(type, callback, false)
|
3031
2891
|
} else {
|
3032
2892
|
elem.attachEvent("on" + type, callback)
|
3033
2893
|
}
|
3034
2894
|
var old = data.rollback
|
3035
|
-
data.rollback = function() {
|
2895
|
+
data.rollback = function () {
|
3036
2896
|
elem.avalonSetter = null
|
3037
2897
|
avalon.unbind(elem, type, callback)
|
3038
2898
|
old && old()
|
@@ -3054,32 +2914,44 @@ function fixNull(val) {
|
|
3054
2914
|
}
|
3055
2915
|
avalon.duplexHooks = {
|
3056
2916
|
checked: {
|
3057
|
-
get: function(val, data) {
|
2917
|
+
get: function (val, data) {
|
3058
2918
|
return !data.element.oldValue
|
3059
2919
|
}
|
3060
2920
|
},
|
3061
2921
|
string: {
|
3062
|
-
get: function(val) { //同步到VM
|
2922
|
+
get: function (val) { //同步到VM
|
3063
2923
|
return val
|
3064
2924
|
},
|
3065
2925
|
set: fixNull
|
3066
2926
|
},
|
3067
2927
|
"boolean": {
|
3068
|
-
get: function(val) {
|
2928
|
+
get: function (val) {
|
3069
2929
|
return val === "true"
|
3070
2930
|
},
|
3071
2931
|
set: fixNull
|
3072
2932
|
},
|
3073
2933
|
number: {
|
3074
|
-
get: function(val) {
|
3075
|
-
|
2934
|
+
get: function (val, data) {
|
2935
|
+
var number = parseFloat(val)
|
2936
|
+
if (-val === -number) {
|
2937
|
+
return number
|
2938
|
+
}
|
2939
|
+
var arr = /strong|medium|weak/.exec(data.element.getAttribute("data-duplex-number")) || ["medium"]
|
2940
|
+
switch (arr[0]) {
|
2941
|
+
case "strong":
|
2942
|
+
return 0
|
2943
|
+
case "medium":
|
2944
|
+
return val === "" ? "" : 0
|
2945
|
+
case "weak":
|
2946
|
+
return val
|
2947
|
+
}
|
3076
2948
|
},
|
3077
2949
|
set: fixNull
|
3078
2950
|
}
|
3079
2951
|
}
|
3080
2952
|
|
3081
2953
|
function pipe(val, data, action, e) {
|
3082
|
-
data.param.replace(/\w+/g, function(name) {
|
2954
|
+
data.param.replace(/\w+/g, function (name) {
|
3083
2955
|
var hook = avalon.duplexHooks[name]
|
3084
2956
|
if (hook && typeof hook[action] === "function") {
|
3085
2957
|
val = hook[action](val, data)
|
@@ -3089,18 +2961,8 @@ function pipe(val, data, action, e) {
|
|
3089
2961
|
}
|
3090
2962
|
|
3091
2963
|
var TimerID, ribbon = []
|
3092
|
-
function W3CFire(el, name, detail) {
|
3093
|
-
var event = DOC.createEvent("Events")
|
3094
|
-
event.initEvent(name, true, true)
|
3095
|
-
event.fireByAvalon = true//签名,标记事件是由avalon触发
|
3096
|
-
//event.isTrusted = false 设置这个opera会报错
|
3097
|
-
if (detail)
|
3098
|
-
event.detail = detail
|
3099
|
-
el.dispatchEvent(event)
|
3100
|
-
}
|
3101
2964
|
|
3102
|
-
|
3103
|
-
avalon.tick = function(fn) {
|
2965
|
+
avalon.tick = function (fn) {
|
3104
2966
|
if (ribbon.push(fn) === 1) {
|
3105
2967
|
TimerID = setInterval(ticker, 60)
|
3106
2968
|
}
|
@@ -3119,15 +2981,18 @@ function ticker() {
|
|
3119
2981
|
}
|
3120
2982
|
|
3121
2983
|
var watchValueInTimer = noop
|
3122
|
-
|
2984
|
+
var rmsinput = /text|password|hidden/
|
2985
|
+
new function () {// jshint ignore:line
|
3123
2986
|
try {//#272 IE9-IE11, firefox
|
3124
2987
|
var setters = {}
|
3125
2988
|
var aproto = HTMLInputElement.prototype
|
3126
2989
|
var bproto = HTMLTextAreaElement.prototype
|
3127
|
-
function newSetter(value) {
|
2990
|
+
function newSetter(value) {// jshint ignore:line
|
3128
2991
|
if (avalon.contains(root, this)) {
|
3129
2992
|
setters[this.tagName].call(this, value)
|
3130
|
-
if (this.
|
2993
|
+
if (!rmsinput.test(this.type))
|
2994
|
+
return
|
2995
|
+
if (!this.msFocus && this.avalonSetter) {
|
3131
2996
|
this.avalonSetter()
|
3132
2997
|
}
|
3133
2998
|
}
|
@@ -3145,12 +3010,12 @@ new function() {
|
|
3145
3010
|
} catch (e) {
|
3146
3011
|
watchValueInTimer = avalon.tick
|
3147
3012
|
}
|
3148
|
-
}
|
3013
|
+
}// jshint ignore:line
|
3149
3014
|
|
3150
3015
|
|
3151
3016
|
//处理radio, checkbox, text, textarea, password
|
3152
|
-
duplexBinding.INPUT = function(element, evaluator, data) {
|
3153
|
-
var type = element.type,
|
3017
|
+
duplexBinding.INPUT = function (element, evaluator, data) {
|
3018
|
+
var $type = element.type,
|
3154
3019
|
bound = data.bound,
|
3155
3020
|
$elem = avalon(element),
|
3156
3021
|
composing = false
|
@@ -3164,7 +3029,8 @@ duplexBinding.INPUT = function(element, evaluator, data) {
|
|
3164
3029
|
composing = false
|
3165
3030
|
}
|
3166
3031
|
//当value变化时改变model的值
|
3167
|
-
|
3032
|
+
|
3033
|
+
var updateVModel = function () {
|
3168
3034
|
if (composing)//处理中文输入法在minlengh下引发的BUG
|
3169
3035
|
return
|
3170
3036
|
var val = element.oldValue = element.value //防止递归调用形成死循环
|
@@ -3173,35 +3039,35 @@ duplexBinding.INPUT = function(element, evaluator, data) {
|
|
3173
3039
|
evaluator(lastValue)
|
3174
3040
|
callback.call(element, lastValue)
|
3175
3041
|
if ($elem.data("duplex-focus")) {
|
3176
|
-
avalon.nextTick(function() {
|
3042
|
+
avalon.nextTick(function () {
|
3177
3043
|
element.focus()
|
3178
3044
|
})
|
3179
3045
|
}
|
3180
3046
|
}
|
3181
3047
|
}
|
3182
3048
|
//当model变化时,它就会改变value的值
|
3183
|
-
data.handler = function() {
|
3049
|
+
data.handler = function () {
|
3184
3050
|
var val = data.pipe(evaluator(), data, "set") + ""
|
3185
3051
|
if (val !== element.oldValue) {
|
3186
3052
|
element.value = val
|
3187
3053
|
}
|
3188
3054
|
}
|
3189
|
-
if (data.isChecked ||
|
3190
|
-
updateVModel = function() {
|
3055
|
+
if (data.isChecked || $type === "radio") {
|
3056
|
+
updateVModel = function () {
|
3191
3057
|
if ($elem.data("duplex-observe") !== false) {
|
3192
3058
|
var lastValue = data.pipe(element.value, data, "get")
|
3193
3059
|
evaluator(lastValue)
|
3194
3060
|
callback.call(element, lastValue)
|
3195
3061
|
}
|
3196
3062
|
}
|
3197
|
-
data.handler = function() {
|
3063
|
+
data.handler = function () {
|
3198
3064
|
var val = evaluator()
|
3199
3065
|
var checked = data.isChecked ? !!val : val + "" === element.value
|
3200
3066
|
element.checked = element.oldValue = checked
|
3201
3067
|
}
|
3202
3068
|
bound("click", updateVModel)
|
3203
|
-
} else if (type === "checkbox") {
|
3204
|
-
updateVModel = function() {
|
3069
|
+
} else if ($type === "checkbox") {
|
3070
|
+
updateVModel = function () {
|
3205
3071
|
if ($elem.data("duplex-observe") !== false) {
|
3206
3072
|
var method = element.checked ? "ensure" : "remove"
|
3207
3073
|
var array = evaluator()
|
@@ -3213,17 +3079,17 @@ duplexBinding.INPUT = function(element, evaluator, data) {
|
|
3213
3079
|
callback.call(element, array)
|
3214
3080
|
}
|
3215
3081
|
}
|
3216
|
-
data.handler = function() {
|
3082
|
+
data.handler = function () {
|
3217
3083
|
var array = [].concat(evaluator()) //强制转换为数组
|
3218
3084
|
element.checked = array.indexOf(data.pipe(element.value, data, "get")) > -1
|
3219
3085
|
}
|
3220
3086
|
bound("change", updateVModel)
|
3221
3087
|
} else {
|
3222
|
-
var events = element.getAttribute("data-duplex-event") ||
|
3088
|
+
var events = element.getAttribute("data-duplex-event") || "input"
|
3223
3089
|
if (element.attributes["data-event"]) {
|
3224
3090
|
log("data-event指令已经废弃,请改用data-duplex-event")
|
3225
3091
|
}
|
3226
|
-
events.replace(rword, function(name) {
|
3092
|
+
events.replace(rword, function (name) {
|
3227
3093
|
switch (name) {
|
3228
3094
|
case "input":
|
3229
3095
|
bound("input", updateVModel)
|
@@ -3238,21 +3104,27 @@ duplexBinding.INPUT = function(element, evaluator, data) {
|
|
3238
3104
|
break
|
3239
3105
|
}
|
3240
3106
|
})
|
3241
|
-
|
3242
|
-
|
3243
|
-
if (/text|password/.test(element.type)) {
|
3244
|
-
watchValueInTimer(function() {
|
3245
|
-
if (root.contains(element)) {
|
3246
|
-
if (element.value !== element.oldValue) {
|
3247
|
-
updateVModel()
|
3248
|
-
}
|
3249
|
-
} else if (!element.msRetain) {
|
3250
|
-
return false
|
3251
|
-
}
|
3107
|
+
bound("focus", function () {
|
3108
|
+
element.msFocus = true
|
3252
3109
|
})
|
3110
|
+
bound("blur", function () {
|
3111
|
+
element.msFocus = false
|
3112
|
+
})
|
3113
|
+
if (rmsinput.test($type)) {
|
3114
|
+
watchValueInTimer(function () {
|
3115
|
+
if (root.contains(element)) {
|
3116
|
+
if (!element.msFocus && element.oldValue !== element.value) {
|
3117
|
+
updateVModel()
|
3118
|
+
}
|
3119
|
+
} else if (!element.msRetain) {
|
3120
|
+
return false
|
3121
|
+
}
|
3122
|
+
})
|
3123
|
+
}
|
3124
|
+
|
3125
|
+
element.avalonSetter = updateVModel
|
3253
3126
|
}
|
3254
3127
|
|
3255
|
-
element.avalonSetter = updateVModel
|
3256
3128
|
element.oldValue = element.value
|
3257
3129
|
registerSubscriber(data)
|
3258
3130
|
callback.call(element, element.value)
|
@@ -3303,6 +3175,135 @@ duplexBinding.SELECT = function(element, evaluator, data) {
|
|
3303
3175
|
}
|
3304
3176
|
|
3305
3177
|
|
3178
|
+
// bindingHandlers.html 定义在if.js
|
3179
|
+
bindingExecutors.html = function(val, elem, data) {
|
3180
|
+
val = val == null ? "" : val
|
3181
|
+
var isHtmlFilter = "group" in data
|
3182
|
+
var parent = isHtmlFilter ? elem.parentNode : elem
|
3183
|
+
if (!parent)
|
3184
|
+
return
|
3185
|
+
if (val.nodeType === 11) { //将val转换为文档碎片
|
3186
|
+
var fragment = val
|
3187
|
+
} else if (val.nodeType === 1 || val.item) {
|
3188
|
+
var nodes = val.nodeType === 1 ? val.childNodes : val.item ? val : []
|
3189
|
+
fragment = hyperspace.cloneNode(true)
|
3190
|
+
while (nodes[0]) {
|
3191
|
+
fragment.appendChild(nodes[0])
|
3192
|
+
}
|
3193
|
+
} else {
|
3194
|
+
fragment = avalon.parseHTML(val)
|
3195
|
+
}
|
3196
|
+
//插入占位符, 如果是过滤器,需要有节制地移除指定的数量,如果是html指令,直接清空
|
3197
|
+
var comment = DOC.createComment("ms-html")
|
3198
|
+
if (isHtmlFilter) {
|
3199
|
+
parent.insertBefore(comment, elem)
|
3200
|
+
var n = data.group, i = 1
|
3201
|
+
while (i < n) {
|
3202
|
+
var node = elem.nextSibling
|
3203
|
+
if (node) {
|
3204
|
+
parent.removeChild(node)
|
3205
|
+
i++
|
3206
|
+
}
|
3207
|
+
}
|
3208
|
+
parent.removeChild(elem)
|
3209
|
+
data.element = comment //防止被CG
|
3210
|
+
} else {
|
3211
|
+
avalon.clearHTML(parent).appendChild(comment)
|
3212
|
+
}
|
3213
|
+
if (isHtmlFilter) {
|
3214
|
+
data.group = fragment.childNodes.length || 1
|
3215
|
+
}
|
3216
|
+
nodes = avalon.slice(fragment.childNodes)
|
3217
|
+
if (nodes[0]) {
|
3218
|
+
if (comment.parentNode)
|
3219
|
+
comment.parentNode.replaceChild(fragment, comment)
|
3220
|
+
if (isHtmlFilter) {
|
3221
|
+
data.element = nodes[0]
|
3222
|
+
}
|
3223
|
+
}
|
3224
|
+
scanNodeArray(nodes, data.vmodels)
|
3225
|
+
}
|
3226
|
+
|
3227
|
+
bindingHandlers["if"] =
|
3228
|
+
bindingHandlers.data =
|
3229
|
+
bindingHandlers.text =
|
3230
|
+
bindingHandlers.html =
|
3231
|
+
function(data, vmodels) {
|
3232
|
+
parseExprProxy(data.value, vmodels, data)
|
3233
|
+
}
|
3234
|
+
|
3235
|
+
bindingExecutors["if"] = function(val, elem, data) {
|
3236
|
+
if (val) { //插回DOM树
|
3237
|
+
if (elem.nodeType === 8) {
|
3238
|
+
elem.parentNode.replaceChild(data.template, elem)
|
3239
|
+
elem = data.element = data.template //这时可能为null
|
3240
|
+
}
|
3241
|
+
if (elem.getAttribute(data.name)) {
|
3242
|
+
elem.removeAttribute(data.name)
|
3243
|
+
scanAttr(elem, data.vmodels)
|
3244
|
+
}
|
3245
|
+
data.rollback = null
|
3246
|
+
} else { //移出DOM树,并用注释节点占据原位置
|
3247
|
+
if (elem.nodeType === 1) {
|
3248
|
+
var node = data.element = DOC.createComment("ms-if")
|
3249
|
+
elem.parentNode.replaceChild(node, elem)
|
3250
|
+
data.template = elem //元素节点
|
3251
|
+
ifGroup.appendChild(elem)
|
3252
|
+
data.rollback = function() {
|
3253
|
+
if (elem.parentNode === ifGroup) {
|
3254
|
+
ifGroup.removeChild(elem)
|
3255
|
+
}
|
3256
|
+
}
|
3257
|
+
}
|
3258
|
+
}
|
3259
|
+
}
|
3260
|
+
|
3261
|
+
|
3262
|
+
//ms-important绑定已经在scanTag 方法中实现
|
3263
|
+
//ms-include绑定已由ms-attr绑定实现
|
3264
|
+
|
3265
|
+
var rdash = /\(([^)]*)\)/
|
3266
|
+
bindingHandlers.on = function(data, vmodels) {
|
3267
|
+
var value = data.value
|
3268
|
+
data.type = "on"
|
3269
|
+
var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
|
3270
|
+
if (typeof bindingHandlers.on[eventType + "Hook"] === "function") {
|
3271
|
+
bindingHandlers.on[eventType + "Hook"](data)
|
3272
|
+
}
|
3273
|
+
if (value.indexOf("(") > 0 && value.indexOf(")") > -1) {
|
3274
|
+
var matched = (value.match(rdash) || ["", ""])[1].trim()
|
3275
|
+
if (matched === "" || matched === "$event") { // aaa() aaa($event)当成aaa处理
|
3276
|
+
value = value.replace(rdash, "")
|
3277
|
+
}
|
3278
|
+
}
|
3279
|
+
parseExprProxy(value, vmodels, data)
|
3280
|
+
}
|
3281
|
+
|
3282
|
+
bindingExecutors.on = function(callback, elem, data) {
|
3283
|
+
callback = function(e) {
|
3284
|
+
var fn = data.evaluator || noop
|
3285
|
+
return fn.apply(this, data.args.concat(e))
|
3286
|
+
}
|
3287
|
+
var eventType = data.param.replace(/-\d+$/, "") // ms-on-mousemove-10
|
3288
|
+
if (eventType === "scan") {
|
3289
|
+
callback.call(elem, {
|
3290
|
+
type: eventType
|
3291
|
+
})
|
3292
|
+
} else if (typeof data.specialBind === "function") {
|
3293
|
+
data.specialBind(elem, callback)
|
3294
|
+
} else {
|
3295
|
+
var removeFn = avalon.bind(elem, eventType, callback)
|
3296
|
+
}
|
3297
|
+
data.rollback = function() {
|
3298
|
+
if (typeof data.specialUnbind === "function") {
|
3299
|
+
data.specialUnbind()
|
3300
|
+
} else {
|
3301
|
+
avalon.unbind(elem, eventType, removeFn)
|
3302
|
+
}
|
3303
|
+
}
|
3304
|
+
}
|
3305
|
+
|
3306
|
+
|
3306
3307
|
bindingHandlers.repeat = function(data, vmodels) {
|
3307
3308
|
var type = data.type
|
3308
3309
|
parseExprProxy(data.value, vmodels, data, 0, 1)
|
@@ -3313,11 +3314,10 @@ bindingHandlers.repeat = function(data, vmodels) {
|
|
3313
3314
|
var xtype = avalon.type($repeat)
|
3314
3315
|
if (xtype !== "object" && xtype !== "array") {
|
3315
3316
|
freturn = true
|
3316
|
-
avalon.log("warning:" + data.value + "
|
3317
|
+
avalon.log("warning:" + data.value + "只能是对象或数组")
|
3317
3318
|
}
|
3318
3319
|
} catch (e) {
|
3319
3320
|
freturn = true
|
3320
|
-
avalon.log("warning:" + data.value + "编译出错")
|
3321
3321
|
}
|
3322
3322
|
|
3323
3323
|
var arr = data.value.split(".") || []
|
@@ -3659,7 +3659,7 @@ function recycleProxies(proxies, type) {
|
|
3659
3659
|
proxy.$events[i].forEach(function(data) {
|
3660
3660
|
if (typeof data === "object")
|
3661
3661
|
disposeData(data)
|
3662
|
-
})
|
3662
|
+
})// jshint ignore:line
|
3663
3663
|
proxy.$events[i].length = 0
|
3664
3664
|
}
|
3665
3665
|
}
|
@@ -3676,6 +3676,134 @@ function recycleProxies(proxies, type) {
|
|
3676
3676
|
|
3677
3677
|
|
3678
3678
|
|
3679
|
+
/*********************************************************************
|
3680
|
+
* 各种指令 *
|
3681
|
+
**********************************************************************/
|
3682
|
+
//ms-skip绑定已经在scanTag 方法中实现
|
3683
|
+
// bindingHandlers.text 定义在if.js
|
3684
|
+
bindingExecutors.text = function(val, elem) {
|
3685
|
+
val = val == null ? "" : val //不在页面上显示undefined null
|
3686
|
+
if (elem.nodeType === 3) { //绑定在文本节点上
|
3687
|
+
try { //IE对游离于DOM树外的节点赋值会报错
|
3688
|
+
elem.data = val
|
3689
|
+
} catch (e) {
|
3690
|
+
}
|
3691
|
+
} else { //绑定在特性节点上
|
3692
|
+
elem.textContent = val
|
3693
|
+
}
|
3694
|
+
}
|
3695
|
+
|
3696
|
+
function parseDisplay(nodeName, val) {
|
3697
|
+
//用于取得此类标签的默认display值
|
3698
|
+
var key = "_" + nodeName
|
3699
|
+
if (!parseDisplay[key]) {
|
3700
|
+
var node = DOC.createElement(nodeName)
|
3701
|
+
root.appendChild(node)
|
3702
|
+
if (W3C) {
|
3703
|
+
val = getComputedStyle(node, null).display
|
3704
|
+
} else {
|
3705
|
+
val = node.currentStyle.display
|
3706
|
+
}
|
3707
|
+
root.removeChild(node)
|
3708
|
+
parseDisplay[key] = val
|
3709
|
+
}
|
3710
|
+
return parseDisplay[key]
|
3711
|
+
}
|
3712
|
+
|
3713
|
+
avalon.parseDisplay = parseDisplay
|
3714
|
+
|
3715
|
+
bindingHandlers.visible = function(data, vmodels) {
|
3716
|
+
var elem = avalon(data.element)
|
3717
|
+
var display = elem.css("display")
|
3718
|
+
if (display === "none") {
|
3719
|
+
var style = elem[0].style
|
3720
|
+
var has = /visibility/i.test(style.cssText)
|
3721
|
+
var visible = elem.css("visibility")
|
3722
|
+
style.display = ""
|
3723
|
+
style.visibility = "hidden"
|
3724
|
+
display = elem.css("display")
|
3725
|
+
if (display === "none") {
|
3726
|
+
display = parseDisplay(elem[0].nodeName)
|
3727
|
+
}
|
3728
|
+
style.visibility = has ? visible : ""
|
3729
|
+
}
|
3730
|
+
data.display = display
|
3731
|
+
parseExprProxy(data.value, vmodels, data)
|
3732
|
+
}
|
3733
|
+
|
3734
|
+
bindingExecutors.visible = function(val, elem, data) {
|
3735
|
+
elem.style.display = val ? data.display : "none"
|
3736
|
+
}
|
3737
|
+
|
3738
|
+
bindingHandlers.widget = function(data, vmodels) {
|
3739
|
+
var args = data.value.match(rword)
|
3740
|
+
var elem = data.element
|
3741
|
+
var widget = args[0]
|
3742
|
+
var id = args[1]
|
3743
|
+
if (!id || id === "$") {//没有定义或为$时,取组件名+随机数
|
3744
|
+
id = generateID(widget)
|
3745
|
+
}
|
3746
|
+
var optName = args[2] || widget//没有定义,取组件名
|
3747
|
+
var constructor = avalon.ui[widget]
|
3748
|
+
if (typeof constructor === "function") { //ms-widget="tabs,tabsAAA,optname"
|
3749
|
+
vmodels = elem.vmodels || vmodels
|
3750
|
+
for (var i = 0, v; v = vmodels[i++]; ) {
|
3751
|
+
if (v.hasOwnProperty(optName) && typeof v[optName] === "object") {
|
3752
|
+
var vmOptions = v[optName]
|
3753
|
+
vmOptions = vmOptions.$model || vmOptions
|
3754
|
+
break
|
3755
|
+
}
|
3756
|
+
}
|
3757
|
+
if (vmOptions) {
|
3758
|
+
var wid = vmOptions[widget + "Id"]
|
3759
|
+
if (typeof wid === "string") {
|
3760
|
+
id = wid
|
3761
|
+
}
|
3762
|
+
}
|
3763
|
+
//抽取data-tooltip-text、data-tooltip-attr属性,组成一个配置对象
|
3764
|
+
var widgetData = avalon.getWidgetData(elem, widget)
|
3765
|
+
data.value = [widget, id, optName].join(",")
|
3766
|
+
data[widget + "Id"] = id
|
3767
|
+
data.evaluator = noop
|
3768
|
+
elem.msData["ms-widget-id"] = id
|
3769
|
+
var options = data[widget + "Options"] = avalon.mix({}, constructor.defaults, vmOptions || {}, widgetData)
|
3770
|
+
elem.removeAttribute("ms-widget")
|
3771
|
+
var vmodel = constructor(elem, data, vmodels) || {} //防止组件不返回VM
|
3772
|
+
if (vmodel.$id) {
|
3773
|
+
avalon.vmodels[id] = vmodel
|
3774
|
+
createSignalTower(elem, vmodel)
|
3775
|
+
if (vmodel.hasOwnProperty("$init")) {
|
3776
|
+
vmodel.$init(function() {
|
3777
|
+
avalon.scan(elem, [vmodel].concat(vmodels))
|
3778
|
+
if (typeof options.onInit === "function") {
|
3779
|
+
options.onInit.call(elem, vmodel, options, vmodels)
|
3780
|
+
}
|
3781
|
+
})
|
3782
|
+
}
|
3783
|
+
data.rollback = function() {
|
3784
|
+
try {
|
3785
|
+
vmodel.widgetElement = null
|
3786
|
+
vmodel.$remove()
|
3787
|
+
} catch (e) {
|
3788
|
+
}
|
3789
|
+
elem.msData = {}
|
3790
|
+
delete avalon.vmodels[vmodel.$id]
|
3791
|
+
}
|
3792
|
+
addSubscribers(data, widgetList)
|
3793
|
+
if (window.chrome) {
|
3794
|
+
elem.addEventListener("DOMNodeRemovedFromDocument", function() {
|
3795
|
+
setTimeout(removeSubscribers)
|
3796
|
+
})
|
3797
|
+
}
|
3798
|
+
} else {
|
3799
|
+
avalon.scan(elem, vmodels)
|
3800
|
+
}
|
3801
|
+
} else if (vmodels.length) { //如果该组件还没有加载,那么保存当前的vmodels
|
3802
|
+
elem.vmodels = vmodels
|
3803
|
+
}
|
3804
|
+
}
|
3805
|
+
var widgetList = []
|
3806
|
+
//不存在 bindingExecutors.widget
|
3679
3807
|
/*********************************************************************
|
3680
3808
|
* 自带过滤器 *
|
3681
3809
|
**********************************************************************/
|
@@ -3690,18 +3818,18 @@ var rsanitize = {
|
|
3690
3818
|
var rsurrogate = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g
|
3691
3819
|
var rnoalphanumeric = /([^\#-~| |!])/g;
|
3692
3820
|
|
3693
|
-
function numberFormat(number, decimals,
|
3821
|
+
function numberFormat(number, decimals, point, thousands) {
|
3694
3822
|
//form http://phpjs.org/functions/number_format/
|
3695
3823
|
//number 必需,要格式化的数字
|
3696
3824
|
//decimals 可选,规定多少个小数位。
|
3697
|
-
//
|
3698
|
-
//
|
3825
|
+
//point 可选,规定用作小数点的字符串(默认为 . )。
|
3826
|
+
//thousands 可选,规定用作千位分隔符的字符串(默认为 , ),如果设置了该参数,那么所有其他参数都是必需的。
|
3699
3827
|
number = (number + '')
|
3700
3828
|
.replace(/[^0-9+\-Ee.]/g, '')
|
3701
3829
|
var n = !isFinite(+number) ? 0 : +number,
|
3702
|
-
prec = !isFinite(+decimals) ?
|
3703
|
-
sep =
|
3704
|
-
dec =
|
3830
|
+
prec = !isFinite(+decimals) ? 3 : Math.abs(decimals),
|
3831
|
+
sep = thousands || ",",
|
3832
|
+
dec = point || ".",
|
3705
3833
|
s = '',
|
3706
3834
|
toFixedFix = function(n, prec) {
|
3707
3835
|
var k = Math.pow(10, prec)
|
@@ -3763,7 +3891,7 @@ var filters = avalon.filters = {
|
|
3763
3891
|
if (reg) {
|
3764
3892
|
a = a.replace(reg, function(s, name, value) {
|
3765
3893
|
var quote = value.charAt(0)
|
3766
|
-
return name + "=" + quote + "javascript:void(0)" + quote
|
3894
|
+
return name + "=" + quote + "javascript:void(0)" + quote// jshint ignore:line
|
3767
3895
|
})
|
3768
3896
|
}
|
3769
3897
|
}
|
@@ -3788,9 +3916,7 @@ var filters = avalon.filters = {
|
|
3788
3916
|
currency: function(amount, symbol, fractionSize) {
|
3789
3917
|
return (symbol || "\uFFE5") + numberFormat(amount, isFinite(fractionSize) ? fractionSize : 2)
|
3790
3918
|
},
|
3791
|
-
number:
|
3792
|
-
return numberFormat(number, isFinite(fractionSize) ? fractionSize : 3)
|
3793
|
-
}
|
3919
|
+
number: numberFormat
|
3794
3920
|
}
|
3795
3921
|
/*
|
3796
3922
|
'yyyy': 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
|
@@ -3825,7 +3951,7 @@ var filters = avalon.filters = {
|
|
3825
3951
|
'mediumTime': equivalent to 'h:mm:ss a' for en_US locale (e.g. 12:05:08 pm)
|
3826
3952
|
'shortTime': equivalent to 'h:mm a' for en_US locale (e.g. 12:05 pm)
|
3827
3953
|
*/
|
3828
|
-
new function() {
|
3954
|
+
new function() {// jshint ignore:line
|
3829
3955
|
function toInt(str) {
|
3830
3956
|
return parseInt(str, 10) || 0
|
3831
3957
|
}
|
@@ -4025,8 +4151,43 @@ new function() {
|
|
4025
4151
|
}
|
4026
4152
|
locate.SHORTMONTH = locate.MONTH
|
4027
4153
|
filters.date.locate = locate
|
4028
|
-
}
|
4154
|
+
}// jshint ignore:line
|
4155
|
+
/*********************************************************************
|
4156
|
+
* END *
|
4157
|
+
**********************************************************************/
|
4029
4158
|
new function() {
|
4159
|
+
avalon.config({
|
4160
|
+
loader: false
|
4161
|
+
})
|
4162
|
+
var fns = [], fn, loaded
|
4163
|
+
function flush(f) {
|
4164
|
+
loaded = 1
|
4165
|
+
while (f = fns.shift())
|
4166
|
+
f()
|
4167
|
+
}
|
4168
|
+
if (W3C) {
|
4169
|
+
avalon.bind(DOC, "DOMContentLoaded", fn = function() {
|
4170
|
+
avalon.unbind(DOC, "DOMContentLoaded", fn)
|
4171
|
+
flush()
|
4172
|
+
})
|
4173
|
+
} else {
|
4174
|
+
var id = setInterval(function() {
|
4175
|
+
if (document.readyState === "complete" && document.body) {
|
4176
|
+
clearInterval(id)
|
4177
|
+
flush()
|
4178
|
+
}
|
4179
|
+
}, 50)
|
4180
|
+
}
|
4181
|
+
avalon.ready = function(fn) {
|
4182
|
+
loaded ? fn(avalon) : fns.push(fn)
|
4183
|
+
}
|
4184
|
+
avalon.ready(function() {
|
4185
|
+
avalon.scan(DOC.body)
|
4186
|
+
})
|
4187
|
+
}
|
4188
|
+
|
4189
|
+
new function() {// jshint ignore:line
|
4190
|
+
// http://www.cnblogs.com/yexiaochai/p/3462657.html
|
4030
4191
|
var ua = navigator.userAgent
|
4031
4192
|
var isAndroid = ua.indexOf("Android") > 0
|
4032
4193
|
var isIOS = /iP(ad|hone|od)/.test(ua)
|
@@ -4061,83 +4222,15 @@ new function() {
|
|
4061
4222
|
} else if (IE9_10touch) {
|
4062
4223
|
touchNames = ["MSPointerDown", "MSPointerMove", "MSPointerUp", "MSPointerCancel"]
|
4063
4224
|
}
|
4064
|
-
|
4065
|
-
|
4066
|
-
coordinates: [],
|
4067
|
-
addUnderFrame: function(event) {
|
4068
|
-
var underFrame = null
|
4069
|
-
if(!clickbuster.underFrame) {
|
4070
|
-
underFrame = document.createElement('div');
|
4071
|
-
underFrame.style.cssText = [
|
4072
|
-
"opacity: 0",
|
4073
|
-
"display: none;",
|
4074
|
-
"border-radius: 60px;",
|
4075
|
-
"position: absolute;",
|
4076
|
-
"z-index: 99999;",
|
4077
|
-
"width: 60px;",
|
4078
|
-
"height: 60px"
|
4079
|
-
].join("");
|
4080
|
-
document.body.appendChild(underFrame)
|
4081
|
-
}
|
4082
|
-
clickbuster.underFrame = underFrame
|
4083
|
-
underFrame.style.top = (event.changedTouches[0].clientY - 30) + "px"
|
4084
|
-
underFrame.style.left = (event.changedTouches[0].clientX - 30) + "px"
|
4085
|
-
underFrame.style.display = "block"
|
4086
|
-
setTimeout(function(){
|
4087
|
-
underFrame.style.display = "none"
|
4088
|
-
}, 360)
|
4089
|
-
},
|
4090
|
-
preventGhostClick: function(x, y) {
|
4091
|
-
clickbuster.coordinates.push(x, y);
|
4092
|
-
window.setTimeout(clickbuster.pop, 2500)
|
4093
|
-
},
|
4094
|
-
pop: function() {
|
4095
|
-
clickbuster.coordinates.splice(0, 2)
|
4096
|
-
},
|
4097
|
-
onClick: function(event) {
|
4098
|
-
for (var i = 0; i < clickbuster.coordinates.length; i += 2) {
|
4099
|
-
var x = clickbuster.coordinates[i]
|
4100
|
-
var y = clickbuster.coordinates[i + 1]
|
4101
|
-
if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
|
4102
|
-
event.stopPropagation();
|
4103
|
-
event.preventDefault();
|
4104
|
-
}
|
4105
|
-
}
|
4106
|
-
}
|
4225
|
+
function isPrimaryTouch(event){
|
4226
|
+
return (event.pointerType === 'touch' || event.pointerType === event.MSPOINTER_TYPE_TOUCH) && event.isPrimary
|
4107
4227
|
}
|
4108
4228
|
|
4109
|
-
|
4110
|
-
|
4111
|
-
//当通过touchstart, touchend等事件混合计算得当前场景应该需要执行click, tap,那么
|
4112
|
-
//直接执行el["msdispatch"]方法
|
4113
|
-
"click,tap".replace(/\w+/g, function(method) {
|
4114
|
-
avalon.eventHooks[method] = {
|
4115
|
-
type: method,
|
4116
|
-
deel: function(el, type, fn, isAdd) {
|
4117
|
-
var listName = "ms" + method + "list"
|
4118
|
-
var fns = el[listName] || (el[listName] = [])
|
4119
|
-
if (!el["msdispatch"]) {
|
4120
|
-
el["msdispatch"] = function(event) {
|
4121
|
-
if (event.fireByAvalon) {
|
4122
|
-
for (var i = 0, fn; fn = fns[i++]; ) {
|
4123
|
-
fn.call(el, event)
|
4124
|
-
}
|
4125
|
-
}
|
4126
|
-
}
|
4127
|
-
el.addEventListener(type, el["msdispatch"])
|
4128
|
-
}
|
4129
|
-
if (isAdd) {
|
4130
|
-
fns.push(fn)
|
4131
|
-
} else {
|
4132
|
-
avalon.Array.remove(fns, fn)
|
4133
|
-
}
|
4134
|
-
fn.unbind = true
|
4135
|
-
return fn
|
4136
|
-
}
|
4137
|
-
}
|
4138
|
-
})
|
4229
|
+
function isPointerEventType(e, type){
|
4230
|
+
return (e.type === 'pointer'+type || e.type.toLowerCase() === 'mspointer'+type)
|
4139
4231
|
}
|
4140
4232
|
|
4233
|
+
var touchTimeout, longTapTimeout
|
4141
4234
|
//判定滑动方向
|
4142
4235
|
function swipeDirection(x1, x2, y1, y2) {
|
4143
4236
|
return Math.abs(x1 - x2) >=
|
@@ -4151,31 +4244,95 @@ new function() {
|
|
4151
4244
|
y: e.clientY
|
4152
4245
|
}
|
4153
4246
|
}
|
4154
|
-
|
4247
|
+
function fireEvent(el, name, detail) {
|
4248
|
+
var event = document.createEvent("Events")
|
4249
|
+
event.initEvent(name, true, true)
|
4250
|
+
event.fireByAvalon = true//签名,标记事件是由avalon触发
|
4251
|
+
//event.isTrusted = false 设置这个opera会报错
|
4252
|
+
if (detail)
|
4253
|
+
event.detail = detail
|
4254
|
+
el.dispatchEvent(event)
|
4255
|
+
}
|
4256
|
+
function onMouse(event) {
|
4257
|
+
if (event.fireByAvalon) {
|
4258
|
+
return true
|
4259
|
+
}
|
4260
|
+
if (event.stopImmediatePropagation) {
|
4261
|
+
event.stopImmediatePropagation()
|
4262
|
+
} else {
|
4263
|
+
event.propagationStopped = true
|
4264
|
+
}
|
4265
|
+
event.stopPropagation()
|
4266
|
+
event.preventDefault()
|
4267
|
+
}
|
4268
|
+
function cancelLongTap() {
|
4269
|
+
if (longTapTimeout) clearTimeout(longTapTimeout)
|
4270
|
+
longTapTimeout = null
|
4271
|
+
}
|
4272
|
+
function touchstart(event) {
|
4273
|
+
var _isPointerType = isPointerEventType(event, 'down'),
|
4274
|
+
firstTouch = _isPointerType ? event : event.touches[0],
|
4275
|
+
element = 'tagName' in firstTouch.target ? firstTouch.target: firstTouch.target.parentNode,
|
4276
|
+
now = Date.now(),
|
4277
|
+
delta = now - (touchProxy.last || now)
|
4278
|
+
|
4279
|
+
if (_isPointerType && !isPrimaryTouch(event)) return
|
4280
|
+
|
4281
|
+
avalon.mix(touchProxy, getCoordinates(event))
|
4282
|
+
touchProxy.mx = 0
|
4283
|
+
touchProxy.my = 0
|
4284
|
+
if (delta > 0 && delta <= 250) {
|
4285
|
+
touchProxy.isDoubleTap = true
|
4286
|
+
}
|
4287
|
+
touchProxy.last = now
|
4288
|
+
touchProxy.element = element
|
4289
|
+
/*
|
4290
|
+
当触发hold和longtap事件时会触发touchcancel事件,从而阻止touchend事件的触发,继而保证在同时绑定tap和hold(longtap)事件时只触发其中一个事件
|
4291
|
+
*/
|
4292
|
+
avalon(element).addClass(fastclick.activeClass)
|
4293
|
+
longTapTimeout = setTimeout(function() {
|
4294
|
+
longTapTimeout = null
|
4295
|
+
fireEvent(element, "hold")
|
4296
|
+
fireEvent(element, "longtap")
|
4297
|
+
touchProxy = {}
|
4298
|
+
avalon(element).removeClass(fastclick.activeClass)
|
4299
|
+
}, fastclick.clickDuration)
|
4300
|
+
return true
|
4301
|
+
}
|
4302
|
+
function touchmove(event) {
|
4303
|
+
var _isPointerType = isPointerEventType(event, 'down'),
|
4304
|
+
e = getCoordinates(event)
|
4305
|
+
if (_isPointerType && !isPrimaryTouch(event)) return
|
4306
|
+
|
4307
|
+
cancelLongTap()
|
4308
|
+
touchProxy.mx += Math.abs(touchProxy.x - e.x)
|
4309
|
+
touchProxy.my += Math.abs(touchProxy.y - e.y)
|
4310
|
+
}
|
4155
4311
|
function touchend(event) {
|
4156
|
-
var
|
4157
|
-
|
4312
|
+
var _isPointerType = isPointerEventType(event, 'down')
|
4313
|
+
element = touchProxy.element
|
4314
|
+
|
4315
|
+
if (_isPointerType && !isPrimaryTouch(event)) return
|
4316
|
+
|
4317
|
+
if (!element) {
|
4158
4318
|
return
|
4319
|
+
}
|
4320
|
+
cancelLongTap()
|
4159
4321
|
var e = getCoordinates(event)
|
4160
|
-
var diff = Date.now() - touchProxy.startTime //经过时间
|
4161
4322
|
var totalX = Math.abs(touchProxy.x - e.x)
|
4162
4323
|
var totalY = Math.abs(touchProxy.y - e.y)
|
4163
|
-
if (touchProxy.doubleIndex === 2 && avalon.config.stopZoom) {//如果已经点了两次,就可以触发dblclick 回调
|
4164
|
-
event.preventDefault()
|
4165
|
-
}
|
4166
4324
|
if (totalX > 30 || totalY > 30) {
|
4167
4325
|
//如果用户滑动的距离有点大,就认为是swipe事件
|
4168
4326
|
var direction = swipeDirection(touchProxy.x, e.x, touchProxy.y, e.y)
|
4169
4327
|
var details = {
|
4170
4328
|
direction: direction
|
4171
4329
|
}
|
4172
|
-
|
4173
|
-
|
4330
|
+
fireEvent(element, "swipe", details)
|
4331
|
+
fireEvent(element, "swipe" + direction, details)
|
4332
|
+
avalon(element).removeClass(fastclick.activeClass)
|
4333
|
+
touchProxy = {}
|
4174
4334
|
} else {
|
4175
|
-
|
4176
|
-
if (fastclick.canClick(element) &&
|
4177
|
-
touchProxy.mx < fastclick.dragDistance &&
|
4178
|
-
touchProxy.my < fastclick.dragDistance) {
|
4335
|
+
if (fastclick.canClick(element) && touchProxy.mx < fastclick.dragDistance && touchProxy.my < fastclick.dragDistance) {
|
4179
4336
|
// 失去焦点的处理
|
4180
4337
|
if (document.activeElement && document.activeElement !== element) {
|
4181
4338
|
document.activeElement.blur()
|
@@ -4190,92 +4347,39 @@ new function() {
|
|
4190
4347
|
} else {
|
4191
4348
|
fastclick.focus(element)
|
4192
4349
|
}
|
4193
|
-
|
4194
|
-
|
4195
|
-
|
4196
|
-
|
4197
|
-
|
4198
|
-
|
4199
|
-
|
4200
|
-
|
4201
|
-
|
4202
|
-
|
4203
|
-
|
4204
|
-
|
4205
|
-
|
4206
|
-
|
4207
|
-
|
4208
|
-
}
|
4209
|
-
}
|
4210
|
-
|
4211
|
-
if (diff > fastclick.clickDuration) {
|
4212
|
-
W3CFire(element, "hold")
|
4213
|
-
W3CFire(element, "longtap")
|
4214
|
-
touchProxy.doubleIndex = 0
|
4350
|
+
event.preventDefault()
|
4351
|
+
fireEvent(element, 'tap')
|
4352
|
+
avalon.fastclick.fireEvent(element, "click", event)
|
4353
|
+
avalon(element).removeClass(fastclick.activeClass)
|
4354
|
+
if (touchProxy.isDoubleTap) {
|
4355
|
+
fireEvent(element, "doubletap")
|
4356
|
+
avalon.fastclick.fireEvent(element, "dblclick", event)
|
4357
|
+
touchProxy = {}
|
4358
|
+
avalon(element).removeClass(fastclick.activeClass)
|
4359
|
+
} else {
|
4360
|
+
touchTimeout = setTimeout(function() {
|
4361
|
+
clearTimeout(touchTimeout)
|
4362
|
+
touchTimeout = null
|
4363
|
+
touchProxy = {}
|
4364
|
+
avalon(element).removeClass(fastclick.activeClass)
|
4365
|
+
}, 250)
|
4215
4366
|
}
|
4216
4367
|
}
|
4217
4368
|
}
|
4218
|
-
avalon(element).removeClass(fastclick.activeClass)
|
4219
|
-
touchProxy.element = null
|
4220
4369
|
}
|
4221
|
-
|
4222
|
-
|
4223
|
-
document.addEventListener(
|
4224
|
-
document.addEventListener(touchNames[1],
|
4225
|
-
if (!touchProxy.element)
|
4226
|
-
return
|
4227
|
-
var e = getCoordinates(event)
|
4228
|
-
touchProxy.mx += Math.abs(touchProxy.cx - e.x)
|
4229
|
-
touchProxy.my += Math.abs(touchProxy.cy - e.y)
|
4230
|
-
if (touchProxy.tapping && (touchProxy.mx > fastclick.dragDistance || touchProxy.my > fastclick.dragDistance)) {
|
4231
|
-
touchProxy.element = null
|
4232
|
-
}
|
4233
|
-
})
|
4234
|
-
|
4370
|
+
document.addEventListener('mousedown', onMouse, true)
|
4371
|
+
document.addEventListener('click', onMouse, true)
|
4372
|
+
document.addEventListener(touchNames[0], touchstart)
|
4373
|
+
document.addEventListener(touchNames[1], touchmove)
|
4235
4374
|
document.addEventListener(touchNames[2], touchend)
|
4236
4375
|
if (touchNames[3]) {
|
4237
|
-
document.addEventListener(touchNames[3],
|
4238
|
-
|
4239
|
-
|
4240
|
-
|
4241
|
-
|
4242
|
-
|
4243
|
-
touchProxy.cx = touchProxy.x
|
4244
|
-
touchProxy.cy = touchProxy.y
|
4245
|
-
touchProxy.mx = 0 //计算总结移动了多少距离,指在移动距离重分
|
4246
|
-
touchProxy.my = 0
|
4247
|
-
// touchProxy.startTime = Date.now()
|
4248
|
-
touchProxy.event = data.param
|
4249
|
-
touchProxy.tapping = /click|tap|hold$/.test(touchProxy.event)
|
4250
|
-
|
4251
|
-
//--------------处理双击事件--------------
|
4252
|
-
if (!touchProxy.doubleIndex) {
|
4253
|
-
touchProxy.doubleIndex = 1
|
4254
|
-
touchProxy.startTime = Date.now()
|
4255
|
-
} else {
|
4256
|
-
touchProxy.doubleIndex = 2
|
4257
|
-
}
|
4258
|
-
touchProxy.element = element
|
4259
|
-
if (touchProxy.tapping && avalon.fastclick.canClick(element)) {
|
4260
|
-
avalon(element).addClass(fastclick.activeClass)
|
4261
|
-
}
|
4262
|
-
}
|
4263
|
-
function needFixClick(type) {
|
4264
|
-
return type === "click"
|
4265
|
-
}
|
4266
|
-
if (needFixClick(data.param) ? touchSupported : true) {
|
4267
|
-
data.specialBind = function(element, callback) {
|
4268
|
-
element.addEventListener(touchNames[0], touchstart)
|
4269
|
-
data.msCallback = callback
|
4270
|
-
avalon.bind(element, data.param, callback)
|
4271
|
-
}
|
4272
|
-
data.specialUnbind = function() {
|
4273
|
-
element.removeEventListener(touchNames[0], touchstart)
|
4274
|
-
avalon.bind(data.element, data.param, data.msCallback)
|
4275
|
-
}
|
4276
|
-
}
|
4376
|
+
document.addEventListener(touchNames[3], function(event) {
|
4377
|
+
if (longTapTimeout) clearTimeout(longTapTimeout)
|
4378
|
+
if (touchTimeout) clearTimeout(touchTimeout)
|
4379
|
+
longTapTimeout = touchTimeout = null
|
4380
|
+
touchProxy = {}
|
4381
|
+
})
|
4277
4382
|
}
|
4278
|
-
|
4279
4383
|
//fastclick只要是处理移动端点击存在300ms延迟的问题
|
4280
4384
|
//这是苹果乱搞异致的,他们想在小屏幕设备上通过快速点击两次,将放大了的网页缩放至原始比例。
|
4281
4385
|
var fastclick = avalon.fastclick = {
|
@@ -4343,63 +4447,9 @@ new function() {
|
|
4343
4447
|
["swipe", "swipeleft", "swiperight", "swipeup", "swipedown", "doubletap", "tap", "dblclick", "longtap", "hold"].forEach(function(method) {
|
4344
4448
|
me[method + "Hook"] = me["clickHook"]
|
4345
4449
|
})
|
4346
|
-
if (touchSupported) {
|
4347
|
-
me[touchNames[2] + "Hook"] = function(data) {
|
4348
|
-
data.specialBind = function(element, callback) {
|
4349
|
-
var _callback = callback
|
4350
|
-
if (element.hasAttribute('avoidFocus')) {
|
4351
|
-
_callback = function(event) {
|
4352
|
-
var e = getCoordinates(event)
|
4353
|
-
clickbuster.preventGhostClick(e.x, e.y)
|
4354
|
-
clickbuster.addUnderFrame(event)
|
4355
|
-
callback.apply(this, [].slice.call(arguments))
|
4356
|
-
}
|
4357
|
-
}
|
4358
|
-
data.msCallback = _callback
|
4359
|
-
avalon.bind(element, data.param, _callback)
|
4360
|
-
}
|
4361
|
-
data.specialUnbind = function() {
|
4362
|
-
avalon.unbind(data.element, data.param, data.msCallback)
|
4363
|
-
}
|
4364
|
-
}
|
4365
|
-
}
|
4366
|
-
//各种摸屏事件的示意图 http://quojs.tapquo.com/ http://touch.code.baidu.com/
|
4367
|
-
}
|
4368
|
-
|
4369
|
-
/*********************************************************************
|
4370
|
-
* END *
|
4371
|
-
**********************************************************************/
|
4372
|
-
new function() {
|
4373
|
-
avalon.config({
|
4374
|
-
loader: false
|
4375
|
-
})
|
4376
|
-
var fns = [], fn, loaded
|
4377
|
-
function flush(f) {
|
4378
|
-
loaded = 1
|
4379
|
-
while (f = fns.shift())
|
4380
|
-
f()
|
4381
|
-
}
|
4382
|
-
if (W3C) {
|
4383
|
-
avalon.bind(DOC, "DOMContentLoaded", fn = function() {
|
4384
|
-
avalon.unbind(DOC, "DOMContentLoaded", fn)
|
4385
|
-
flush()
|
4386
|
-
})
|
4387
|
-
} else {
|
4388
|
-
var id = setInterval(function() {
|
4389
|
-
if (document.readyState === "complete" && document.body) {
|
4390
|
-
clearInterval(id)
|
4391
|
-
flush()
|
4392
|
-
}
|
4393
|
-
}, 50)
|
4394
|
-
}
|
4395
|
-
avalon.ready = function(fn) {
|
4396
|
-
loaded ? fn(avalon) : fns.push(fn)
|
4397
|
-
}
|
4398
|
-
avalon.ready(function() {
|
4399
|
-
avalon.scan(DOC.body)
|
4400
|
-
})
|
4401
|
-
}
|
4402
4450
|
|
4451
|
+
//各种摸屏事件的示意图 http://quojs.tapquo.com/ http://touch.code.baidu.com/
|
4452
|
+
}// jshint ignore:line
|
4403
4453
|
|
4404
4454
|
// Register as a named AMD module, since avalon can be concatenated with other
|
4405
4455
|
// files that may use define, but not via a proper concatenation script that
|
@@ -4422,15 +4472,15 @@ new function() {
|
|
4422
4472
|
var _avalon = window.avalon
|
4423
4473
|
avalon.noConflict = function(deep) {
|
4424
4474
|
if (deep && window.avalon === avalon) {
|
4425
|
-
window.avalon =
|
4475
|
+
window.avalon = _avalon
|
4426
4476
|
}
|
4427
4477
|
return avalon
|
4428
4478
|
}
|
4429
|
-
// Expose avalon
|
4479
|
+
// Expose avalon identifiers, even in AMD
|
4430
4480
|
// and CommonJS for browser emulators
|
4431
4481
|
if (noGlobal === void 0) {
|
4432
4482
|
window.avalon = avalon
|
4433
4483
|
}
|
4434
4484
|
return avalon
|
4435
4485
|
|
4436
|
-
}));
|
4486
|
+
}));
|