diff --git a/static/src/js/lib/avalon/avalon.js b/static/src/js/lib/avalon/avalon.js
index bb809d5..48c2021 100644
--- a/static/src/js/lib/avalon/avalon.js
+++ b/static/src/js/lib/avalon/avalon.js
@@ -3,9 +3,9 @@
http://www.cnblogs.com/rubylouvre/
https://github.com/RubyLouvre
http://weibo.com/jslouvre/
-
+
Released under the MIT license
- avalon.shim.js 1.5.4 built in 2015.10.15
+ avalon.shim.js 1.5.4 built in 2015.10.18
support IE6+ and other browsers
==================================================*/
(function(global, factory) {
@@ -954,7 +954,7 @@ function $watch(expr, binding) {
}
binding.wildcard = /\*/.test(expr)
}
-
+
if (!binding.update) {
if (/\w\.*\B/.test(expr)) {
binding.getter = noop
@@ -1489,7 +1489,7 @@ if (!canHideOwn) {
//添加普通属性,因为VBScript对象不能像JS那样随意增删属性,必须在这里预先定义好
var uniq = {}
- //添加访问器属性
+ //添加访问器属性
for (name in accessors) {
uniq[name] = true
buffer.push(
@@ -1593,7 +1593,7 @@ var newProto = {
if (all.indexOf(this[i]) !== -1) {
_splice.call(this.$track, i, 1)
_splice.call(this, i, 1)
-
+
}
}
} else if (typeof all === "function") {
@@ -1602,7 +1602,7 @@ var newProto = {
if (all(el, i)) {
_splice.call(this.$track, i, 1)
_splice.call(this, i, 1)
-
+
}
}
} else {
@@ -2517,7 +2517,7 @@ function showHidden(node, array) {
var node = this[0]
if (arguments.length === 0) {
if (node.setTimeout) { //取得窗口尺寸
- return node["inner" + name] ||
+ return node["inner" + name] ||
node.document.documentElement[clientProp] ||
node.document.body[clientProp] //IE6下前两个分别为undefined,0
}
@@ -2972,7 +2972,7 @@ function executeBindings(bindings, vmodels) {
for (var i = 0, binding; binding = bindings[i++]; ) {
binding.vmodels = vmodels
directives[binding.type].init(binding)
-
+
avalon.injectBinding(binding)
if (binding.getter && binding.element.nodeType === 1) { //移除数据绑定,防止被二次解析
//chrome使用removeAttributeNode移除不存在的特性节点时会报错 https://github.com/RubyLouvre/avalon/issues/99
@@ -3169,9 +3169,6 @@ function scanNodeArray(nodes, vmodels) {
switch (node.nodeType) {
case 1:
var elem = node, fn
-
- scanTag(node, vmodels) //扫描元素节点
-
if (!elem.msResolved && elem.parentNode && elem.parentNode.nodeType === 1) {
var library = isWidget(elem)
if (library) {
@@ -3190,6 +3187,7 @@ function scanNodeArray(nodes, vmodels) {
}
}
}
+ scanTag(node, vmodels) //扫描元素节点
if (node.msHasEvent) {
avalon.fireDom(node, "datasetchanged", {
bubble: node.msHasEvent
@@ -3232,7 +3230,7 @@ function scanTag(elem, vmodels, node) {
avalon(elem).removeClass(name)
createSignalTower(elem, newVmodel)
}
-
+
scanAttr(elem, vmodels) //扫描特性节点
}
@@ -3424,6 +3422,7 @@ avalon.component = function (name, opts) {
elem.msResolved = 1
vmodel.$init(vmodel, elem)
global.$init(vmodel, elem)
+ console.log("init")
var nodes = elem.childNodes
//收集插入点
var slots = {}, snode
@@ -3483,11 +3482,11 @@ avalon.component = function (name, opts) {
e.stopPropagation()
}
}
-
+ console.log("dependencies "+dependencies)
if (dependencies === 0) {
var id1 = setTimeout(function () {
clearTimeout(id1)
-
+
vmodel.$ready(vmodel, elem, host.vmodels)
global.$ready(vmodel, elem, host.vmodels)
}, children ? Math.max(children * 17, 100) : 17)
@@ -3510,9 +3509,10 @@ avalon.component = function (name, opts) {
}
})
- scanTag(elem, [vmodel].concat(host.vmodels))
+ scanTag(elem, [vmodel].concat(host.vmodels))
avalon.vmodels[vmodel.$id] = vmodel
+ avalon.log("添加组件VM: "+vmodel.$id)
if (!elem.childNodes.length) {
avalon.fireDom(elem, "datasetchanged", {library: library, vm: vmodel, childReady: -1})
} else {
@@ -3585,7 +3585,7 @@ function isWidget(el) { //如果为自定义标签,返回UI库的名字
if(el.scopeName && el.scopeName !== "HTML" ){
return el.scopeName
}
- var fullName = el.nodeName.toLowerCase()
+ var fullName = el.nodeName.toLowerCase()
var index = fullName.indexOf(":")
if (index > 0) {
return fullName.slice(0, index)
@@ -3794,7 +3794,7 @@ avalon.directive("data", {
//双工绑定
var rduplexType = /^(?:checkbox|radio)$/
var rduplexParam = /^(?:radio|checked)$/
-var rnoduplexInput = /^(file|button|reset|submit|checkbox|radio)$/
+var rnoduplexInput = /^(file|button|reset|submit|checkbox|radio|range)$/
var duplexBinding = avalon.directive("duplex", {
priority: 2000,
init: function (binding, hasCast) {
@@ -3949,15 +3949,26 @@ var duplexBinding = avalon.directive("duplex", {
}
}
})
+ binding.bound("datasetchanged", function (e) {
+ if (e.bubble === "selectDuplex") {
+ var value = binding._value
+ var curValue = Array.isArray(value) ? value.map(String) : value + ""
+ avalon(elem).val(curValue)
+ elem.oldValue = curValue + ""
+ binding.changed.call(elem, curValue)
+ }
+ })
break
}
- binding.bound("focus", function() {
- elem.msFocus = true
- })
- binding.bound("blur", function() {
- elem.msFocus = false
- })
if (binding.xtype === "input" && !rnoduplexInput.test(elem.type)) {
+ if (elem.type !== "hidden") {
+ binding.bound("focus", function () {
+ elem.msFocus = true
+ })
+ binding.bound("blur", function () {
+ elem.msFocus = false
+ })
+ }
elem.avalonSetter = updateVModel //#765
watchValueInTimer(function () {
if (elem.contains(elem)) {
@@ -3987,7 +3998,18 @@ var duplexBinding = avalon.directive("duplex", {
case "change":
curValue = this.pipe(value, this, "set") //fix #673
if (curValue !== this.oldValue) {
+ var fixCaret = false
+ if (elem.msFocus) {
+ var pos = getCaret(elem)
+ if (pos.start === pos.end) {
+ pos = pos.start
+ fixCaret = true
+ }
+ }
elem.value = this.oldValue = curValue
+ if (fixCaret) {
+ setCaret(element, pos, pos)
+ }
}
break
case "radio":
@@ -4012,18 +4034,14 @@ var duplexBinding = avalon.directive("duplex", {
case "select":
//必须变成字符串后才能比较
binding._value = value
- elem.msHasEvent = "selectDuplex"
- //必须等到其孩子准备好才触发
- avalon.bind(elem, "datasetchanged", function (e) {
- if (e.bubble === "selectDuplex") {
- var value = binding._value
- var curValue = Array.isArray(value) ? value.map(String) : value + ""
- avalon(elem).val(curValue)
- elem.oldValue = curValue + ""
- binding.changed.call(elem, curValue)
- }
- })
-
+ if(!elem.msHasEvent){
+ elem.msHasEvent = "selectDuplex"
+ //必须等到其孩子准备好才触发
+ }else{
+ avalon.fireDom(elem, "datasetchanged", {
+ bubble: elem.msHasEvent
+ })
+ }
break
}
if (binding.xtype !== "select") {
@@ -4121,7 +4139,7 @@ new function () { // jshint ignore:line
var bproto = HTMLTextAreaElement.prototype
function newSetter(value) { // jshint ignore:line
setters[this.tagName].call(this, value)
- if (!this.msFocus && this.avalonSetter && this.oldValue !== value) {
+ if (!this.msFocus && this.avalonSetter && this.oldValue !== value) {
this.avalonSetter()
}
}
@@ -4143,6 +4161,34 @@ new function () { // jshint ignore:line
watchValueInTimer = avalon.tick
}
} // jshint ignore:line
+function getCaret(ctrl, start, end) {
+ if (ctrl.setSelectionRange) {
+ start = ctrl.selectionStart
+ end = ctrl.selectionEnd
+ } else if (document.selection && document.selection.createRange) {
+ var range = document.selection.createRange()
+ start = 0 - range.duplicate().moveStart('character', -100000)
+ end = start + range.text.length
+ }
+ return {
+ start: start,
+ end: end
+ }
+}
+function setCaret(ctrl, begin, end) {
+ if (!ctrl.value || ctrl.readOnly)
+ return
+ if (ctrl.setSelectionRange) {
+ ctrl.selectionStart = begin
+ ctrl.selectionEnd = end
+ } else {
+ var range = ctrl.createTextRange()
+ range.collapse(true);
+ range.moveStart("character", begin)
+ range.moveEnd("character", end - begin)
+ range.select()
+ }
+}
avalon.directive("effect", {
priority: 5,
@@ -4326,7 +4372,7 @@ function upperFirstChar(str) {
}
var effectBuffer = new Buffer()
function Effect() {
-}// 动画实例,做成类的形式,是为了共用所有原型方法
+}// 动画实例,做成类的形式,是为了共用所有原型方法
Effect.prototype = {
contrustor: Effect,
@@ -4349,7 +4395,7 @@ Effect.prototype = {
callEffectHook(me, "abort" + upperFirstChar(oppositeName))
callEffectHook(me, "before" + upperFirstChar(name))
if (!isLeave)
- before(el) // 这里可能做插入DOM树的操作,因此必须在修改类名前执行
+ before(el) // 这里可能做插入DOM树的操作,因此必须在修改类名前执行
var cssCallback = function (cancel) {
el.removeEventListener(me.cssEvent, me.cssCallback)
if (isLeave) {
@@ -4576,7 +4622,7 @@ avalon.directive("if", {
elem.required = false
elem.setAttribute("_required", "true")
}
- try {// 如果不支持querySelectorAll或:required,可以直接无视
+ try {// 如果不支持querySelectorAll或:required,可以直接无视
avalon.each(elem.querySelectorAll(":required"), function (el) {
elem.required = false
el.setAttribute("_required", "true")
@@ -4679,7 +4725,7 @@ avalon.directive("include", {
leaveEl.className = effectClass
target.insertBefore(leaveEl, binding.start) // 插入到start之前,防止被错误的移动
}
-
+
// cache or animate,移动节点
(templateCache || {})[lastID] = leaveEl
var fragOnDom = binding.recoverNodes() // 恢复动画中的节点
@@ -4733,7 +4779,7 @@ avalon.directive("include", {
return nodesToFrag(nodes)
}
} else {
- before = function () {// 新添加元素的动画
+ before = function () {// 新添加元素的动画
target.insertBefore(fragment, binding.end)
scanNodeArray(nodes, vmodels)
}
@@ -4827,7 +4873,7 @@ var onDir = avalon.directive("on", {
var fn = binding.getter || noop
return fn.apply(this, binding.args.concat(e))
}
-
+
var eventType = binding.param.replace(/-\d+$/, "") // ms-on-mousemove-10
if (eventType === "scan") {
callback.call(elem, {
@@ -4860,7 +4906,7 @@ avalon.directive("repeat", {
effectBinding(elem, binding)
binding.param = binding.param || "el"
binding.sortedCallback = getBindingCallback(elem, "data-with-sorted", binding.vmodels)
- // binding.renderedCallback =
+ // binding.renderedCallback =
var rendered = getBindingCallback(elem, "data-" + type + "-rendered", binding.vmodels)
var signature = generateID(type)
@@ -4965,7 +5011,7 @@ avalon.directive("repeat", {
}
//重写proxy
- if (this.enterCount === 1) {// 防止多次进入,导致位置不对
+ if (this.enterCount === 1) {// 防止多次进入,导致位置不对
proxy.$active = false
proxy.$oldIndex = proxy.$index
proxy.$active = true
@@ -4978,7 +5024,7 @@ avalon.directive("repeat", {
proxy.$last = i === length - 1
// proxy[param] = value[i]
} else {
- proxy.$val = toJson(value[keyOrId]) // 这里是处理vm.object = newObject的情况
+ proxy.$val = toJson(value[keyOrId]) // 这里是处理vm.object = newObject的情况
}
proxies.push(proxy)
}
@@ -5029,7 +5075,7 @@ avalon.directive("repeat", {
} else if (proxy.$index !== proxy.$oldIndex) {
(function (proxy2, preElement) {
staggerIndex = mayStaggerAnimate(binding.effectEnterStagger, function () {
- var curNode = removeItem(proxy2.$anchor)// 如果位置被挪动了
+ var curNode = removeItem(proxy2.$anchor)// 如果位置被挪动了
var inserted = avalon.slice(curNode.childNodes)
parent.insertBefore(curNode, preElement.nextSibling)
animateRepeat(inserted, 1, binding)
@@ -5410,7 +5456,7 @@ var filters = avalon.filters = {
truncate: function(str, length, truncation) {
//length,新字符串长度,truncation,新字符串的结尾的字段,返回新字符串
length = length || 30
- truncation = typeof truncation === "string" ? truncation : "..."
+ truncation = typeof truncation === "string" ? truncation : "..."
return str.length > length ? str.slice(0, length - truncation.length) + truncation : String(str)
},
$filter: function(val) {
@@ -5426,7 +5472,7 @@ var filters = avalon.filters = {
},
camelize: camelize,
//https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
- // chrome
+ // chrome
// chrome
// IE67chrome
// IE67chrome
@@ -5447,7 +5493,7 @@ var filters = avalon.filters = {
})
},
escape: function(str) {
- //将字符串经过 str 转义得到适合在页面中显示的内容, 例如替换 < 为 <
+ //将字符串经过 str 转义得到适合在页面中显示的内容, 例如替换 < 为 <
return String(str).
replace(/&/g, '&').
replace(rsurrogate, function(value) {
@@ -5489,7 +5535,7 @@ var filters = avalon.filters = {
'a': am/pm marker
'Z': 4 digit (+sign) representation of the timezone offset (-1200-+1200)
format string can also be one of the following predefined localizable formats:
-
+
'medium': equivalent to 'MMM d, y h:mm:ss a' for en_US locale (e.g. Sep 3, 2010 12:05:08 pm)
'short': equivalent to 'M/d/yy h:mm a' for en_US locale (e.g. 9/3/10 12:05 pm)
'fullDate': equivalent to 'EEEE, MMMM d,y' for en_US locale (e.g. Friday, September 3, 2010)