diff --git a/src/anot.js b/src/anot.js index 2a6d829..442f0c4 100644 --- a/src/anot.js +++ b/src/anot.js @@ -1,5 +1,4 @@ -import { Anot } from './seed/core' -import './seed/lang' +import Anot from './seed/index' import './filters/index' import './dom/modern' diff --git a/src/anot.touch.js b/src/anot.touch.js index ef11796..1f639a1 100644 --- a/src/anot.touch.js +++ b/src/anot.touch.js @@ -1,5 +1,4 @@ -import { Anot } from './seed/core' -import './seed/lang' +import Anot from './seed/index' import './filters/index' import './dom/modern' diff --git a/src/directives/attr.js b/src/directives/attr.js index 8900884..73b4038 100644 --- a/src/directives/attr.js +++ b/src/directives/attr.js @@ -1,4 +1,4 @@ -import { Anot } from '../seed/core' +import Anot from '../seed/index' import { cssDiff } from './css' import { updateAttrs } from '../dom/attr/modern' diff --git a/src/directives/duplex/share.js b/src/directives/duplex/share.js index 7330de3..06ce07a 100644 --- a/src/directives/duplex/share.js +++ b/src/directives/duplex/share.js @@ -7,6 +7,21 @@ import { updateModel } from './updateDataHandle' var rchangeFilter = /\|\s*change\b/ var rdebounceFilter = /\|\s*debounce(?:\(([^)]+)\))?/ +var PARSER_FN = { + number(a) { + return a === '' ? '' : +a || 0 + }, + string(a) { + return a === null || a === void 0 ? '' : a + '' + }, + boolean(a) { + if (a === '') { + return a + } + return a === 'true' || a === '1' + } +} + export function duplexBeforeInit() { var expr = this.expr if (rchangeFilter.test(expr)) { @@ -144,7 +159,7 @@ try { function parseValue(val) { for (var i = 0, k; (k = this.parsers[i++]); ) { - var fn = Anot.parsers[k] + var fn = PARSER_FN[k] if (fn) { val = fn.call(this, val) } diff --git a/src/directives/expr.js b/src/directives/expr.js index 8af7308..54b5e06 100644 --- a/src/directives/expr.js +++ b/src/directives/expr.js @@ -1,4 +1,4 @@ -import { Anot } from '../seed/core' +import Anot from '../seed/index' Anot.directive('expr', { update: function(vdom, value) { diff --git a/src/directives/for.js b/src/directives/for.js index 0ef6082..1acb6ec 100644 --- a/src/directives/for.js +++ b/src/directives/for.js @@ -1,4 +1,11 @@ -import { Anot, createFragment, platform, isObject, ap } from '../seed/core' +import { + Anot, + createFragment, + platform, + isObject, + ap, + makeHashCode +} from '../seed/core' import { VFragment } from '../vdom/VFragment' import { $$skipArray } from '../vmodel/reserved' @@ -39,7 +46,7 @@ Anot.directive('for', { this.expr = arr[1] this.keyName = kv[0] this.valName = kv[1] - this.signature = Anot.makeHashCode('for') + this.signature = makeHashCode('for') if (asName) { this.asName = asName } diff --git a/src/directives/visible.js b/src/directives/visible.js index 278b588..3f70d9a 100644 --- a/src/directives/visible.js +++ b/src/directives/visible.js @@ -44,11 +44,11 @@ Anot.directive('visible', { } } } + // fix firefox BUG,必须挂到页面上 if ( dom.style.display === '' && Anot(dom).css('display') === none && - // fix firefox BUG,必须挂到页面上 - Anot.contains(dom.ownerDocument, dom) + dom.ownerDocument.contains(dom) ) { value = parseDisplay(dom) } diff --git a/src/dom/css/share.js b/src/dom/css/share.js index 9dd5816..f24f886 100644 --- a/src/dom/css/share.js +++ b/src/dom/css/share.js @@ -5,7 +5,7 @@ export { cssMap, cssHooks } Anot.cssNumber = oneObject( 'animationIterationCount,columnCount,order,flex,flexGrow,flexShrink,fillOpacity,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom' ) -var prefixes = ['', '-webkit-', '-o-', '-moz-', '-ms-'] +var prefixes = ['', '-webkit-', '-moz-'] /* istanbul ignore next */ Anot.cssName = function(name, host, camelCase) { if (cssMap[name]) { @@ -171,103 +171,97 @@ function showHidden(node, array) { } } /* istanbul ignore next*/ -Anot.each( - { - Width: 'width', - Height: 'height' - }, - function(name, method) { - var clientProp = 'client' + name, - scrollProp = 'scroll' + name, - offsetProp = 'offset' + name - cssHooks[method + ':get'] = function(node, which, override) { - var boxSizing = -4 - if (typeof override === 'number') { - boxSizing = override - } - which = name === 'Width' ? ['Left', 'Right'] : ['Top', 'Bottom'] - var ret = node[offsetProp] // border-box 0 - if (boxSizing === 2) { - // margin-box 2 - return ( - ret + - Anot.css(node, 'margin' + which[0], true) + - Anot.css(node, 'margin' + which[1], true) - ) - } - if (boxSizing < 0) { - // padding-box -2 - ret = - ret - - Anot.css(node, 'border' + which[0] + 'Width', true) - - Anot.css(node, 'border' + which[1] + 'Width', true) - } - if (boxSizing === -4) { - // content-box -4 - ret = - ret - - Anot.css(node, 'padding' + which[0], true) - - Anot.css(node, 'padding' + which[1], true) - } - return ret +Anot.each({ Width: 'width', Height: 'height' }, function(name, method) { + var clientProp = 'client' + name, + scrollProp = 'scroll' + name, + offsetProp = 'offset' + name + cssHooks[method + ':get'] = function(node, which, override) { + var boxSizing = -4 + if (typeof override === 'number') { + boxSizing = override } - cssHooks[method + '&get'] = function(node) { - var hidden = [] - showHidden(node, hidden) - var val = cssHooks[method + ':get'](node) - for (var i = 0, obj; (obj = hidden[i++]); ) { - node = obj.node - for (var n in obj) { - if (typeof obj[n] === 'string') { - node.style[n] = obj[n] - } - } - } - return val - } - Anot.fn[method] = function(value) { - //会忽视其display - var node = this[0] - if (arguments.length === 0) { - if (node.setTimeout) { - //取得窗口尺寸 - return ( - node['inner' + name] || - node.document.documentElement[clientProp] || - node.document.body[clientProp] - ) //IE6下前两个分别为undefined,0 - } - if (node.nodeType === 9) { - //取得页面尺寸 - var doc = node.documentElement - //FF chrome html.scrollHeight< body.scrollHeight - //IE 标准模式 : html.scrollHeight> body.scrollHeight - //IE 怪异模式 : html.scrollHeight 最大等于可视窗口多一点? - return Math.max( - node.body[scrollProp], - doc[scrollProp], - node.body[offsetProp], - doc[offsetProp], - doc[clientProp] - ) - } - return cssHooks[method + '&get'](node) - } else { - return this.css(method, value) - } - } - Anot.fn['inner' + name] = function() { - return cssHooks[method + ':get'](this[0], void 0, -2) - } - Anot.fn['outer' + name] = function(includeMargin) { - return cssHooks[method + ':get']( - this[0], - void 0, - includeMargin === true ? 2 : 0 + which = name === 'Width' ? ['Left', 'Right'] : ['Top', 'Bottom'] + var ret = node[offsetProp] // border-box 0 + if (boxSizing === 2) { + // margin-box 2 + return ( + ret + + Anot.css(node, 'margin' + which[0], true) + + Anot.css(node, 'margin' + which[1], true) ) } + if (boxSizing < 0) { + // padding-box -2 + ret = + ret - + Anot.css(node, 'border' + which[0] + 'Width', true) - + Anot.css(node, 'border' + which[1] + 'Width', true) + } + if (boxSizing === -4) { + // content-box -4 + ret = + ret - + Anot.css(node, 'padding' + which[0], true) - + Anot.css(node, 'padding' + which[1], true) + } + return ret } -) + cssHooks[method + '&get'] = function(node) { + var hidden = [] + showHidden(node, hidden) + var val = cssHooks[method + ':get'](node) + for (var i = 0, obj; (obj = hidden[i++]); ) { + node = obj.node + for (var n in obj) { + if (typeof obj[n] === 'string') { + node.style[n] = obj[n] + } + } + } + return val + } + Anot.fn[method] = function(value) { + //会忽视其display + var node = this[0] + if (arguments.length === 0) { + if (node.setTimeout) { + //取得窗口尺寸 + return ( + node['inner' + name] || + node.document.documentElement[clientProp] || + node.document.body[clientProp] + ) //IE6下前两个分别为undefined,0 + } + if (node.nodeType === 9) { + //取得页面尺寸 + var doc = node.documentElement + //FF chrome html.scrollHeight< body.scrollHeight + //IE 标准模式 : html.scrollHeight> body.scrollHeight + //IE 怪异模式 : html.scrollHeight 最大等于可视窗口多一点? + return Math.max( + node.body[scrollProp], + doc[scrollProp], + node.body[offsetProp], + doc[offsetProp], + doc[clientProp] + ) + } + return cssHooks[method + '&get'](node) + } else { + return this.css(method, value) + } + } + Anot.fn['inner' + name] = function() { + return cssHooks[method + ':get'](this[0], void 0, -2) + } + Anot.fn['outer' + name] = function(includeMargin) { + return cssHooks[method + ':get']( + this[0], + void 0, + includeMargin === true ? 2 : 0 + ) + } +}) export function getWindow(node) { return node.window || node.defaultView || node.parentWindow || false diff --git a/src/dom/html/index.js b/src/dom/html/index.js index f51a627..899e7a8 100644 --- a/src/dom/html/index.js +++ b/src/dom/html/index.js @@ -20,7 +20,7 @@ Anot.parseHTML = function(html) { html = html.replace(rxhtml, '<$1>').trim() var hasCache = htmlCache.get(html) if (hasCache) { - return Anot.cloneNode(hasCache) + return hasCache.cloneNode(true) } var vnodes = fromString(html) for (var i = 0, el; (el = vnodes[i++]); ) { diff --git a/src/dom/modern.js b/src/dom/modern.js index 200b08a..fcc5de4 100644 --- a/src/dom/modern.js +++ b/src/dom/modern.js @@ -3,8 +3,6 @@ * shim,class,data,css,val,html,event,ready * ********************************************************************/ -import './shim/modern' -import './class/modern' import './attr/modern' import './css/modern' import './val/modern' diff --git a/src/dom/ready/modern.js b/src/dom/ready/modern.js index d19f292..b5411fc 100644 --- a/src/dom/ready/modern.js +++ b/src/dom/ready/modern.js @@ -16,10 +16,6 @@ Anot.ready = function(fn) { } } -Anot.ready(function() { - Anot.scan && Anot.scan(document.body) -}) - /* istanbul ignore next */ function bootstrap() { if (document.readyState === 'complete') { diff --git a/src/dom/shim/fixContains.js b/src/dom/shim/fixContains.js deleted file mode 100644 index f3cde37..0000000 --- a/src/dom/shim/fixContains.js +++ /dev/null @@ -1,10 +0,0 @@ -/* istanbul ignore next */ -export function fixContains(root, el) { - try { - //IE6-8,游离于DOM树外的文本节点,访问parentNode有时会抛错 - while ((el = el.parentNode)) { - if (el === root) return true - } - } catch (e) {} - return false -} diff --git a/src/dom/shim/modern.js b/src/dom/shim/modern.js deleted file mode 100644 index e26ed6c..0000000 --- a/src/dom/shim/modern.js +++ /dev/null @@ -1,41 +0,0 @@ -//safari5+是把contains方法放在Element.prototype上而不是Node.prototype -import { Anot, root } from '../../seed/core' -import { fixContains } from './fixContains' -export { Anot } - -Anot.contains = fixContains - -Anot.cloneNode = function(a) { - return a.cloneNode(true) -} - -if (!document.contains) { - Node.prototype.contains = function(child) { - //IE6-8没有Node对象 - return fixContains(this, child) - } -} -function fixFF(prop, cb) { - //firefox12 http://caniuse.com/#search=outerHTML - if (!(prop in root)) { - HTMLElement.prototype.__defineGetter__(prop, cb) - } -} -fixFF('outerHTML', function() { - //https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/children - var div = document.createElement('div') - div.appendChild(this) - return div.innerHTML -}) -fixFF('children', function() { - var children = [] - for (var i = 0, el; (el = this.childNodes[i++]); ) { - if (el.nodeType === 1) { - children.push(el) - } - } - return children -}) -fixFF('innerText', function() { - return this.textContent -}) diff --git a/src/filters/array.js b/src/filters/array.js index e3d87e2..214d1a2 100644 --- a/src/filters/array.js +++ b/src/filters/array.js @@ -1,4 +1,4 @@ -import { Anot, escapeRegExp } from '../seed/core' +import { Anot, escapeRegExp, isObject } from '../seed/core' import { $$skipArray } from '../vmodel/reserved' export function orderBy(array, by, decend) { @@ -96,7 +96,7 @@ export function filterBy(array, search, ...args) { } export function selectBy(data, array, defaults) { - if (Anot.isObject(data) && !Array.isArray(data)) { + if (isObject(data) && !Array.isArray(data)) { var target = [] return recovery(target, array, function(name) { target.push( diff --git a/src/parser/attributes.js b/src/parser/attributes.js index e0e2544..edcff5b 100644 --- a/src/parser/attributes.js +++ b/src/parser/attributes.js @@ -1,5 +1,5 @@ -import { Anot, directives } from '../seed/core' -export var eventMap = Anot.oneObject( +import { Anot, directives, oneObject } from '../seed/core' +export var eventMap = oneObject( 'animationend,blur,change,input,' + 'click,dblclick,focus,keydown,keypress,keyup,mousedown,mouseenter,' + 'mouseleave,mousemove,mouseout,mouseover,mouseup,scan,scroll,submit', diff --git a/src/parser/index.js b/src/parser/index.js index c905942..fce0978 100644 --- a/src/parser/index.js +++ b/src/parser/index.js @@ -1,7 +1,7 @@ -import { Anot, Cache } from '../seed/core' +import { Anot, Cache, oneObject } from '../seed/core' import { clearString, stringPool, fill, rfill, dig } from '../vtree/clearString' -var keyMap = Anot.oneObject( +var keyMap = oneObject( 'break,case,catch,continue,debugger,default,delete,do,else,false,' + 'finally,for,function,if,in,instanceof,new,null,return,switch,this,' + 'throw,true,try,typeof,var,void,while,with,' /* 关键字*/ + diff --git a/src/seed/core.js b/src/seed/core.js index f3be7f5..25862cb 100644 --- a/src/seed/core.js +++ b/src/seed/core.js @@ -7,12 +7,6 @@ export function Anot(el) { return new Anot.init(el) } -Anot.init = function(el) { - this[0] = this.element = el -} - -Anot.fn = Anot.prototype = Anot.init.prototype - export var rword = /[^, ]+/g export var rnowhite = /\S+/g //存在非空字符 export var platform = {} //用于放置平台差异的方法与属性 @@ -114,7 +108,6 @@ export var validators = {} export var cssHooks = {} window.Anot = Anot -Anot.platform = platform /* istanbul ignore next */ export function createFragment() { @@ -170,24 +163,6 @@ Object.assign(Anot, { } }, evaluatorPool: new Cache(888), - parsers: { - number: function(a) { - return a === '' ? '' : +a || 0 - }, - string: function(a) { - return a === null || a === void 0 ? '' : a + '' - }, - boolean: function(a) { - if (a === '') { - return a - } - return a === 'true' || a === '1' - } - }, - - oneObject, - inspect, - ohasOwn, vmodels: {}, directives, @@ -195,15 +170,11 @@ Object.assign(Anot, { eventHooks, eventListeners, - validators, cssHooks, noop, - isObject, range, hyphen, - camelize, - - makeHashCode + camelize }) diff --git a/src/seed/lang.js b/src/seed/index.js similarity index 71% rename from src/seed/lang.js rename to src/seed/index.js index 0ae7fa3..417c4fb 100644 --- a/src/seed/lang.js +++ b/src/seed/index.js @@ -1,6 +1,7 @@ //这里放置存在异议的方法 -import { Anot, ohasOwn, inspect } from './core' -export { Anot } +import { Anot, inspect, platform, isObject } from './core' +export default Anot + var rwindow = /^\[object (?:Window|DOMWindow|global)\]$/ var rarraylike = /(Array|List|Collection|Map|Arguments|Set)\]$/ @@ -39,6 +40,67 @@ Anot.isPlainObject = function(obj) { ) } +Anot.nextTick = (function() { + let queue = [] + function callback() { + let n = queue.length + for (let i = 0; i < n; i++) { + queue[i]() + } + queue = queue.slice(n) + } + + let node = document.createTextNode('') + new MutationObserver(callback).observe(node, { characterData: true }) + + let bool = false + return function(fn) { + queue.push(fn) + bool = !bool + node.data = bool + } +})() + +Anot.init = function(source) { + if (source) { + if (Anot.isPlainObject(source)) { + var id = source.$id + var vm = Anot.vmodels[id] + + if (!id) { + throw new Error(`vm的$id必须声明`) + } + + if (vm) { + throw new Error(`vm实例[${id}]已经存在`) + } + vm = platform.modelFactory(source) + Anot.vmodels[id] = vm + + Anot.nextTick(function() { + let $elem = document.querySelector('[anot=' + vm.$id + ']') + if ($elem) { + if ($elem === document.body) { + Anot.scan($elem) + } else { + let _parent = $elem + while ((_parent = _parent.parentNode)) { + if (_parent.__VM__) { + break + } + } + Anot.scan($elem.parentNode, _parent && _parent.__VM__) + } + } + }) + } + return vm + } + this[0] = this.element = source +} + +Anot.fn = Anot.prototype = Anot.init.prototype + //与jQuery.extend方法,可用于浅拷贝,深拷贝 Anot.mix = Anot.fn.mix = function() { var options, diff --git a/src/vdom/VElement.modern.js b/src/vdom/VElement.modern.js index a27ef1b..3c4ec88 100644 --- a/src/vdom/VElement.modern.js +++ b/src/vdom/VElement.modern.js @@ -1,4 +1,4 @@ -import { Anot } from '../seed/core' +import { Anot, oneObject } from '../seed/core' export function VElement(type, props, children, isVoidTag) { this.nodeName = type @@ -84,7 +84,7 @@ function createSVG(type) { return document.createElementNS('http://www.w3.org/2000/svg', type) } -var svgTags = Anot.oneObject( +var svgTags = oneObject( 'circle,defs,ellipse,image,line,' + 'path,polygon,polyline,rect,symbol,text,use,g,svg' ) diff --git a/src/vmodel/Mutation.js b/src/vmodel/Mutation.js index 1367a96..17a2b29 100644 --- a/src/vmodel/Mutation.js +++ b/src/vmodel/Mutation.js @@ -4,7 +4,7 @@ import { reportObserved, propagateChanged } from './transaction' -import { Anot, platform } from '../seed/core' +import { Anot, platform, isObject } from '../seed/core' /** * @@ -59,7 +59,7 @@ export class Mutation { set(newValue) { var oldValue = this.value if (newValue !== oldValue) { - if (Anot.isObject(newValue)) { + if (isObject(newValue)) { var hash = oldValue && oldValue.$hashcode var childVM = platform.createProxy(newValue, this) if (childVM) { diff --git a/src/vmodel/ProxyArray.js b/src/vmodel/ProxyArray.js index 03a4109..2b0653b 100644 --- a/src/vmodel/ProxyArray.js +++ b/src/vmodel/ProxyArray.js @@ -1,4 +1,4 @@ -import { Anot, ap, platform, isObject } from '../seed/core' +import { Anot, ap, platform, isObject, makeHashCode } from '../seed/core' import { Mutation } from './Mutation' var _splice = ap.splice @@ -105,7 +105,7 @@ export function listFactory(array, stop, dd) { Object.defineProperty(array, '$model', platform.modelAccessor) - platform.hideProperty(array, '$hashcode', Anot.makeHashCode('$')) + platform.hideProperty(array, '$hashcode', makeHashCode('$')) platform.hideProperty(array, '$events', { __dep__: dd || new Mutation() }) } var _dd = array.$events && array.$events.__dep__ diff --git a/src/vmodel/share.js b/src/vmodel/share.js index 5ed13ba..dc67af4 100644 --- a/src/vmodel/share.js +++ b/src/vmodel/share.js @@ -1,11 +1,10 @@ -import { Anot, platform, isObject } from '../seed/core' +import { Anot, platform, isObject, makeHashCode } from '../seed/core' import { $$skipArray } from './reserved' import { Mutation } from './Mutation' import { Computed } from './Computed' /** * 这里放置ViewModel模块的共用方法 - * Anot.define: 全框架最重要的方法,生成用户VM * IProxy, 基本用户数据产生的一个数据对象,基于$model与vmodel之间的形态 * modelFactory: 生成用户VM * canHijack: 判定此属性是否该被劫持,加入数据监听与分发的的逻辑 @@ -15,18 +14,6 @@ import { Computed } from './Computed' * fuseFactory: 两个ms-controller间产生的代理VM的生成工厂 */ -Anot.define = function(definition) { - var $id = definition.$id - if (!$id) { - console.error('vm.$id must be specified') - } - if (Anot.vmodels[$id]) { - console.warn('error:[' + $id + '] had defined!') - } - var vm = platform.modelFactory(definition) - return (Anot.vmodels[$id] = vm) -} - /** * Anot改用Proxy来创建VM,因此 */ @@ -34,7 +21,7 @@ Anot.define = function(definition) { export function IProxy(definition, dd) { Anot.mix(this, definition) Anot.mix(this, $$skipArray) - this.$hashcode = Anot.makeHashCode('$') + this.$hashcode = makeHashCode('$') this.$id = this.$id || this.$hashcode this.$events = { __dep__: dd || new Mutation(this.$id)