avalon2
Version:
an elegant efficient express mvvm framework
297 lines (257 loc) • 8.52 kB
JavaScript
import { win, document, msie, inBrowser, root, modern } from './browser'
import { Cache } from './cache'
import { directive, directives, delayCompileNodes } from './directive'
export var window = win
export function avalon(el) {
return new avalon.init(el)
}
avalon.init = function (el) {
this[0] = this.element = el
}
avalon.fn = avalon.prototype = avalon.init.prototype
export function shadowCopy(destination, source) {
for (var property in source) {
destination[property] = source[property]
}
return destination
}
export var rword = /[^, ]+/g
export var rnowhite = /\S+/g //存在非空字符
export var platform = {} //用于放置平台差异的方法与属性
export var isArray = function (target) {
return avalon.type(target) === 'array'
}
export function oneObject(array, val) {
if (typeof array === 'string') {
array = array.match(rword) || []
}
var result = {},
value = val !== void 0 ? val : 1
for (var i = 0, n = array.length; i < n; i++) {
result[array[i]] = value
}
return result
}
var op = Object.prototype
export function quote(str) {
return avalon._quote(str)
}
export var inspect = op.toString
export var ohasOwn = op.hasOwnProperty
export var ap = Array.prototype
var hasConsole = typeof console === 'object'
avalon.config = { debug: true }
export function log() {
if (hasConsole && avalon.config.debug) {
Function.apply.call(console.log, console, arguments)
}
}
export {
Cache, directive, directives, delayCompileNodes,
document, root, msie, modern, inBrowser
}
export function warn() {
if (hasConsole && avalon.config.debug) {
var method = console.warn || console.log
// http://qiang106.iteye.com/blog/1721425
Function.apply.call(method, console, arguments)
}
}
export function error(e, str) {
throw (e || Error)(str)
}
export function noop() { }
export function isObject(a) {
return a !== null && typeof a === 'object'
}
export function range(start, end, step) { // 用于生成整数数组
step || (step = 1)
if (end == null) {
end = start || 0
start = 0
}
var index = - 1,
length = Math.max(0, Math.ceil((end - start) / step)),
result = new Array(length)
while (++index < length) {
result[index] = start
start += step
}
return result
}
var rhyphen = /([a-z\d])([A-Z]+)/g
export function hyphen(target) {
//转换为连字符线风格
return target.replace(rhyphen, '$1-$2').toLowerCase()
}
var rcamelize = /[-_][^-_]/g
export function camelize(target) {
//提前判断,提高getStyle等的效率
if (!target || target.indexOf('-') < 0 && target.indexOf('_') < 0) {
return target
}
//转换为驼峰风格
return target.replace(rcamelize, function (match) {
return match.charAt(1).toUpperCase()
})
}
export var _slice = ap.slice
export function slice(nodes, start, end) {
return _slice.call(nodes, start, end)
}
var rhashcode = /\d\.\d{4}/
//生成UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
export function makeHashCode(prefix) {
/* istanbul ignore next*/
prefix = prefix || 'avalon'
/* istanbul ignore next*/
return String(Math.random() + Math.random()).replace(rhashcode, prefix)
}
//生成事件回调的UUID(用户通过ms-on指令)
export function getLongID(fn) {
/* istanbul ignore next */
return fn.uuid || (fn.uuid = makeHashCode('e'))
}
var UUID = 1
//生成事件回调的UUID(用户通过avalon.bind)
export function getShortID(fn) {
/* istanbul ignore next */
return fn.uuid || (fn.uuid = '_' + (++UUID))
}
var rescape = /[-.*+?^${}()|[\]\/\\]/g
export function escapeRegExp(target) {
//http://stevenlevithan.com/regex/xregexp/
//将字符串安全格式化为正则表达式的源码
return (target + '').replace(rescape, '\\$&')
}
export var eventHooks = {}
export var eventListeners = {}
export var validators = {}
export var cssHooks = {}
window.avalon = avalon
export function createFragment() {
/* istanbul ignore next */
return document.createDocumentFragment()
}
var rentities = /&[a-z0-9#]{2,10};/
var temp = document.createElement('div')
shadowCopy(avalon, {
Array: {
merge: function (target, other) {
//合并两个数组 avalon2新增
target.push.apply(target, other)
},
ensure: function (target, item) {
//只有当前数组不存在此元素时只添加它
if (target.indexOf(item) === - 1) {
return target.push(item)
}
},
removeAt: function (target, index) {
//移除数组中指定位置的元素,返回布尔表示成功与否
return !!target.splice(index, 1).length
},
remove: function (target, item) {
//移除数组中第一个匹配传参的那个元素,返回布尔表示成功与否
var index = target.indexOf(item)
if (~index)
return avalon.Array.removeAt(target, index)
return false
}
},
evaluatorPool: new Cache(888),
parsers: {
number: function (a) {
return a === '' ? '' : parseFloat(a) || 0
},
string: function (a) {
return a === null || a === void 0 ? '' : a + ''
},
boolean: function (a) {
if (a === '')
return a
return a === 'true' || a === '1'
}
},
_decode: function _decode(str) {
if (rentities.test(str)) {
temp.innerHTML = str
return temp.innerText || temp.textContent
}
return str
}
})
//============== config ============
export function config(settings) {
for (var p in settings) {
var val = settings[p]
if (typeof config.plugins[p] === 'function') {
config.plugins[p](val)
} else {
config[p] = val
}
}
return this
}
var plugins = {
interpolate: function (array) {
var openTag = array[0]
var closeTag = array[1]
if (openTag === closeTag) {
throw new SyntaxError('interpolate openTag cannot equal to closeTag')
}
var str = openTag + 'test' + closeTag
if (/[<>]/.test(str)) {
throw new SyntaxError('interpolate cannot contains "<" or ">"')
}
config.openTag = openTag
config.closeTag = closeTag
var o = escapeRegExp(openTag)
var c = escapeRegExp(closeTag)
config.rtext = new RegExp(o + '(.+?)' + c, 'g')
config.rexpr = new RegExp(o + '([\\s\\S]*)' + c)
}
}
export function createAnchor(nodeValue){
return document.createComment(nodeValue)
}
config.plugins = plugins
config({
interpolate: ['{{', '}}'],
debug: true
})
//============ config ============
shadowCopy(avalon, {
shadowCopy,
oneObject,
inspect,
ohasOwn,
rword,
version: 1,
vmodels: {},
directives,
directive,
eventHooks,
eventListeners,
validators,
cssHooks,
log,
noop,
warn,
error,
config,
modern,
msie,
root,
document,
window,
inBrowser,
isObject,
range,
slice,
hyphen,
camelize,
escapeRegExp,
quote,
makeHashCode,
})