1/*! 2built in 2017-5-9:11:38 version 2.2.6 by å¸å¾æ£ç¾ 3https://github.com/RubyLouvre/avalon/tree/2.2.4 4 5ä¿®æ£IEä¸ orderBy BUG 6æ´æ¹ä¸è½½Promiseçæç¤º 7ä¿®å¤avalon.modern å¨Proxy 模å¼ä¸ä½¿ç¨ms-for 循ç¯å¯¹è±¡æ¶åºéçBUG 8ä¿®å¤effectå é¨ä¼ å BUG 9éæms-validateçç»å®äºä»¶çæºå¶ 10 11*/(function (global, factory) { 12 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.avalon = factory(); 13})(this, function () { 14 'use strict'; 15 16 var win = typeof window === 'object' ? window : typeof global === 'object' ? global : {}; 17 18 var inBrowser = !!win.location && win.navigator; 19 /* istanbul ignore if */ 20 21 var document$1 = inBrowser ? win.document : { 22 createElement: Object, 23 createElementNS: Object, 24 documentElement: 'xx', 25 contains: Boolean 26 }; 27 var root = inBrowser ? document$1.documentElement : { 28 outerHTML: 'x' 29 }; 30 31 var versions = { 32 objectobject: 7, //IE7-8 33 objectundefined: 6, //IE6 34 undefinedfunction: NaN, // other modern browsers 35 undefinedobject: NaN }; 36 /* istanbul ignore next */ 37 var msie = document$1.documentMode || versions[typeof document$1.all + typeof XMLHttpRequest]; 38 39 var modern = /NaN|undefined/.test(msie) || msie > 8; 40 41 /* 42 https://github.com/rsms/js-lru 43 entry entry entry entry 44 ______ ______ ______ ______ 45 | head |.newer => | |.newer => | |.newer => | tail | 46 | A | | B | | C | | D | 47 |______| <= older.|______| <= older.|______| <= older.|______| 48 49 removed <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- added 50 */ 51 function Cache(maxLength) { 52 // æ è¯å½åç¼åæ°ç»çå¤§å° 53 this.size = 0; 54 // æ è¯ç¼åæ°ç»è½è¾¾å°çæå¤§é¿åº¦ 55 this.limit = maxLength; 56 // headï¼æä¸å¸¸ç¨ç项ï¼ï¼tailï¼æå¸¸ç¨ç项ï¼å ¨é¨åå§å为undefined 57 58 this.head = this.tail = void 0; 59 this._keymap = {}; 60 } 61 62 Cache.prototype = { 63 put: function put(key, value) { 64 var entry = { 65 key: key, 66 value: value 67 }; 68 this._keymap[key] = entry; 69 if (this.tail) { 70 // 妿åå¨tailï¼ç¼åæ°ç»çé¿åº¦ä¸ä¸º0ï¼ï¼å°tailæåæ°ç entry 71 this.tail.newer = entry; 72 entry.older = this.tail; 73 } else { 74 // 妿ç¼åæ°ç»çé¿åº¦ä¸º0ï¼å°headæåæ°çentry 75 this.head = entry; 76 } 77 this.tail = entry; 78 // 妿ç¼åæ°ç»è¾¾å°ä¸éï¼åå å é¤ head æåçç¼å对象 79 /* istanbul ignore if */ 80 if (this.size === this.limit) { 81 this.shift(); 82 } else { 83 this.size++; 84 } 85 return value; 86 }, 87 shift: function shift() { 88 /* istanbul ignore next */ 89 var entry = this.head; 90 /* istanbul ignore if */ 91 if (entry) { 92 // å é¤ head ï¼å¹¶æ¹åæå 93 this.head = this.head.newer; 94 // åæ¥æ´æ° _keymap éé¢ç屿§å¼ 95 this.head.older = entry.newer = entry.older = this._keymap[entry.key] = void 0; 96 delete this._keymap[entry.key]; //#1029 97 // åæ¥æ´æ° ç¼åæ°ç»çé¿åº¦ 98 this.size--; 99 } 100 }, 101 get: function get(key) { 102 var entry = this._keymap[key]; 103 // å¦ææ¥æ¾ä¸å°å«æ`key`è¿ä¸ªå±æ§çç¼å对象 104 if (entry === void 0) return; 105 // å¦ææ¥æ¾å°çç¼åå¯¹è±¡å·²ç»æ¯ tail (æè¿ä½¿ç¨è¿ç) 106 /* istanbul ignore if */ 107 if (entry === this.tail) { 108 return entry.value; 109 } 110 // HEAD--------------TAIL 111 // <.older .newer> 112 // <--- add direction -- 113 // A B C <D> E 114 if (entry.newer) { 115 // å¤ç newer æå 116 if (entry === this.head) { 117 // å¦ææ¥æ¾å°çç¼åå¯¹è±¡æ¯ head (æè¿æå°ä½¿ç¨è¿ç) 118 // åå° head æåå head ç newer ææåçç¼å对象 119 this.head = entry.newer; 120 } 121 // å°ææ¥æ¾çç¼å对象çä¸ä¸çº§ç older æåææ¥æ¾çç¼å对象çolderææåçå¼ 122 // ä¾å¦ï¼A B C D E 123 // å¦ææ¥æ¾å°çæ¯Dï¼é£ä¹å°EæåCï¼ä¸åæåD 124 entry.newer.older = entry.older; // C <-- E. 125 } 126 if (entry.older) { 127 // å¤ç older æå 128 // å¦ææ¥æ¾å°çæ¯Dï¼é£ä¹CæåEï¼ä¸åæåD 129 entry.older.newer = entry.newer; // C. --> E 130 } 131 // å¤çææ¥æ¾å°ç对象ç newer 以å older æå 132 entry.newer = void 0; // D --x 133 // olderæåä¹å使ç¨è¿çåéï¼å³DæåE 134 entry.older = this.tail; // D. --> E 135 if (this.tail) { 136 // å°EçneweræåD 137 this.tail.newer = entry; // E. <-- D 138 } 139 // æ¹å tail 为D 140 this.tail = entry; 141 return entry.value; 142 } 143 }; 144 145 var delayCompile = {}; 146 147 var directives = {}; 148 149 function directive(name, opts) { 150 if (directives[name]) { 151 avalon.warn(name, 'directive have defined! '); 152 } 153 directives[name] = opts; 154 if (!opts.update) { 155 opts.update = function () {}; 156 } 157 if (opts.delay) { 158 delayCompile[name] = 1; 159 } 160 return opts; 161 } 162 163 function delayCompileNodes(dirs) { 164 for (var i in delayCompile) { 165 if ('ms-' + i in dirs) { 166 return true; 167 } 168 } 169 } 170 171 var window$1 = win; 172 function avalon(el) { 173 return new avalon.init(el); 174 } 175 176 avalon.init = function (el) { 177 this[0] = this.element = el; 178 }; 179 180 avalon.fn = avalon.prototype = avalon.init.prototype; 181 182 function shadowCopy(destination, source) { 183 for (var property in source) { 184 destination[property] = source[property]; 185 } 186 return destination; 187 } 188 var rword = /[^, ]+/g; 189 var rnowhite = /\S+/g; //åå¨é空å符 190 var platform = {}; //ç¨äºæ¾ç½®å¹³å°å·®å¼çæ¹æ³ä¸å±æ§ 191 192 193 function oneObject(array, val) { 194 if (typeof array === 'string') { 195 array = array.match(rword) || []; 196 } 197 var result = {}, 198 value = val !== void 0 ? val : 1; 199 for (var i = 0, n = array.length; i < n; i++) { 200 result[array[i]] = value; 201 } 202 return result; 203 } 204 205 var op = Object.prototype; 206 function quote(str) { 207 return avalon._quote(str); 208 } 209 var inspect = op.toString; 210 var ohasOwn = op.hasOwnProperty; 211 var ap = Array.prototype; 212 213 var hasConsole = typeof console === 'object'; 214 avalon.config = { debug: true }; 215 function log() { 216 if (hasConsole && avalon.config.debug) { 217 Function.apply.call(console.log, console, arguments); 218 } 219 } 220 function warn() { 221 if (hasConsole && avalon.config.debug) { 222 var method = console.warn || console.log; 223 // http://qiang106.iteye.com/blog/1721425 224 Function.apply.call(method, console, arguments); 225 } 226 } 227 function error(str, e) { 228 throw (e || Error)(str); 229 } 230 function noop() {} 231 function isObject(a) { 232 return a !== null && typeof a === 'object'; 233 } 234 235 function range(start, end, step) { 236 // ç¨äºçææ´æ°æ°ç» 237 step || (step = 1); 238 if (end == null) { 239 end = start || 0; 240 start = 0; 241 } 242 var index = -1, 243 length = Math.max(0, Math.ceil((end - start) / step)), 244 result = new Array(length); 245 while (++index < length) { 246 result[index] = start; 247 start += step; 248 } 249 return result; 250 } 251 252 var rhyphen = /([a-z\d])([A-Z]+)/g; 253 function hyphen(target) { 254 //转æ¢ä¸ºè¿åç¬¦çº¿é£æ ¼ 255 return target.replace(rhyphen, '$1-$2').toLowerCase(); 256 } 257 258 var rcamelize = /[-_][^-_]/g; 259 function camelize(target) { 260 //æåå¤æï¼æé«getStyleççæç 261 if (!target || target.indexOf('-') < 0 && target.indexOf('_') < 0) { 262 return target; 263 } 264 //转æ¢ä¸ºé©¼å³°é£æ ¼ 265 return target.replace(rcamelize, function (match) { 266 return match.charAt(1).toUpperCase(); 267 }); 268 } 269 270 var _slice = ap.slice; 271 function slice(nodes, start, end) { 272 return _slice.call(nodes, start, end); 273 } 274 275 var rhashcode = /\d\.\d{4}/; 276 //çæUUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript 277 function makeHashCode(prefix) { 278 /* istanbul ignore next*/ 279 prefix = prefix || 'avalon'; 280 /* istanbul ignore next*/ 281 return String(Math.random() + Math.random()).replace(rhashcode, prefix); 282 } 283 //çæäºä»¶åè°çUUID(ç¨æ·éè¿ms-onæä»¤) 284 function getLongID(fn) { 285 /* istanbul ignore next */ 286 return fn.uuid || (fn.uuid = makeHashCode('e')); 287 } 288 var UUID = 1; 289 //çæäºä»¶åè°çUUID(ç¨æ·éè¿avalon.bind) 290 function getShortID(fn) { 291 /* istanbul ignore next */ 292 return fn.uuid || (fn.uuid = '_' + ++UUID); 293 } 294 295 var rescape = /[-.*+?^${}()|[\]\/\\]/g; 296 function escapeRegExp(target) { 297 //http://stevenlevithan.com/regex/xregexp/ 298 //å°å符串å®å ¨æ ¼å¼å为æ£å表达å¼çæºç 299 return (target + '').replace(rescape, '\\$&'); 300 } 301 302 var eventHooks = {}; 303 var eventListeners = {};
304 var validators = {}; 305 var cssHooks = {}; 306 307 window$1.avalon = avalon; 308 309 function createFragment() { 310 /* istanbul ignore next */ 311 return document$1.createDocumentFragment(); 312 } 313 314 var rentities = /&[a-z0-9#]{2,10};/; 315 var temp = document$1.createElement('div'); 316 shadowCopy(avalon, { 317 Array: { 318 merge: function merge(target, other) { 319 //å并两个æ°ç» avalon2æ°å¢ 320 target.push.apply(target, other); 321 }, 322 ensure: function ensure(target, item) { 323 //åªæå½åæ°ç»ä¸å卿¤å ç´ æ¶åªæ·»å å® 324 if (target.indexOf(item) === -1) { 325 return target.push(item); 326 } 327 }, 328 removeAt: function removeAt(target, index) { 329 //ç§»é¤æ°ç»ä¸æå®ä½ç½®çå ç´ ï¼è¿åå¸å°è¡¨ç¤ºæåä¸å¦ 330 return !!target.splice(index, 1).length; 331 }, 332 remove: function remove(target, item) { 333 //ç§»é¤æ°ç»ä¸ç¬¬ä¸ä¸ªå¹é ä¼ åçé£ä¸ªå ç´ ï¼è¿åå¸å°è¡¨ç¤ºæåä¸å¦ 334 var index = target.indexOf(item); 335 if (~index) return avalon.Array.removeAt(target, index); 336 return false; 337 } 338 }, 339 evaluatorPool: new Cache(888), 340 parsers: { 341 number: function number(a) { 342 return a === '' ? '' : parseFloat(a) || 0; 343 }, 344 string: function string(a) { 345 return a === null || a === void 0 ? '' : a + ''; 346 }, 347 "boolean": function boolean(a) { 348 if (a === '') return a; 349 return a === 'true' || a === '1'; 350 } 351 }, 352 _decode: function _decode(str) { 353 if (rentities.test(str)) { 354 temp.innerHTML = str; 355 return temp.innerText || temp.textContent; 356 } 357 return str; 358 } 359 }); 360 361 //============== config ============ 362 function config(settings) { 363 for (var p in settings) { 364 var val = settings[p]; 365 if (typeof config.plugins[p] === 'function') { 366 config.plugins[p](val); 367 } else { 368 config[p] = val; 369 } 370 } 371 return this; 372 } 373 374 var plugins = { 375 interpolate: function interpolate(array) { 376 var openTag = array[0]; 377 var closeTag = array[1]; 378 if (openTag === closeTag) { 379 throw new SyntaxError('interpolate openTag cannot equal to closeTag'); 380 } 381 var str = openTag + 'test' + closeTag; 382 383 if (/[<>]/.test(str)) { 384 throw new SyntaxError('interpolate cannot contains "<" or ">"'); 385 } 386 387 config.openTag = openTag; 388 config.closeTag = closeTag; 389 var o = escapeRegExp(openTag); 390 var c = escapeRegExp(closeTag); 391 392 config.rtext = new RegExp(o + '(.+?)' + c, 'g'); 393 config.rexpr = new RegExp(o + '([\\s\\S]*)' + c); 394 } 395 }; 396 function createAnchor(nodeValue) { 397 return document$1.createComment(nodeValue); 398 } 399 config.plugins = plugins; 400 config({ 401 interpolate: ['{{', '}}'], 402 debug: true 403 }); 404 //============ config ============ 405 406 shadowCopy(avalon, { 407 shadowCopy: shadowCopy, 408 409 oneObject: oneObject, 410 inspect: inspect, 411 ohasOwn: ohasOwn, 412 rword: rword, 413 version: "2.2.6", 414 vmodels: {}, 415 416 directives: directives, 417 directive: directive, 418 419 eventHooks: eventHooks, 420 eventListeners: eventListeners, 421 validators: validators, 422 cssHooks: cssHooks, 423 424 log: log, 425 noop: noop, 426 warn: warn, 427 error: error, 428 config: config, 429 430 modern: modern, 431 msie: msie, 432 root: root, 433 document: document$1, 434 window: window$1, 435 inBrowser: inBrowser, 436 437 isObject: isObject, 438 range: range, 439 slice: slice, 440 hyphen: hyphen, 441 camelize: camelize, 442 escapeRegExp: escapeRegExp, 443 quote: quote, 444 445 makeHashCode: makeHashCode 446 447 }); 448 449 /** 450 * æ¤æ¨¡åç¨äºä¿®å¤è¯è¨çåºå±ç¼ºé· 451 */ 452 function isNative(fn) { 453 return (/\[native code\]/.test(fn) 454 ); 455 } 456 457 /* istanbul ignore if*/ 458 if (!isNative('å¸å¾æ£ç¾'.trim)) { 459 var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; 460 String.prototype.trim = function () { 461 return this.replace(rtrim, ''); 462 }; 463 } 464 if (!Object.create) { 465 Object.create = function () { 466 function F() {} 467 468 return function (o) { 469 if (arguments.length != 1) { 470 throw new Error('Object.create implementation only accepts one parameter.'); 471 } 472 F.prototype = o; 473 return new F(); 474 }; 475 }(); 476 } 477 var hasDontEnumBug = !{ 478 'toString': null 479 }.propertyIsEnumerable('toString'); 480 var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');
481 var dontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor']; 482 var dontEnumsLength = dontEnums.length; 483 /* istanbul ignore if*/ 484 if (!isNative(Object.keys)) { 485 Object.keys = function (object) { 486 //ecma262v5 15.2.3.14 487 var theKeys = []; 488 var skipProto = hasProtoEnumBug && typeof object === 'function'; 489 if (typeof object === 'string' || object && object.callee) { 490 for (var i = 0; i < object.length; ++i) { 491 theKeys.push(String(i)); 492 } 493 } else { 494 for (var name in object) { 495 if (!(skipProto && name === 'prototype') && ohasOwn.call(object, name)) { 496 theKeys.push(String(name)); 497 } 498 } 499 } 500 501 if (hasDontEnumBug) { 502 var ctor = object.constructor, 503 skipConstructor = ctor && ctor.prototype === object; 504 for (var j = 0; j < dontEnumsLength; j++) { 505 var dontEnum = dontEnums[j]; 506 if (!(skipConstructor && dontEnum === 'constructor') && ohasOwn.call(object, dontEnum)) { 507 theKeys.push(dontEnum); 508 } 509 } 510 } 511 return theKeys; 512 }; 513 } 514 /* istanbul ignore if*/ 515 if (!isNative(Array.isArray)) { 516 Array.isArray = function (a) { 517 return Object.prototype.toString.call(a) === '[object Array]'; 518 }; 519 } 520 521 /* istanbul ignore if*/ 522 if (!isNative(isNative.bind)) { 523 /* istanbul ignore next*/ 524 Function.prototype.bind = function (scope) { 525 if (arguments.length < 2 && scope === void 0) return this; 526 var fn = this, 527 argv = arguments; 528 return function () { 529 var args = [], 530 i; 531 for (i = 1; i < argv.length; i++) { 532 args.push(argv[i]); 533 }for (i = 0; i < arguments.length; i++) { 534 args.push(arguments[i]); 535 }return fn.apply(scope, args); 536 }; 537 }; 538 } 539 //https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice 540 /** 541 * Shim for "fixing" IE's lack of support (IE < 9) for applying slice 542 * on host objects like NamedNodeMap, NodeList, and HTMLCollection 543 * (technically, since host objects have been implementation-dependent, 544 * at least before ES6, IE hasn't needed to work this way). 545 * Also works on strings, fixes IE < 9 to allow an explicit undefined 546 * for the 2nd argument (as in Firefox), and prevents errors when 547 * called on other DOM objects. 548 */ 549 550 try { 551 // Can't be used with DOM elements in IE < 9 552 _slice.call(avalon.document.documentElement); 553 } catch (e) { 554 // Fails in IE < 9 555 // This will work for genuine arrays, array-like objects, 556 // NamedNodeMap (attributes, entities, notations), 557 // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes), 558 // and will not fail on other DOM objects (as do DOM elements in IE < 9) 559 /* istanbul ignore next*/ 560 ap.slice = function (begin, end) { 561 // IE < 9 gets unhappy with an undefined end argument 562 end = typeof end !== 'undefined' ? end : this.length; 563 564 // For native Array objects, we use the native slice function 565 if (Array.isArray(this)) { 566 return _slice.call(this, begin, end); 567 } 568 569 // For array like object we handle it ourselves. 570 var i, 571 cloned = [], 572 size, 573 len = this.length; 574 575 // Handle negative value for "begin" 576 var start = begin || 0; 577 start = start >= 0 ? start : len + start; 578 579 // Handle negative value for "end" 580 var upTo = end ? end : len; 581 if (end < 0) { 582 upTo = len + end; 583 } 584 585 // Actual expected size of the slice 586 size = upTo - start; 587 588 if (size > 0) { 589 cloned = new Array(size); 590 if (this.charAt) { 591 for (i = 0; i < size; i++) { 592 cloned[i] = this.charAt(start + i); 593 } 594 } else { 595 for (i = 0; i < size; i++) { 596 cloned[i] = this[start + i]; 597 } 598 } 599 } 600 601 return cloned; 602 }; 603 } 604 /* istanbul ignore next*/ 605 function iterator(vars, body, ret) { 606 var fun = 'for(var ' + vars + 'i=0,n = this.length; i < n; i++){' + body.replace('_', '((i in this) && fn.call(scope,this[i],i,this))') + '}' + ret; 607 /* jshint ignore:start */ 608 return Function('fn,scope', fun); 609 /* jshint ignore:end */ 610 } 611 /* istanbul ignore if*/ 612 if (!isNative(ap.map)) { 613 avalon.shadowCopy(ap, { 614 //å®ä½æä½ï¼è¿åæ°ç»ä¸ç¬¬ä¸ä¸ªçäºç»å®åæ°çå ç´ çç´¢å¼å¼ã 615 indexOf: function indexOf(item, index) { 616 var n = this.length, 617 i = ~~index; 618 if (i < 0) i += n; 619 for (; i < n; i++) { 620 if (this[i] === item) return i; 621 }return -1; 622 }, 623 //å®ä½æä½ï¼åä¸ï¼ä¸è¿æ¯ä»åéåã 624 lastIndexOf: function lastIndexOf(item, index) { 625 var n = this.length, 626 i = index == null ? n - 1 : index; 627 if (i < 0) i = Math.max(0, n + i); 628 for (; i >= 0; i--) { 629 if (this[i] === item) return i; 630 }return -1; 631 }, 632 //è¿ä»£æä½ï¼å°æ°ç»çå ç´ æ¨ä¸ªå¿ä¼ å ¥ä¸ä¸ªå½æ°ä¸æ§è¡ãPrototype.jsç对åºåå为eachã
633 forEach: iterator('', '_', ''), 634 //è¿ä»£ç±» 卿°ç»ä¸çæ¯ä¸ªé¡¹ä¸è¿è¡ä¸ä¸ªå½æ°ï¼å¦ææ¤å½æ°çå¼ä¸ºçï¼åæ¤å ç´ ä½ä¸ºæ°æ°ç»çå ç´ æ¶éèµ·æ¥ï¼å¹¶è¿åæ°æ°ç» 635 filter: iterator('r=[],j=0,', 'if(_)r[j++]=this[i]', 'return r'), 636 //æ¶éæä½ï¼å°æ°ç»çå ç´ æ¨ä¸ªå¿ä¼ å ¥ä¸ä¸ªå½æ°ä¸æ§è¡ï¼ç¶åæå®ä»¬çè¿åå¼ç»æä¸ä¸ªæ°æ°ç»è¿åãPrototype.jsç对åºåå为collectã 637 map: iterator('r=[],', 'r[i]=_', 'return r'), 638 //åªè¦æ°ç»ä¸æä¸ä¸ªå ç´ æ»¡è¶³æ¡ä»¶ï¼æ¾è¿ç»å®å½æ°è¿åtrueï¼ï¼é£ä¹å®å°±è¿åtrueãPrototype.jsç对åºåå为anyã 639 some: iterator('', 'if(_)return true', 'return false'), 640 //åªææ°ç»ä¸çå ç´ é½æ»¡è¶³æ¡ä»¶ï¼æ¾è¿ç»å®å½æ°è¿åtrueï¼ï¼å®æè¿åtrueãPrototype.jsç对åºåå为allã 641 every: iterator('', 'if(!_)return false', 'return true') 642 }); 643 } 644 645 //è¿éæ¾ç½®åå¨å¼è®®çæ¹æ³ 646 var compaceQuote = function () { 647 //https://github.com/bestiejs/json3/blob/master/lib/json3.js 648 var Escapes = { 649 92: "\\\\", 650 34: '\\"', 651 8: "\\b", 652 12: "\\f", 653 10: "\\n", 654 13: "\\r", 655 9: "\\t" 656 }; 657 658 var leadingZeroes = '000000'; 659 var toPaddedString = function toPaddedString(width, value) { 660 return (leadingZeroes + (value || 0)).slice(-width); 661 }; 662 var unicodePrefix = '\\u00'; 663 var escapeChar = function escapeChar(character) { 664 var charCode = character.charCodeAt(0), 665 escaped = Escapes[charCode]; 666 if (escaped) { 667 return escaped; 668 } 669 return unicodePrefix + toPaddedString(2, charCode.toString(16)); 670 }; 671 var reEscape = /[\x00-\x1f\x22\x5c]/g; 672 return function (value) { 673 /* istanbul ignore next */ 674 reEscape.lastIndex = 0; 675 /* istanbul ignore next */ 676 return '"' + (reEscape.test(value) ? String(value).replace(reEscape, escapeChar) : value) + '"'; 677 }; 678 }(); 679 try { 680 avalon._quote = JSON.stringify; 681 } catch (e) { 682 /* istanbul ignore next */ 683 avalon._quote = compaceQuote; 684 } 685 686 var class2type = {}; 687 'Boolean Number String Function Array Date RegExp Object Error'.replace(avalon.rword, function (name) { 688 class2type['[object ' + name + ']'] = name.toLowerCase(); 689 }); 690 691 avalon.type = function (obj) { 692 //åå¾ç®æ çç±»å 693 if (obj == null) { 694 return String(obj); 695 } 696 // æ©æçwebkitå æ ¸æµè§å¨å®ç°äºå·²åºå¼çecma262v4æ åï¼å¯ä»¥å°æ£ååé¢éå½ä½å½æ°ä½¿ç¨ï¼å æ¤typeofå¨å¤å®æ£åæ¶ä¼è¿åfunction 697 return typeof obj === 'object' || typeof obj === 'function' ? class2type[inspect.call(obj)] || 'object' : typeof obj; 698 }; 699 700 var rfunction = /^\s*\bfunction\b/; 701 702 avalon.isFunction = /* istanbul ignore if */typeof alert === 'object' ? function (fn) { 703 /* istanbul ignore next */ 704 try { 705 /* istanbul ignore next */ 706 return rfunction.test(fn + ''); 707 } catch (e) { 708 /* istanbul ignore next */ 709 return false; 710 } 711 } : function (fn) { 712 return inspect.call(fn) === '[object Function]'; 713 }; 714 715 // å©ç¨IE678 window == document为true,document == windowç«ç¶ä¸ºfalseçç¥å¥ç¹æ§ 716 // æ åæµè§å¨åIE9ï¼IE10çä½¿ç¨ æ£åæ£æµ 717 /* istanbul ignore next */ 718 function isWindowCompact(obj) { 719 if (!obj) { 720 return false; 721 } 722 return obj == obj.document && obj.document != obj; //jshint ignore:line 723 } 724 725 var rwindow = /^\[object (?:Window|DOMWindow|global)\]$/; 726 727 function isWindowModern(obj) { 728 return rwindow.test(inspect.call(obj)); 729 } 730 731 avalon.isWindow = isWindowModern(avalon.window) ? isWindowModern : isWindowCompact; 732 733 var enu; 734 var enumerateBUG; 735 for (enu in avalon({})) { 736 break; 737 } 738 739 enumerateBUG = enu !== '0'; //IE6ä¸ä¸ºtrue, å ¶ä»ä¸ºfalse 740 741 /*å¤å®æ¯å¦æ¯ä¸ä¸ªæ´ç´ çjavascript对象ï¼Objectï¼ï¼ä¸æ¯DOM对象ï¼ä¸æ¯BOM对象ï¼ä¸æ¯èªå
741®ä¹ç±»çå®ä¾*/ 742 /* istanbul ignore next */ 743 function isPlainObjectCompact(obj, key) { 744 if (!obj || avalon.type(obj) !== 'object' || obj.nodeType || avalon.isWindow(obj)) { 745 return false; 746 } 747 try { 748 //IEå 置对象没æconstructor 749 if (obj.constructor && !ohasOwn.call(obj, 'constructor') && !ohasOwn.call(obj.constructor.prototype, 'isPrototypeOf')) { 750 return false; 751 } 752 var isVBscript = obj.$vbthis; 753 } catch (e) { 754 //IE8 9ä¼å¨è¿éæé 755 return false; 756 } 757 /* istanbul ignore if */ 758 if (enumerateBUG) { 759 for (key in obj) { 760 return ohasOwn.call(obj, key); 761 } 762 } 763 for (key in obj) {} 764 return key === undefined$1 || ohasOwn.call(obj, key); 765 } 766 767 /* istanbul ignore next */ 768 function isPlainObjectModern(obj) { 769 // ç®åç typeof obj === 'object'æ£æµï¼ä¼è´ä½¿ç¨isPlainObject(window)å¨operaä¸éä¸è¿ 770 return inspect.call(obj) === '[object Object]' && Object.getPrototypeOf(obj) === Object.prototype; 771 } 772 /* istanbul ignore next */ 773 avalon.isPlainObject = /\[native code\]/.test(Object.getPrototypeOf) ? isPlainObjectModern : isPlainObjectCompact; 774 775 var rcanMix = /object|function/; 776 777 //ä¸jQuery.extendæ¹æ³ï¼å¯ç¨äºæµ æ·è´ï¼æ·±æ·è´ 778 /* istanbul ignore next */ 779 avalon.mix = avalon.fn.mix = function () { 780 var n = arguments.length, 781 isDeep = false, 782 i = 0, 783 array = []; 784 if (arguments[0] === true) { 785 isDeep = true; 786 i = 1; 787 } 788 //å°ææé空对象åæç©ºå¯¹è±¡ 789 for (; i < n; i++) { 790 var el = arguments[i]; 791 el = el && rcanMix.test(typeof el) ? el : {}; 792 array.push(el); 793 } 794 if (array.length === 1) { 795 array.unshift(this); 796 } 797 return innerExtend(isDeep, array); 798 }; 799 var undefined$1; 800 801 function innerExtend(isDeep, array) { 802 var target = array[0], 803 copyIsArray, 804 clone, 805 name; 806 for (var i = 1, length = array.length; i < length; i++) { 807 //åªå¤çéç©ºåæ° 808 var options = array[i]; 809 var noCloneArrayMethod = Array.isArray(options); 810 for (name in options) { 811 if (noCloneArrayMethod && !options.hasOwnProperty(name)) { 812 continue; 813 } 814 try { 815 var src = target[name]; 816 var copy = options[name]; //å½options为VBSå¯¹è±¡æ¶æ¥é 817 } catch (e) { 818 continue; 819 } 820 821 // 鲿¢ç¯å¼ç¨ 822 if (target === copy) { 823 continue; 824 } 825 if (isDeep && copy && (avalon.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) { 826 827 if (copyIsArray) { 828 copyIsArray = false; 829 clone = src && Array.isArray(src) ? src : []; 830 } else { 831 clone = src && avalon.isPlainObject(src) ? src : {}; 832 } 833 834 target[name] = innerExtend(isDeep, [clone, copy]); 835 } else if (copy !== undefined$1) { 836 target[name] = copy; 837 } 838 } 839 } 840 return target; 841 } 842 843 var rarraylike = /(Array|List|Collection|Map|Arguments)\]$/; 844 /*å¤å®æ¯å¦ç±»æ°ç»ï¼å¦èç¹éåï¼çº¯æ°ç»ï¼arguments䏿¥æéè´æ´æ°çlength屿§ç纯JS对象*/ 845 /* istanbul ignore next */ 846 function isArrayLike(obj) { 847 if (!obj) return false; 848 var n = obj.length; 849 if (n === n >>> 0) { 850 //æ£æµlength屿§æ¯å¦ä¸ºéè´æ´æ° 851 var type = inspect.call(obj); 852 if (rarraylike.test(type)) return true; 853 if (type !== '[object Object]') return false; 854 try { 855 if ({}.propertyIsEnumerable.call(obj, 'length') === false) { 856 //妿æ¯åç对象 857 return rfunction.test(obj.item || obj.callee); 858 } 859 return true; 860 } catch (e) { 861 //IEçNodeListç´æ¥æé 862 return !obj.window; //IE6-8 window 863 } 864 } 865 return false;
866 } 867 868 avalon.each = function (obj, fn) { 869 if (obj) { 870 //æé¤null, undefined 871 var i = 0; 872 if (isArrayLike(obj)) { 873 for (var n = obj.length; i < n; i++) { 874 if (fn(i, obj[i]) === false) break; 875 } 876 } else { 877 for (i in obj) { 878 if (obj.hasOwnProperty(i) && fn(i, obj[i]) === false) { 879 break; 880 } 881 } 882 } 883 } 884 }; 885 (function () { 886 var welcomeIntro = ["%cavalon.js %c" + avalon.version + " %cin debug mode, %cmore...", "color: rgb(114, 157, 52); font-weight: normal;", "color: rgb(85, 85, 85); font-weight: normal;", "color: rgb(85, 85, 85); font-weight: normal;", "color: rgb(82, 140, 224); font-weight: normal; text-decoration: underline;"]; 887 var welcomeMessage = "You're running avalon in debug mode - messages will be printed to the console to help you fix problems and optimise your application.\n\n" + 'To disable debug mode, add this line at the start of your app:\n\n avalon.config({debug: false});\n\n' + 'Debug mode also automatically shut down amicably when your app is minified.\n\n' + "Get help and support:\n https://segmentfault.com/t/avalon\n http://avalonjs.coding.me/\n http://www.baidu-x.com/?q=avalonjs\n http://www.avalon.org.cn/\n\nFound a bug? Raise an issue:\n https://github.com/RubyLouvre/avalon/issues\n\n"; 888 if (typeof console === 'object') { 889 var con = console; 890 var method = con.groupCollapsed || con.log; 891 Function.apply.call(method, con, welcomeIntro); 892 con.log(welcomeMessage); 893 if (method !== console.log) { 894 con.groupEnd(welcomeIntro); 895 } 896 } 897 })(); 898 899 function toFixedFix(n, prec) { 900 var k = Math.pow(10, prec); 901 return '' + (Math.round(n * k) / k).toFixed(prec); 902 } 903 function numberFilter(number, decimals, point, thousands) { 904 //https://github.com/txgruppi/number_format 905 //form http://phpjs.org/functions/number_format/ 906 //number å¿ éï¼è¦æ ¼å¼åçæ°å 907 //decimals å¯éï¼è§å®å¤å°ä¸ªå°æ°ä½ã 908 //point å¯éï¼è§å®ç¨ä½å°æ°ç¹çå符串ï¼é»è®¤ä¸º . ï¼ã 909 //thousands å¯éï¼è§å®ç¨ä½åä½åé符çå符串ï¼é»è®¤ä¸º , ï¼ï¼å¦æè®¾ç½®äºè¯¥åæ°ï¼é£ä¹ææå ¶ä»åæ°é½æ¯å¿ éçã 910 number = (number + '').replace(/[^0-9+\-Ee.]/g, ''); 911 var n = !isFinite(+number) ? 0 : +number, 912 prec = !isFinite(+decimals) ? 3 : Math.abs(decimals), 913 sep = typeof thousands === 'string' ? thousands : ",", 914 dec = point || ".", 915 s = ''; 916 917 // Fix for IE parseFloat(0.55).toFixed(0) = 0; 918 s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.'); 919 if (s[0].length > 3) { 920 s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep); 921 } 922 /** //好忲¡æç¨ 923 var s1 = s[1] || '' 924 925 if (s1.length < prec) { 926 s1 += new Array(prec - s[1].length + 1).join('0') 927 s[1] = s1 928 } 929 **/ 930 return s.join(dec); 931 } 932 933 var rscripts = /<script[^>]*>([\S\s]*?)<\/script\s*>/gim; 934 var ron = /\s+(on[^=\s]+)(?:=("[^"]*"|'[^']*'|[^\s>]+))?/g; 935 var ropen = /<\w+\b(?:(["'])[^"]*?(\1)|[^>])*>/ig; 936 var rsanitize = { 937 a: /\b(href)\=("javascript[^"]*"|'javascript[^']*')/ig, 938 img: /\b(src)\=("javascript[^"]*"|'javascript[^']*')/ig, 939 form: /\b(action)\=("javascript[^"]*"|'javascript[^']*')/ig 940 }; 941 942 //https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet 943 // <a href="javasc
ript:alert('XSS')">chrome</a> 944 // <a href="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">chrome</a> 945 // <a href="jav ascript:alert('XSS');">IE67chrome</a> 946 // <a href="jav	ascript:alert('XSS');">IE67chrome</a> 947 // <a href="jav
ascript:alert('XSS');">IE67chrome</a> 948 function sanitizeFilter(str) { 949 return str.replace(rscripts, "").replace(ropen, function (a, b) { 950 var match = a.toLowerCase().match(/<(\w+)\s/); 951 if (match) { 952 //å¤çaæ ç¾çhref屿§ï¼imgæ ç¾çsrc屿§ï¼formæ ç¾çaction屿§ 953 var reg = rsanitize[match[1]]; 954 if (reg) { 955 a = a.replace(reg, function (s, name, value) { 956 var quote = value.charAt(0); 957 return name + "=" + quote + "javascript:void(0)" + quote; // jshint ignore:line 958 }); 959 } 960 } 961 return a.replace(ron, " ").replace(/\s+/g, " "); //ç§»é¤onXXXäºä»¶ 962 }); 963 } 964 965 /* 966 'yyyy': 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) 967 'yy': 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) 968 'y': 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) 969 'MMMM': Month in year (January-December) 970 'MMM': Month in year (Jan-Dec) 971 'MM': Month in year, padded (01-12) 972 'M': Month in year (1-12) 973 'dd': Day in month, padded (01-31) 974 'd': Day in month (1-31) 975 'EEEE': Day in Week,(Sunday-Saturday) 976 'EEE': Day in Week, (Sun-Sat) 977 'HH': Hour in day, padded (00-23) 978 'H': Hour in day (0-23) 979 'hh': Hour in am/pm, padded (01-12) 980 'h': Hour in am/pm, (1-12) 981 'mm': Minute in hour, padded (00-59) 982 'm': Minute in hour (0-59) 983 'ss': Second in minute, padded (00-59) 984 's': Second in minute (0-59) 985 'a': am/pm marker 986 'Z': 4 digit (+sign) representation of the timezone offset (-1200-+1200)
987 format string can also be one of the following predefined localizable formats: 988 989 'medium': equivalent to 'MMM d, y h:mm:ss a' for en_US locale (e.g. Sep 3, 2010 12:05:08 pm) 990 'short': equivalent to 'M/d/yy h:mm a' for en_US locale (e.g. 9/3/10 12:05 pm) 991 'fullDate': equivalent to 'EEEE, MMMM d,y' for en_US locale (e.g. Friday, September 3, 2010) 992 'longDate': equivalent to 'MMMM d, y' for en_US locale (e.g. September 3, 2010 993 'mediumDate': equivalent to 'MMM d, y' for en_US locale (e.g. Sep 3, 2010) 994 'shortDate': equivalent to 'M/d/yy' for en_US locale (e.g. 9/3/10) 995 'mediumTime': equivalent to 'h:mm:ss a' for en_US locale (e.g. 12:05:08 pm) 996 'shortTime': equivalent to 'h:mm a' for en_US locale (e.g. 12:05 pm) 997 */ 998 999 function toInt(str) { 1000 return parseInt(str, 10) || 0; 1001 } 1002 1003 function padNumber(num, digits, trim) { 1004 var neg = ''; 1005 /* istanbul ignore if*/ 1006 if (num < 0) { 1007 neg = '-'; 1008 num = -num; 1009 } 1010 num = '' + num; 1011 while (num.length < digits) { 1012 num = '0' + num; 1013 }if (trim) num = num.substr(num.length - digits); 1014 return neg + num; 1015 } 1016 1017 function dateGetter(name, size, offset, trim) { 1018 return function (date) { 1019 var value = date["get" + name](); 1020 if (offset > 0 || value > -offset) value += offset; 1021 if (value === 0 && offset === -12) { 1022 /* istanbul ignore next*/ 1023 value = 12; 1024 } 1025 return padNumber(value, size, trim); 1026 }; 1027 } 1028 1029 function dateStrGetter(name, shortForm) { 1030 return function (date, formats) { 1031 var value = date["get" + name](); 1032 var get = (shortForm ? "SHORT" + name : name).toUpperCase(); 1033 return formats[get][value]; 1034 }; 1035 } 1036 1037 function timeZoneGetter(date) { 1038 var zone = -1 * date.getTimezoneOffset(); 1039 var paddedZone = zone >= 0 ? "+" : ""; 1040 paddedZone += padNumber(Math[zone > 0 ? "floor" : "ceil"](zone / 60), 2) + padNumber(Math.abs(zone % 60), 2); 1041 return paddedZone; 1042 } 1043 //åå¾ä¸åä¸å 1044 function ampmGetter(date, formats) { 1045 return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; 1046 } 1047 var DATE_FORMATS = { 1048 yyyy: dateGetter("FullYear", 4), 1049 yy: dateGetter("FullYear", 2, 0, true), 1050 y: dateGetter("FullYear", 1), 1051 MMMM: dateStrGetter("Month"), 1052 MMM: dateStrGetter("Month", true), 1053 MM: dateGetter("Month", 2, 1), 1054 M: dateGetter("Month", 1, 1), 1055 dd: dateGetter("Date", 2), 1056 d: dateGetter("Date", 1), 1057 HH: dateGetter("Hours", 2), 1058 H: dateGetter("Hours", 1), 1059 hh: dateGetter("Hours", 2, -12), 1060 h: dateGetter("Hours", 1, -12), 1061 mm: dateGetter("Minutes", 2), 1062 m: dateGetter("Minutes", 1), 1063 ss: dateGetter("Seconds", 2), 1064 s: dateGetter("Seconds", 1), 1065 sss: dateGetter("Milliseconds", 3), 1066 EEEE: dateStrGetter("Day"), 1067 EEE: dateStrGetter("Day", true), 1068 a: ampmGetter, 1069 Z: timeZoneGetter 1070 }; 1071 var rdateFormat = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/; 1072 var raspnetjson = /^\/Date\((\d+)\)\/$/; 1073 function dateFilter(date, format) { 1074 var locate = dateFilter.locate, 1075 text = "", 1076 parts = [], 1077 fn, 1078 match; 1079 format = format || "mediumDate"; 1080 format = locate[format] || format; 1081 if (typeof date === "string") { 1082 if (/^\d+$/.test(date)) { 1083 date = toInt(date); 1084 } else if (raspnetjson.test(date)) { 1085 date = +RegExp.$1; 1086 } else { 1087 var trimDate = date.trim(); 1088 var dateArray = [0, 0, 0, 0, 0, 0, 0]; 1089 var oDate = new Date(0); 1090 //åå¾å¹´ææ¥ 1091 trimDate = trimDate.replace(/^(\d+)\D(\d+)\D(\d+)/, function (_, a, b, c) { 1092 var array = c.length === 4 ? [c, a, b] : [a, b, c]; 1093 dateArray[0] = toInt(array[0]); //å¹´ 1094 dateArray[1] = toInt(array[1]) - 1; //æ 1095 dateArray[2] = toInt(array[2]); //æ¥ 1096 return ""; 1097 }); 1098 var dateSetter = oDate.setFullYear; 1099 var timeSetter = oDate.setHours; 1100 trimDate = trimDate.replace(/[T\s](\d+):(\d+):?(\d+)?\.?(\d)?/, function (_, a, b, c, d) {
1101 dateArray[3] = toInt(a); //å°æ¶ 1102 dateArray[4] = toInt(b); //åé 1103 dateArray[5] = toInt(c); //ç§ 1104 if (d) { 1105 //æ¯«ç§ 1106 dateArray[6] = Math.round(parseFloat("0." + d) * 1000); 1107 } 1108 return ""; 1109 }); 1110 var tzHour = 0; 1111 var tzMin = 0; 1112 trimDate = trimDate.replace(/Z|([+-])(\d\d):?(\d\d)/, function (z, symbol, c, d) { 1113 dateSetter = oDate.setUTCFullYear; 1114 timeSetter = oDate.setUTCHours; 1115 if (symbol) { 1116 tzHour = toInt(symbol + c); 1117 tzMin = toInt(symbol + d); 1118 } 1119 return ''; 1120 }); 1121 1122 dateArray[3] -= tzHour; 1123 dateArray[4] -= tzMin; 1124 dateSetter.apply(oDate, dateArray.slice(0, 3)); 1125 timeSetter.apply(oDate, dateArray.slice(3)); 1126 date = oDate; 1127 } 1128 } 1129 if (typeof date === 'number') { 1130 date = new Date(date); 1131 } 1132 1133 while (format) { 1134 match = rdateFormat.exec(format); 1135 /* istanbul ignore else */ 1136 if (match) { 1137 parts = parts.concat(match.slice(1)); 1138 format = parts.pop(); 1139 } else { 1140 parts.push(format); 1141 format = null; 1142 } 1143 } 1144 parts.forEach(function (value) { 1145 fn = DATE_FORMATS[value]; 1146 text += fn ? fn(date, locate) : value.replace(/(^'|'$)/g, "").replace(/''/g, "'"); 1147 }); 1148 return text; 1149 } 1150 1151 var locate = { 1152 AMPMS: { 1153 0: 'ä¸å', 1154 1: 'ä¸å' 1155 }, 1156 DAY: { 1157 0: 'æææ¥', 1158 1: 'ææä¸', 1159 2: 'ææäº', 1160 3: 'ææä¸', 1161 4: 'ææå', 1162 5: 'ææäº', 1163 6: 'ææå ' 1164 }, 1165 MONTH: { 1166 0: '1æ', 1167 1: '2æ', 1168 2: '3æ', 1169 3: '4æ', 1170 4: '5æ', 1171 5: '6æ', 1172 6: '7æ', 1173 7: '8æ', 1174 8: '9æ', 1175 9: '10æ', 1176 10: '11æ', 1177 11: '12æ' 1178 }, 1179 SHORTDAY: { 1180 '0': '卿¥', 1181 '1': 'å¨ä¸', 1182 '2': 'å¨äº', 1183 '3': 'å¨ä¸', 1184 '4': 'å¨å', 1185 '5': 'å¨äº', 1186 '6': 'å¨å ' 1187 }, 1188 fullDate: 'yå¹´Mædæ¥EEEE', 1189 longDate: 'yå¹´Mædæ¥', 1190 medium: 'yyyy-M-d H:mm:ss', 1191 mediumDate: 'yyyy-M-d', 1192 mediumTime: 'H:mm:ss', 1193 'short': 'yy-M-d ah:mm', 1194 shortDate: 'yy-M-d', 1195 shortTime: 'ah:mm' 1196 }; 1197 locate.SHORTMONTH = locate.MONTH; 1198 dateFilter.locate = locate; 1199 1200 /** 1201 $$skipArray:æ¯ç³»ç»çº§éç¨çä¸å¯çå¬å±æ§ 1202 $skipArray: æ¯å½åå¯¹è±¡ç¹æçä¸å¯çå¬å±æ§ 1203 1204 ä¸åç¹æ¯ 1205 $$skipArray被hasOwnPropertyåè¿åfalse 1206 $skipArray被hasOwnPropertyåè¿åtrue 1207 */ 1208 var falsy; 1209 var $$skipArray = { 1210 $id: falsy, 1211 $render: falsy, 1212 $track: falsy, 1213 $element: falsy, 1214 $computed: falsy, 1215 $watch: falsy, 1216 $fire: falsy, 1217 $events: falsy, 1218 $accessors: falsy, 1219 $hashcode: falsy, 1220 $mutations: falsy, 1221 $vbthis: falsy, 1222 $vbsetter: falsy 1223 }; 1224 1225 /* 1226 https://github.com/hufyhang/orderBy/blob/master/index.js 1227 */ 1228 1229 function orderBy(array, by, decend) { 1230 var type = avalon.type(array); 1231 if (type !== 'array' && type !== 'object') throw 'orderByåªè½å¤çå¯¹è±¡ææ°ç»'; 1232 var criteria = typeof by == 'string' ? function (el) { 1233 return el && el[by]; 1234 } : typeof by === 'function' ? by : function (el) { 1235 return el; 1236 }; 1237 var mapping = {}; 1238 var temp = []; 1239 __repeat(array, Array.isArray(array), function (key) { 1240 var val = array[key]; 1241 var k = criteria(val, key); 1242 if (k in mapping) { 1243 mapping[k].push(key); 1244 } else { 1245 mapping[k] = [key]; 1246 } 1247 temp.push(k); 1248 }); 1249 1250 temp.sort(); 1251 if (decend < 0) { 1252 temp.reverse(); 1253 } 1254 var _array = type === 'array'; 1255 var target = _array ? [] : {}; 1256 return recovery(target, temp, function (k) { 1257 var key = mapping[k].shift(); 1258 if (_array) { 1259 target.push(array[key]); 1260 } else { 1261 target[key] = array[key]; 1262 } 1263 }); 1264 } 1265 1266 function __repeat(array, isArray$$1, cb) { 1267 if (isArray$$1) { 1268 array.forEach(function (val, index) { 1269 cb(index); 1270 }); 1271 } else if (typeof array.$track === 'string') { 1272 array.$track.replace(/[^â¥]+/g, function (k) { 1273 cb(k); 1274 }); 1275 } else { 1276 for (var i in array) { 1277 if (array.hasOwnProperty(i)) { 1278 cb(i); 1279 } 1280 } 1281 } 1282 } 1283 function filterBy(array, search) { 1284 var type = avalon.type(array); 1285 if (type !== 'array' && type !== 'object') throw 'filterByåªè½å¤çå¯¹è±¡ææ°ç»'; 1286 var args = avalon.slice(arguments, 2); 1287 var stype = avalon.type(search); 1288 if (stype === 'function') { 1289 var criteria = search._orig || search; 1290 } else if (stype === 'string' || stype === 'number') { 1291 if (search === '') { 1292 return array; 1293 } else { 1294 var reg = new RegExp(avalon.escapeRegExp(search), 'i'); 1295 criteria = function criteria(el) { 1296 return reg.test(el); 1297 }; 1298 } 1299 } else { 1300 return array; 1301 } 1302 var isArray$$1 = type === 'array'; 1303 var target = isArray$$1 ? [] : {}; 1304 __repeat(array, isArray$$1, function (key) { 1305 var val = array[key]; 1306 if (criteria.apply({ 1307 key: key 1308 }, [val, key].concat(args))) { 1309 if (isArray$$1) { 1310 target.push(val); 1311 } else { 1312 target[key] = val; 1313 } 1314 } 1315 }); 1316 return target; 1317 } 1318 1319 function selectBy(data, array, defaults) { 1320 if (avalon.isObject(data) && !Array.isArray(data)) { 1321 var target = []; 1322 return recovery(target, array, function (name) { 1323 target.push(data.hasOwnProperty(name) ? data[name] : defaults ? defaults[name] : ''); 1324 }); 1325 } else { 1326 return data; 1327 } 1328 } 1329 1330 function limitBy(input, limit, begin) { 1331 var type = avalon.type(input); 1332 if (type !== 'array' && type !== 'object') throw 'limitByåªè½å¤çå¯¹è±¡ææ°ç»'; 1333 //å¿ é¡»æ¯æ°å¼ 1334 if (typeof limit !== 'number') { 1335 return input; 1336 } 1337 //ä¸è½ä¸ºNaN 1338 if (limit !== limit) { 1339 return input; 1340 } 1341 //å°ç®æ 转æ¢ä¸ºæ°ç» 1342 if (type === 'object') { 1343 input = convertArray(input, false); 1344 } 1345 var n = input.length; 1346 limit = Math.floor(Math.min(n, limit)); 1347 begin = typeof begin === 'number' ? begin : 0; 1348 if (begin < 0) { 1349 begin = Math.max(0, n + begin); 1350 } 1351 var data = []; 1352 for (var i = begin; i < n; i++) { 1353 if (data.length === limit) { 1354 break; 1355 } 1356 data.push(input[i]); 1357 } 1358 var isArray$$1 = type === 'array'; 1359 if (isArray$$1) { 1360 return data; 1361 } 1362 var target = {}; 1363 return recovery(target, data, function (el) { 1364 target[el.key] = el.value; 1365 }); 1366 } 1367 1368 function recovery(ret, array, callback) { 1369 for (var i = 0, n = array.length; i < n; i++) { 1370 callback(array[i]); 1371 } 1372 return ret; 1373 } 1374 1375 //Chromeè°·ææµè§å¨ä¸js代ç Array.sortæåºçbugä¹±åºè§£å³åæ³ 1376 //http://www.cnblogs.com/yzeng/p/3949182.html 1377 function convertArray(array, isArray$$1) { 1378 var ret = [], 1379 i = 0; 1380 __repeat(array, isArray$$1, function (key) { 1381 ret[i] = { 1382 oldIndex: i, 1383 value: array[key], 1384 key: key 1385 }; 1386 i++; 1387 }); 1388 return ret; 1389 } 1390 1391 var eventFilters = { 1392 stop: function stop(e) { 1393 e.stopPropagation(); 1394 return e; 1395 }, 1396 prevent: function prevent(e) { 1397 e.preventDefault(); 1398 return e; 1399 } 1400 }; 1401 var keys = { 1402 esc: 27, 1403 tab: 9, 1404 enter: 13, 1405 space: 32, 1406 del: 46, 1407 up: 38, 1408 left: 37, 1409 right: 39, 1410 down: 40 1411 }; 1412 for (var name$1 in keys) { 1413 (function (filter, key) { 1414 eventFilters[filter] = function (e) { 1415 if (e.which !== key) { 1416 e.$return = true; 1417 } 1418 return e; 1419 }; 1420 })(name$1, keys[name$1]); 1421 } 1422 1423 //https://github.com/teppeis/htmlspecialchars 1424 function escapeFilter(str) { 1425 if (str == null) return ''; 1426 1427 return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '''); 1428 } 1429 1430 var filters = avalon.filters = {}; 1431 1432 avalon.composeFilters = function () { 1433 var args = arguments; 1434 return function (value) { 1435 for (var i = 0, arr; arr = args[i++];) { 1436 var name = arr[0]; 1437 var filter = avalon.filters[name]; 1438 if (typeof filter === 'function') { 1439 arr[0] = value; 1440 try { 1441 value = filter.apply(0, arr); 1442 } catch (e) {} 1443 } 1444 } 1445 return value; 1446 }; 1447 }; 1448 1449 avalon.escapeHtml = escapeFilter; 1450 1451 avalon.mix(filters, { 1452 uppercase: function uppercase(str) { 1453 return String(str).toUpperCase(); 1454 }, 1455 lowercase: function lowercase(str) { 1456 return String(str).toLowerCase(); 1457 }, 1458 truncate: function truncate(str, length, end) { 1459 //lengthï¼æ°å符串é¿åº¦ï¼truncationï¼æ°å符串çç»å°¾çåæ®µ,è¿åæ°å符串 1460 if (!str) { 1461 return ''; 1462 } 1463 str = String(str); 1464 if (isNaN(length)) { 1465 length = 30; 1466 } 1467 end = typeof end === "string" ? end : "..."; 1468 return str.length > length ? str.slice(0, length - end.length) + end : /* istanbul ignore else*/ 1469 str; 1470 }, 1471 1472 camelize: avalon.camelize, 1473 date: dateFilter, 1474 escape: escapeFilter, 1475 sanitize: sanitizeFilter, 1476 number: numberFilter, 1477 currency: function currency(amount, symbol, fractionSize) { 1478 return (symbol || '\xA5') + numberFilter(amount, isFinite(fractionSize) ? /* istanbul ignore else*/fractionSize : 2); 1479 } 1480 }, { filterBy: filterBy, orderBy: orderBy, selectBy: selectBy, limitBy: limitBy }, eventFilters); 1481 1482 var rcheckedType = /^(?:checkbox|radio)$/; 1483 1484 /* istanbul ignore next */ 1485 function fixElement(dest, src) { 1486 if (dest.nodeType !== 1) { 1487 return; 1488 }
1489 var nodeName = dest.nodeName.toLowerCase(); 1490 1491 if (nodeName === "script") { 1492 if (dest.text !== src.text) { 1493 dest.type = "noexec"; 1494 dest.text = src.text; 1495 dest.type = src.type || ""; 1496 } 1497 } else if (nodeName === 'object') { 1498 var params = src.childNodes; 1499 if (dest.childNodes.length !== params.length) { 1500 avalon.clearHTML(dest); 1501 for (var i = 0, el; el = params[i++];) { 1502 dest.appendChild(el.cloneNode(true)); 1503 } 1504 } 1505 } else if (nodeName === 'input' && rcheckedType.test(src.nodeName)) { 1506 1507 dest.defaultChecked = dest.checked = src.checked; 1508 if (dest.value !== src.value) { 1509 dest.value = src.value; 1510 } 1511 } else if (nodeName === 'option') { 1512 dest.defaultSelected = dest.selected = src.defaultSelected; 1513 } else if (nodeName === 'input' || nodeName === 'textarea') { 1514 dest.defaultValue = src.defaultValue; 1515 } 1516 } 1517 1518 /* istanbul ignore next */ 1519 function getAll(context) { 1520 return typeof context.getElementsByTagName !== 'undefined' ? context.getElementsByTagName('*') : typeof context.querySelectorAll !== 'undefined' ? context.querySelectorAll('*') : []; 1521 } 1522 1523 /* istanbul ignore next */ 1524 function fixClone(src) { 1525 var target = src.cloneNode(true); 1526 //http://www.myexception.cn/web/665613.html 1527 // target.expando = null 1528 var t = getAll(target); 1529 var s = getAll(src); 1530 for (var i = 0; i < s.length; i++) { 1531 fixElement(t[i], s[i]); 1532 } 1533 return target; 1534 } 1535 1536 /* istanbul ignore next */ 1537 function fixContains(root, el) { 1538 try { 1539 //IE6-8,游离äºDOMæ å¤çææ¬èç¹ï¼è®¿é®parentNodeææ¶ä¼æé 1540 while (el = el.parentNode) { 1541 if (el === root) return true; 1542 } 1543 } catch (e) {} 1544 return false; 1545 } 1546 1547 avalon.contains = fixContains; 1548 1549 avalon.cloneNode = function (a) { 1550 return a.cloneNode(true); 1551 }; 1552 1553 //IE6-11çææ¡£å¯¹è±¡æ²¡æcontains 1554 /* istanbul ignore next */ 1555 function shimHack() { 1556 if (msie < 10) { 1557 avalon.cloneNode = fixClone; 1558 } 1559 if (!document$1.contains) { 1560 document$1.contains = function (b) { 1561 return fixContains(document$1, b); 1562 }; 1563 } 1564 if (avalon.modern) { 1565 if (!document$1.createTextNode('x').contains) { 1566 Node.prototype.contains = function (child) { 1567 //IE6-8没æNode对象 1568 return fixContains(this, child); 1569 }; 1570 } 1571 } 1572 //firefox å°11æ¶ææouterHTML 1573 function fixFF(prop, cb) { 1574 if (!(prop in root) && HTMLElement.prototype.__defineGetter__) { 1575 HTMLElement.prototype.__defineGetter__(prop, cb); 1576 } 1577 } 1578 fixFF('outerHTML', function () { 1579 var div = document$1.createElement('div'); 1580 div.appendChild(this); 1581 return div.innerHTML; 1582 }); 1583 fixFF('children', function () { 1584 var children = []; 1585 for (var i = 0, el; el = this.childNodes[i++];) { 1586 if (el.nodeType === 1) { 1587 children.push(el); 1588 } 1589 } 1590 return children; 1591 }); 1592 fixFF('innerText', function () { 1593 //firefox45+, chrome4+ http://caniuse.com/#feat=innertext 1594 return this.textContent; 1595 }); 1596 } 1597 1598 if (inBrowser) { 1599 shimHack(); 1600 } 1601 1602 function ClassList(node) { 1603 this.node = node; 1604 } 1605 1606 ClassList.prototype = { 1607 toString: function toString() { 1608 var node = this.node; 1609 var cls = node.className; 1610 var str = typeof cls === 'string' ? cls : cls.baseVal; 1611 var match = str.match(rnowhite); 1612 return match ? match.join(' ') : ''; 1613 }, 1614 contains: function contains(cls) { 1615 return (' ' + this + ' ').indexOf(' ' + cls + ' ') > -1; 1616 }, 1617 add: function add(cls) { 1618 if (!this.contains(cls)) { 1619 this.set(this + ' ' + cls); 1620 } 1621 }, 1622 remove: function remove(cls) { 1623 this.set((' ' + this + ' ').replace(' ' + cls + ' ', ' ')); 1624 }, 1625 set: function set(cls) { 1626 cls = cls.trim(); 1627 var node = this.node; 1628 if (typeof node.className === 'object') { 1629 //SVGå ç´ çclassNameæ¯ä¸ä¸ªå¯¹è±¡ SVGAnimatedString { baseVal='', animVal=''}ï¼åªè½éè¿set/getAttributeæä½ 1630 node.setAttribute('class', cls); 1631 } else { 1632 node.className = cls; 1633 } 1634 if (!cls) { 1635 node.removeAttribute('class'); 1636 } 1637 //toggleåå¨çæ¬å·®å¼ï¼å æ¤ä¸ä½¿ç¨å® 1638 } 1639 }; 1640 1641 function classListFactory(node) { 1642 if (!('classList' in node)) { 1643 node.classList = new ClassList(node); 1644 } 1645 return node.classList; 1646 } 1647 1648 'add,remove'.replace(rword, function (method) { 1649 avalon.fn[method + 'Class'] = function (cls) { 1650 var el = this[0] || {}; 1651 //https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/26 1652 if (cls && typeof cls === 'string' && el.nodeType === 1) { 1653 cls.replace(rnowhite, function (c) { 1654 classListFactory(el)[method](c); 1655 }); 1656 } 1657 return this; 1658 }; 1659 }); 1660 1661 avalon.shadowCopy(avalon.fn, { 1662 hasClass: function hasClass(cls) { 1663 var el = this[0] || {}; 1664 return el.nodeType === 1 && classListFactory(el).contains(cls); 1665 }, 1666 toggleClass: function toggleClass(value, stateVal) { 1667 var isBool = typeof stateVal === 'boolean'; 1668 var me = this; 1669 String(value).replace(rnowhite, function (c) { 1670 var state = isBool ? stateVal : !me.hasClass(c); 1671 me[state ? 'addClass' : 'removeClass'](c); 1672 }); 1673 return this; 1674 } 1675 }); 1676 1677 var propMap = {}; //ä¸è§åç屿§åæ å° 1678 1679 1680 //鲿¢å缩æ¶åºé 1681 'accept-charset,acceptCharset|char,ch|charoff,chOff|class,className|for,htmlFor|http-equiv,httpEquiv'.replace(/[^\|]+/g, function (a) { 1682 var k = a.split(','); 1683 propMap[k[0]] = k[1]; 1684 }); 1685 /* 1686 contenteditable䏿¯å¸å°å±æ§ 1687 http://www.zhangxinxu.com/wordpress/2016/01/contenteditable-plaintext-only/ 1688 contenteditable='' 1689 contenteditable='events' 1690 contenteditable='caret' 1691 contenteditable='plaintext-only' 1692 contenteditable='true' 1693 contenteditable='false' 1694 */ 1695 var bools = ['autofocus,autoplay,async,allowTransparency,checked,controls', 'declare,disabled,defer,defaultChecked,defaultSelected,', 'isMap,loop,multiple,noHref,noResize,noShade', 'open,readOnly,selected'].join(','); 1696 1697 bools.replace(/\w+/g, function (name) { 1698 propMap[name.toLowerCase()] = name; 1699 }); 1700 1701 var anomaly = ['accessKey,bgColor,cellPadding,cellSpacing,codeBase,codeType,colSpan', 'dateTime,defaultValue,contentEditable,frameBorder,longDesc,maxLength,' + 'marginWidth,marginHeight,rowSpan,tabIndex,useMap,vSpace,valueType,vAlign'].join(','); 1702 1703 anomaly.replace(/\w+/g, function (name) { 1704 propMap[name.toLowerCase()] = name; 1705 }); 1706 1707 //module.exports = propMap 1708 1709 function isVML(src) { 1710 var nodeName = src.nodeName; 1711 return nodeName.toLowerCase() === nodeName && !!src.scopeName && src.outerText === ''; 1712 } 1713 1714 var rvalidchars = /^[\],:{}\s]*$/; 1715 var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g; 1716 var rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g; 1717 var rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g; 1718 1719 function compactParseJSON(data) { 1720 if (typeof data === 'string') { 1721 data = data.trim(); 1722 if (data) { 1723 if (rvalidchars.test(data.replace(rvalidescape, '@').replace(rvalidtokens, ']').replace(rvalidbraces, ''))) { 1724 return new Function('return ' + data)(); // jshint ignore:line 1725 } 1726 } 1727 throw TypeError('Invalid JSON: [' + data + ']'); 1728 } 1729 return data; 1730 } 1731 1732 var rsvg = /^\[object SVG\w*Element\]$/; 1733 var ramp = /&/g; 1734 function updateAttrs(node, attrs) { 1735 for (var attrName in attrs) { 1736 try { 1737 var val = attrs[attrName]; 1738 // å¤çè·¯å¾å±æ§ 1739 /* istanbul ignore if*/ 1740 1741 //å¤çHTML5 data-*屿§ SVG 1742 if (attrName.indexOf('data-') === 0 || rsvg.test(node)) { 1743 node.setAttribute(attrName, val); 1744 } else { 1745 var propName = propMap[attrName] || attrName; 1746 /* istanbul ignore if */ 1747 if (typeof node[propName] === 'boolean') { 1748 if (propName === 'checked') { 1749 node.defaultChecked = !!val; 1750 } 1751 node[propName] = !!val; 1752 //å¸å°å±æ§å¿ 须使ç¨el.xxx = true|falseæ¹å¼è®¾å¼ 1753 //å¦æä¸ºfalse, IEå ¨ç³»åä¸ç¸å½äºsetAttribute(xxx,''), 1754 //ä¼å½±åå°æ ·å¼,éè¦è¿ä¸æ¥å¤ç 1755 } 1756 1757 if (val === false) { 1758 //ç§»é¤å±æ§ 1759 node.removeAttribute(propName); 1760 continue; 1761 } 1762 //IE6ä¸classNamme, htmlForçæ æ³æ£æµå®ä»¬ä¸ºå å»ºå±æ§ã 1763 if (avalon.msie < 8 && /[A-Z]/.test(propName)) { 1764 node[propName] = val + ''; 1765 continue; 1766 } 1767 //SVGåªè½ä½¿ç¨setAttribute(xxx, yyy), VMLåªè½ä½¿ç¨node.xxx = yyy , 1768 //HTMLçåºæå±æ§å¿ é¡»node.xxx = yyy 1769 /* istanbul ignore next */ 1770 var isInnate = !avalon.modern && isVML(node) ? true : isInnateProps(node.nodeName, attrName); 1771 if (isInnate) { 1772 if (attrName === 'href' || attrName === 'src') { 1773 /* istanbul ignore if */ 1774 if (avalon.msie < 8) { 1775 val = String(val).replace(ramp, '&'); //å¤çIE67èªå¨è½¬ä¹çé®é¢ 1776 } 1777 } 1778 node[propName] = val + ''; 1779 } else { 1780 node.setAttribute(attrName, val); 1781 } 1782 } 1783 } catch (e) { 1784 // å¯¹è±¡ä¸æ¯ææ¤å±æ§ææ¹æ³ src https://github.com/ecomfe/zrender 1785 // æªç¥åç§°ã\/n 1786 // e.message大æ¦è¿æ ·,éè¦trim 1787 //IE6-8,å ç´ èç¹ä¸æ¯æå ¶ä»å ç´ èç¹çå ç½®å±æ§,å¦src, href, for 1788 /* istanbul ignore next */ 1789 avalon.log(String(e.message).trim(), attrName, val); 1790 } 1791 } 1792 } 1793 var innateMap = {}; 1794 1795 function isInnateProps(nodeName, attrName) { 1796 var key = nodeName + ":" + attrName; 1797 if (key in innateMap) { 1798 return innateMap[key]; 1799 } 1800 return innateMap[key] = attrName in document$1.createElement(nodeName); 1801 } 1802 try { 1803 avalon.parseJSON = JSON.parse; 1804 } catch (e) { 1805 /* istanbul ignore next */ 1806 avalon.parseJSON = compactParseJSON; 1807 } 1808 1809 avalon.fn.attr = function (name, value) { 1810 if (arguments.length === 2) { 1811 this[0].setAttribute(name, value); 1812 return this; 1813 } else { 1814 return this[0].getAttribute(name); 1815 } 1816 }; 1817 1818 var cssMap = oneObject('float', 'cssFloat'); 1819 avalon.cssNumber = oneObject('animationIterationCount,columnCount,order,flex,flexGrow,flexShrink,fillOpacity,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom'); 1820 var prefixes = ['', '-webkit-', '-o-', '-moz-', '-ms-']; 1821 /* istanbul ignore next */ 1822 avalon.cssName = function (name, host, camelCase) { 1823 if (cssMap[name]) { 1824 return cssMap[name]; 1825 } 1826 host = host || avalon.root.style || {}; 1827 for (var i = 0, n = prefixes.length; i < n; i++) { 1828 camelCase = avalon.camelize(prefixes[i] + name); 1829 if (camelCase in host) { 1830 return cssMap[name] = camelCase; 1831 } 1832 } 1833 return null; 1834 }; 1835 /* istanbul ignore next */ 1836 avalon.css = function (node, name, value, fn) { 1837 //读åå é¤å ç´ èç¹çæ ·å¼ 1838 if (node instanceof avalon) { 1839 node = node[0]; 1840 } 1841 if (node.nodeType !== 1) { 1842 return; 1843 } 1844 var prop = avalon.camelize(name); 1845 name = avalon.cssName(prop) || /* istanbul ignore next*/prop; 1846 if (value === void 0 || typeof value === 'boolean') { 1847 //è·åæ ·å¼ 1848 fn = cssHooks[prop + ':get'] || cssHooks['@:get']; 1849 if (name === 'background') { 1850 name = 'backgroundColor'; 1851 } 1852 var val = fn(node, name); 1853 return value === true ? parseFloat(val) || 0 : val; 1854 } else if (value === '') { 1855 //è¯·é¤æ ·å¼ 1856 node.style[name] = ''; 1857 } else { 1858 //è®¾ç½®æ ·å¼ 1859 if (value == null || value !== value) { 1860 return; 1861 } 1862 if (isFinite(value) && !avalon.cssNumber[prop]) { 1863 value += 'px'; 1864 } 1865 fn = cssHooks[prop + ':set'] || cssHooks['@:set']; 1866 fn(node, name, value); 1867 } 1868 }; 1869 /* istanbul ignore next */ 1870 avalon.fn.css = function (name, value) { 1871 if (avalon.isPlainObject(name)) { 1872 for (var i in name) { 1873 avalon.css(this, i, name[i]); 1874 } 1875 } else { 1876 var ret = avalon.css(this, name, value); 1877 } 1878 return ret !== void 0 ? ret : this; 1879 }; 1880 /* istanbul ignore next */ 1881 avalon.fn.position = function () { 1882 var offsetParent, 1883 offset, 1884 elem = this[0], 1885 parentOffset = { 1886 top: 0, 1887 left: 0 1888 }; 1889 if (!elem) { 1890 return parentOffset; 1891 } 1892 if (this.css('position') === 'fixed') { 1893 offset = elem.getBoundingClientRect(); 1894 } else { 1895 offsetParent = this.offsetParent(); //å¾å°çæ£çoffsetParent 1896 offset = this.offset(); // å¾å°æ£ç¡®çoffsetParent 1897 if (offsetParent[0].tagName !== 'HTML') { 1898 parentOffset = offsetParent.offset(); 1899 } 1900 parentOffset.top += avalon.css(offsetParent[0], 'borderTopWidth', true); 1901 parentOffset.left += avalon.css(offsetParent[0], 'borderLeftWidth', true); 1902 1903 // Subtract offsetParent scroll positions 1904 parentOffset.top -= offsetParent.scrollTop(); 1905 parentOffset.left -= offsetParent.scrollLeft(); 1906 } 1907 return { 1908 top: offset.top - parentOffset.top - avalon.css(elem, 'marginTop', true), 1909 left: offset.left - parentOffset.left - avalon.css(elem, 'marginLeft', true) 1910 }; 1911 }; 1912 /* istanbul ignore next */ 1913 avalon.fn.offsetParent = function () { 1914 var offsetParent = this[0].offsetParent; 1915 while (offsetParent && avalon.css(offsetParent, 'position') === 'static') { 1916 offsetParent = offsetParent.offsetParent; 1917 } 1918 return avalon(offsetParent || avalon.root); 1919 }; 1920 1921 /* istanbul ignore next */ 1922 cssHooks['@:set'] = function (node, name, value) { 1923 try { 1924 //node.style.width = NaN;node.style.width = 'xxxxxxx'; 1925 //node.style.width = undefine 卿§å¼IEä¸ä¼æå¼å¸¸ 1926 node.style[name] = value; 1927 } catch (e) {} 1928 }; 1929 /* istanbul ignore next */ 1930 cssHooks['@:get'] = function (node, name) { 1931 if (!node || !node.style) { 1932 throw new Error('getComputedStyleè¦æ±ä¼ å ¥ä¸ä¸ªèç¹ ' + node); 1933 } 1934 var ret, 1935
1935 styles = window$1.getComputedStyle(node, null); 1936 if (styles) { 1937 ret = name === 'filter' ? styles.getPropertyValue(name) : styles[name]; 1938 if (ret === '') { 1939 ret = node.style[name]; //å ¶ä»æµè§å¨éè¦æä»¬æå¨åå èæ ·å¼ 1940 } 1941 } 1942 return ret; 1943 }; 1944 1945 cssHooks['opacity:get'] = function (node) { 1946 var ret = cssHooks['@:get'](node, 'opacity'); 1947 return ret === '' ? '1' : ret; 1948 }; 1949 1950 'top,left'.replace(avalon.rword, function (name) { 1951 cssHooks[name + ':get'] = function (node) { 1952 var computed = cssHooks['@:get'](node, name); 1953 return (/px$/.test(computed) ? computed : avalon(node).position()[name] + 'px' 1954 ); 1955 }; 1956 }); 1957 1958 var cssShow = { 1959 position: 'absolute', 1960 visibility: 'hidden', 1961 display: 'block' 1962 }; 1963 1964 var rdisplayswap = /^(none|table(?!-c[ea]).+)/; 1965 /* istanbul ignore next */ 1966 function showHidden(node, array) { 1967 //http://www.cnblogs.com/rubylouvre/archive/2012/10/27/2742529.html 1968 if (node.offsetWidth <= 0) { 1969 //opera.offsetWidthå¯è½å°äº0 1970 if (rdisplayswap.test(cssHooks['@:get'](node, 'display'))) { 1971 var obj = { 1972 node: node 1973 }; 1974 for (var name in cssShow) { 1975 obj[name] = node.style[name]; 1976 node.style[name] = cssShow[name]; 1977 } 1978 array.push(obj); 1979 } 1980 var parent = node.parentNode; 1981 if (parent && parent.nodeType === 1) { 1982 showHidden(parent, array); 1983 } 1984 } 1985 } 1986 /* istanbul ignore next*/ 1987 avalon.each({ 1988 Width: 'width', 1989 Height: 'height' 1990 }, function (name, method) { 1991 var clientProp = 'client' + name, 1992 scrollProp = 'scroll' + name, 1993 offsetProp = 'offset' + name; 1994 cssHooks[method + ':get'] = function (node, which, override) { 1995 var boxSizing = -4; 1996 if (typeof override === 'number') { 1997 boxSizing = override; 1998 } 1999 which = name === 'Width' ? ['Left', 'Right'] : ['Top', 'Bottom']; 2000 var ret = node[offsetProp]; // border-box 0 2001 if (boxSizing === 2) { 2002 // margin-box 2 2003 return ret + avalon.css(node, 'margin' + which[0], true) + avalon.css(node, 'margin' + which[1], true); 2004 } 2005 if (boxSizing < 0) { 2006 // padding-box -2 2007 ret = ret - avalon.css(node, 'border' + which[0] + 'Width', true) - avalon.css(node, 'border' + which[1] + 'Width', true); 2008 } 2009 if (boxSizing === -4) { 2010 // content-box -4 2011 ret = ret - avalon.css(node, 'padding' + which[0], true) - avalon.css(node, 'padding' + which[1], true); 2012 } 2013 return ret; 2014 }; 2015 cssHooks[method + '&get'] = function (node) { 2016 var hidden = []; 2017 showHidden(node, hidden); 2018 var val = cssHooks[method + ':get'](node); 2019 for (var i = 0, obj; obj = hidden[i++];) { 2020 node = obj.node; 2021 for (var n in obj) { 2022 if (typeof obj[n] === 'string') { 2023 node.style[n] = obj[n]; 2024 } 2025 } 2026 } 2027 return val; 2028 }; 2029 avalon.fn[method] = function (value) { 2030 //ä¼å¿½è§å ¶display 2031 var node = this[0]; 2032 if (arguments.length === 0) { 2033 if (node.setTimeout) { 2034 //åå¾çªå£å°ºå¯¸ 2035 return node['inner' + name] || node.document.documentElement[clientProp] || node.document.body[clientProp]; //IE6ä¸å两个åå«ä¸ºundefined,0 2036 } 2037 if (node.nodeType === 9) { 2038 //åå¾é¡µé¢å°ºå¯¸ 2039 var doc = node.documentElement; 2040 //FF chrome html.scrollHeight< body.scrollHeight 2041 //IE æ 忍¡å¼ : html.scrollHeight> body.scrollHeight 2042 //IE æªå¼æ¨¡å¼ : html.scrollHeight æå¤§çäºå¯è§çªå£å¤ä¸ç¹ï¼ 2043 return Math.max(node.body[scrollProp], doc[scrollProp], node.body[offsetProp], doc[offsetProp], doc[clientProp]); 2044 } 2045 return cssHooks[method + '&get'](node); 2046 } else { 2047 return this.css(method, value); 2048 } 2049 }; 2050 avalon.fn['inner' + name] = function () { 2051 return cssHooks[method + ':get'](this[0], void 0, -2); 2052 };
2053 avalon.fn['outer' + name] = function (includeMargin) { 2054 return cssHooks[method + ':get'](this[0], void 0, includeMargin === true ? 2 : 0); 2055 }; 2056 }); 2057 2058 function getWindow(node) { 2059 return node.window || node.defaultView || node.parentWindow || false; 2060 } 2061 2062 /* istanbul ignore if */ 2063 if (msie < 9) { 2064 avalon.shadowCopy(cssMap, oneObject('float', 'styleFloat')); 2065 var rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i; 2066 var rposition = /^(top|right|bottom|left)$/; 2067 var ralpha = /alpha\([^)]+\)/i; 2068 var ropactiy = /(opacity|\d(\d|\.)*)/g; 2069 var ie8 = msie === 8; 2070 var salpha = 'DXImageTransform.Microsoft.Alpha'; 2071 var border = { 2072 thin: ie8 ? '1px' : '2px', 2073 medium: ie8 ? '3px' : '4px', 2074 thick: ie8 ? '5px' : '6px' 2075 }; 2076 cssHooks['@:get'] = function (node, name) { 2077 //åå¾ç²¾ç¡®å¼ï¼ä¸è¿å®æå¯è½æ¯å¸¦em,pc,mm,pt,%çåä½ 2078 var currentStyle = node.currentStyle; 2079 var ret = currentStyle[name]; 2080 if (rnumnonpx.test(ret) && !rposition.test(ret)) { 2081 //â ï¼ä¿ååæçstyle.left, runtimeStyle.left, 2082 var style = node.style, 2083 left = style.left, 2084 rsLeft = node.runtimeStyle.left; 2085 //â¡ç±äºâ¢å¤çstyle.left = xxxä¼å½±åå°currentStyle.leftï¼ 2086 //å æ¤æå®currentStyle.leftæ¾å°runtimeStyle.leftï¼ 2087 //runtimeStyle.leftæ¥ææé«ä¼å 级ï¼ä¸ä¼style.leftå½±å 2088 node.runtimeStyle.left = currentStyle.left; 2089 //â¢å°ç²¾ç¡®å¼èµç»å°style.leftï¼ç¶åéè¿IEçå¦ä¸ä¸ªç§æå±æ§ style.pixelLeft 2090 //å¾å°åä½ä¸ºpxçç»æï¼fontSizeç忝è§http://bugs.jquery.com/ticket/760 2091 style.left = name === 'fontSize' ? '1em' : ret || 0; 2092 ret = style.pixelLeft + 'px'; 2093 //â£è¿å style.leftï¼runtimeStyle.left 2094 style.left = left; 2095 node.runtimeStyle.left = rsLeft; 2096 } 2097 if (ret === 'medium') { 2098 name = name.replace('Width', 'Style'); 2099 //border width é»è®¤å¼ä¸ºmediumï¼å³ä½¿å ¶ä¸º0' 2100 if (currentStyle[name] === 'none') { 2101 ret = '0px'; 2102 } 2103 } 2104 return ret === '' ? 'auto' : border[ret] || ret; 2105 }; 2106 cssHooks['opacity:set'] = function (node, name, value) { 2107 var style = node.style; 2108 2109 var opacity = Number(value) <= 1 ? 'alpha(opacity=' + value * 100 + ')' : ''; 2110 var filter = style.filter || ''; 2111 style.zoom = 1; 2112 //ä¸è½ä½¿ç¨ä»¥ä¸æ¹å¼è®¾ç½®éæåº¦ 2113 //node.filters.alpha.opacity = value * 100 2114 style.filter = (ralpha.test(filter) ? filter.replace(ralpha, opacity) : filter + ' ' + opacity).trim(); 2115 2116 if (!style.filter) { 2117 style.removeAttribute('filter'); 2118 } 2119 }; 2120 cssHooks['opacity:get'] = function (node) { 2121 var match = node.style.filter.match(ropactiy) || []; 2122 var ret = false;
2123 for (var i = 0, el; el = match[i++];) { 2124 if (el === 'opacity') { 2125 ret = true; 2126 } else if (ret) { 2127 return el / 100 + ''; 2128 } 2129 } 2130 return '1'; //ç¡®ä¿è¿åçæ¯å符串 2131 }; 2132 } 2133 2134 /* istanbul ignore next */ 2135 avalon.fn.offset = function () { 2136 //åå¾è·ç¦»é¡µé¢å·¦å³è§çåæ 2137 var node = this[0], 2138 box = { 2139 left: 0, 2140 top: 0 2141 }; 2142 if (!node || !node.tagName || !node.ownerDocument) { 2143 return box; 2144 } 2145 var doc = node.ownerDocument; 2146 var body = doc.body; 2147 var root$$1 = doc.documentElement; 2148 var win = doc.defaultView || doc.parentWindow; 2149 if (!avalon.contains(root$$1, node)) { 2150 return box; 2151 } 2152 //http://hkom.blog1.fc2.com/?mode=m&no=750 bodyçåç§»éæ¯ä¸å å«marginç 2153 //æä»¬å¯ä»¥éè¿getBoundingClientRectæ¥è·å¾å ç´ ç¸å¯¹äºclientçrect. 2154 //http://msdn.microsoft.com/en-us/library/ms536433.aspx 2155 if (node.getBoundingClientRect) { 2156 box = node.getBoundingClientRect(); // BlackBerry 5, iOS 3 (original iPhone) 2157 } 2158 //chrome/IE6: body.scrollTop, firefox/other: root.scrollTop 2159 var clientTop = root$$1.clientTop || body.clientTop, 2160 clientLeft = root$$1.clientLeft || body.clientLeft, 2161 scrollTop = Math.max(win.pageYOffset || 0, root$$1.scrollTop, body.scrollTop), 2162 scrollLeft = Math.max(win.pageXOffset || 0, root$$1.scrollLeft, body.scrollLeft); 2163 // ææ»å¨è·ç¦»å å°left,topä¸å»ã 2164 // IEä¸äºçæ¬ä¸ä¼èªå¨ä¸ºHTMLå ç´ å ä¸2pxçborderï¼æä»¬éè¦å»æå® 2165 // http://msdn.microsoft.com/en-us/library/ms533564(VS.85).aspx 2166 return { 2167 top: box.top + scrollTop - clientTop, 2168 left: box.left + scrollLeft - clientLeft 2169 }; 2170 }; 2171 2172 //çæavalon.fn.scrollLeft, avalon.fn.scrollTopæ¹æ³ 2173 /* istanbul ignore next */ 2174 avalon.each({ 2175 scrollLeft: 'pageXOffset', 2176 scrollTop: 'pageYOffset' 2177 }, function (method, prop) { 2178 avalon.fn[method] = function (val) { 2179 var node = this[0] || {}; 2180 var win = getWindow(node); 2181 var root$$1 = avalon.root; 2182 var top = method === 'scrollTop'; 2183 if (!arguments.length) { 2184 return win ? prop in win ? win[prop] : root$$1[method] : node[method]; 2185 } else { 2186 if (win) { 2187 win.scrollTo(!top ? val : avalon(win).scrollLeft(), top ? val : avalon(win).scrollTop()); 2188 } else { 2189 node[method] = val; 2190 } 2191 } 2192 }; 2193 }); 2194 2195 function getDuplexType(elem) { 2196 var ret = elem.tagName.toLowerCase(); 2197 if (ret === 'input') { 2198 return rcheckedType.test(elem.type) ? 'checked' : elem.type; 2199 } 2200 return ret; 2201 } 2202 2203 /** 2204 * IE6/7/8ä¸ï¼å¦æoption没ævalueå¼ï¼é£ä¹å°è¿å空å符串ã 2205 * IE9/Firefox/Safari/Chrome/Opera ä¸å åoptionçvalueå¼ï¼å¦ææ²¡ævalue屿§ï¼ååoptionçinnerTextå¼ã 2206 * IE11åW3Cï¼å¦ææ²¡ææå®valueï¼é£ä¹node.valueé»è®¤ä¸ºnode.textï¼åå¨trimä½ï¼ï¼ä½IE9-10忝åinnerHTML(没trimæä½) 2207 */ 2208 2209 function getOption(node) { 2210 if (node.hasAttribute && node.hasAttribute('value')) { 2211 return node.getAttribute('value'); 2212 } 2213 var attr = node.getAttributeNode('value'); 2214 if (attr && attr.specified) { 2215 return attr.value; 2216 } 2217 return node.innerHTML.trim(); 2218 } 2219 2220 var valHooks = { 2221 'option:get': msie ? getOption : function (node) { 2222 return node.value; 2223 }, 2224 'select:get': function selectGet(node, value) { 2225 var option, 2226 options = node.options, 2227 index = node.selectedIndex, 2228 getter = valHooks['option:get'], 2229 one = node.type === 'select-one' || index < 0, 2230 values = one ? null : [], 2231 max = one ? index + 1 : options.length, 2232 i = index < 0 ? max : one ? index : 0; 2233 for (; i < max; i++) { 2234 option = options[i]; 2235 //IE6-9å¨resetåä¸ä¼æ¹åselectedï¼éè¦æ¹ç¨i === indexå¤å® 2236 //æä»¬è¿æ»¤æædisabledçoptionå ç´ ï¼ä½å¨safari5ä¸ï¼ 2237 //å¦æè®¾ç½®optgroup为disableï¼é£ä¹å ¶ææå©åé½disable 2238 //å æ¤å½ä¸ä¸ªå ç´ ä¸ºdisableï¼éè¦æ£æµå ¶æ¯å¦æ¾å¼è®¾ç½®äºdisableåå ¶ç¶èç¹çdisableæ åµ 2239 if ((option.selected || i === index) && !option.disabled && (!option.parentNode.disabled || option.parentNode.tagName !== 'OPTGROUP')) { 2240 value = getter(option); 2241 if (one) { 2242 return value; 2243 } 2244 //æ¶éææselectedå¼ç»ææ°ç»è¿å 2245 values.push(value); 2246 } 2247 } 2248 return values; 2249 }, 2250 'select:set': function selectSet(node, values, optionSet) { 2251 values = [].concat(values); //强å¶è½¬æ¢ä¸ºæ°ç» 2252 var getter = valHooks['option:get']; 2253 for (var i = 0, el; el = node.options[i++];) { 2254 if (el.selected = values.indexOf(getter(el)) > -1) { 2255 optionSet = true; 2256 } 2257 } 2258 if (!optionSet) { 2259 node.selectedIndex = -1; 2260 } 2261 } 2262 }; 2263 2264 avalon.fn.val = function (value) { 2265 var node = this[0]; 2266 if (node && node.nodeType === 1) { 2267 var get = arguments.length === 0; 2268 var access = get ? ':get' : ':set'; 2269 var fn = valHooks[getDuplexType(node) + access]; 2270 if (fn) { 2271 var val = fn(node, value); 2272 } else if (get) { 2273 return (node.value || '').replace(/\r/g, ''); 2274 } else { 2275 node.value = value; 2276 } 2277 } 2278 return get ? val : this; 2279 }; 2280 2281 var voidTag = { 2282 area: 1, 2283 base: 1, 2284 basefont: 1, 2285 bgsound: 1, 2286 br: 1, 2287 col: 1, 2288 command: 1, 2289 embed: 1, 2290 frame: 1, 2291 hr: 1, 2292 img: 1, 2293 input: 1, 2294 keygen: 1, 2295 link: 1, 2296 meta: 1, 2297 param: 1, 2298 source: 1, 2299 track: 1, 2300 wbr: 1 2301 }; 2302 2303 function makeObject(str) { 2304 return oneObject(str + ',template,#document-fragment,#comment'); 2305 } 2306 var pNestChild = oneObject('div,ul,ol,dl,table,h1,h2,h3,h4,h5,h6,form,fieldset'); 2307 var tNestChild = makeObject('tr,style,script'); 2308 var nestObject = { 2309 p: pNestChild, 2310 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect 2311 select: makeObject('option,optgroup,#text'), 2312 optgroup: makeObject('option,#text'), 2313 option: makeObject('#text'), 2314 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd 2315 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption 2316 // No special behavior since these rules fall back to "in body" mode for 2317 // all except special table nodes which cause bad parsing behavior anyway. 2318 2319 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr 2320 tr: makeObject('th,td,style,script'), 2321 2322 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody 2323 tbody: tNestChild, 2324 tfoot: tNestChild, 2325 thead: tNestChild, 2326 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup 2327 colgroup: makeObject('col'), 2328 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable 2329 // table: oneObject('caption,colgroup,tbody,thead,tfoot,style,script,template,#document-fragment'), 2330 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead 2331 head: makeObject('base,basefont,bgsound,link,style,script,meta,title,noscript,noframes'), 2332 // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element 2333 html: oneObject('head,body') 2334 }; 2335 2336 /** 2337 * ------------------------------------------------------------ 2338 * avalon2.2.6çæ°å¼lexer 2339 * å°å符串åæä¸ä¸ªèæDOMæ ,æ¹ä¾¿ä»¥åè¿ä¸æ¥åææ¨¡æ¿å½æ° 2340 * æ¤é¶æ®µåªä¼çæVElement,VText,VComment 2341 * ------------------------------------------------------------ 2342 */ 2343 var specalTag = { xmp: 1, style: 1, script: 1, noscript: 1, textarea: 1, '#comment': 1, template: 1 }; 2344 var hiddenTag = { style: 1, script: 1, noscript: 1, template: 1 }; 2345 var rcontent = /\S/; //å¤å®éé¢ææ²¡æå 容 2346 var rsp = /\s/; 2347 function fromString(str) { 2348 return from(str); 2349 } 2350 avalon.lexer = fromString; 2351 2352 var strCache = new Cache(100); 2353 2354 function from(str) { 2355 var cacheKey = str; 2356 var cached = strCache.get(cacheKey); 2357 if (cached) { 2358 return avalon.mix(true, [], cached); 2359 } 2360 2361 var ret = parse(str, false); 2362 strCache.put(cacheKey, avalon.mix(true, [], ret)); 2363 return ret; 2364 } 2365 2366 /** 2367 * 2368 * 2369 * @param {any} string 2370 * @param {any} getOne åªè¿åä¸ä¸ªèç¹ 2371 * @returns 2372 */ 2373 function parse(string, getOne) { 2374 getOne = getOne === void 666 || getOne === true; 2375 var ret = lexer(string, getOne); 2376 if (getOne) { 2377 return typeof ret[0] === 'string' ? ret[1] : ret[0]; 2378 } 2379 return ret; 2380 } 2381 2382 function lexer(string, getOne) { 2383 var tokens = []; 2384 var breakIndex = 9990; 2385 var stack = []; 2386 var origString = string; 2387 var origLength = string.length; 2388 2389 stack.last = function () { 2390 return stack[stack.length - 1]; 2391 }; 2392 var ret = []; 2393 2394 function addNode(node) { 2395 var p = stack.last(); 2396 if (p && p.children) { 2397 p.children.push(node); 2398 } else {
2399 ret.push(node); 2400 } 2401 } 2402 2403 var lastNode; 2404 do { 2405 if (--breakIndex === 0) { 2406 break; 2407 } 2408 var arr = getCloseTag(string); 2409 2410 if (arr) { 2411 //å¤çå ³éæ ç¾ 2412 string = string.replace(arr[0], ''); 2413 var _node = stack.pop(); 2414 if (!_node) { 2415 throw 'æ¯ä¸æ¯æå±æ§å¼æ²¡æç¨å¼å·æ¬èµ·'; 2416 } 2417 //å¤çä¸é¢ä¸¤ç§ç¹æ®æ åµï¼ 2418 //1. optionä¼èªå¨ç§»é¤å ç´ èç¹ï¼å°å®ä»¬çnodeValueç»ææ°çææ¬èç¹ 2419 //2. tableä¼å°æ²¡æè¢«thead, tbody, tfootå èµ·æ¥çtræææ¬èç¹ï¼æ¶éå°ä¸ä¸ªæ°çtbodyå ç´ ä¸ 2420 2421 if (_node.nodeName === 'option') { 2422 _node.children = [{ 2423 nodeName: '#text', 2424 nodeValue: getText(_node) 2425 }]; 2426 } else if (_node.nodeName === 'table') { 2427 insertTbody(_node.children); 2428 } 2429 lastNode = null; 2430 if (getOne && ret.length === 1 && !stack.length) { 2431 return [origString.slice(0, origLength - string.length), ret[0]]; 2432 } 2433 continue; 2434 } 2435 2436 var arr = getOpenTag(string); 2437 if (arr) { 2438 string = string.replace(arr[0], ''); 2439 var node = arr[1]; 2440 addNode(node); 2441 var selfClose = !!(node.isVoidTag || specalTag[node.nodeName]); 2442 if (!selfClose) { 2443 //æ¾å°è¿éå¯ä»¥æ·»å å©å 2444 stack.push(node); 2445 } 2446 if (getOne && selfClose && !stack.length) { 2447 return [origString.slice(0, origLength - string.length), node]; 2448 } 2449 lastNode = node; 2450 continue; 2451 } 2452 2453 var text = ''; 2454 do { 2455 //å¤ç<div><<<<<<div>çæ åµ 2456 var _index = string.indexOf('<'); 2457 if (_index === 0) { 2458 text += string.slice(0, 1); 2459 string = string.slice(1); 2460 } else { 2461 break; 2462 } 2463 } while (string.length); 2464 2465 //å¤ç<div>{aaa}</div>,<div>xxx{aaa}xxx</div>,<div>xxx</div>{aaa}sssçæ åµ 2466 var index = string.indexOf('<'); //å¤å®å®å颿¯å¦å卿 ç¾ 2467 if (index === -1) { 2468 text = string; 2469 string = ''; 2470 } else { 2471 var openIndex = string.indexOf(config.openTag); 2472 2473 if (openIndex !== -1 && openIndex < index) { 2474 if (openIndex !== 0) { 2475 text += string.slice(0, openIndex); 2476 } 2477 var dirString = string.slice(openIndex); 2478 var textDir = parseTextDir(dirString); 2479 text += textDir; 2480 string = dirString.slice(textDir.length); 2481 } else { 2482 text += string.slice(0, index); 2483 string = string.slice(index); 2484 } 2485 } 2486 var mayNode = addText(lastNode, text, addNode); 2487 if (mayNode) { 2488 lastNode = mayNode; 2489 } 2490 } while (string.length); 2491 return ret; 2492 } 2493 2494 function addText(lastNode, text, addNode) { 2495 if (rcontent.test(text)) { 2496 if (lastNode && lastNode.nodeName === '#text') { 2497 lastNode.nodeValue += text; 2498 return lastNode; 2499 } else { 2500 lastNode = { 2501 nodeName: '#text', 2502 nodeValue: text 2503 }; 2504 addNode(lastNode); 2505 return lastNode; 2506 } 2507 } 2508 } 2509 2510 function parseTextDir(string) { 2511 var closeTag = config.closeTag; 2512 var openTag = config.openTag; 2513 var closeTagFirst = closeTag.charAt(0); 2514 var closeTagLength = closeTag.length; 2515 var state = 'code', 2516 quote$$1, 2517 escape; 2518 for (var i = openTag.length, n = string.length; i < n; i++) { 2519 2520 var c = string.charAt(i); 2521 switch (state) { 2522 case 'code': 2523 if (c === '"' || c === "'") { 2524 state = 'string'; 2525 quote$$1 = c; 2526 } else if (c === closeTagFirst) { 2527 //妿éå°} 2528 if (string.substr(i, closeTagLength) === closeTag) { 2529 return string.slice(0, i + closeTagLength); 2530 } 2531 } 2532 break; 2533 case 'string': 2534 if (c === '\\' && /"'/.test(string.charAt(i + 1))) { 2535 escape = !escape; 2536 } 2537 if (c === quote$$1 && !escape) { 2538 state = 'code'; 2539 } 2540 break; 2541 } 2542 } 2543 throw 'æ¾ä¸å°çå®ç¬¦' + closeTag; 2544 } 2545 2546 var rtbody = /^(tbody|thead|tfoot)$/; 2547 2548 function insertTbody(nodes) { 2549 var tbody = false;
2550 for (var i = 0, n = nodes.length; i < n; i++) { 2551 var node = nodes[i]; 2552 if (rtbody.test(node.nodeName)) { 2553 tbody = false; 2554 continue; 2555 } 2556 2557 if (node.nodeName === 'tr') { 2558 if (tbody) { 2559 nodes.splice(i, 1); 2560 tbody.children.push(node); 2561 n--; 2562 i--; 2563 } else { 2564 tbody = { 2565 nodeName: 'tbody', 2566 props: {}, 2567 children: [node] 2568 }; 2569 nodes.splice(i, 1, tbody); 2570 } 2571 } else { 2572 if (tbody) { 2573 nodes.splice(i, 1); 2574 tbody.children.push(node); 2575 n--; 2576 i--; 2577 } 2578 } 2579 } 2580 } 2581 2582 //<div>{{<div/>}}</div> 2583 function getCloseTag(string) { 2584 if (string.indexOf("</") === 0) { 2585 var match = string.match(/\<\/(\w+[^\s\/\>]*)>/); 2586 if (match) { 2587 var tag = match[1]; 2588 string = string.slice(3 + tag.length); 2589 return [match[0], { 2590 nodeName: tag 2591 }]; 2592 } 2593 } 2594 return null; 2595 } 2596 var ropenTag = /\<(\w[^\s\/\>]*)/; 2597 2598 function getOpenTag(string) { 2599 if (string.indexOf("<") === 0) { 2600 var i = string.indexOf('<!--'); //å¤ç注éèç¹ 2601 if (i === 0) { 2602 var l = string.indexOf('-->'); 2603 if (l === -1) { 2604 thow('注éèç¹æ²¡æéå ' + string.slice(0, 100)); 2605 } 2606 var node = { 2607 nodeName: '#comment', 2608 nodeValue: string.slice(4, l) 2609 }; 2610 return [string.slice(0, l + 3), node]; 2611 } 2612 var match = string.match(ropenTag); //å¤çå ç´ èç¹ 2613 if (match) { 2614 var leftContent = match[0], 2615 tag = match[1]; 2616 var node = { 2617 nodeName: tag, 2618 props: {}, 2619 children: [] 2620 }; 2621 2622 string = string.replace(leftContent, ''); //廿æ ç¾å(rightContent) 2623 try { 2624 var arr = getAttrs(string); //å¤ç屿§ 2625 } catch (e) {} 2626 if (arr) { 2627 node.props = arr[1]; 2628 string = string.replace(arr[0], ''); 2629 leftContent += arr[0]; 2630 } 2631 2632 if (string.charAt(0) === '>') { 2633 //å¤ç弿 ç¾çè¾¹ç符 2634 leftContent += '>'; 2635 string = string.slice(1); 2636 if (voidTag[node.nodeName]) { 2637 node.isVoidTag = true; 2638 } 2639 } else if (string.slice(0, 2) === '/>') { 2640 //å¤ç弿 ç¾çè¾¹ç符 2641 leftContent += '/>'; 2642 string = string.slice(2); 2643 node.isVoidTag = true; 2644 } 2645 2646 if (!node.isVoidTag && specalTag[tag]) { 2647 //妿æ¯script, style, xmpçå ç´ 2648 var closeTag = '</' + tag + '>'; 2649 var j = string.indexOf(closeTag); 2650 var nodeValue = string.slice(0, j); 2651 leftContent += nodeValue + closeTag; 2652 node.children.push({ 2653 nodeName: '#text', 2654 nodeValue: nodeValue 2655 }); 2656 if (tag === 'textarea') { 2657 node.props.type = tag; 2658 node.props.value = nodeValue; 2659 } 2660 } 2661 return [leftContent, node]; 2662 } 2663 } 2664 } 2665 2666 function getText(node) { 2667 var ret = ''; 2668 node.children.forEach(function (el) { 2669 if (el.nodeName === '#text') { 2670 ret += el.nodeValue; 2671 } else if (el.children && !hiddenTag[el.nodeName]) { 2672 ret += getText(el); 2673 } 2674 }); 2675 return ret; 2676 } 2677 2678 function getAttrs(string) { 2679 var state = 'AttrName', 2680 attrName = '', 2681 attrValue = '', 2682 quote$$1, 2683 escape, 2684 props = {}; 2685 for (var i = 0, n = string.length; i < n; i++) { 2686 var c = string.charAt(i); 2687 switch (state) { 2688 case 'AttrName': 2689 if (c === '/' && string.charAt(i + 1) === '>' || c === '>') { 2690 if (attrName) props[attrName] = attrName; 2691 return [string.slice(0, i), props]; 2692 } 2693 if (rsp.test(c)) { 2694 if (attrName) { 2695 state = 'AttrEqual'; 2696 } 2697 } else if (c === '=') { 2698 if (!attrName) { 2699 throw 'å¿ é¡»æå®å±æ§å'; 2700 } 2701 state = 'AttrQuote'; 2702 } else { 2703 attrName += c; 2704 } 2705 break; 2706 case 'AttrEqual': 2707 if (c === '=') { 2708 state = 'AttrQuote'; 2709 } else if (rcontent.test(c)) { 2710 props[attrName] = attrName; 2711 attrName = c; 2712 state = 'AttrName'; 2713 } 2714 break; 2715 case 'AttrQuote': 2716 if (c === '"' || c === "'") { 2717 quote$$1 = c; 2718 state = 'AttrValue'; 2719 escape = false;
2720 } 2721 break; 2722 case 'AttrValue': 2723 if (c === '\\' && /"'/.test(string.charAt(i + 1))) { 2724 escape = !escape; 2725 } 2726 if (c === '\n') { 2727 break; 2728 } 2729 if (c !== quote$$1) { 2730 attrValue += c; 2731 } else if (c === quote$$1 && !escape) { 2732 props[attrName] = attrValue; 2733 attrName = attrValue = ''; 2734 state = 'AttrName'; 2735 } 2736 break; 2737 } 2738 } 2739 throw 'å¿ é¡»å ³éæ ç¾'; 2740 } 2741 2742 var rhtml = /<|&#?\w+;/; 2743 var htmlCache = new Cache(128); 2744 var rxhtml = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig; 2745 2746 avalon.parseHTML = function (html) { 2747 var fragment = createFragment(); 2748 //å¤çéå符串 2749 if (typeof html !== 'string') { 2750 return fragment; 2751 } 2752 //å¤çéHTMLå符串 2753 if (!rhtml.test(html)) { 2754 return document$1.createTextNode(html); 2755 } 2756 2757 html = html.replace(rxhtml, '<$1></$2>').trim(); 2758 var hasCache = htmlCache.get(html); 2759 if (hasCache) { 2760 return avalon.cloneNode(hasCache); 2761 } 2762 var vnodes = fromString(html); 2763 for (var i = 0, el; el = vnodes[i++];) { 2764 var child = avalon.vdom(el, 'toDOM'); 2765 fragment.appendChild(child); 2766 } 2767 if (html.length < 1024) { 2768 htmlCache.put(html, fragment); 2769 } 2770 return fragment; 2771 }; 2772 2773 avalon.innerHTML = function (node, html) { 2774 var parsed = avalon.parseHTML(html); 2775 this.clearHTML(node); 2776 node.appendChild(parsed); 2777 }; 2778 2779 //https://github.com/karloespiritu/escapehtmlent/blob/master/index.js 2780 avalon.unescapeHTML = function (html) { 2781 return String(html).replace(/"/g, '"').replace(/'/g, '\'').replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&'); 2782 }; 2783 2784 avalon.clearHTML = function (node) { 2785 /* istanbul ignore next */ 2786 while (node.lastChild) { 2787 node.removeChild(node.lastChild); 2788 } 2789 return node; 2790 }; 2791 2792 2793 //http://segmentfault.com/q/1010000000687977/a-1020000000688757 2794 var canBubbleUp = { 2795 click: true, 2796 dblclick: true, 2797 keydown: true, 2798 keypress: true, 2799 keyup: true, 2800 mousedown: true, 2801 mousemove: true, 2802 mouseup: true, 2803 mouseover: true, 2804 mouseout: true, 2805 wheel: true, 2806 mousewheel: true, 2807 input: true, 2808 change: true, 2809 beforeinput: true, 2810 compositionstart: true, 2811 compositionupdate: true, 2812 compositionend: true, 2813 select: true, 2814 //http://blog.csdn.net/lee_magnum/article/details/17761441 2815 cut: true, 2816 copy: true, 2817 paste: true, 2818 beforecut: true, 2819 beforecopy: true, 2820 beforepaste: true, 2821 focusin: true, 2822 focusout: true, 2823 DOMFocusIn: true, 2824 DOMFocusOut: true, 2825 DOMActivate: true, 2826 dragend: true, 2827 datasetchanged: true 2828 }; 2829 2830 /* istanbul ignore if */ 2831 var hackSafari = avalon.modern && document$1.ontouchstart; 2832 2833 //æ·»å fn.bind, fn.unbind, bind, unbind 2834 avalon.fn.bind = function (type, fn, phase) { 2835 if (this[0]) { 2836 //æ¤æ¹æ³ä¸ä¼é¾ 2837 return avalon.bind(this[0], type, fn, phase); 2838 } 2839 }; 2840 2841 avalon.fn.unbind = function (type, fn, phase) { 2842 if (this[0]) { 2843 var args = _slice.call(arguments); 2844 args.unshift(this[0]); 2845 avalon.unbind.apply(0, args); 2846 } 2847 return this; 2848 }; 2849 2850 /*ç»å®äºä»¶*/ 2851 avalon.bind = function (elem, type, fn) { 2852 if (elem.nodeType === 1) { 2853 var value = elem.getAttribute('avalon-events') || ''; 2854 //妿æ¯ä½¿ç¨ms-on-*ç»å®çåè°,å ¶uuidæ ¼å¼ä¸ºe12122324, 2855 //妿æ¯ä½¿ç¨bindæ¹æ³ç»å®çåè°,å ¶uuidæ ¼å¼ä¸º_12 2856 var uuid = getShortID(fn); 2857 var hook = eventHooks[type]; 2858 /* istanbul ignore if */ 2859 if (type === 'click' && hackSafari) { 2860 elem.addEventListener('click', avalon.noop); 2861 } 2862 /* istanbul ignore if */ 2863 if (hook) { 2864 type = hook.type || type; 2865 if (hook.fix) { 2866 fn = hook.fix(elem, fn); 2867 fn.uuid = uuid; 2868 } 2869 } 2870 var key = type + ':' + uuid; 2871 avalon.eventListeners[fn.uuid] = fn; 2872 /* istanbul ignore if */ 2873 if (value.indexOf(type + ':') === -1) { 2874 //åä¸ç§äºä»¶åªç»å®ä¸æ¬¡ 2875 if (canBubbleUp[type] || avalon.modern && focusBlur[type]) { 2876 delegateEvent(type); 2877 } else { 2878 avalon._nativeBind(elem, type, dispatch); 2879 } 2880 } 2881 var keys = value.split(','); 2882 /* istanbul ignore if */ 2883 if (keys[0] === '') { 2884 keys.shift(); 2885 } 2886 if (keys.indexOf(key) === -1) { 2887 keys.push(key); 2888 setEventId(elem, keys.join(','));
2889 //å°ä»¤çæ¾è¿avalon-events屿§ä¸ 2890 } 2891 return fn; 2892 } else { 2893 /* istanbul ignore next */ 2894 var cb = function cb(e) { 2895 fn.call(elem, new avEvent(e)); 2896 }; 2897 2898 avalon._nativeBind(elem, type, cb); 2899 return cb; 2900 } 2901 }; 2902 2903 function setEventId(node, value) { 2904 node.setAttribute('avalon-events', value); 2905 } 2906 /* istanbul ignore next */ 2907 avalon.unbind = function (elem, type, fn) { 2908 if (elem.nodeType === 1) { 2909 var value = elem.getAttribute('avalon-events') || ''; 2910 switch (arguments.length) { 2911 case 1: 2912 avalon._nativeUnBind(elem, type, dispatch); 2913 elem.removeAttribute('avalon-events'); 2914 break; 2915 case 2: 2916 value = value.split(',').filter(function (str) { 2917 return str.indexOf(type + ':') === -1; 2918 }).join(','); 2919 setEventId(elem, value); 2920 break; 2921 default: 2922 var search = type + ':' + fn.uuid; 2923 value = value.split(',').filter(function (str) { 2924 return str !== search; 2925 }).join(','); 2926 setEventId(elem, value); 2927 delete avalon.eventListeners[fn.uuid]; 2928 break; 2929 } 2930 } else { 2931 avalon._nativeUnBind(elem, type, fn); 2932 } 2933 }; 2934 2935 var typeRegExp = {}; 2936 2937 function collectHandlers(elem, type, handlers) { 2938 var value = elem.getAttribute('avalon-events'); 2939 if (value && (elem.disabled !== true || type !== 'click')) { 2940 var uuids = []; 2941 var reg = typeRegExp[type] || (typeRegExp[type] = new RegExp("\\b" + type + '\\:([^,\\s]+)', 'g')); 2942 value.replace(reg, function (a, b) { 2943 uuids.push(b); 2944 return a; 2945 }); 2946 if (uuids.length) { 2947 handlers.push({ 2948 elem: elem, 2949 uuids: uuids 2950 }); 2951 } 2952 } 2953 elem = elem.parentNode; 2954 var g = avalon.gestureEvents || {}; 2955 if (elem && elem.getAttribute && (canBubbleUp[type] || g[type])) { 2956 collectHandlers(elem, type, handlers); 2957 } 2958 } 2959 2960 var rhandleHasVm = /^e/; 2961 2962 function dispatch(event) { 2963 event = new avEvent(event); 2964 var type = event.type; 2965 var elem = event.target; 2966 var handlers = []; 2967 collectHandlers(elem, type, handlers); 2968 var i = 0, 2969 j, 2970 uuid, 2971 handler; 2972 while ((handler = handlers[i++]) && !event.cancelBubble) { 2973 var host = event.currentTarget = handler.elem; 2974 j = 0; 2975 while (uuid = handler.uuids[j++]) { 2976 if (event.stopImmediate) { 2977 break; 2978 } 2979 var fn = avalon.eventListeners[uuid]; 2980 if (fn) { 2981 var vm = rhandleHasVm.test(uuid) ? handler.elem._ms_context_ : 0; 2982 if (vm && vm.$hashcode === false) { 2983 return avalon.unbind(elem, type, fn); 2984 } 2985 var ret = fn.call(vm || elem, event); 2986 2987 if (ret === false) { 2988 event.preventDefault(); 2989 event.stopPropagation(); 2990 } 2991 } 2992 } 2993 } 2994 } 2995 2996 var focusBlur = { 2997 focus: true, 2998 blur: true 2999 }; 3000 3001 function delegateEvent(type) { 3002 var value = root.getAttribute('delegate-events') || ''; 3003 if (value.indexOf(type) === -1) { 3004 //IE6-8ä¼å¤æ¬¡ç»å®åç§ç±»åçåä¸ä¸ªå½æ°,å ¶ä»æ¸¸è§å¨ä¸ä¼ 3005 var arr = value.match(avalon.rword) || []; 3006 arr.push(type); 3007 root.setAttribute('delegate-events', arr.join(',')); 3008 avalon._nativeBind(root, type, dispatch, !!focusBlur[type]); 3009 } 3010 } 3011 3012 var eventProto = { 3013 webkitMovementY: 1, 3014 webkitMovementX: 1, 3015 keyLocation: 1, 3016 fixEvent: function fixEvent() {}, 3017 preventDefault: function preventDefault() { 3018 var e = this.originalEvent || {}; 3019 e.returnValue = this.returnValue = false;
3020 if (modern && e.preventDefault) { 3021 e.preventDefault(); 3022 } 3023 }, 3024 stopPropagation: function stopPropagation() { 3025 var e = this.originalEvent || {}; 3026 e.cancelBubble = this.cancelBubble = true; 3027 if (modern && e.stopPropagation) { 3028 e.stopPropagation(); 3029 } 3030 }, 3031 stopImmediatePropagation: function stopImmediatePropagation() { 3032 this.stopPropagation(); 3033 this.stopImmediate = true; 3034 }, 3035 toString: function toString() { 3036 return '[object Event]'; //#1619 3037 } 3038 }; 3039 3040 function avEvent(event) { 3041 if (event.originalEvent) { 3042 return event; 3043 } 3044 for (var i in event) { 3045 if (!eventProto[i]) { 3046 this[i] = event[i]; 3047 } 3048 } 3049 if (!this.target) { 3050 this.target = event.srcElement; 3051 } 3052 var target = this.target; 3053 this.fixEvent(); 3054 this.timeStamp = new Date() - 0; 3055 this.originalEvent = event; 3056 } 3057 avEvent.prototype = eventProto; 3058 //é对firefox, chromeä¿®æ£mouseenter, mouseleave 3059 /* istanbul ignore if */ 3060 if (!('onmouseenter' in root)) { 3061 avalon.each({ 3062 mouseenter: 'mouseover', 3063 mouseleave: 'mouseout' 3064 }, function (origType, fixType) { 3065 eventHooks[origType] = { 3066 type: fixType, 3067 fix: function fix(elem, fn) { 3068 return function (e) { 3069 var t = e.relatedTarget; 3070 if (!t || t !== elem && !(elem.compareDocumentPosition(t) & 16)) { 3071 delete e.type; 3072 e.type = origType; 3073 return fn.apply(this, arguments); 3074 } 3075 }; 3076 } 3077 }; 3078 }); 3079 } 3080 //é对IE9+, w3cä¿®æ£animationend 3081 avalon.each({ 3082 AnimationEvent: 'animationend', 3083 WebKitAnimationEvent: 'webkitAnimationEnd' 3084 }, function (construct, fixType) { 3085 if (window$1[construct] && !eventHooks.animationend) { 3086 eventHooks.animationend = { 3087 type: fixType 3088 }; 3089 } 3090 }); 3091 3092 /* istanbul ignore if */ 3093 if (!("onmousewheel" in document$1)) { 3094 /* IE6-11 chrome mousewheel wheelDetla ä¸ -120 ä¸ 120 3095 firefox DOMMouseScroll detail ä¸3 ä¸-3 3096 firefox wheel detlaY ä¸3 ä¸-3 3097 IE9-11 wheel deltaY ä¸40 ä¸-40 3098 chrome wheel deltaY ä¸100 ä¸-100 */ 3099 var fixWheelType = document$1.onwheel !== void 0 ? 'wheel' : 'DOMMouseScroll'; 3100 var fixWheelDelta = fixWheelType === 'wheel' ? 'deltaY' : 'detail'; 3101 eventHooks.mousewheel = { 3102 type: fixWheelType, 3103 fix: function fix(elem, fn) { 3104 return function (e) { 3105 var delta = e[fixWheelDelta] > 0 ? -120 : 120; 3106 e.wheelDelta = ~~elem._ms_wheel_ + delta; 3107 elem._ms_wheel_ = e.wheelDeltaY = e.wheelDelta; 3108 e.wheelDeltaX = 0; 3109 if (Object.defineProperty) { 3110 Object.defineProperty(e, 'type', { 3111 value: 'mousewheel' 3112 }); 3113 } 3114 return fn.apply(this, arguments); 3115 }; 3116 } 3117 }; 3118 } 3119 3120 /* istanbul ignore if */ 3121 if (!modern) { 3122 delete canBubbleUp.change; 3123 delete canBubbleUp.select; 3124 } 3125 /* istanbul ignore next */ 3126 avalon._nativeBind = modern ? function (el, type, fn, capture) { 3127 el.addEventListener(type, fn, !!capture); 3128 } : function (el, type, fn) { 3129 el.attachEvent('on' + type, fn); 3130 }; 3131 /* istanbul ignore next */ 3132 avalon._nativeUnBind = modern ? function (el, type, fn, a) { 3133 el.removeEventListener(type, fn, !!a); 3134 } : function (el, type, fn) { 3135 el.detachEvent('on' + type, fn); 3136 }; 3137 /* istanbul ignore next */ 3138 avalon.fireDom = function (elem, type, opts) { 3139 if (document$1.createEvent) { 3140 var hackEvent = document$1.createEvent('Events'); 3141 hackEvent.initEvent(type, true, true, opts); 3142 avalon.shadowCopy(hackEvent, opts); 3143 elem.dispatchEvent(hackEvent); 3144 } else if (root.contains(elem)) { 3145 //IE6-8触åäºä»¶å¿ é¡»ä¿è¯å¨DOMæ ä¸,å¦åæ¥'SCRIPT16389: æªææçé误' 3146 hackEvent = document$1.createEventObject(); 3147 if (opts) avalon.shadowCopy(hackEvent, opts); 3148 try { 3149 elem.fireEvent('on' + type, hackEvent); 3150 } catch (e) { 3151 avalon.log('fireDom', type, 'args error'); 3152 } 3153 } 3154 }; 3155 3156 var rmouseEvent = /^(?:mouse|contextmenu|drag)|click/; 3157 /* istanbul ignore next */ 3158 avEvent.prototype.fixEvent = function () { 3159 var event = this; 3160 if (event.which == null && event.type.indexOf('key') === 0) { 3161 event.which = event.charCode != null ? event.charCode : event.keyCode; 3162 } 3163 if (rmouseEvent.test(event.type) && !('pageX' in event)) { 3164 var DOC = event.target.ownerDocument || document$1; 3165 var box = DOC.compatMode === 'BackCompat' ? DOC.body : DOC.documentElement; 3166 event.pageX = event.clientX + (box.scrollLeft >> 0) - (box.clientLeft >> 0); 3167 event.pageY = event.clientY + (box.scrollTop >> 0) - (box.clientTop >> 0); 3168 event.wheelDeltaY = ~~event.wheelDelta; 3169 event.wheelDeltaX = 0; 3170 } 3171 }; 3172 3173 //é对IE6-8ä¿®æ£input 3174 /* istanbul ignore if */ 3175 if (!('oninput' in document$1.createElement('input'))) { 3176 eventHooks.input = { 3177 type: 'propertychange', 3178 fix: function fix(elem, fn) { 3179 return function (e) { 3180 if (e.propertyName === 'value') { 3181 e.type = 'input'; 3182 return fn.apply(this, arguments); 3183 } 3184 }; 3185 } 3186 }; 3187 } 3188 3189 var readyList = []; 3190 3191 function fireReady(fn) { 3192 avalon.isReady = true; 3193 while (fn = readyList.shift()) { 3194 fn(avalon); 3195 } 3196 } 3197 3198 avalon.ready = function (fn) { 3199 readyList.push(fn); 3200 if (avalon.isReady) { 3201 fireReady(); 3202 } 3203 }; 3204 3205 avalon.ready(function () { 3206 avalon.scan && avalon.scan(document$1.body); 3207 }); 3208 3209 /* istanbul ignore next */ 3210 function bootstrap() { 3211 function doScrollCheck() { 3212 try { 3213 //IEä¸éè¿doScrollCheckæ£æµDOMæ æ¯å¦å»ºå® 3214 root.doScroll('left'); 3215 fireReady(); 3216 } catch (e) { 3217 setTimeout(doScrollCheck); 3218 } 3219 } 3220 if (document$1.readyState === 'complete') { 3221 setTimeout(fireReady); //妿å¨domReadyä¹å¤å è½½ 3222 } else if (document$1.addEventListener) { 3223 document$1.addEventListener('DOMContentLoaded', fireReady, false); 3224 } else if (document$1.attachEvent) { 3225 //å¿ é¡»ä¼ å ¥ä¸ä¸ªåæ°ï¼å¦åå¨firefox4-26䏿¥é 3226 //caught exception: [Exception... "Not enough arguments" nsresult: "0x 3227 document$1.attachEvent('onreadystatechange', function () { 3228 if (document$1.readyState === 'complete') { 3229 fireReady(); 3230 } 3231 }); 3232 try { 3233 var isTop = window$1.frameElement === null; 3234 } catch (e) {} 3235 if (root.doScroll && isTop && window$1.external) { 3236 //fix IE iframe BUG 3237 doScrollCheck(); 3238 } 3239 } 3240 3241 avalon.bind(window$1, 'load', fireReady); 3242 } 3243 if (inBrowser) { 3244 bootstrap(); 3245 } 3246 3247 /** 3248 * ------------------------------------------------------------ 3249 * DOM Api 3250 * shim,class,data,css,val,html,event,ready 3251 * ------------------------------------------------------------ 3252 */ 3253 3254 var orphanTag = { 3255 script: 1, 3256 style: 1, 3257 textarea: 1, 3258 xmp: 1, 3259 noscript: 1, 3260 template: 1 3261 }; 3262 3263 /* 3264 * æ¤æ¨¡ååªç¨äºææ¬è½¬èæDOM, 3265 * å 为å¨ç宿µè§å¨ä¼å¯¹æä»¬çHTMLåæ´å¤å¤ç, 3266 * å¦, æ·»å é¢å¤å±æ§, æ¹åç»æ 3267 * æ¤æ¨¡åå°±æ¯ç¨äºæ¨¡æè¿äºè¡ä¸º 3268 */ 3269 function makeOrphan(node, nodeName, innerHTML) { 3270 switch (nodeName) { 3271 case 'style': 3272 case 'script': 3273 case 'noscript': 3274 case 'template': 3275 case 'xmp': 3276 node.children = [{ 3277 nodeName: '#text', 3278 nodeValue: innerHTML 3279 }]; 3280 break; 3281 case 'textarea': 3282 var props = node.props; 3283 props.type = nodeName; 3284 props.value = innerHTML; 3285 node.children = [{ 3286 nodeName: '#text', 3287 nodeValue: innerHTML 3288 }]; 3289 break; 3290 case 'option': 3291 node.children = [{ 3292 nodeName: '#text', 3293 nodeValue: trimHTML(innerHTML) 3294 }]; 3295 break; 3296 } 3297 } 3298 3299 //ä¸é¨ç¨äºå¤çoptionæ ç¾éé¢çæ ç¾ 3300 var rtrimHTML = /<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi; 3301 function trimHTML(v) { 3302 return String(v).replace(rtrimHTML, '').trim(); 3303 } 3304 3305 //widget rule duplex validate 3306 3307 function fromDOM(dom) { 3308 return [from$1(dom)]; 3309 } 3310 3311 function from$1(node) { 3312 var type = node.nodeName.toLowerCase(); 3313 switch (type) { 3314 case '#text': 3315 case '#comment': 3316 return { 3317 nodeName: type, 3318 dom: node, 3319 nodeValue: node.nodeValue 3320 }; 3321 default: 3322 var props = markProps(node, node.attributes || []); 3323 var vnode = { 3324 nodeName: type, 3325 dom: node, 3326 isVoidTag: !!voidTag[type], 3327 props: props 3328 }; 3329 if (type === 'option') { 3330 //å³ä¾¿ä½ 设置äºoption.selected = true, 3331 //option.attributes乿¾ä¸å°selected屿§ 3332 props.selected = node.selected; 3333 } 3334 if (orphanTag[type] || type === 'option') {
3335 makeOrphan(vnode, type, node.text || node.innerHTML); 3336 if (node.childNodes.length === 1) { 3337 vnode.children[0].dom = node.firstChild; 3338 } 3339 } else if (!vnode.isVoidTag) { 3340 vnode.children = []; 3341 for (var i = 0, el; el = node.childNodes[i++];) { 3342 var child = from$1(el); 3343 if (/\S/.test(child.nodeValue)) { 3344 vnode.children.push(child); 3345 } 3346 } 3347 } 3348 return vnode; 3349 } 3350 } 3351 3352 var rformElement = /input|textarea|select/i; 3353 3354 function markProps(node, attrs) { 3355 var ret = {}; 3356 for (var i = 0, n = attrs.length; i < n; i++) { 3357 var attr = attrs[i]; 3358 if (attr.specified) { 3359 //IE6-9ä¸ä¼å°å±æ§ååå°å,æ¯å¦å®ä¼å°ç¨æ·çcontenteditableåæcontentEditable 3360 ret[attr.name.toLowerCase()] = attr.value; 3361 } 3362 } 3363 if (rformElement.test(node.nodeName)) { 3364 ret.type = node.type; 3365 var a = node.getAttributeNode('value'); 3366 if (a && /\S/.test(a.value)) { 3367 //IE6,7䏿 æ³åå¾checkbox,radioçvalue 3368 ret.value = a.value; 3369 } 3370 } 3371 var style = node.style.cssText; 3372 if (style) { 3373 ret.style = style; 3374 } 3375 //ç±»å = å»é(éæç±»å+å¨æç±»å+ hoverç±»å? + activeç±»å) 3376 if (ret.type === 'select-one') { 3377 ret.selectedIndex = node.selectedIndex; 3378 } 3379 return ret; 3380 } 3381 3382 function VText(text) { 3383 this.nodeName = '#text'; 3384 this.nodeValue = text; 3385 } 3386 3387 VText.prototype = { 3388 constructor: VText, 3389 toDOM: function toDOM() { 3390 /* istanbul ignore if*/ 3391 if (this.dom) return this.dom; 3392 var v = avalon._decode(this.nodeValue); 3393 return this.dom = document$1.createTextNode(v); 3394 }, 3395 toHTML: function toHTML() { 3396 return this.nodeValue; 3397 } 3398 }; 3399 3400 function VComment(text) { 3401 this.nodeName = '#comment'; 3402 this.nodeValue = text; 3403 } 3404 VComment.prototype = { 3405 constructor: VComment, 3406 toDOM: function toDOM() { 3407 if (this.dom) return this.dom; 3408 return this.dom = document$1.createComment(this.nodeValue); 3409 }, 3410 toHTML: function toHTML() { 3411 return '<!--' + this.nodeValue + '-->'; 3412 } 3413 }; 3414 3415 function VElement(type, props, children, isVoidTag) { 3416 this.nodeName = type; 3417 this.props = props; 3418 this.children = children; 3419 this.isVoidTag = isVoidTag; 3420 } 3421 VElement.prototype = { 3422 constructor: VElement, 3423 toDOM: function toDOM() { 3424 if (this.dom) return this.dom; 3425 var dom, 3426 tagName = this.nodeName; 3427 if (avalon.modern && svgTags[tagName]) { 3428 dom = createSVG(tagName); 3429 /* istanbul ignore next*/ 3430 } else if (!avalon.modern && (VMLTags[tagName] || rvml.test(tagName))) { 3431 dom = createVML(tagName); 3432 } else { 3433 dom = document$1.createElement(tagName); 3434 } 3435 3436 var props = this.props || {}; 3437 3438 for (var i in props) { 3439 var val = props[i]; 3440 if (skipFalseAndFunction(val)) { 3441 /* istanbul ignore if*/ 3442 if (specalAttrs[i] && avalon.msie < 8) { 3443 specalAttrs[i](dom, val); 3444 } else { 3445 dom.setAttribute(i, val + ''); 3446 } 3447 } 3448 } 3449 var c = this.children || []; 3450 var template = c[0] ? c[0].nodeValue : ''; 3451 switch (this.nodeName) { 3452 case 'script': 3453 dom.type = 'noexec'; 3454 dom.text = template; 3455 try { 3456 dom.innerHTML = template; 3457 } catch (e) {} 3458 dom.type = props.type || ''; 3459 break; 3460 case 'noscript': 3461 dom.textContent = template; 3462 case 'style': 3463 case 'xmp': 3464 case 'template': 3465 try { 3466 dom.innerHTML = template; 3467 } catch (e) { 3468 /* istanbul ignore next*/ 3469 hackIE(dom, this.nodeName, template); 3470 } 3471 break; 3472 case 'option': 3473 //IE6-8,为optionæ·»å ææ¬åèç¹,ä¸ä¼åæ¥å°text屿§ä¸ 3474 /* istanbul ignore next */ 3475 if (msie < 9) dom.text = template; 3476 default: 3477 /* istanbul ignore next */ 3478 if (!this.isVoidTag && this.children) {
3479 this.children.forEach(function (el) { 3480 return c && dom.appendChild(avalon.vdom(c, 'toDOM')); 3481 }); 3482 } 3483 break; 3484 } 3485 return this.dom = dom; 3486 }, 3487 3488 /* istanbul ignore next */ 3489 3490 toHTML: function toHTML() { 3491 var arr = []; 3492 var props = this.props || {}; 3493 for (var i in props) { 3494 var val = props[i]; 3495 if (skipFalseAndFunction(val)) { 3496 arr.push(i + '=' + avalon.quote(props[i] + '')); 3497 } 3498 } 3499 arr = arr.length ? ' ' + arr.join(' ') : ''; 3500 var str = '<' + this.nodeName + arr; 3501 if (this.isVoidTag) { 3502 return str + '/>'; 3503 } 3504 str += '>'; 3505 if (this.children) { 3506 str += this.children.map(function (el) { 3507 return el ? avalon.vdom(el, 'toHTML') : ''; 3508 }).join(''); 3509 } 3510 return str + '</' + this.nodeName + '>'; 3511 } 3512 }; 3513 function hackIE(dom, nodeName, template) { 3514 switch (nodeName) { 3515 case 'style': 3516 dom.setAttribute('type', 'text/css'); 3517 dom.styleSheet.cssText = template; 3518 break; 3519 case 'xmp': //IE6-8,XMPå ç´ éé¢åªè½æææ¬èç¹,ä¸è½ä½¿ç¨innerHTML 3520 case 'noscript': 3521 dom.textContent = template; 3522 break; 3523 } 3524 } 3525 function skipFalseAndFunction(a) { 3526 return a !== false && Object(a) !== a; 3527 } 3528 /* istanbul ignore next */ 3529 var specalAttrs = { 3530 "class": function _class(dom, val) { 3531 dom.className = val; 3532 }, 3533 style: function style(dom, val) { 3534 dom.style.cssText = val; 3535 }, 3536 type: function type(dom, val) { 3537 try { 3538 //textarea,button å ç´ å¨IE6,7设置 type 屿§ä¼æé 3539 dom.type = val; 3540 } catch (e) {} 3541 }, 3542 'for': function _for(dom, val) { 3543 dom.setAttribute('for', val); 3544 dom.htmlFor = val; 3545 } 3546 }; 3547 3548 function createSVG(type) { 3549 return document$1.createElementNS('http://www.w3.org/2000/svg', type); 3550 } 3551 var svgTags = avalon.oneObject('circle,defs,ellipse,image,line,' + 'path,polygon,polyline,rect,symbol,text,use,g,svg'); 3552 3553 var rvml = /^\w+\:\w+/; 3554 /* istanbul ignore next*/ 3555 function createVML(type) { 3556 if (document$1.styleSheets.length < 31) { 3557 document$1.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); 3558 } else { 3559 // no more room, add to the existing one 3560 // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx 3561 document$1.styleSheets[0].addRule(".rvml", "behavior:url(#default#VML)"); 3562 } 3563 var arr = type.split(':'); 3564 if (arr.length === 1) { 3565 arr.unshift('v'); 3566 } 3567 var tag = arr[1]; 3568 var ns = arr[0]; 3569 if (!document$1.namespaces[ns]) { 3570 document$1.namespaces.add(ns, "urn:schemas-microsoft-com:vml"); 3571 } 3572 return document$1.createElement('<' + ns + ':' + tag + ' class="rvml">'); 3573 } 3574 3575 var VMLTags = avalon.oneObject('shape,line,polyline,rect,roundrect,oval,arc,' + 'curve,background,image,shapetype,group,fill,' + 'stroke,shadow, extrusion, textbox, imagedata, textpath'); 3576 3577 function VFragment(children, key, val, index) { 3578 this.nodeName = '#document-fragment'; 3579 this.children = children; 3580 this.key = key; 3581 this.val = val; 3582 this.index = index; 3583 this.props = {}; 3584 } 3585 VFragment.prototype = { 3586 constructor: VFragment, 3587 toDOM: function toDOM() { 3588 if (this.dom) return this.dom; 3589 var f = this.toFragment(); 3590 //IE6-11 docment-fragment齿²¡æchildren屿§ 3591 this.split = f.lastChild; 3592 return this.dom = f; 3593 }, 3594 dispose: function dispose() { 3595 this.toFragment(); 3596 this.innerRender && this.innerRender.dispose(); 3597 for (var i in this) { 3598 this[i] = null; 3599 } 3600 }, 3601 toFragment: function toFragment() { 3602 var f = createFragment();
3603 this.children.forEach(function (el) { 3604 return f.appendChild(avalon.vdom(el, 'toDOM')); 3605 }); 3606 return f; 3607 }, 3608 toHTML: function toHTML() { 3609 var c = this.children; 3610 return c.map(function (el) { 3611 return avalon.vdom(el, 'toHTML'); 3612 }).join(''); 3613 } 3614 }; 3615 3616 /** 3617 * èæDOMç4大æé å¨ 3618 */ 3619 avalon.mix(avalon, { 3620 VText: VText, 3621 VComment: VComment, 3622 VElement: VElement, 3623 VFragment: VFragment 3624 }); 3625 3626 var constNameMap = { 3627 '#text': 'VText', 3628 '#document-fragment': 'VFragment', 3629 '#comment': 'VComment' 3630 }; 3631 3632 var vdom = avalon.vdomAdaptor = avalon.vdom = function (obj, method) { 3633 if (!obj) { 3634 //objå¨ms-for循ç¯éé¢å¯è½æ¯null 3635 return method === "toHTML" ? '' : createFragment(); 3636 } 3637 var nodeName = obj.nodeName; 3638 if (!nodeName) { 3639 return new avalon.VFragment(obj)[method](); 3640 } 3641 var constName = constNameMap[nodeName] || 'VElement'; 3642 return avalon[constName].prototype[method].call(obj); 3643 }; 3644 3645 avalon.domize = function (a) { 3646 return avalon.vdom(a, 'toDOM'); 3647 }; 3648 3649 avalon.pendingActions = []; 3650 avalon.uniqActions = {}; 3651 avalon.inTransaction = 0; 3652 config.trackDeps = false; 3653 avalon.track = function () { 3654 if (config.trackDeps) { 3655 avalon.log.apply(avalon, arguments); 3656 } 3657 }; 3658 3659 /** 3660 * Batch is a pseudotransaction, just for purposes of memoizing ComputedValues when nothing else does. 3661 * During a batch `onBecomeUnobserved` will be called at most once per observable. 3662 * Avoids unnecessary recalculations. 3663 */ 3664 3665 function runActions() { 3666 if (avalon.isRunningActions === true || avalon.inTransaction > 0) return; 3667 avalon.isRunningActions = true; 3668 var tasks = avalon.pendingActions.splice(0, avalon.pendingActions.length); 3669 for (var i = 0, task; task = tasks[i++];) { 3670 task.update(); 3671 delete avalon.uniqActions[task.uuid]; 3672 } 3673 avalon.isRunningActions = false; 3674 } 3675 3676 function propagateChanged(target) { 3677 var list = target.observers; 3678 for (var i = 0, el; el = list[i++];) { 3679 el.schedule(); //éç¥action, computedåå®ä»¬è¯¥åçäº 3680 } 3681 } 3682 3683 //å°èªå·±æå°å¸åºä¸å 3684 function reportObserved(target) { 3685 var action = avalon.trackingAction || null; 3686 if (action !== null) { 3687 3688 avalon.track('徿¶å°', target.expr); 3689 action.mapIDs[target.uuid] = target; 3690 } 3691 } 3692 3693 var targetStack = []; 3694 3695 function collectDeps(action, getter) { 3696 if (!action.observers) return; 3697 var preAction = avalon.trackingAction; 3698 if (preAction) { 3699 targetStack.push(preAction); 3700 } 3701 avalon.trackingAction = action; 3702 avalon.track('ãactionã', action.type, action.expr, 'å¼å§å¾æ¶ä¾èµé¡¹'); 3703 //å¤ä¸ªobserveææåä¸ä¸ªaction 3704 action.mapIDs = {}; //éæ°æ¶éä¾èµ 3705 var hasError = true, 3706 result; 3707 try { 3708 result = getter.call(action); 3709 hasError = false; 3710 } finally { 3711 if (hasError) { 3712 avalon.warn('collectDeps fail', getter + ''); 3713 action.mapIDs = {}; 3714 avalon.trackingAction = preAction; 3715 } else { 3716 // 确ä¿å®æ»æ¯ä¸ºnull 3717 avalon.trackingAction = targetStack.pop(); 3718 try { 3719 resetDeps(action); 3720 } catch (e) { 3721 avalon.warn(e); 3722 } 3723 } 3724 return result; 3725 } 3726 } 3727 3728 function resetDeps(action) { 3729 var prev = action.observers, 3730 curr = [], 3731 checked = {}, 3732 ids = []; 3733 for (var i in action.mapIDs) { 3734 var dep = action.mapIDs[i]; 3735 if (!dep.isAction) { 3736 if (!dep.observers) { 3737 //妿å®å·²ç»è¢«éæ¯ 3738 delete action.mapIDs[i]; 3739 continue; 3740 } 3741 ids.push(dep.uuid);
3742 curr.push(dep); 3743 checked[dep.uuid] = 1; 3744 if (dep.lastAccessedBy === action.uuid) { 3745 continue; 3746 } 3747 dep.lastAccessedBy = action.uuid; 3748 avalon.Array.ensure(dep.observers, action); 3749 } 3750 } 3751 var ids = ids.sort().join(','); 3752 if (ids === action.ids) { 3753 return; 3754 } 3755 action.ids = ids; 3756 if (!action.isComputed) { 3757 action.observers = curr; 3758 } else { 3759 action.depsCount = curr.length; 3760 action.deps = avalon.mix({}, action.mapIDs); 3761 action.depsVersion = {}; 3762 for (var _i in action.mapIDs) { 3763 var _dep = action.mapIDs[_i]; 3764 action.depsVersion[_dep.uuid] = _dep.version; 3765 } 3766 } 3767 3768 for (var _i2 = 0, _dep2; _dep2 = prev[_i2++];) { 3769 if (!checked[_dep2.uuid]) { 3770 avalon.Array.remove(_dep2.observers, action); 3771 } 3772 } 3773 } 3774 3775 function transaction(action, thisArg, args) { 3776 args = args || []; 3777 var name = 'transaction ' + (action.name || action.displayName || 'noop'); 3778 transactionStart(name); 3779 var res = action.apply(thisArg, args); 3780 transactionEnd(name); 3781 return res; 3782 } 3783 avalon.transaction = transaction; 3784 3785 function transactionStart(name) { 3786 avalon.inTransaction += 1; 3787 } 3788 3789 function transactionEnd(name) { 3790 if (--avalon.inTransaction === 0) { 3791 avalon.isRunningActions = false; 3792 runActions(); 3793 } 3794 } 3795 3796 /* 3797 * å°è¦æ£æµçå符串çåç¬¦ä¸²æ¿æ¢æ??123è¿æ ·çæ ¼å¼ 3798 */ 3799 var stringNum = 0; 3800 var stringPool = { 3801 map: {} 3802 }; 3803 var rfill = /\?\?\d+/g; 3804 function dig(a) { 3805 var key = '??' + stringNum++; 3806 stringPool.map[key] = a; 3807 return key + ' '; 3808 } 3809 function fill(a) { 3810 var val = stringPool.map[a]; 3811 return val; 3812 } 3813 function clearString(str) { 3814 var array = readString(str); 3815 for (var i = 0, n = array.length; i < n; i++) { 3816 str = str.replace(array[i], dig); 3817 } 3818 return str; 3819 } 3820 //https://github.com/RubyLouvre/avalon/issues/1944 3821 function readString(str, i, ret) { 3822 var end = false, 3823 s = 0, 3824 i = i || 0; 3825 ret = ret || []; 3826 for (var n = str.length; i < n; i++) { 3827 var c = str.charAt(i); 3828 if (!end) { 3829 if (c === "'") { 3830 end = "'"; 3831 s = i; 3832 } else if (c === '"') { 3833 end = '"'; 3834 s = i; 3835 } 3836 } else { 3837 if (c === end) { 3838 ret.push(str.slice(s, i + 1)); 3839 end = false; 3840 } 3841 } 3842 } 3843 if (end !== false) { 3844 return readString(str, s + 1, ret); 3845 } 3846 return ret; 3847 } 3848 3849 var keyMap = avalon.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," + /* å ³é®å*/ 3850 "abstract,boolean,byte,char,class,const,double,enum,export,extends," + "final,float,goto,implements,import,int,interface,long,native," + "package,private,protected,public,short,static,super,synchronized," + "throws,transient,volatile,arguments"); 3851 3852 var skipMap = avalon.mix({ 3853 Math: 1, 3854 Date: 1, 3855 $event: 1, 3856 window: 1, 3857 __vmodel__: 1, 3858 avalon: 1 3859 }, keyMap); 3860 3861 var rvmKey = /(^|[^\w\u00c0-\uFFFF_])(@|##)(?=[$\w])/g; 3862 var ruselessSp = /\s*(\.|\|)\s*/g; 3863 var rshortCircuit = /\|\|/g; 3864 var brackets = /\(([^)]*)\)/; 3865 var rpipeline = /\|(?=\?\?)/; 3866 var rregexp = /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/g; 3867 var robjectProp = /\.[\w\.\$]+/g; //对象ç屿§ el.xxx ä¸çxxx 3868 var robjectKey = /(\{|\,)\s*([\$\w]+)\s*:/g; //对象çé®åä¸åå· {xxx:1,yyy: 2}ä¸çxxx, yyy 3869 var rfilterName = /\|(\w+)/g; 3870 var rlocalVar = /[$a-zA-Z_][$a-zA-Z0-9_]*/g; 3871 3872 var exprCache = new Cache(300); 3873 3874 function addScopeForLocal(str) { 3875 return str.replace(robjectProp, dig).replace(rlocalVar, function (el) { 3876 if (!skipMap[el]) { 3877 return "__vmodel__." + el; 3878 } 3879 return el; 3880 }); 3881 } 3882 3883 function addScope(expr, type) { 3884 var cacheKey = expr + ':' + type; 3885 var cache = exprCache.get(cacheKey); 3886 if (cache) { 3887 return cache.slice(0); 3888 } 3889
3890 stringPool.map = {}; 3891 //https://github.com/RubyLouvre/avalon/issues/1849 3892 var input = expr.replace(rregexp, function (a, b) { 3893 return b + dig(a.slice(b.length)); 3894 }); //ç§»é¤æææ£å 3895 input = clearString(input); //ç§»é¤ææå符串 3896 input = input.replace(rshortCircuit, dig). //ç§»é¤ææçè·¯è¿ç®ç¬¦ 3897 replace(ruselessSp, '$1'). //ç§»é¤.|ä¸¤ç«¯ç©ºç½ 3898 3899 replace(robjectKey, function (_, a, b) { 3900 //ç§»é¤ææé®å 3901 return a + dig(b) + ':'; //æ¯å¦ ms-widget="[{is:'ms-address-wrap', $id:'address'}]"è¿æ ·æç«¯çæ åµ 3902 }).replace(rvmKey, '$1__vmodel__.'). //转æ¢@ä¸##为__vmodel__ 3903 replace(rfilterName, function (a, b) { 3904 //ç§»é¤ææè¿æ»¤å¨çåå 3905 return '|' + dig(b); 3906 }); 3907 input = addScopeForLocal(input); //卿¬å°åéåæ·»å __vmodel__ 3908 3909 var filters = input.split(rpipeline); //æ ¹æ®ç®¡é符åå²è¡¨è¾¾å¼ 3910 var body = filters.shift().replace(rfill, fill).trim(); 3911 if (/\?\?\d/.test(body)) { 3912 body = body.replace(rfill, fill); 3913 } 3914 if (filters.length) { 3915 filters = filters.map(function (filter) { 3916 var bracketArgs = ''; 3917 filter = filter.replace(brackets, function (a, b) { 3918 if (/\S/.test(b)) { 3919 bracketArgs += ',' + b; //è¿åå符串,æ£å,çè·¯è¿ç®ç¬¦ 3920 } 3921 return ''; 3922 }); 3923 var arg = '[' + avalon.quote(filter.trim()) + bracketArgs + ']'; 3924 return arg; 3925 }); 3926 filters = 'avalon.composeFilters(' + filters + ')(__value__)'; 3927 filters = filters.replace(rfill, fill); 3928 } else { 3929 filters = ''; 3930 } 3931 return exprCache.put(cacheKey, [body, filters]); 3932 } 3933 var rhandleName = /^__vmodel__\.[$\w\.]+$/; 3934 var rfixIE678 = /__vmodel__\.([^(]+)\(([^)]*)\)/; 3935 function makeHandle(body) { 3936 if (rhandleName.test(body)) { 3937 body = body + '($event)'; 3938 } 3939 /* istanbul ignore if */ 3940 if (msie < 9) { 3941 body = body.replace(rfixIE678, function (a, b, c) { 3942 return '__vmodel__.' + b + '.call(__vmodel__' + (/\S/.test(c) ? ',' + c : '') + ')'; 3943 }); 3944 } 3945 return body; 3946 } 3947 function createGetter(expr, type) { 3948 var arr = addScope(expr, type), 3949 body; 3950 if (!arr[1]) { 3951 body = arr[0]; 3952 } else { 3953 body = arr[1].replace(/__value__\)$/, arr[0] + ')'); 3954 } 3955 try { 3956 return new Function('__vmodel__', 'return ' + body + ';'); 3957 /* istanbul ignore next */ 3958 } catch (e) { 3959 avalon.log('parse getter: [', expr, body, ']error'); 3960 return avalon.noop; 3961 } 3962 } 3963 3964 /** 3965 * çæè¡¨è¾¾å¼è®¾å¼å½æ° 3966 * @param {String} expr 3967 */ 3968 function createSetter(expr, type) { 3969 var arr = addScope(expr, type); 3970 var body = 'try{ ' + arr[0] + ' = __value__}catch(e){avalon.log(e, "in on dir")}'; 3971 try { 3972 return new Function('__vmodel__', '__value__', body + ';'); 3973 /* istanbul ignore next */ 3974 } catch (e) { 3975 avalon.log('parse setter: ', expr, ' error'); 3976 return avalon.noop; 3977 } 3978 } 3979 3980 var actionUUID = 1; 3981 //éè¦éæ 3982 function Action(vm, options, callback) { 3983 for (var i in options) { 3984 if (protectedMenbers[i] !== 1) { 3985 this[i] = options[i]; 3986 } 3987 } 3988 3989 this.vm = vm; 3990 this.observers = []; 3991 this.callback = callback; 3992 this.uuid = ++actionUUID; 3993 this.ids = ''; 3994 this.mapIDs = {}; //è¿ä¸ªç¨äºå»é 3995 this.isAction = true; 3996 var expr = this.expr; 3997 // ç¼ååå¼å½æ° 3998 if (typeof this.getter !== 'function') { 3999 this.getter = createGetter(expr, this.type); 4000 } 4001 // ç¼å设å¼å½æ°ï¼ååæ°æ®ç»å®ï¼
4002 if (this.type === 'duplex') { 4003 this.setter = createSetter(expr, this.type); 4004 } 4005 // ç¼åè¡¨è¾¾å¼æ§å¼ 4006 this.value = NaN; 4007 // 表达å¼åå§å¼ & æåä¾èµ 4008 if (!this.node) { 4009 this.value = this.get(); 4010 } 4011 } 4012 4013 Action.prototype = { 4014 getValue: function getValue() { 4015 var scope = this.vm; 4016 try { 4017 return this.getter.call(scope, scope); 4018 } catch (e) { 4019 avalon.log(this.getter + ' exec error'); 4020 } 4021 }, 4022 setValue: function setValue(value) { 4023 var scope = this.vm; 4024 if (this.setter) { 4025 this.setter.call(scope, scope, value); 4026 } 4027 }, 4028 4029 4030 // get --> getValue --> getter 4031 get: function get(fn) { 4032 var name = 'action track ' + this.type; 4033 4034 if (this.deep) { 4035 avalon.deepCollect = true; 4036 } 4037 4038 var value = collectDeps(this, this.getValue); 4039 if (this.deep && avalon.deepCollect) { 4040 avalon.deepCollect = false; 4041 } 4042 4043 return value; 4044 }, 4045 4046 4047 /** 4048 * 卿´æ°è§å¾åä¿ååæçvalue 4049 */ 4050 beforeUpdate: function beforeUpdate() { 4051 return this.oldValue = getPlainObject(this.value); 4052 }, 4053 update: function update(args, uuid) { 4054 var oldVal = this.beforeUpdate(); 4055 var newVal = this.value = this.get(); 4056 var callback = this.callback; 4057 if (callback && this.diff(newVal, oldVal, args)) { 4058 callback.call(this.vm, this.value, oldVal, this.expr); 4059 } 4060 this._isScheduled = false; 4061 }, 4062 schedule: function schedule() { 4063 if (!this._isScheduled) { 4064 this._isScheduled = true; 4065 if (!avalon.uniqActions[this.uuid]) { 4066 avalon.uniqActions[this.uuid] = 1; 4067 avalon.pendingActions.push(this); 4068 } 4069 4070 runActions(); //è¿éä¼è¿å_isScheduled 4071 4072 } 4073 }, 4074 removeDepends: function removeDepends() { 4075 var self = this; 4076 this.observers.forEach(function (depend) { 4077 avalon.Array.remove(depend.observers, self); 4078 }); 4079 }, 4080 4081 4082 /** 4083 * æ¯è¾ä¸¤ä¸ªè®¡ç®å¼æ¯å¦,ä¸è´,å¨for, classçè½å¤ææ°æ®ç±»åçæä»¤ä¸,å®ä»¬ä¼éådiff夿³ 4084 */ 4085 diff: function diff(a, b) { 4086 return a !== b; 4087 }, 4088 4089 4090 /** 4091 * 鿝æä»¤ 4092 */ 4093 dispose: function dispose() { 4094 this.value = null; 4095 this.removeDepends(); 4096 if (this.beforeDispose) { 4097 this.beforeDispose(); 4098 } 4099 for (var i in this) { 4100 delete this[i]; 4101 } 4102 } 4103 }; 4104 4105 function getPlainObject(v) { 4106 if (v && typeof v === 'object') { 4107 if (v && v.$events) { 4108 return v.$model; 4109 } else if (Array.isArray(v)) { 4110 var ret = []; 4111 for (var i = 0, n = v.length; i < n; i++) { 4112 ret.push(getPlainObject(v[i])); 4113 } 4114 return ret; 4115 } else { 4116 var _ret = {}; 4117 for (var _i3 in v) { 4118 _ret[_i3] = getPlainObject(v[_i3]); 4119 } 4120 return _ret; 4121 } 4122 } else { 4123 return v; 4124 } 4125 } 4126 4127 var protectedMenbers = { 4128 vm: 1, 4129 callback: 1, 4130 4131 observers: 1, 4132 oldValue: 1, 4133 value: 1, 4134 getValue: 1, 4135 setValue: 1, 4136 get: 1, 4137 4138 removeDepends: 1, 4139 beforeUpdate: 1, 4140 update: 1, 4141 //diff 4142 //getter 4143 //setter 4144 //expr 4145 //vdom 4146 //type: "for" 4147 //name: "ms-for" 4148 //attrName: ":for" 4149 //param: "click" 4150 //beforeDispose 4151 dispose: 1 4152 }; 4153 4154 /** 4155 * 4156 ä¸Computedçå ±äº«UUID 4157 */ 4158 var obid = 1; 4159 function Mutation(expr, value, vm) { 4160 //æé 彿° 4161 this.expr = expr; 4162 if (value) { 4163 var childVm = platform.createProxy(value, this); 4164 if (childVm) { 4165 value = childVm; 4166 } 4167 } 4168 this.value = value; 4169 this.vm = vm; 4170 try { 4171 vm.$mutations[expr] = this; 4172 } catch (ignoreIE) {} 4173 this.uuid = ++obid; 4174 this.updateVersion(); 4175 this.mapIDs = {}; 4176 this.observers = []; 4177 } 4178 4179 Mutation.prototype = { 4180 get: function get() { 4181 if (avalon.trackingAction) { 4182 this.collect(); //被æ¶é 4183 var childOb = this.value; 4184 if (childOb && childOb.$events) { 4185 if (Array.isArray(childOb)) { 4186 childOb.forEach(function (item) { 4187 if (item && item.$events) { 4188 item.$events.__dep__.collect(); 4189 } 4190 }); 4191 } else if (avalon.deepCollect) { 4192 for (var key in childOb) { 4193 if (childOb.hasOwnProperty(key)) { 4194 var collectIt = childOb[key]; 4195 } 4196 } 4197 } 4198 } 4199 } 4200 return this.value; 4201 }, 4202 collect: function collect() { 4203 avalon.track(name, '被æ¶é'); 4204 reportObserved(this); 4205 }, 4206 updateVersion: function updateVersion() { 4207 this.version = Math.random() + Math.random(); 4208 }, 4209 notify: function notify() { 4210 transactionStart(); 4211 propagateChanged(this); 4212 transactionEnd(); 4213 }, 4214 set: function set(newValue) { 4215 var oldValue = this.value; 4216 if (newValue !== oldValue) { 4217 if (avalon.isObject(newValue)) { 4218 var hash = oldValue && oldValue.$hashcode; 4219 var childVM = platform.createProxy(newValue, this); 4220 if (childVM) { 4221 if (hash) { 4222 childVM.$hashcode = hash; 4223 } 4224 newValue = childVM; 4225 } 4226 } 4227 this.value = newValue; 4228 this.updateVersion(); 4229 this.notify(); 4230 } 4231 } 4232 }; 4233 4234 function getBody(fn) { 4235 var entire = fn.toString(); 4236 return entire.substring(entire.indexOf('{}') + 1, entire.lastIndexOf('}')); 4237 } 4238 //妿ä¸åå¨ä¸ç®,if,æ¹æ³ 4239 var instability = /(\?|if\b|\(.+\))/; 4240 4241 function __create(o) { 4242 var __ = function __() {}; 4243 __.prototype = o; 4244 return new __(); 4245 } 4246 4247 function __extends(child, parent) { 4248 if (typeof parent === 'function') { 4249 var proto = child.prototype = __create(parent.prototype); 4250 proto.constructor = child; 4251 } 4252 } 4253 var Computed = function (_super) { 4254 __extends(Computed, _super); 4255 4256 function Computed(name, options, vm) { 4257 //æé 彿° 4258 _super.call(this, name, undefined, vm); 4259 delete options.get; 4260 delete options.set; 4261 4262 avalon.mix(this, options); 4263 this.deps = {}; 4264 this.type = 'computed'; 4265 this.depsVersion = {}; 4266 this.isComputed = true; 4267 this.trackAndCompute(); 4268 if (!('isStable' in this)) { 4269 this.isStable = !instability.test(getBody(this.getter)); 4270 } 4271 } 4272 var cp = Computed.prototype; 4273 cp.trackAndCompute = function () { 4274 if (this.isStable && this.depsCount > 0) { 4275 this.getValue(); 4276 } else { 4277 collectDeps(this, this.getValue.bind(this)); 4278 } 4279 }; 4280 4281 cp.getValue = function () { 4282 return this.value = this.getter.call(this.vm); 4283 }; 4284 4285 cp.schedule = function () { 4286 var observers = this.observers; 4287 var i = observers.length; 4288 while (i--) { 4289 var d = observers[i]; 4290 if (d.schedule) { 4291 d.schedule(); 4292 } 4293 } 4294 }; 4295 4296 cp.shouldCompute = function () { 4297 if (this.isStable) { 4298 //妿åå¨å åç¡®å®,é£ä¹åªæ¯è¾åå¨å åççæ¬ 4299 var toComputed = false;
4300 for (var i in this.deps) { 4301 if (this.deps[i].version !== this.depsVersion[i]) { 4302 toComputed = true; 4303 this.deps[i].version = this.depsVersion[i]; 4304 } 4305 } 4306 return toComputed; 4307 } 4308 return true; 4309 }; 4310 cp.set = function () { 4311 if (this.setter) { 4312 avalon.transaction(this.setter, this.vm, arguments); 4313 } 4314 }; 4315 cp.get = function () { 4316 4317 //å½è¢«è®¾ç½®äºå°±ä¸ç¨³å®,å½å®è¢«è®¿é®äºä¸æ¬¡å°±æ¯ç¨³å® 4318 this.collect(); 4319 4320 if (this.shouldCompute()) { 4321 this.trackAndCompute(); 4322 // console.log('computed 2 忝') 4323 this.updateVersion(); 4324 // this.reportChanged() 4325 } 4326 4327 //ä¸é¢è¿ä¸è¡å¥½åæ²¡ç¨ 4328 return this.value; 4329 }; 4330 return Computed; 4331 }(Mutation); 4332 4333 /** 4334 * è¿éæ¾ç½®ViewModel模åçå ±ç¨æ¹æ³ 4335 * avalon.define: å ¨æ¡æ¶æéè¦çæ¹æ³,çæç¨æ·VM 4336 * IProxy, åºæ¬ç¨æ·æ°æ®äº§ççä¸ä¸ªæ°æ®å¯¹è±¡,åºäº$modelä¸vmodelä¹é´çå½¢æ 4337 * modelFactory: çæç¨æ·VM 4338 * canHijack: å¤å®æ¤å±æ§æ¯å¦è¯¥è¢«å«æ,å å ¥æ°æ®çå¬ä¸ååççé»è¾ 4339 * createProxy: listFactoryä¸modelFactoryçå°è£ 4340 * createAccessor: å®ç°æ°æ®çå¬ä¸ååçéè¦å¯¹è±¡ 4341 * itemFactory: ms-for循ç¯ä¸äº§çç代çVMççæå·¥å 4342 * fuseFactory: 两个ms-controlleré´äº§çç代çVMççæå·¥å 4343 */ 4344 4345 avalon.define = function (definition) { 4346 var $id = definition.$id; 4347 if (!$id) { 4348 avalon.error('vm.$id must be specified'); 4349 } 4350 if (avalon.vmodels[$id]) { 4351 avalon.warn('error:[' + $id + '] had defined!'); 4352 } 4353 var vm = platform.modelFactory(definition); 4354 return avalon.vmodels[$id] = vm; 4355 }; 4356 4357 /** 4358 * 卿ªæ¥ççæ¬,avalonæ¹ç¨Proxyæ¥å建VM,å æ¤ 4359 */ 4360 4361 function IProxy(definition, dd) { 4362 avalon.mix(this, definition); 4363 avalon.mix(this, $$skipArray); 4364 this.$hashcode = avalon.makeHashCode('$'); 4365 this.$id = this.$id || this.$hashcode; 4366 this.$events = { 4367 __dep__: dd || new Mutation(this.$id) 4368 }; 4369 if (avalon.config.inProxyMode) { 4370 delete this.$mutations; 4371 this.$accessors = {}; 4372 this.$computed = {}; 4373 this.$track = ''; 4374 } else { 4375 this.$accessors = { 4376 $model: modelAccessor 4377 }; 4378 } 4379 if (dd === void 0) { 4380 this.$watch = platform.watchFactory(this.$events); 4381 this.$fire = platform.fireFactory(this.$events); 4382 } else { 4383 delete this.$watch; 4384 delete this.$fire; 4385 } 4386 } 4387 4388 platform.modelFactory = function modelFactory(definition, dd) { 4389 var $computed = definition.$computed || {}; 4390 delete definition.$computed; 4391 var core = new IProxy(definition, dd); 4392 var $accessors = core.$accessors; 4393 var keys = []; 4394 4395 platform.hideProperty(core, '$mutations', {}); 4396 4397 for (var key in definition) { 4398 if (key in $$skipArray) continue; 4399 var val = definition[key]; 4400 keys.push(key); 4401 if (canHijack(key, val)) { 4402 $accessors[key] = createAccessor(key, val); 4403 } 4404 } 4405 for (var _key in $computed) { 4406 if (_key in $$skipArray) continue; 4407 var val = $computed[_key]; 4408 if (typeof val === 'function') { 4409 val = { 4410 get: val 4411 }; 4412 } 4413 if (val && val.get) { 4414 val.getter = val.get; 4415 val.setter = val.set; 4416 avalon.Array.ensure(keys, _key); 4417 $accessors[_key] = createAccessor(_key, val, true); 4418 } 4419 } 4420 //å°ç³»ç»API以unenumerableå½¢å¼å å ¥vm, 4421 //æ·»å ç¨æ·çå ¶ä»ä¸å¯çå¬å±æ§ææ¹æ³ 4422 //éå$track 4423 //å¹¶å¨IE6-8ä¸å¢æ·»å ä¸åå¨çhasOwnPropertæ¹æ³ 4424 var vm = platform.createViewModel(core, $accessors, core); 4425 platform.afterCreate(vm, core, keys, !dd); 4426 return vm; 4427 }; 4428 var $proxyItemBackdoorMap = {}; 4429 4430 function canHijack(key, val, $proxyItemBackdoor) { 4431 if (key in $$skipArray) return false;
4432 if (key.charAt(0) === '$') { 4433 if ($proxyItemBackdoor) { 4434 if (!$proxyItemBackdoorMap[key]) { 4435 $proxyItemBackdoorMap[key] = 1; 4436 avalon.warn('ms-for\u4E2D\u7684\u53D8\u91CF' + key + '\u4E0D\u518D\u5EFA\u8BAE\u4EE5$\u4E3A\u524D\u7F00'); 4437 } 4438 return true; 4439 } 4440 return false; 4441 } 4442 if (val == null) { 4443 avalon.warn('å®ä¹vmodelæ¶' + key + 'ç屿§å¼ä¸è½ä¸ºnull undefine'); 4444 return true; 4445 } 4446 if (/error|date|function|regexp/.test(avalon.type(val))) { 4447 return false; 4448 } 4449 return !(val && val.nodeName && val.nodeType); 4450 } 4451 4452 function createProxy(target, dd) { 4453 if (target && target.$events) { 4454 return target; 4455 } 4456 var vm; 4457 if (Array.isArray(target)) { 4458 vm = platform.listFactory(target, false, dd); 4459 } else if (isObject(target)) { 4460 vm = platform.modelFactory(target, dd); 4461 } 4462 return vm; 4463 } 4464 4465 platform.createProxy = createProxy; 4466 4467 platform.itemFactory = function itemFactory(before, after) { 4468 var keyMap = before.$model; 4469 var core = new IProxy(keyMap); 4470 var state = avalon.shadowCopy(core.$accessors, before.$accessors); //鲿¢äºç¸æ±¡æ 4471 var data = after.data; 4472 //coreæ¯å å«ç³»ç»å±æ§ç对象 4473 //keyMapæ¯ä¸å å«ç³»ç»å±æ§ç对象, keys 4474 for (var key in data) { 4475 var val = keyMap[key] = core[key] = data[key]; 4476 state[key] = createAccessor(key, val); 4477 } 4478 var keys = Object.keys(keyMap); 4479 var vm = platform.createViewModel(core, state, core); 4480 platform.afterCreate(vm, core, keys); 4481 return vm; 4482 }; 4483 4484 function createAccessor(key, val, isComputed) { 4485 var mutation = null; 4486 var Accessor = isComputed ? Computed : Mutation; 4487 return { 4488 get: function Getter() { 4489 if (!mutation) { 4490 mutation = new Accessor(key, val, this); 4491 } 4492 return mutation.get(); 4493 }, 4494 set: function Setter(newValue) { 4495 if (!mutation) { 4496 mutation = new Accessor(key, val, this); 4497 } 4498 mutation.set(newValue); 4499 }, 4500 enumerable: true, 4501 configurable: true 4502 }; 4503 } 4504 4505 platform.fuseFactory = function fuseFactory(before, after) { 4506 var keyMap = avalon.mix(before.$model, after.$model); 4507 var core = new IProxy(avalon.mix(keyMap, { 4508 $id: before.$id + after.$id 4509 })); 4510 var state = avalon.mix(core.$accessors, before.$accessors, after.$accessors); //鲿¢äºç¸æ±¡æ 4511 4512 var keys = Object.keys(keyMap); 4513 //å°ç³»ç»API以unenumerableå½¢å¼å å ¥vm,å¹¶å¨IE6-8䏿·»å hasOwnPropertæ¹æ³ 4514 var vm = platform.createViewModel(core, state, core); 4515 platform.afterCreate(vm, core, keys, false); 4516 return vm; 4517 }; 4518 4519 function toJson(val) { 4520 var xtype = avalon.type(val); 4521 if (xtype === 'array') { 4522 var array = []; 4523 for (var i = 0; i < val.length; i++) { 4524 array[i] = toJson(val[i]); 4525 } 4526 return array; 4527 } else if (xtype === 'object') { 4528 if (typeof val.$track === 'string') { 4529 var obj = {}; 4530 var arr = val.$track.match(/[^â¥]+/g) || []; 4531 arr.forEach(function (i) { 4532 var value = val[i]; 4533 obj[i] = value && value.$events ? toJson(value) : value; 4534 }); 4535 return obj; 4536 } 4537 } 4538 return val; 4539 } 4540 4541 var modelAccessor = { 4542 get: function get() { 4543 return toJson(this); 4544 }, 4545 set: avalon.noop, 4546 enumerable: false, 4547 configurable: true 4548 }; 4549 4550 platform.toJson = toJson; 4551 platform.modelAccessor = modelAccessor; 4552 4553 var _splice = ap.splice; 4554 var __array__ = { 4555 set: function set(index, val) { 4556 if (index >>> 0 === index && this[index] !== val) { 4557 if (index > this.length) { 4558 throw Error(index + 'setæ¹æ³ç第ä¸ä¸ªåæ°ä¸è½å¤§äºåæ°ç»é¿åº¦'); 4559 } 4560 this.splice(index, 1, val); 4561 } 4562 }, 4563 toJSON: function toJSON() { 4564 //为äºè§£å³IE6-8çè§£å³,éè¿æ¤æ¹æ³æ¾å¼å°æ±åæ°ç»ç$model 4565 return this.$model = platform.toJson(this); 4566 }, 4567 contains: function contains(el) { 4568 //å¤å®æ¯å¦å å« 4569 return this.indexOf(el) !== -1; 4570 }, 4571 ensure: function ensure(el) { 4572 if (!this.contains(el)) { 4573 //åªæä¸å卿push 4574 this.push(el); 4575 return true; 4576 } 4577 return false;
4578 }, 4579 pushArray: function pushArray(arr) { 4580 return this.push.apply(this, arr); 4581 }, 4582 remove: function remove(el) { 4583 //ç§»é¤ç¬¬ä¸ä¸ªçäºç»å®å¼çå ç´ 4584 return this.removeAt(this.indexOf(el)); 4585 }, 4586 removeAt: function removeAt(index) { 4587 //ç§»é¤æå®ç´¢å¼ä¸çå ç´ 4588 if (index >>> 0 === index) { 4589 return this.splice(index, 1); 4590 } 4591 return []; 4592 }, 4593 clear: function clear() { 4594 this.removeAll(); 4595 return this; 4596 }, 4597 removeAll: function removeAll(all) { 4598 //ç§»é¤N个å ç´ 4599 var size = this.length; 4600 var eliminate = Array.isArray(all) ? function (el) { 4601 return all.indexOf(el) !== -1; 4602 } : typeof all === 'function' ? all : false; 4603 4604 if (eliminate) { 4605 for (var i = this.length - 1; i >= 0; i--) { 4606 if (eliminate(this[i], i)) { 4607 _splice.call(this, i, 1); 4608 } 4609 } 4610 } else { 4611 _splice.call(this, 0, this.length); 4612 } 4613 this.toJSON(); 4614 this.$events.__dep__.notify(); 4615 } 4616 }; 4617 function hijackMethods(array) { 4618 for (var i in __array__) { 4619 platform.hideProperty(array, i, __array__[i]); 4620 } 4621 } 4622 var __method__ = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']; 4623 4624 __method__.forEach(function (method) { 4625 var original = ap[method]; 4626 __array__[method] = function () { 4627 // ç»§ç»å°è¯å«ææ°ç»å ç´ ç屿§ 4628 var core = this.$events; 4629 4630 var args = platform.listFactory(arguments, true, core.__dep__); 4631 var result = original.apply(this, args); 4632 4633 this.toJSON(); 4634 core.__dep__.notify(method); 4635 return result; 4636 }; 4637 }); 4638 4639 function listFactory(array, stop, dd) { 4640 if (!stop) { 4641 hijackMethods(array); 4642 if (modern) { 4643 Object.defineProperty(array, '$model', platform.modelAccessor); 4644 } 4645 platform.hideProperty(array, '$hashcode', avalon.makeHashCode('$')); 4646 platform.hideProperty(array, '$events', { __dep__: dd || new Mutation() }); 4647 } 4648 var _dd = array.$events && array.$events.__dep__; 4649 for (var i = 0, n = array.length; i < n; i++) { 4650 var item = array[i]; 4651 if (isObject(item)) { 4652 array[i] = platform.createProxy(item, _dd); 4653 } 4654 } 4655 return array; 4656 } 4657 4658 platform.listFactory = listFactory; 4659 4660 //妿æµè§å¨ä¸æ¯æecma262v5çObject.definePropertiesæè åå¨BUGï¼æ¯å¦IE8 4661 //æ åæµè§å¨ä½¿ç¨__defineGetter__, __defineSetter__å®ç° 4662 var canHideProperty = true; 4663 try { 4664 Object.defineProperty({}, '_', { 4665 value: 'x' 4666 }); 4667 delete $$skipArray.$vbsetter; 4668 delete $$skipArray.$vbthis; 4669 } catch (e) { 4670 /* istanbul ignore next*/ 4671 canHideProperty = false; 4672 } 4673 4674 var protectedVB = { $vbthis: 1, $vbsetter: 1 }; 4675 /* istanbul ignore next */ 4676 function hideProperty(host, name, value) { 4677 if (canHideProperty) { 4678 Object.defineProperty(host, name, { 4679 value: value, 4680 writable: true, 4681 enumerable: false, 4682 configurable: true 4683 }); 4684 } else if (!protectedVB[name]) { 4685 /* istanbul ignore next */ 4686 host[name] = value; 4687 } 4688 } 4689 4690 function watchFactory(core) { 4691 return function $watch(expr, callback, deep) { 4692 var w = new Action(core.__proxy__, { 4693 deep: deep, 4694 type: 'user', 4695 expr: expr 4696 }, callback); 4697 if (!core[expr]) { 4698 core[expr] = [w]; 4699 } else { 4700 core[expr].push(w); 4701 } 4702 4703 return function () { 4704 w.dispose(); 4705 avalon.Array.remove(core[expr], w); 4706 if (core[expr].length === 0) { 4707 delete core[expr]; 4708 } 4709 }; 4710 }; 4711 } 4712 4713 function fireFactory(core) { 4714 return function $fire(expr, a) { 4715 var list = core[expr]; 4716 if (Array.isArray(list)) { 4717 for (var i = 0, w; w = list[i++];) { 4718 w.callback.call(w.vm, a, w.value, w.expr); 4719 } 4720 } 4721 }; 4722 } 4723 4724 function wrapIt(str) { 4725 return 'â¥' + str + 'â¥'; 4726 } 4727 4728 function afterCreate(vm, core, keys, bindThis) { 4729 var ac = vm.$accessors; 4730 //éèç³»ç»å±æ§ 4731 for (var key in $$skipArray) { 4732 if (avalon.msie < 9 && core[key] === void 0) continue; 4733 hideProperty(vm, key, core[key]); 4734 } 4735 //为ä¸å¯çå¬ç屿§ææ¹æ³èµå¼ 4736 for (var i = 0; i < keys.length; i++) { 4737 var _key2 = keys[i]; 4738 if (!(_key2 in ac)) { 4739 var val = core[_key2]; 4740 if (bindThis && typeof val === 'function') { 4741 vm[_key2] = val.bind(vm); 4742 vm[_key2]._orig = val; 4743 continue; 4744 } 4745 vm[_key2] = val; 4746 } 4747 } 4748 vm.$track = keys.join('â¥'); 4749 4750 function hasOwnKey(key) { 4751 return wrapIt(vm.$track).indexOf(wrapIt(key)) > -1; 4752 } 4753 if (avalon.msie < 9) { 4754 vm.hasOwnProperty = hasOwnKey; 4755 } 4756 vm.$events.__proxy__ = vm; 4757 } 4758 4759 platform.hideProperty = hideProperty; 4760 platform.fireFactory = fireFactory; 4761 platform.watchFactory = watchFactory; 4762 platform.afterCreate = afterCreate; 4763 4764 var createViewModel = Object.defineProperties; 4765 var defineProperty; 4766 4767 var timeBucket = new Date() - 0; 4768 /* istanbul ignore if*/ 4769 if (!canHideProperty) { 4770 if ('__defineGetter__' in avalon) { 4771 defineProperty = function defineProperty(obj, prop, desc) { 4772 if ('value' in desc) { 4773 obj[prop] = desc.value; 4774 } 4775 if ('get' in desc) { 4776 obj.__defineGetter__(prop, desc.get); 4777 } 4778 if ('set' in desc) { 4779 obj.__defineSetter__(prop, desc.set); 4780 } 4781 return obj; 4782 }; 4783 createViewModel = function createViewModel(obj, descs) { 4784 for (var prop in descs) { 4785 if (descs.hasOwnProperty(prop)) { 4786 defineProperty(obj, prop, descs[prop]); 4787 } 4788 } 4789 return obj; 4790 }; 4791 } 4792 /* istanbul ignore if*/ 4793 if (msie < 9) { 4794 var VBClassPool = {}; 4795 window.execScript([// jshint ignore:line 4796 'Function parseVB(code)', '\tExecuteGlobal(code)', 'End Function' //转æ¢ä¸æ®µææ¬ä¸ºVB代ç 4797 ].join('\n'), 'VBScript'); 4798 4799 var VBMediator = function VBMediator(instance, accessors, name, value) { 4800 // jshint ignore:line 4801 var accessor = accessors[name]; 4802 if (arguments.length === 4) { 4803 accessor.set.call(instance, value); 4804 } else { 4805 return accessor.get.call(instance); 4806 } 4807 }; 4808 createViewModel = function createViewModel(name, accessors, properties) { 4809 // jshint ignore:line 4810 var buffer = []; 4811 buffer.push('\tPrivate [$vbsetter]', '\tPublic [$accessors]', '\tPublic Default Function [$vbthis](ac' + timeBucket + ', s' + timeBucket + ')', '\t\tSet [$accessors] = ac' + timeBucket + ': set [$vbsetter] = s' + timeBucket, '\t\tSet [$vbthis] = Me', //é¾å¼è°ç¨ 4812 '\tEnd Function'); 4813 //æ·»å æ®é屿§,å 为VBScript对象ä¸è½åJS飿 ·éæå¢å 屿§ï¼å¿ é¡»å¨è¿éé¢å å®ä¹å¥½ 4814 var uniq = { 4815 $vbthis: true, 4816 $vbsetter: true, 4817 $accessors: true 4818 }; 4819 for (name in $$skipArray) { 4820 if (!uniq[name]) {
4821 buffer.push('\tPublic [' + name + ']'); 4822 uniq[name] = true; 4823 } 4824 } 4825 //æ·»å 访é®å¨å±æ§ 4826 for (name in accessors) { 4827 if (uniq[name]) { 4828 continue; 4829 } 4830 uniq[name] = true; 4831 buffer.push( 4832 //ç±äºä¸ç¥å¯¹æ¹ä¼ä¼ å ¥ä»ä¹,å æ¤set, leté½ç¨ä¸ 4833 '\tPublic Property Let [' + name + '](val' + timeBucket + ')', //setter 4834 '\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Set [' + name + '](val' + timeBucket + ')', //setter 4835 '\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Get [' + name + ']', //getter 4836 '\tOn Error Resume Next', //å¿ é¡»ä¼å 使ç¨setè¯å¥,å¦åå®ä¼è¯¯å°æ°ç»å½å符串è¿å 4837 '\t\tSet[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tIf Err.Number <> 0 Then', '\t\t[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tEnd If', '\tOn Error Goto 0', '\tEnd Property'); 4838 } 4839 4840 for (name in properties) { 4841 if (!uniq[name]) { 4842 uniq[name] = true; 4843 buffer.push('\tPublic [' + name + ']'); 4844 } 4845 } 4846 4847 buffer.push('\tPublic [hasOwnProperty]'); 4848 buffer.push('End Class'); 4849 var body = buffer.join('\r\n'); 4850 var className = VBClassPool[body]; 4851 if (!className) { 4852 className = avalon.makeHashCode('VBClass'); 4853 window.parseVB('Class ' + className + body); 4854 window.parseVB(['Function ' + className + 'Factory(acc, vbm)', //å建å®ä¾å¹¶ä¼ å ¥ä¸¤ä¸ªå ³é®çåæ° 4855 '\tDim o', '\tSet o = (New ' + className + ')(acc, vbm)', '\tSet ' + className + 'Factory = o', 'End Function'].join('\r\n')); 4856 VBClassPool[body] = className; 4857 } 4858 var ret = window[className + 'Factory'](accessors, VBMediator); //å¾å°å ¶äº§å 4859 return ret; //å¾å°å ¶äº§å 4860 }; 4861 } 4862 } 4863 4864 platform.createViewModel = createViewModel; 4865 4866 var impDir = avalon.directive('important', { 4867 priority: 1, 4868 getScope: function getScope(name, scope) { 4869 var v = avalon.vmodels[name]; 4870 if (v) return v; 4871 throw 'error! no vmodel called ' + name; 4872 }, 4873 update: function update(node, attrName, $id) { 4874 if (!avalon.inBrowser) return; 4875 var dom = avalon.vdom(node, 'toDOM'); 4876 if (dom.nodeType === 1) { 4877 dom.removeAttribute(attrName); 4878 avalon(dom).removeClass('ms-controller'); 4879 } 4880 var vm = avalon.vmodels[$id]; 4881 if (vm) { 4882 vm.$element = dom; 4883 vm.$render = this; 4884 vm.$fire('onReady'); 4885 delete vm.$events.onReady; 4886 } 4887 } 4888 }); 4889 4890 var impCb = impDir.update; 4891 4892 avalon.directive('controller', { 4893 priority: 2, 4894 getScope: function getScope(name, scope) { 4895 var v = avalon.vmodels[name]; 4896 if (v) { 4897 v.$render = this; 4898 if (scope && scope !== v) { 4899 return platform.fuseFactory(scope, v); 4900 } 4901 return v; 4902 } 4903 return scope; 4904 }, 4905 update: impCb 4906 }); 4907 4908 avalon.directive('skip', { 4909 delay: true 4910 }); 4911 4912 var arrayWarn = {}; 4913 var cssDir = avalon.directive('css', { 4914 diff: function diff(newVal, oldVal) { 4915 if (Object(newVal) === newVal) { 4916 newVal = platform.toJson(newVal); //å®å ¨çéåVBscript 4917 if (Array.isArray(newVal)) { 4918 //è½¬æ¢æå¯¹è±¡ 4919 var b = {}; 4920 newVal.forEach(function (el) { 4921 el && avalon.shadowCopy(b, el); 4922 }); 4923 newVal = b; 4924 if (!arrayWarn[this.type]) { 4925 avalon.warn('ms-' + this.type + 'æä»¤çå¼ä¸å»ºè®®ä½¿ç¨æ°ç»å½¢å¼äºï¼'); 4926 arrayWarn[this.type] = 1; 4927 } 4928 } 4929 4930 var hasChange = false;
4931 var patch = {}; 4932 if (!oldVal) { 4933 //妿ä¸å¼å§ä¸ºç©º 4934 patch = newVal; 4935 hasChange = true; 4936 } else { 4937 if (this.deep) { 4938 var deep = typeof this.deep === 'number' ? this.deep : 6; 4939 for (var i in newVal) { 4940 //diffå·®å¼ç¹ 4941 if (!deepEquals(newVal[i], oldVal[i], 4)) { 4942 this.value = newVal; 4943 return true; 4944 } 4945 patch[i] = newVal[i]; 4946 } 4947 } else { 4948 for (var _i4 in newVal) { 4949 //diffå·®å¼ç¹ 4950 if (newVal[_i4] !== oldVal[_i4]) { 4951 hasChange = true; 4952 } 4953 patch[_i4] = newVal[_i4]; 4954 } 4955 } 4956 4957 for (var _i5 in oldVal) { 4958 if (!(_i5 in patch)) { 4959 hasChange = true; 4960 patch[_i5] = ''; 4961 } 4962 } 4963 } 4964 if (hasChange) { 4965 this.value = patch; 4966 return true; 4967 } 4968 } 4969 return false; 4970 }, 4971 update: function update(vdom, value) { 4972 4973 var dom = vdom.dom; 4974 if (dom && dom.nodeType === 1) { 4975 var wrap = avalon(dom); 4976 for (var name in value) { 4977 wrap.css(name, value[name]); 4978 } 4979 } 4980 } 4981 }); 4982 4983 var cssDiff = cssDir.diff; 4984 4985 function getEnumerableKeys(obj) { 4986 var res = []; 4987 for (var key in obj) { 4988 res.push(key); 4989 }return res; 4990 } 4991 4992 function deepEquals(a, b, level) { 4993 if (level === 0) return a === b; 4994 if (a === null && b === null) return true; 4995 if (a === undefined && b === undefined) return true; 4996 var aIsArray = Array.isArray(a); 4997 if (aIsArray !== Array.isArray(b)) { 4998 return false; 4999 } 5000 if (aIsArray) { 5001 return equalArray(a, b, level); 5002 } else if (typeof a === "object" && typeof b === "object") { 5003 return equalObject(a, b, level); 5004 } 5005 return a === b; 5006 } 5007 5008 function equalArray(a, b, level) { 5009 if (a.length !== b.length) { 5010 return false; 5011 } 5012 for (var i = a.length - 1; i >= 0; i--) { 5013 try { 5014 if (!deepEquals(a[i], b[i], level - 1)) { 5015 return false; 5016 } 5017 } catch (noThisPropError) { 5018 return false; 5019 } 5020 } 5021 return true; 5022 } 5023 5024 function equalObject(a, b, level) { 5025 if (a === null || b === null) return false; 5026 if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length) return false; 5027 for (var prop in a) { 5028 if (!(prop in b)) return false; 5029 try { 5030 if (!deepEquals(a[prop], b[prop], level - 1)) { 5031 return false; 5032 } 5033 } catch (noThisPropError) { 5034 return false; 5035 } 5036 } 5037 return true; 5038 } 5039 5040 /** 5041 * ------------------------------------------------------------ 5042 * æ£æµæµè§å¨å¯¹CSSå¨ç»çæ¯æä¸APIå 5043 * ------------------------------------------------------------ 5044 */ 5045 5046 var checker = { 5047 TransitionEvent: 'transitionend', 5048 WebKitTransitionEvent: 'webkitTransitionEnd', 5049 OTransitionEvent: 'oTransitionEnd', 5050 otransitionEvent: 'otransitionEnd' 5051 }; 5052 var css3 = void 0; 5053 var tran = void 0; 5054 var ani = void 0; 5055 var name$2 = void 0; 5056 var animationEndEvent = void 0; 5057 var transitionEndEvent = void 0; 5058 var transition = false; 5059 var animation = false; 5060 //æçæµè§å¨åæ¶æ¯æç§æå®ç°ä¸æ ååæ³ï¼æ¯å¦webkitæ¯æå两ç§ï¼Operaæ¯æ1ã3ã4 5061 for (name$2 in checker) { 5062 if (window$1[name$2]) { 5063 tran = checker[name$2]; 5064 break; 5065 } 5066 /* istanbul ignore next */ 5067 try { 5068 var a = document.createEvent(name$2); 5069 tran = checker[name$2]; 5070 break; 5071 } catch (e) {} 5072 } 5073 if (typeof tran === 'string') { 5074 transition = css3 = true; 5075 transitionEndEvent = tran; 5076 } 5077 5078 //animationendæä¸¤ä¸ªå¯ç¨å½¢æ 5079 //IE10+, Firefox 16+ & Opera 12.1+: animationend 5080 //Chrome/Safari: webkitAnimationEnd 5081 //http://blogs.msdn.com/b/davrous/archive/2011/12/06/introduction-to-css3-animat ions.aspx 5082 //IE10ä¹å¯ä»¥ä½¿ç¨MSAnimationEndçå¬ï¼ä½æ¯åè°éçäºä»¶ typeä¾ç¶ä¸ºanimationend 5083 // el.addEventListener('MSAnimationEnd', function(e) { 5084 // alert(e.type)// animationendï¼ï¼ï¼ 5085 // }) 5086 checker = { 5087 'AnimationEvent': 'animationend', 5088 'WebKitAnimationEvent': 'webkitAnimationEnd' 5089 }; 5090 for (name$2 in checker) { 5091 if (window$1[name$2]) { 5092 ani = checker[name$2]; 5093 break; 5094 } 5095 } 5096 if (typeof ani === 'string') { 5097 animation = css3 = true; 5098 animationEndEvent = ani; 5099 } 5100 5101 var effectDir = avalon.directive('effect', { 5102 priority: 5, 5103 diff: function diff(effect) { 5104 var vdom = this.node; 5105 if (typeof effect === 'string') { 5106 this.value = effect = { 5107 is: effect 5108 }; 5109 avalon.warn('ms-effectçæä»¤å¼ä¸åæ¯æå符串,å¿ é¡»æ¯ä¸ä¸ªå¯¹è±¡'); 5110 } 5111 this.value = vdom.effect = effect; 5112 var ok = cssDiff.call(this, effect, this.oldValue); 5113 var me = this; 5114 if (ok) { 5115 setTimeout(function () { 5116 vdom.animating = true; 5117 effectDir.update.call(me, vdom, vdom.effect); 5118 }); 5119 vdom.animating = false;
5120 return true; 5121 } 5122 return false; 5123 }, 5124 5125 update: function update(vdom, change, opts) { 5126 var dom = vdom.dom; 5127 if (dom && dom.nodeType === 1) { 5128 //è¦æ±é ç½®å¯¹è±¡å¿ é¡»æå®is屿§ï¼actionå¿ é¡»æ¯å¸å°æenter,leave,move 5129 var option = change || opts; 5130 var is = option.is; 5131 5132 var globalOption = avalon.effects[is]; 5133 if (!globalOption) { 5134 //å¦ææ²¡æå®ä¹ç¹æ 5135 avalon.warn(is + ' effect is undefined'); 5136 return; 5137 } 5138 var finalOption = {}; 5139 var action = actionMaps[option.action]; 5140 if (typeof Effect.prototype[action] !== 'function') { 5141 avalon.warn('action is undefined'); 5142 return; 5143 } 5144 //å¿ é¡»é¢å®ä¹ç¹æ 5145 5146 var effect = new avalon.Effect(dom); 5147 avalon.mix(finalOption, globalOption, option, { action: action }); 5148 5149 if (finalOption.queue) { 5150 animationQueue.push(function () { 5151 effect[action](finalOption); 5152 }); 5153 callNextAnimation(); 5154 } else { 5155 5156 effect[action](finalOption); 5157 } 5158 return true; 5159 } 5160 } 5161 }); 5162 5163 var move = 'move'; 5164 var leave = 'leave'; 5165 var enter = 'enter'; 5166 var actionMaps = { 5167 'true': enter, 5168 'false': leave, 5169 enter: enter, 5170 leave: leave, 5171 move: move, 5172 'undefined': enter 5173 }; 5174 5175 var animationQueue = []; 5176 function callNextAnimation() { 5177 var fn = animationQueue[0]; 5178 if (fn) { 5179 fn(); 5180 } 5181 } 5182 5183 avalon.effects = {}; 5184 avalon.effect = function (name, opts) { 5185 var definition = avalon.effects[name] = opts || {}; 5186 if (css3 && definition.css !== false) { 5187 patchObject(definition, 'enterClass', name + '-enter'); 5188 patchObject(definition, 'enterActiveClass', definition.enterClass + '-active'); 5189 patchObject(definition, 'leaveClass', name + '-leave'); 5190 patchObject(definition, 'leaveActiveClass', definition.leaveClass + '-active'); 5191 } 5192 return definition; 5193 }; 5194 5195 function patchObject(obj, name, value) { 5196 if (!obj[name]) { 5197 obj[name] = value; 5198 } 5199 } 5200 5201 var Effect = function Effect(dom) { 5202 this.dom = dom; 5203 }; 5204 5205 avalon.Effect = Effect; 5206 5207 Effect.prototype = { 5208 enter: createAction('Enter'), 5209 leave: createAction('Leave'), 5210 move: createAction('Move') 5211 }; 5212 5213 function execHooks(options, name, el) { 5214 var fns = [].concat(options[name]); 5215 for (var i = 0, fn; fn = fns[i++];) { 5216 if (typeof fn === 'function') { 5217 fn(el); 5218 } 5219 } 5220 } 5221 var staggerCache = new Cache(128); 5222 5223 function createAction(action) { 5224 var lower = action.toLowerCase(); 5225 return function (option) { 5226 var dom = this.dom; 5227 var elem = avalon(dom); 5228 //å¤çä¸ms-foræä»¤ç¸å ³çstagger 5229 //========BEGIN===== 5230 var staggerTime = isFinite(option.stagger) ? option.stagger * 1000 : 0; 5231 if (staggerTime) { 5232 if (option.staggerKey) { 5233 var stagger = staggerCache.get(option.staggerKey) || staggerCache.put(option.staggerKey, { 5234 count: 0, 5235 items: 0 5236 }); 5237 stagger.count++; 5238 stagger.items++; 5239 } 5240 } 5241 var staggerIndex = stagger && stagger.count || 0; 5242 //=======END========== 5243 var stopAnimationID; 5244 var animationDone = function animationDone(e) { 5245 var isOk = e !== false; 5246 if (--dom.__ms_effect_ === 0) { 5247 avalon.unbind(dom, transitionEndEvent); 5248 avalon.unbind(dom, animationEndEvent); 5249 } 5250 clearTimeout(stopAnimationID); 5251 var dirWord = isOk ? 'Done' : 'Abort'; 5252 execHooks(option, 'on' + action + dirWord, dom); 5253 if (stagger) { 5254 if (--stagger.items === 0) { 5255 stagger.count = 0; 5256 } 5257 } 5258 if (option.queue) { 5259 animationQueue.shift(); 5260 callNextAnimation(); 5261 } 5262 }; 5263 //æ§è¡å¼å§åçé©å 5264 execHooks(option, 'onBefore' + action, dom); 5265 5266 if (option[lower]) {
5267 //使ç¨JSæ¹å¼æ§è¡å¨ç» 5268 option[lower](dom, function (ok) { 5269 animationDone(ok !== false); 5270 }); 5271 } else if (css3) { 5272 //使ç¨CSS3æ¹å¼æ§è¡å¨ç» 5273 elem.addClass(option[lower + 'Class']); 5274 elem.removeClass(getNeedRemoved(option, lower)); 5275 5276 if (!dom.__ms_effect_) { 5277 //ç»å®å¨ç»ç»æäºä»¶ 5278 elem.bind(transitionEndEvent, animationDone); 5279 elem.bind(animationEndEvent, animationDone); 5280 dom.__ms_effect_ = 1; 5281 } else { 5282 dom.__ms_effect_++; 5283 } 5284 setTimeout(function () { 5285 //ç¨xxx-active代æ¿xxxç±»åçæ¹å¼ è§¦åCSS3å¨ç» 5286 var time = avalon.root.offsetWidth === NaN; 5287 elem.addClass(option[lower + 'ActiveClass']); 5288 //计ç®å¨ç»æ¶é¿ 5289 time = getAnimationTime(dom); 5290 if (!time === 0) { 5291 //ç«å³ç»æå¨ç» 5292 animationDone(false); 5293 } else if (!staggerTime) { 5294 //妿å¨ç»è¶ åºæ¶é¿è¿æ²¡æè°ç¨ç»æäºä»¶,è¿å¯è½æ¯å ç´ è¢«ç§»é¤äº 5295 //å¦æå¼ºå¶ç»æå¨ç» 5296 stopAnimationID = setTimeout(function () { 5297 animationDone(false); 5298 }, time + 32); 5299 } 5300 }, 17 + staggerTime * staggerIndex); // = 1000/60 5301 } 5302 }; 5303 } 5304 5305 avalon.applyEffect = function (dom, vdom, opts) { 5306 var cb = opts.cb; 5307 var curEffect = vdom.effect; 5308 if (curEffect && dom && dom.nodeType === 1) { 5309 var hook = opts.hook; 5310 var old = curEffect[hook]; 5311 if (cb) { 5312 if (Array.isArray(old)) { 5313 old.push(cb); 5314 } else if (old) { 5315 curEffect[hook] = [old, cb]; 5316 } else { 5317 curEffect[hook] = [cb]; 5318 } 5319 } 5320 getAction(opts); 5321 avalon.directives.effect.update(vdom, curEffect, avalon.shadowCopy({}, opts)); 5322 } else if (cb) { 5323 cb(dom); 5324 } 5325 }; 5326 /** 5327 * è·åæ¹å 5328 */ 5329 function getAction(opts) { 5330 if (!opts.action) { 5331 return opts.action = opts.hook.replace(/^on/, '').replace(/Done$/, '').toLowerCase(); 5332 } 5333 } 5334 /** 5335 * éè¦ç§»é¤çç±»å 5336 */ 5337 function getNeedRemoved(options, name) { 5338 var name = name === 'leave' ? 'enter' : 'leave'; 5339 return Array(name + 'Class', name + 'ActiveClass').map(function (cls) { 5340 return options[cls]; 5341 }).join(' '); 5342 } 5343 /** 5344 * 计ç®å¨ç»é¿åº¦ 5345 */ 5346 var transitionDuration = avalon.cssName('transition-duration'); 5347 var animationDuration = avalon.cssName('animation-duration'); 5348 var rsecond = /\d+s$/; 5349 function toMillisecond(str) { 5350 var ratio = rsecond.test(str) ? 1000 : 1; 5351 return parseFloat(str) * ratio; 5352 } 5353 5354 function getAnimationTime(dom) { 5355 var computedStyles = window$1.getComputedStyle(dom, null); 5356 var tranDuration = computedStyles[transitionDuration]; 5357 var animDuration = computedStyles[animationDuration]; 5358 return toMillisecond(tranDuration) || toMillisecond(animDuration); 5359 } 5360 /** 5361 * 5362 <!DOCTYPE html> 5363 <html> 5364 <head> 5365 <meta charset="UTF-8"> 5366 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 5367 <script src="dist/avalon.js"></script> 5368 <script> 5369 avalon.effect('animate') 5370 var vm = avalon.define({ 5371 $id: 'ani', 5372 a: true 5373 }) 5374 </script> 5375 <style> 5376 .animate-enter, .animate-leave{ 5377 width:100px; 5378 height:100px; 5379 background: #29b6f6; 5380 transition:all 2s; 5381 -moz-transition: all 2s; 5382 -webkit-transition: all 2s; 5383 -o-transition:all 2s; 5384 } 5385 .animate-enter-active, .animate-leave{ 5386 width:300px; 5387 height:300px; 5388 } 5389 .animate-leave-active{ 5390 width:100px; 5391 height:100px; 5392 } 5393 </style> 5394 </head> 5395 <body> 5396 <div :controller='ani' > 5397 <p><input type='button' value='click' :click='@a =!@a'></p> 5398 <div :effect="{is:'animate',action:@a}"></div> 5399 </div> 5400 </body> 5401 </html> 5402 * 5403 */ 5404 5405 var none = 'none'; 5406 function parseDisplay(elem, val) { 5407 //ç¨äºå徿¤ç±»æ ç¾çé»è®¤displayå¼ 5408 var doc = elem.ownerDocument; 5409 var nodeName = elem.nodeName; 5410 var key = '_' + nodeName; 5411 if (!parseDisplay[key]) { 5412 var temp = doc.body.appendChild(doc.createElement(nodeName)); 5413 val = avalon.css(temp, 'display'); 5414 doc.body.removeChild(temp); 5415 if (val === none) { 5416 val = 'block'; 5417 } 5418 parseDisplay[key] = val; 5419 } 5420 return parseDisplay[key]; 5421 } 5422 5423 avalon.parseDisplay = parseDisplay; 5424 avalon.directive('visible', { 5425 diff: function diff(newVal, oldVal) { 5426 var n = !!newVal; 5427 if (oldVal === void 0 || n !== oldVal) { 5428 this.value = n; 5429 return true; 5430 } 5431 }, 5432 ready: true, 5433 update: function update(vdom, show) { 5434 var dom = vdom.dom; 5435 if (dom && dom.nodeType === 1) { 5436 var display = dom.style.display; 5437 var value; 5438 if (show) { 5439 if (display === none) { 5440 value = vdom.displayValue; 5441 if (!value) { 5442 dom.style.display = ''; 5443 if (dom.style.cssText === '') { 5444 dom.removeAttribute('style'); 5445 } 5446 } 5447 } 5448 if (dom.style.display === '' && avalon(dom).css('display') === none && 5449 // fix firefox BUG,å¿ é¡»æå°é¡µé¢ä¸ 5450 avalon.contains(dom.ownerDocument, dom)) { 5451 value = parseDisplay(dom); 5452 } 5453 } else { 5454 5455 if (display !== none) { 5456 value = none; 5457 vdom.displayValue = display; 5458 } 5459 } 5460 var cb = function cb() { 5461 if (value !== void 0) { 5462 dom.style.display = value; 5463 } 5464 }; 5465 5466 avalon.applyEffect(dom, vdom, { 5467 hook: show ? 'onEnterDone' : 'onLeaveDone', 5468 cb: cb
5469 }); 5470 } 5471 } 5472 }); 5473 5474 avalon.directive('text', { 5475 delay: true, 5476 init: function init() { 5477 5478 var node = this.node; 5479 if (node.isVoidTag) { 5480 avalon.error('èªéåå ç´ ä¸è½ä½¿ç¨ms-text'); 5481 } 5482 var child = { nodeName: '#text', nodeValue: this.getValue() }; 5483 node.children.splice(0, node.children.length, child); 5484 if (inBrowser) { 5485 avalon.clearHTML(node.dom); 5486 node.dom.appendChild(avalon.vdom(child, 'toDOM')); 5487 } 5488 this.node = child; 5489 var type = 'expr'; 5490 this.type = this.name = type; 5491 var directive$$1 = avalon.directives[type]; 5492 var me = this; 5493 this.callback = function (value) { 5494 directive$$1.update.call(me, me.node, value); 5495 }; 5496 } 5497 }); 5498 5499 avalon.directive('expr', { 5500 update: function update(vdom, value) { 5501 value = value == null || value === '' ? '\u200B' : value; 5502 vdom.nodeValue = value; 5503 //https://github.com/RubyLouvre/avalon/issues/1834 5504 if (vdom.dom) vdom.dom.data = value; 5505 } 5506 }); 5507 5508 avalon.directive('attr', { 5509 diff: cssDiff, 5510 update: function update(vdom, value) { 5511 var props = vdom.props; 5512 for (var i in value) { 5513 if (!!value[i] === false) { 5514 delete props[i]; 5515 } else { 5516 props[i] = value[i]; 5517 } 5518 } 5519 var dom = vdom.dom; 5520 if (dom && dom.nodeType === 1) { 5521 updateAttrs(dom, value); 5522 } 5523 } 5524 }); 5525 5526 avalon.directive('html', { 5527 5528 update: function update(vdom, value) { 5529 this.beforeDispose(); 5530 5531 this.innerRender = avalon.scan('<div class="ms-html-container">' + value + '</div>', this.vm, function () { 5532 var oldRoot = this.root; 5533 if (vdom.children) vdom.children.length = 0; 5534 vdom.children = oldRoot.children; 5535 this.root = vdom; 5536 if (vdom.dom) avalon.clearHTML(vdom.dom); 5537 }); 5538 }, 5539 beforeDispose: function beforeDispose() { 5540 if (this.innerRender) { 5541 this.innerRender.dispose(); 5542 } 5543 }, 5544 delay: true 5545 }); 5546 5547 avalon.directive('if', { 5548 delay: true, 5549 priority: 5, 5550 init: function init() { 5551 this.placeholder = createAnchor('if'); 5552 var props = this.node.props; 5553 delete props['ms-if']; 5554 delete props[':if']; 5555 this.fragment = avalon.vdom(this.node, 'toHTML'); 5556 }, 5557 diff: function diff(newVal, oldVal) { 5558 var n = !!newVal; 5559 if (oldVal === void 0 || n !== oldVal) { 5560 this.value = n; 5561 return true; 5562 } 5563 }, 5564 update: function update(vdom, value) { 5565 if (this.isShow === void 0 && value) { 5566 continueScan(this, vdom); 5567 return; 5568 } 5569 this.isShow = value; 5570 var placeholder = this.placeholder; 5571 5572 if (value) { 5573 var p = placeholder.parentNode; 5574 continueScan(this, vdom); 5575 p && p.replaceChild(vdom.dom, placeholder); 5576 } else { 5577 //ç§»é¤DOM 5578 this.beforeDispose(); 5579 vdom.nodeValue = 'if'; 5580 vdom.nodeName = '#comment'; 5581 delete vdom.children; 5582 var dom = vdom.dom; 5583 var p = dom && dom.parentNode; 5584 vdom.dom = placeholder; 5585 if (p) { 5586 p.replaceChild(placeholder, dom); 5587 } 5588 } 5589 }, 5590 beforeDispose: function beforeDispose() { 5591 if (this.innerRender) { 5592 this.innerRender.dispose(); 5593 } 5594 } 5595 }); 5596 5597 function continueScan(instance, vdom) { 5598 var innerRender = instance.innerRender = avalon.scan(instance.fragment, instance.vm); 5599 avalon.shadowCopy(vdom, innerRender.root); 5600 delete vdom.nodeValue; 5601 } 5602 5603 avalon.directive('on', { 5604 beforeInit: function beforeInit() { 5605 this.getter = avalon.noop; 5606 },
5607 init: function init() { 5608 var vdom = this.node; 5609 var underline = this.name.replace('ms-on-', 'e').replace('-', '_'); 5610 var uuid = underline + '_' + this.expr.replace(/\s/g, '').replace(/[^$a-z]/ig, function (e) { 5611 return e.charCodeAt(0); 5612 }); 5613 var fn = avalon.eventListeners[uuid]; 5614 if (!fn) { 5615 var arr = addScope(this.expr); 5616 var body = arr[0], 5617 filters = arr[1]; 5618 body = makeHandle(body); 5619 5620 if (filters) { 5621 filters = filters.replace(/__value__/g, '$event'); 5622 filters += '\nif($event.$return){\n\treturn;\n}'; 5623 } 5624 var ret = ['try{', '\tvar __vmodel__ = this;', '\t' + filters, '\treturn ' + body, '}catch(e){avalon.log(e, "in on dir")}'].filter(function (el) { 5625 return (/\S/.test(el) 5626 ); 5627 }); 5628 fn = new Function('$event', ret.join('\n')); 5629 fn.uuid = uuid; 5630 avalon.eventListeners[uuid] = fn; 5631 } 5632 5633 var dom = avalon.vdom(vdom, 'toDOM'); 5634 dom._ms_context_ = this.vm; 5635 5636 this.eventType = this.param.replace(/\-(\d)$/, ''); 5637 delete this.param;
5638 avalon(dom).bind(this.eventType, fn); 5639 }, 5640 5641 beforeDispose: function beforeDispose() { 5642 avalon(this.node.dom).unbind(this.eventType); 5643 } 5644 }); 5645 5646 var rforAs = /\s+as\s+([$\w]+)/; 5647 var rident = /^[$a-zA-Z_][$a-zA-Z0-9_]*$/; 5648 var rinvalid = /^(null|undefined|NaN|window|this|\$index|\$id)$/; 5649 var rargs = /[$\w_]+/g; 5650 avalon.directive('for', { 5651 delay: true, 5652 priority: 3, 5653 beforeInit: function beforeInit() { 5654 var str = this.expr, 5655 asName; 5656 str = str.replace(rforAs, function (a, b) { 5657 /* istanbul ignore if */ 5658 if (!rident.test(b) || rinvalid.test(b)) { 5659 avalon.error('alias ' + b + ' is invalid --- must be a valid JS identifier which is not a reserved name.'); 5660 } else { 5661 asName = b; 5662 } 5663 return ''; 5664 }); 5665 5666 var arr = str.split(' in '); 5667 var kv = arr[0].match(rargs); 5668 if (kv.length === 1) { 5669 //ç¡®ä¿avalon._eachçåè°æä¸ä¸ªåæ° 5670 kv.unshift('$key'); 5671 } 5672 this.expr = arr[1]; 5673 this.keyName = kv[0]; 5674 this.valName = kv[1]; 5675 this.signature = avalon.makeHashCode('for'); 5676 if (asName) { 5677 this.asName = asName; 5678 } 5679 5680 delete this.param; 5681 }, 5682 init: function init() { 5683 var cb = this.userCb; 5684 if (typeof cb === 'string' && cb) { 5685 var arr = addScope(cb, 'for'); 5686 var body = makeHandle(arr[0]); 5687 this.userCb = new Function('$event', 'var __vmodel__ = this\nreturn ' + body); 5688 } 5689 this.node.forDir = this; //æ´é²ç»component/index.jsä¸çresetParentChildrenæ¹æ³ä½¿ç¨ 5690 this.fragment = ['<div>', this.fragment, '<!--', this.signature, '--></div>'].join(''); 5691 this.cache = {}; 5692 }, 5693 diff: function diff(newVal, oldVal) { 5694 /* istanbul ignore if */ 5695 if (this.updating) { 5696 return; 5697 } 5698 this.updating = true; 5699 var traceIds = createFragments(this, newVal); 5700 5701 if (this.oldTrackIds === void 0) return true; 5702 5703 if (this.oldTrackIds !== traceIds) { 5704 this.oldTrackIds = traceIds; 5705 return true; 5706 } 5707 }, 5708 update: function update() { 5709 5710 if (!this.preFragments) { 5711 this.fragments = this.fragments || []; 5712 mountList(this); 5713 } else { 5714 diffList(this); 5715 updateList(this); 5716 } 5717 5718 if (this.userCb) { 5719 var me = this; 5720 setTimeout(function () { 5721 me.userCb.call(me.vm, { 5722 type: 'rendered', 5723 target: me.begin.dom, 5724 signature: me.signature 5725 }); 5726 }, 0); 5727 } 5728 delete this.updating; 5729 }, 5730 beforeDispose: function beforeDispose() { 5731 this.fragments.forEach(function (el) { 5732 el.dispose(); 5733 }); 5734 } 5735 }); 5736 5737 function getTraceKey(item) { 5738 var type = typeof item; 5739 return item && type === 'object' ? item.$hashcode : type + ':' + item; 5740 } 5741 5742 //å建ä¸ç»fragmentçèæDOM 5743 function createFragments(instance, obj) { 5744 if (isObject(obj)) { 5745 var array = Array.isArray(obj); 5746 var ids = []; 5747 var fragments = [], 5748 i = 0; 5749 5750 instance.isArray = array; 5751 if (instance.fragments) { 5752 instance.preFragments = instance.fragments; 5753 avalon.each(obj, function (key, value) { 5754 var k = array ? getTraceKey(value) : key; 5755 5756 fragments.push({ 5757 key: k, 5758 val: value, 5759 index: i++ 5760 }); 5761 ids.push(k); 5762 }); 5763 instance.fragments = fragments; 5764 } else { 5765 avalon.each(obj, function (key, value) { 5766 if (!(key in $$skipArray)) { 5767 var k = array ? getTraceKey(value) : key; 5768 fragments.push(new VFragment([], k, value, i++)); 5769 ids.push(k); 5770 } 5771 }); 5772 instance.fragments = fragments; 5773 } 5774 return ids.join(';;'); 5775 } else { 5776 return NaN; 5777 } 5778 } 5779 5780 function mountList(instance) { 5781 var args = instance.fragments.map(function (fragment, index) { 5782 FragmentDecorator(fragment, instance, index); 5783 saveInCache(instance.cache, fragment); 5784 return fragment; 5785 }); 5786 var list = instance.parentChildren; 5787 var i = list.indexOf(instance.begin); 5788 list.splice.apply(list, [i + 1, 0].concat(args)); 5789 } 5790 5791 function diffList(instance) { 5792 var cache = instance.cache; 5793 var newCache = {}; 5794 var fuzzy = []; 5795 var list = instance.preFragments; 5796 5797 list.forEach(function (el) { 5798 el._dispose = true; 5799 }); 5800
5801 instance.fragments.forEach(function (c, index) { 5802 var fragment = isInCache(cache, c.key); 5803 //ååºä¹åçææ¡£ç¢ç 5804 if (fragment) { 5805 delete fragment._dispose; 5806 fragment.oldIndex = fragment.index; 5807 fragment.index = index; // ç¸å½äº c.index 5808 5809 resetVM(fragment.vm, instance.keyName); 5810 fragment.vm[instance.valName] = c.val; 5811 fragment.vm[instance.keyName] = instance.isArray ? index : fragment.key; 5812 saveInCache(newCache, fragment); 5813 } else { 5814 //妿æ¾ä¸å°å°±è¿è¡æ¨¡ç³æç´¢ 5815 fuzzy.push(c); 5816 } 5817 }); 5818 fuzzy.forEach(function (c) { 5819 var fragment = fuzzyMatchCache(cache, c.key); 5820 if (fragment) { 5821 //éå¤å©ç¨ 5822 fragment.oldIndex = fragment.index; 5823 fragment.key = c.key; 5824 var val = fragment.val = c.val; 5825 var index = fragment.index = c.index; 5826 5827 fragment.vm[instance.valName] = val; 5828 fragment.vm[instance.keyName] = instance.isArray ? index : fragment.key; 5829 delete fragment._dispose; 5830 } else { 5831 5832 c = new VFragment([], c.key, c.val, c.index); 5833 fragment = FragmentDecorator(c, instance, c.index); 5834 list.push(fragment); 5835 } 5836 saveInCache(newCache, fragment); 5837 }); 5838 5839 instance.fragments = list; 5840 list.sort(function (a, b) { 5841 return a.index - b.index; 5842 }); 5843 instance.cache = newCache; 5844 } 5845 5846 function resetVM(vm, a, b) { 5847 if (avalon.config.inProxyMode) { 5848 vm.$accessors[a].value = NaN; 5849 } else { 5850 vm.$accessors[a].set(NaN); 5851 } 5852 } 5853 5854 function updateList(instance) { 5855 var before = instance.begin.dom; 5856 var parent = before.parentNode; 5857 var list = instance.fragments; 5858 var end = instance.end.dom; 5859 for (var i = 0, item; item = list[i]; i++) { 5860 if (item._dispose) { 5861 list.splice(i, 1); 5862 i--; 5863 item.dispose(); 5864 continue; 5865 } 5866 if (item.oldIndex !== item.index) { 5867 var f = item.toFragment(); 5868 var isEnd = before.nextSibling === null; 5869 parent.insertBefore(f, before.nextSibling); 5870 if (isEnd && !parent.contains(end)) { 5871 parent.insertBefore(end, before.nextSibling); 5872 } 5873 } 5874 before = item.split; 5875 } 5876 var ch = instance.parentChildren; 5877 var startIndex = ch.indexOf(instance.begin); 5878 var endIndex = ch.indexOf(instance.end); 5879 5880 list.splice.apply(ch, [startIndex + 1, endIndex - startIndex].concat(list)); 5881 } 5882 5883 /** 5884 * 5885 * @param {type} fragment 5886 * @param {type} this 5887 * @param {type} index 5888 * @returns { key, val, index, oldIndex, this, dom, split, vm} 5889 */ 5890 function FragmentDecorator(fragment, instance, index) { 5891 var data = {}; 5892 data[instance.keyName] = instance.isArray ? index : fragment.key; 5893 data[instance.valName] = fragment.val; 5894 if (instance.asName) { 5895 data[instance.asName] = instance.value; 5896 } 5897 var vm = fragment.vm = platform.itemFactory(instance.vm, { 5898 data: data 5899 }); 5900 if (instance.isArray) { 5901 vm.$watch(instance.valName, function (a) { 5902 if (instance.value && instance.value.set) { 5903 instance.value.set(vm[instance.keyName], a); 5904 } 5905 }); 5906 } else { 5907 vm.$watch(instance.valName, function (a) { 5908 instance.value[fragment.key] = a; 5909 }); 5910 } 5911 5912 fragment.index = index; 5913 fragment.innerRender = avalon.scan(instance.fragment, vm, function () { 5914 var oldRoot = this.root; 5915 ap.push.apply(fragment.children, oldRoot.children); 5916 this.root = fragment; 5917 }); 5918 return fragment; 5919 } 5920 // æ°ä½ç½®: æ§ä½ç½®
5921 function isInCache(cache, id) { 5922 var c = cache[id]; 5923 if (c) { 5924 var arr = c.arr; 5925 /* istanbul ignore if*/ 5926 if (arr) { 5927 var r = arr.pop(); 5928 if (!arr.length) { 5929 c.arr = 0; 5930 } 5931 return r; 5932 } 5933 delete cache[id]; 5934 return c; 5935 } 5936 } 5937 //[1,1,1] number1 number1_ number1__ 5938 function saveInCache(cache, component) { 5939 var trackId = component.key; 5940 if (!cache[trackId]) { 5941 cache[trackId] = component; 5942 } else { 5943 var c = cache[trackId]; 5944 var arr = c.arr || (c.arr = []); 5945 arr.push(component); 5946 } 5947 } 5948 5949 function fuzzyMatchCache(cache) { 5950 var key; 5951 for (var id in cache) { 5952 var key = id; 5953 break; 5954 } 5955 if (key) { 5956 return isInCache(cache, key); 5957 } 5958 } 5959 5960 //æ ¹æ®VMç屿§å¼æè¡¨è¾¾å¼çå¼åæ¢ç±»åï¼ms-class='xxx yyy zzz:flag' 5961 //http://www.cnblogs.com/rubylouvre/archive/2012/12/17/2818540.html 5962 function classNames() { 5963 var classes = []; 5964 for (var i = 0; i < arguments.length; i++) { 5965 var arg = arguments[i]; 5966 var argType = typeof arg; 5967 if (argType === 'string' || argType === 'number' || arg === true) { 5968 classes.push(arg); 5969 } else if (Array.isArray(arg)) { 5970 classes.push(classNames.apply(null, arg)); 5971 } else if (argType === 'object') { 5972 for (var key in arg) { 5973 if (arg.hasOwnProperty(key) && arg[key]) { 5974 classes.push(key); 5975 } 5976 } 5977 } 5978 } 5979 5980 return classes.join(' '); 5981 } 5982 5983 avalon.directive('class', { 5984 diff: function diff(newVal, oldVal) { 5985 var type = this.type; 5986 var vdom = this.node; 5987 var classEvent = vdom.classEvent || {}; 5988 if (type === 'hover') { 5989 //å¨ç§»åºç§»å ¥æ¶åæ¢ç±»å 5990 classEvent.mouseenter = activateClass; 5991 classEvent.mouseleave = abandonClass; 5992 } else if (type === 'active') { 5993 //å¨è·å¾ç¦ç¹æ¶åæ¢ç±»å 5994 classEvent.tabIndex = vdom.props.tabindex || -1; 5995 classEvent.mousedown = activateClass; 5996 classEvent.mouseup = abandonClass; 5997 classEvent.mouseleave = abandonClass; 5998 } 5999 vdom.classEvent = classEvent; 6000 6001 var className = classNames(newVal); 6002 6003 if (typeof oldVal === void 0 || oldVal !== className) { 6004 this.value = className; 6005 6006 vdom['change-' + type] = className; 6007 return true; 6008 } 6009 }, 6010 update: function update(vdom, value) { 6011 var dom = vdom.dom; 6012 if (dom && dom.nodeType == 1) { 6013 6014 var dirType = this.type; 6015 var change = 'change-' + dirType; 6016 var classEvent = vdom.classEvent; 6017 if (classEvent) { 6018 for (var i in classEvent) { 6019 if (i === 'tabIndex') { 6020 dom[i] = classEvent[i]; 6021 } else { 6022 avalon.bind(dom, i, classEvent[i]); 6023 } 6024 } 6025 vdom.classEvent = {}; 6026 } 6027 var names = ['class', 'hover', 'active']; 6028 names.forEach(function (type) { 6029 if (dirType !== type) return; 6030 if (type === 'class') { 6031 dom && setClass(dom, value); 6032 } else { 6033 var oldClass = dom.getAttribute(change); 6034 if (oldClass) { 6035 avalon(dom).removeClass(oldClass); 6036 } 6037 var name = 'change-' + type; 6038 dom.setAttribute(name, value); 6039 } 6040 }); 6041 } 6042 } 6043 }); 6044 6045 directives.active = directives.hover = directives['class']; 6046 6047 var classMap = { 6048 mouseenter: 'change-hover', 6049 mouseleave: 'change-hover', 6050 mousedown: 'change-active', 6051 mouseup: 'change-active' 6052 }; 6053 6054 function activateClass(e) { 6055 var elem = e.target; 6056 avalon(elem).addClass(elem.getAttribute(classMap[e.type]) || ''); 6057 } 6058 6059 function abandonClass(e) { 6060 var elem = e.target; 6061 var name = classMap[e.type]; 6062 avalon(elem).removeClass(elem.getAttribute(name) || ''); 6063 if (name !== 'change-active') { 6064 avalon(elem).removeClass(elem.getAttribute('change-active') || ''); 6065 } 6066 } 6067 6068 function setClass(dom, neo) { 6069 var old = dom.getAttribute('change-class'); 6070 if (old !== neo) { 6071 avalon(dom).removeClass(old).addClass(neo); 6072 dom.setAttribute('change-class', neo); 6073 } 6074 } 6075 6076 getLongID(activateClass); 6077 getLongID(abandonClass); 6078 6079 function lookupOption(vdom, values) {
6080 vdom.children && vdom.children.forEach(function (el) { 6081 if (el.nodeName === 'option') { 6082 setOption(el, values); 6083 } else { 6084 lookupOption(el, values); 6085 } 6086 }); 6087 } 6088 6089 function setOption(vdom, values) { 6090 var props = vdom.props; 6091 if (!('disabled' in props)) { 6092 var value = getOptionValue(vdom, props); 6093 value = String(value || '').trim(); 6094 props.selected = values.indexOf(value) !== -1; 6095 6096 if (vdom.dom) { 6097 vdom.dom.selected = props.selected; 6098 var v = vdom.dom.selected; //å¿ é¡»å ä¸è¿ä¸ª,鲿¢ç§»åºèç¹selected失æ 6099 } 6100 } 6101 } 6102 6103 function getOptionValue(vdom, props) { 6104 if (props && 'value' in props) { 6105 return props.value + ''; 6106 } 6107 var arr = []; 6108 vdom.children.forEach(function (el) { 6109 if (el.nodeName === '#text') { 6110 arr.push(el.nodeValue); 6111 } else if (el.nodeName === '#document-fragment') { 6112 arr.push(getOptionValue(el)); 6113 } 6114 }); 6115 return arr.join(''); 6116 } 6117 6118 function getSelectedValue(vdom, arr) { 6119 vdom.children.forEach(function (el) { 6120 if (el.nodeName === 'option') { 6121 if (el.props.selected === true) arr.push(getOptionValue(el, el.props)); 6122 } else if (el.children) { 6123 getSelectedValue(el, arr); 6124 } 6125 }); 6126 return arr; 6127 } 6128 6129 var updateDataActions = { 6130 input: function input(prop) { 6131 //å¤çå个valueå¼å¤ç 6132 var field = this; 6133 prop = prop || 'value'; 6134 var dom = field.dom; 6135 var rawValue = dom[prop]; 6136 var parsedValue = field.parseValue(rawValue); 6137 6138 //ææ¶åparseåä¸è´,vmä¸ä¼æ¹å,ä½inputéé¢çå¼ 6139 field.value = rawValue; 6140 field.setValue(parsedValue); 6141 duplexCb(field); 6142 var pos = field.pos; 6143 /* istanbul ignore if */ 6144 if (dom.caret) { 6145 field.setCaret(dom, pos); 6146 } 6147 //vm.aaa = '1234567890' 6148 //å¤ç <input ms-duplex='@aaa|limitBy(8)'/>{{@aaa}} è¿ç§æ ¼å¼å忥ä¸ä¸è´çæ åµ 6149 }, 6150 radio: function radio() { 6151 var field = this; 6152 if (field.isChecked) { 6153 var val = !field.value; 6154 field.setValue(val); 6155 duplexCb(field); 6156 } else { 6157 updateDataActions.input.call(field); 6158 field.value = NaN; 6159 } 6160 }, 6161 checkbox: function checkbox() { 6162 var field = this; 6163 var array = field.value; 6164 if (!Array.isArray(array)) { 6165 avalon.warn('ms-duplexåºç¨äºcheckboxä¸è¦å¯¹åºä¸ä¸ªæ°ç»'); 6166 array = [array]; 6167 } 6168 var method = field.dom.checked ? 'ensure' : 'remove'; 6169 if (array[method]) { 6170 var val = field.parseValue(field.dom.value); 6171 array[method](val); 6172 duplexCb(field); 6173 } 6174 this.__test__ = array; 6175 }, 6176 select: function select() { 6177 var field = this; 6178 var val = avalon(field.dom).val(); //å符串æå符串æ°ç» 6179 if (val + '' !== this.value + '') { 6180 if (Array.isArray(val)) { 6181 //转æ¢å¸å°æ°ç»æå ¶ä» 6182 val = val.map(function (v) { 6183 return field.parseValue(v); 6184 }); 6185 } else { 6186 val = field.parseValue(val); 6187 } 6188 field.setValue(val); 6189 duplexCb(field); 6190 } 6191 }, 6192 contenteditable: function contenteditable() { 6193 updateDataActions.input.call(this, 'innerHTML'); 6194 } 6195 }; 6196 6197 function duplexCb(field) { 6198 if (field.userCb) { 6199 field.userCb.call(field.vm, { 6200 type: 'changed', 6201 target: field.dom 6202 }); 6203 } 6204 } 6205 6206 function updateDataHandle(event) { 6207 var elem = this; 6208 var field = elem._ms_duplex_; 6209 if (elem.composing) { 6210 //鲿¢onpropertychangeå¼åçæ 6211 return; 6212 } 6213 if (elem.value === field.value) { 6214 return; 6215 } 6216 /* istanbul ignore if*/ 6217 if (elem.caret) { 6218 try { 6219 var pos = field.getCaret(elem); 6220 field.pos = pos; 6221 } catch (e) {} 6222 } 6223 /* istanbul ignore if*/ 6224 if (field.debounceTime > 4) { 6225 var timestamp = new Date(); 6226 var left = timestamp - field.time || 0; 6227 field.time = timestamp; 6228 /* istanbul ignore if*/ 6229 if (left >= field.debounceTime) { 6230 updateDataActions[field.dtype].call(field); 6231 /* istanbul ignore else*/ 6232 } else { 6233 clearTimeout(field.debounceID); 6234 field.debounceID = setTimeout(function () { 6235 updateDataActions[field.dtype].call(field); 6236 }, left); 6237 } 6238 } else if (field.isChanged) { 6239 setTimeout(function () { 6240 //https://github.com/RubyLouvre/avalon/issues/1908 6241 updateDataActions[field.dtype].call(field); 6242 }, 4); 6243 } else { 6244 updateDataActions[field.dtype].call(field); 6245 } 6246 } 6247 6248 var rchangeFilter = /\|\s*change\b/; 6249 var rdebounceFilter = /\|\s*debounce(?:\(([^)]+)\))?/; 6250 function duplexBeforeInit() { 6251 var expr = this.expr; 6252 if (rchangeFilter.test(expr)) { 6253 this.isChanged = true; 6254 expr = expr.replace(rchangeFilter, ''); 6255 } 6256 var match = expr.match(rdebounceFilter); 6257 if (match) { 6258 expr = expr.replace(rdebounceFilter, ''); 6259 if (!this.isChanged) { 6260 this.debounceTime = parseInt(match[1], 10) || 300; 6261 } 6262 } 6263 this.expr = expr; 6264 } 6265 function duplexInit() { 6266 var expr = this.expr; 6267 var node = this.node; 6268 var etype = node.props.type; 6269 this.parseValue = parseValue; 6270 //å¤çæ°æ®è½¬æ¢å¨ 6271 var parsers = this.param, 6272 dtype; 6273 var isChecked = false;
6274 parsers = parsers ? parsers.split('-').map(function (a) { 6275 if (a === 'checked') { 6276 isChecked = true; 6277 } 6278 return a; 6279 }) : []; 6280 node.duplex = this; 6281 if (rcheckedType.test(etype) && isChecked) { 6282 //妿æ¯radio, checkbox,å¤å®ç¨æ·ä½¿ç¨äºcheckedæ ¼å¼å½æ°æ²¡æ 6283 parsers = []; 6284 dtype = 'radio'; 6285 this.isChecked = isChecked; 6286 } 6287 this.parsers = parsers; 6288 if (!/input|textarea|select/.test(node.nodeName)) { 6289 if ('contenteditable' in node.props) { 6290 dtype = 'contenteditable'; 6291 } 6292 } else if (!dtype) { 6293 dtype = node.nodeName === 'select' ? 'select' : etype === 'checkbox' ? 'checkbox' : etype === 'radio' ? 'radio' : 'input'; 6294 } 6295 this.dtype = dtype; 6296 6297 //å¤å®æ¯å¦ä½¿ç¨äº change debounce è¿æ»¤å¨ 6298 // this.isChecked = /boolean/.test(parsers) 6299 if (dtype !== 'input' && dtype !== 'contenteditable') { 6300 delete this.isChanged; 6301 delete this.debounceTime; 6302 } else if (!this.isChecked) { 6303 this.isString = true; 6304 } 6305 6306 var cb = node.props['data-duplex-changed']; 6307 if (cb) { 6308 var arr = addScope(cb, 'xx'); 6309 var body = makeHandle(arr[0]); 6310 this.userCb = new Function('$event', 'var __vmodel__ = this\nreturn ' + body); 6311 } 6312 } 6313 function duplexDiff(newVal, oldVal) { 6314 if (Array.isArray(newVal)) { 6315 if (newVal + '' !== this.compareVal) { 6316 this.compareVal = newVal + ''; 6317 return true; 6318 } 6319 } else { 6320 newVal = this.parseValue(newVal); 6321 if (!this.isChecked) { 6322 this.value = newVal += ''; 6323 } 6324 if (newVal !== this.compareVal) { 6325 this.compareVal = newVal; 6326 return true; 6327 } 6328 } 6329 } 6330 6331 function duplexBind(vdom, addEvent) { 6332 var dom = vdom.dom; 6333 this.dom = dom; 6334 this.vdom = vdom; 6335 this.duplexCb = updateDataHandle; 6336 dom._ms_duplex_ = this; 6337 //ç»å®äºä»¶ 6338 addEvent(dom, this); 6339 } 6340 6341 var valueHijack = true; 6342 try { 6343 //#272 IE9-IE11, firefox 6344 var setters = {}; 6345 var aproto = HTMLInputElement.prototype; 6346 var bproto = HTMLTextAreaElement.prototype; 6347 var newSetter = function newSetter(value) { 6348 // jshint ignore:line 6349 setters[this.tagName].call(this, value); 6350 var data = this._ms_duplex_; 6351 if (!this.caret && data && data.isString) { 6352 data.duplexCb.call(this, { type: 'setter' }); 6353 } 6354 }; 6355 var inputProto = HTMLInputElement.prototype; 6356 Object.getOwnPropertyNames(inputProto); //æ æå¼åIE6-8çæµè§å¨æ¥é 6357 setters['INPUT'] = Object.getOwnPropertyDescriptor(aproto, 'value').set; 6358 6359 Object.defineProperty(aproto, 'value', { 6360 set: newSetter 6361 }); 6362 setters['TEXTAREA'] = Object.getOwnPropertyDescriptor(bproto, 'value').set; 6363 Object.defineProperty(bproto, 'value', { 6364 set: newSetter 6365 }); 6366 valueHijack = false; 6367 } catch (e) { 6368 //å¨chrome 43ä¸ ms-duplexç»äºä¸éè¦ä½¿ç¨å®æ¶å¨å®ç°ååç»å®äº 6369 // http://updates.html5rocks.com/2015/04/DOM-attributes-now-on-the-prototype 6370 // https://docs.google.com/document/d/1jwA8mtClwxI-QJuHT7872Z0pxpZz8PBkf2bGAbsUtqs/edit?pli=1 6371 } 6372 6373 function parseValue(val) { 6374 for (var i = 0, k; k = this.parsers[i++];) { 6375 var fn = avalon.parsers[k]; 6376 if (fn) { 6377 val = fn.call(this, val); 6378 } 6379 } 6380 return val; 6381 } 6382 6383 var updateView = { 6384 input: function input() { 6385 //å¤çå个valueå¼å¤ç 6386 var vdom = this.node; 6387 var value = this.value + ''; 6388 vdom.dom.value = vdom.props.value = value; 6389 }, 6390 updateChecked: function updateChecked(vdom, checked) { 6391 if (vdom.dom) { 6392 vdom.dom.defaultChecked = vdom.dom.checked = checked; 6393 } 6394 }, 6395 radio: function radio() { 6396 //å¤çå个checked屿§ 6397 var node = this.node; 6398 var nodeValue = node.props.value; 6399 var checked; 6400 if (this.isChecked) { 6401 checked = !!this.value; 6402 } else { 6403 checked = this.value + '' === nodeValue; 6404 } 6405 node.props.checked = checked; 6406 updateView.updateChecked(node, checked); 6407 }, 6408 checkbox: function checkbox() { 6409 //å¤çå¤ä¸ªchecked屿§ 6410 var node = this.node; 6411 var props = node.props; 6412 var value = props.value + ''; 6413 var values = [].concat(this.value); 6414 var checked = values.some(function (el) { 6415 return el + '' === value; 6416 }); 6417 6418 props.defaultChecked = props.checked = checked; 6419 updateView.updateChecked(node, checked); 6420 }, 6421 select: function select() { 6422 //å¤çå级çselected屿§ 6423 var a = Array.isArray(this.value) ? this.value.map(String) : this.value + ''; 6424 lookupOption(this.node, a); 6425 }, 6426 contenteditable: function contenteditable() { 6427 //å¤çå个innerHTML 6428 6429 var vnodes = fromString(this.value); 6430 var fragment = createFragment(); 6431 for (var i = 0, el; el = vnodes[i++];) { 6432 var child = avalon.vdom(el, 'toDOM'); 6433 fragment.appendChild(child); 6434 } 6435 avalon.clearHTML(this.dom).appendChild(fragment); 6436 var list = this.node.children; 6437 list.length = 0; 6438 Array.prototype.push.apply(list, vnodes); 6439 6440 this.duplexCb.call(this.dom); 6441 } 6442 }; 6443 6444 /* 6445 * éè¿ç»å®äºä»¶åæ¥vmodel 6446 * æ»å ±æä¸ç§æ¹å¼åæ¥è§å¾ 6447 * 1. åç§äºä»¶ input, change, click, propertychange, keydown... 6448 * 2. value屿§éå 6449 * 3. 宿¶å¨è½®è¯¢ 6450 */ 6451 6452 function updateDataEvents(dom, data) { 6453 var events = {}; 6454 //æ·»å éè¦çå¬çäºä»¶ 6455 switch (data.dtype) { 6456 case 'radio': 6457 case 'checkbox': 6458 events.click = updateDataHandle; 6459 break; 6460 case 'select': 6461 events.change = updateDataHandle; 6462 break; 6463 case 'contenteditable': 6464 /* istanbul ignore if */ 6465 if (data.isChanged) { 6466 events.blur = updateDataHandle; 6467 /* istanbul ignore else */ 6468 } else { 6469 /* istanbul ignore if*/ 6470 6471 if (avalon.modern) { 6472 if (window$1.webkitURL) { 6473 // http://code.metager.de/source/xref/WebKit/LayoutTests/fast/events/ 6474 // https://bugs.webkit.org/show_bug.cgi?id=110742 6475 events.webkitEditableContentChanged = updateDataHandle; 6476 } else if (window$1.MutationEvent) { 6477 events.DOMCharacterDataModified = updateDataHandle; 6478 } 6479 events.input = updateDataHandle; 6480 /* istanbul ignore else */ 6481 } else { 6482 events.keydown = updateModelKeyDown; 6483 events.paste = updateModelDelay; 6484 events.cut = updateModelDelay; 6485 events.focus = closeComposition; 6486 events.blur = openComposition; 6487 } 6488 } 6489 break; 6490 case 'input': 6491 /* istanbul ignore if */ 6492 if (data.isChanged) { 6493 events.change = updateDataHandle; 6494 /* istanbul ignore else */ 6495 } else { 6496 //http://www.cnblogs.com/rubylouvre/archive/2013/02/17/2914604.html 6497 //http://www.matts411.com/post/internet-explorer-9-oninput/ 6498 if (msie < 10) { 6499 //IE6-8çpropertychangeæé®é¢,ç¬¬ä¸æ¬¡ç¨JSä¿®æ¹å¼æ¶ä¸ä¼è§¦å,èä¸ä½ æ¯å ¨é¨æ¸ 空valueä¹ä¸ä¼è§¦å 6500 //IE9çpropertychange䏿¯æèªå¨å®æ,éæ ¼,å é¤,å¤å¶,è´´ç²,åªåæç¹å»å³è¾¹çå°Xçæ¸ 空æä½ 6501 events.propertychange = updateModelHack; 6502 events.paste = updateModelDelay; 6503 events.cut = updateModelDelay; 6504 //IE9å¨ç¬¬ä¸æ¬¡å é¤å符æ¶ä¸ä¼è§¦åoninput 6505 events.keyup = updateModelKeyDown; 6506 } else { 6507 events.input = updateDataHandle; 6508 events.compositionstart = openComposition; 6509 //微软æ¼é³è¾å ¥æ³çé®é¢éè¦å¨compositionendäºä»¶ä¸å¤ç 6510 events.compositionend = closeComposition; 6511 //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray 6512 //å¤çä½çæ¬çæ åæµè§å¨,éè¿Int8Arrayè¿è¡åºå 6513 if (!/\[native code\]/.test(window$1.Int8Array)) { 6514 events.keydown = updateModelKeyDown; //safari < 5 opera < 11 6515 events.paste = updateModelDelay; //safari < 5 6516 events.cut = updateModelDelay; //safari < 5 6517 if (window$1.netscape) { 6518 // Firefox <= 3.6 doesn't fire the 'input' event when text is filled in through autocomplete 6519 events.DOMAutoComplete = updateDataHandle; 6520 } 6521 } 6522 } 6523 } 6524 break; 6525 } 6526 6527 if (/password|text/.test(dom.type)) { 6528 events.focus = openCaret; //å¤å®æ¯å¦ä½¿ç¨å æ ä¿®æ£åè½ 6529 events.blur = closeCaret; 6530 data.getCaret = getCaret; 6531 data.setCaret = setCaret; 6532 } 6533 6534 for (var name in events) { 6535 avalon.bind(dom, name, events[name]); 6536 } 6537 } 6538 6539 function updateModelHack(e) { 6540 if (e.propertyName === 'value') { 6541 updateDataHandle.call(this, e); 6542 } 6543 } 6544 6545 function updateModelDelay(e) { 6546 var elem = this; 6547 setTimeout(function () { 6548 updateDataHandle.call(elem, e); 6549 }, 0); 6550 } 6551 6552 function openCaret() { 6553 this.caret = true; 6554 } 6555 /* istanbul ignore next */ 6556 function closeCaret() { 6557 this.caret = false;
6558 } 6559 /* istanbul ignore next */ 6560 function openComposition() { 6561 this.composing = true; 6562 } 6563 /* istanbul ignore next */ 6564 function closeComposition(e) { 6565 this.composing = false; 6566 updateModelDelay.call(this, e); 6567 } 6568 /* istanbul ignore next */ 6569 function updateModelKeyDown(e) { 6570 var key = e.keyCode; 6571 // ignore 6572 // command modifiers arrows 6573 if (key === 91 || 15 < key && key < 19 || 37 <= key && key <= 40) return; 6574 updateDataHandle.call(this, e); 6575 } 6576 6577 getShortID(openCaret); 6578 getShortID(closeCaret); 6579 getShortID(openComposition); 6580 getShortID(closeComposition); 6581 getShortID(updateDataHandle); 6582 getShortID(updateModelHack); 6583 getShortID(updateModelDelay); 6584 getShortID(updateModelKeyDown); 6585 6586 //IE6-8è¦å¤çå æ æ¶éè¦å¼æ¥ 6587 var mayBeAsync = function mayBeAsync(fn) { 6588 setTimeout(fn, 0); 6589 }; 6590 /* istanbul ignore next */ 6591 function setCaret(target, cursorPosition) { 6592 var range$$1; 6593 if (target.createTextRange) { 6594 mayBeAsync(function () { 6595 target.focus(); 6596 range$$1 = target.createTextRange(); 6597 range$$1.collapse(true); 6598 range$$1.moveEnd('character', cursorPosition); 6599 range$$1.moveStart('character', cursorPosition); 6600 range$$1.select(); 6601 }); 6602 } else { 6603 target.focus(); 6604 if (target.selectionStart !== undefined) { 6605 target.setSelectionRange(cursorPosition, cursorPosition); 6606 } 6607 } 6608 } 6609 /* istanbul ignore next*/ 6610 function getCaret(target) { 6611 var start = 0; 6612 var normalizedValue; 6613 var range$$1; 6614 var textInputRange; 6615 var len; 6616 var endRange; 6617 6618 if (target.selectionStart + target.selectionEnd > -1) { 6619 start = target.selectionStart; 6620 } else { 6621 range$$1 = document$1.selection.createRange(); 6622 6623 if (range$$1 && range$$1.parentElement() === target) { 6624 len = target.value.length; 6625 normalizedValue = target.value.replace(/\r\n/g, '\n'); 6626 6627 textInputRange = target.createTextRange(); 6628 textInputRange.moveToBookmark(range$$1.getBookmark()); 6629 6630 endRange = target.createTextRange(); 6631 endRange.collapse(false); 6632 6633 if (textInputRange.compareEndPoints('StartToEnd', endRange) > -1) { 6634 start = len; 6635 } else { 6636 start = -textInputRange.moveStart('character', -len); 6637 start += normalizedValue.slice(0, start).split('\n').length - 1; 6638 } 6639 } 6640 } 6641 6642 return start; 6643 } 6644 6645 avalon.directive('duplex', { 6646 priority: 9999999, 6647 beforeInit: duplexBeforeInit, 6648 init: duplexInit, 6649 diff: duplexDiff, 6650 update: function update(vdom, value) { 6651 if (!this.dom) { 6652 duplexBind.call(this, vdom, updateDataEvents); 6653 } 6654 //妿䏿¯æinput.valueçObject.definePropertyç屿§æ¯æ, 6655 //éè¦éè¿è½®è¯¢åæ¥, chrome 42å以ä¸çæ¬éè¦è¿ä¸ªhack 6656 pollValue.call(this, avalon.msie, valueHijack); 6657 //æ´æ°è§å¾ 6658 6659 updateView[this.dtype].call(this); 6660 } 6661 }); 6662 6663 function pollValue(isIE, valueHijack$$1) { 6664 var dom = this.dom; 6665 if (this.isString && valueHijack$$1 && !isIE && !dom.valueHijack) { 6666 dom.valueHijack = updateDataHandle; 6667 var intervalID = setInterval(function () { 6668 if (!avalon.contains(avalon.root, dom)) { 6669 clearInterval(intervalID); 6670 } else { 6671 dom.valueHijack({ type: 'poll' }); 6672 } 6673 }, 30); 6674 return intervalID; 6675 } 6676 } 6677 avalon.__pollValue = pollValue; //export to test 6678 /* istanbul ignore if */ 6679 if (avalon.msie < 8) { 6680 var oldUpdate = updateView.updateChecked; 6681 updateView.updateChecked = function (vdom, checked) { 6682 var dom = vdom.dom; 6683 if (dom) { 6684 setTimeout(function () { 6685 oldUpdate(vdom, checked); 6686 dom.firstCheckedIt = 1; 6687 }, dom.firstCheckedIt ? 31 : 16); 6688 //IE6,7 checkbox, radioæ¯ä½¿ç¨defaultCheckedæ§å¶éä¸ç¶æï¼ 6689 //å¹¶ä¸è¦å 设置defaultCheckedå设置checked 6690 //å¹¶ä¸å¿ 须设置延è¿(å ä¸ºå¿ é¡»æå ¥DOMæ æçæ) 6691 } 6692 }; 6693 } 6694 6695 avalon.directive('rules', { 6696 diff: function diff(rules) { 6697 if (isObject(rules)) { 6698 var vdom = this.node; 6699 vdom.rules = platform.toJson(rules); 6700 return true; 6701 } 6702 } 6703 }); 6704 function isRegExp(value) { 6705 return avalon.type(value) === 'regexp'; 6706 } 6707 var rmail = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/i; 6708 var rurl = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; 6709 function isCorrectDate(value) { 6710 if (typeof value === "string" && value) { 6711 //æ¯å符串ä½ä¸è½æ¯ç©ºå符 6712 var arr = value.split("-"); //å¯ä»¥è¢«-åæ3份ï¼å¹¶ä¸ç¬¬1个æ¯4个å符 6713 if (arr.length === 3 && arr[0].length === 4) { 6714 var year = ~~arr[0]; //å ¨é¨è½¬æ¢ä¸ºéè´æ´æ°
6715 var month = ~~arr[1] - 1; 6716 var date = ~~arr[2]; 6717 var d = new Date(year, month, date); 6718 return d.getFullYear() === year && d.getMonth() === month && d.getDate() === date; 6719 } 6720 } 6721 return false; 6722 } 6723 //https://github.com/adform/validator.js/blob/master/validator.js 6724 avalon.shadowCopy(avalon.validators, { 6725 pattern: { 6726 message: 'å¿ é¡»å¹é {{pattern}}è¿æ ·çæ ¼å¼', 6727 get: function get(value, field, next) { 6728 var elem = field.dom; 6729 var data = field.data; 6730 if (!isRegExp(data.pattern)) { 6731 var h5pattern = elem.getAttribute("pattern"); 6732 data.pattern = new RegExp('^(?:' + h5pattern + ')$'); 6733 } 6734 next(data.pattern.test(value)); 6735 return value; 6736 } 6737 }, 6738 digits: { 6739 message: 'å¿ é¡»æ´æ°', 6740 get: function get(value, field, next) { 6741 //æ´æ° 6742 next(/^\-?\d+$/.test(value)); 6743 return value; 6744 } 6745 }, 6746 number: { 6747 message: 'å¿ é¡»æ°å', 6748 get: function get(value, field, next) { 6749 //æ°å¼ 6750 next(!!value && isFinite(value)); // isFinite('') --> true 6751 return value; 6752 } 6753 }, 6754 norequired: { 6755 message: '', 6756 get: function get(value, field, next) { 6757 next(true); 6758 return value; 6759 } 6760 }, 6761 required: { 6762 message: 'å¿ é¡»å¡«å', 6763 get: function get(value, field, next) { 6764 next(value !== ''); 6765 return value; 6766 } 6767 }, 6768 equalto: { 6769 message: 'å¯ç è¾å ¥ä¸ä¸è´', 6770 get: function get(value, field, next) { 6771 var id = String(field.data.equalto); 6772 var other = avalon(document.getElementById(id)).val() || ""; 6773 next(value === other); 6774 return value; 6775 } 6776 }, 6777 date: { 6778 message: 'æ¥ææ ¼å¼ä¸æ£ç¡®', 6779 get: function get(value, field, next) { 6780 var data = field.data; 6781 if (isRegExp(data.date)) { 6782 next(data.date.test(value)); 6783 } else { 6784 next(isCorrectDate(value)); 6785 } 6786 return value; 6787 } 6788 }, 6789 url: { 6790 message: 'URLæ ¼å¼ä¸æ£ç¡®', 6791 get: function get(value, field, next) { 6792 next(rurl.test(value)); 6793 return value; 6794 } 6795 }, 6796 email: { 6797 message: 'emailæ ¼å¼ä¸æ£ç¡®', 6798 get: function get(value, field, next) { 6799 next(rmail.test(value)); 6800 return value; 6801 } 6802 }, 6803 minlength: { 6804 message: 'æå°è¾å ¥{{minlength}}个å', 6805 get: function get(value, field, next) { 6806 var num = parseInt(field.data.minlength, 10); 6807 next(value.length >= num); 6808 return value; 6809 } 6810 }, 6811 maxlength: { 6812 message: 'æå¤è¾å ¥{{maxlength}}个å', 6813 get: function get(value, field, next) { 6814 var num = parseInt(field.data.maxlength, 10); 6815 next(value.length <= num); 6816 return value; 6817 } 6818 }, 6819 min: { 6820 message: 'è¾å ¥å¼ä¸è½å°äº{{min}}', 6821 get: function get(value, field, next) { 6822 var num = parseInt(field.data.min, 10); 6823 next(parseFloat(value) >= num); 6824 return value; 6825 } 6826 }, 6827 max: { 6828 message: 'è¾å ¥å¼ä¸è½å¤§äº{{max}}', 6829 get: function get(value, field, next) { 6830 var num = parseInt(field.data.max, 10); 6831 next(parseFloat(value) <= num); 6832 return value; 6833 } 6834 }, 6835 chs: { 6836 message: 'å¿ é¡»æ¯ä¸æå符', 6837 get: function get(value, field, next) { 6838 next(/^[\u4e00-\u9fa5]+$/.test(value)); 6839 return value; 6840 } 6841 } 6842 }); 6843
6844 var valiDir = avalon.directive('validate', { 6845 diff: function diff(validator) { 6846 var vdom = this.node; 6847 if (vdom.validator) { 6848 return; 6849 } 6850 if (isObject(validator)) { 6851 //注æï¼è¿ä¸ªFormæ ç¾çèæDOMæä¸¤ä¸ªéªè¯å¯¹è±¡ 6852 //ä¸ä¸ªæ¯vmValidatorï¼å®æ¯ç¨æ·VMä¸çé£ä¸ªåå§å对象ï¼ä¹æ¯ä¸ä¸ªVM 6853 //ä¸ä¸ªæ¯validatorï¼å®æ¯vmValidator.$modelï¼ è¿æ¯ä¸ºäºé²æ¢IE6ï¼8æ·»å å屿§æ¶æ·»å çhack 6854 //ä¹å¯ä»¥ç§°ä¹ä¸ºsafeValidate 6855 vdom.validator = validator; 6856 validator = platform.toJson(validator); 6857 validator.vdom = vdom; 6858 validator.dom = vdom.dom; 6859 6860 for (var name in valiDir.defaults) { 6861 if (!validator.hasOwnProperty(name)) { 6862 validator[name] = valiDir.defaults[name]; 6863 } 6864 } 6865 validator.fields = validator.fields || []; 6866 vdom.vmValidator = validator; 6867 return true; 6868 } 6869 }, 6870 update: function update(vdom) { 6871 6872 var vmValidator = vdom.vmValidator; 6873 var validator = vdom.validator; 6874 var dom = vdom.dom; 6875 dom._ms_validate_ = vmValidator; 6876 6877 collectFeild(vdom.children, vmValidator.fields, vmValidator); 6878 var type = window.netscape ? 'keypress' : 'focusin'; 6879 avalon.bind(document, type, findValidator); 6880 //ä¸ºäºæ¹ä¾¿ç¨æ·æå¨æ§è¡éªè¯ï¼æä»¬éè¦ä¸ºåå§vmValidate䏿·»å ä¸ä¸ªonManualæ¹æ³ 6881 function onManual() { 6882 var v = this; 6883 v && valiDir.validateAll.call(v, v.onValidateAll); 6884 } 6885 6886 try { 6887 var fn = vmValidator.onManual = onManual.bind(vmValidator); 6888 validator.onManual = fn; 6889 } catch (e) { 6890 avalon.warn('è¦æ³ä½¿ç¨onManualæ¹æ³ï¼å¿ é¡»å¨validate对象é¢å®ä¹ä¸ä¸ªç©ºçonManual彿°'); 6891 } 6892 delete vdom.vmValidator; 6893 6894 dom.setAttribute('novalidate', 'novalidate'); 6895 6896 /* istanbul ignore if */ 6897 if (vmValidator.validateAllInSubmit) { 6898 avalon.bind(dom, 'submit', validateAllInSubmitFn); 6899 } 6900 }, 6901 validateAll: function validateAll(callback) { 6902 var validator = this; 6903 var vdom = this.vdom; 6904 var fields = validator.fields = []; 6905 collectFeild(vdom.children, fields, validator); 6906 var fn = typeof callback === 'function' ? callback : validator.onValidateAll; 6907 var promises = validator.fields.filter(function (field) { 6908 var el = field.dom; 6909 return el && !el.disabled && validator.dom.contains(el); 6910 }).map(function (field) { 6911 return valiDir.validate(field, true); 6912 }); 6913 var uniq = {}; 6914 return Promise.all(promises).then(function (array) { 6915 var reasons = array.concat.apply([], array); 6916 if (validator.deduplicateInValidateAll) { 6917 reasons = reasons.filter(function (reason) { 6918 var el = reason.element; 6919 var uuid = el.uniqueID || (el.uniqueID = setTimeout('1')); 6920 if (uniq[uuid]) { 6921 return false; 6922 } else { 6923 return uniq[uuid] = true; 6924 } 6925 }); 6926 } 6927 fn.call(vdom.dom, reasons); //è¿éåªæ¾ç½®æªéè¿éªè¯çç»ä»¶ 6928 }); 6929 }, 6930 6931 validate: function validate(field, isValidateAll, event) { 6932 6933 var promises = []; 6934 var value = field.value; 6935 var elem = field.dom; 6936 /* istanbul ignore if */ 6937 if (typeof Promise !== 'function') { 6938 //avalon-promise䏿¯æphantomjs 6939 avalon.warn('æµè§å¨ä¸æ¯æåçPromise,请ä¸è½½å¹¶<script src=url>å¼å ¥\nhttps://github.com/RubyLouvre/avalon/blob/master/test/promise.js'); 6940 } 6941 /* istanbul ignore if */ 6942 if (elem.disabled) return; 6943 var rules = field.vdom.rules; 6944 var ngs = [], 6945 isOk = true; 6946 if (!(rules.norequired && value === '')) { 6947 for (var ruleName in rules) { 6948 var ruleValue = rules[ruleName]; 6949 if (ruleValue === false) continue; 6950 var hook = avalon.validators[ruleName]; 6951 var resolve; 6952 promises.push(new Promise(function (a, b) { 6953 resolve = a; 6954 })); 6955 var next = function next(a) { 6956 var reason = { 6957 element: elem, 6958 data: field.data, 6959 message: elem.getAttribute('data-' + ruleName + '-message') || elem.getAttribute('data-message') || hook.message, 6960 validateRule: ruleName, 6961 getMessage: getMessage 6962 }; 6963 if (a) { 6964 resolve(true); 6965 } else { 6966 isOk = false;
6967 ngs.push(reason); 6968 resolve(false); 6969 } 6970 }; 6971 field.data = {}; 6972 field.data[ruleName] = ruleValue; 6973 hook.get(value, field, next); 6974 } 6975 } 6976 6977 //妿promisesä¸ä¸ºç©ºï¼è¯´æç»è¿éªè¯æ¦æªå¨ 6978 return Promise.all(promises).then(function (array) { 6979 if (!isValidateAll) { 6980 var validator = field.validator; 6981 if (isOk) { 6982 validator.onSuccess.call(elem, [{ 6983 data: field.data, 6984 element: elem 6985 }], event); 6986 } else { 6987 validator.onError.call(elem, ngs, event); 6988 } 6989 validator.onComplete.call(elem, ngs, event); 6990 } 6991 return ngs; 6992 }); 6993 } 6994 }); 6995 6996 //https://github.com/RubyLouvre/avalon/issues/1977 6997 function getValidate(dom) { 6998 while (dom.tagName !== 'FORM') { 6999 dom = dom.parentNode; 7000 } 7001 return dom._ms_validate_; 7002 } 7003 7004 function validateAllInSubmitFn(e) { 7005 e.preventDefault(); 7006 var v = getValidate(e.target); 7007 if (v && v.onManual) { 7008 v.onManual(); 7009 } 7010 } 7011 7012 function collectFeild(nodes, fields, validator) { 7013 for (var i = 0, vdom; vdom = nodes[i++];) { 7014 var duplex = vdom.rules && vdom.duplex; 7015 if (duplex) { 7016 fields.push(duplex); 7017 bindValidateEvent(duplex, validator); 7018 } else if (vdom.children) { 7019 collectFeild(vdom.children, fields, validator); 7020 } else if (Array.isArray(vdom)) { 7021 collectFeild(vdom, fields, validator); 7022 } 7023 } 7024 } 7025 7026 function findValidator(e) { 7027 var dom = e.target; 7028 var duplex = dom._ms_duplex_; 7029 var vdom = (duplex || {}).vdom; 7030 if (duplex && vdom.rules && !duplex.validator) { 7031 var msValidator = getValidate(dom); 7032 if (msValidator && avalon.Array.ensure(msValidator.fields, duplex)) { 7033 bindValidateEvent(duplex, msValidator); 7034 } 7035 } 7036 } 7037 7038 function singleValidate(e) { 7039 var dom = e.target; 7040 var duplex = dom._ms_duplex_; 7041 var msValidator = getValidate(e.target); 7042 msValidator && msValidator.validate(duplex, 0, e); 7043 } 7044 7045 function bindValidateEvent(field, validator) { 7046 7047 var node = field.dom; 7048 if (field.validator) { 7049 return; 7050 } 7051 field.validator = validator; 7052 /* istanbul ignore if */ 7053 if (validator.validateInKeyup && !field.isChanged && !field.debounceTime) { 7054 avalon.bind(node, 'keyup', singleValidate); 7055 } 7056 /* istanbul ignore if */ 7057 if (validator.validateInBlur) { 7058 avalon.bind(node, 'blur', singleValidate); 7059 } 7060 /* istanbul ignore if */ 7061 if (validator.resetInFocus) { 7062 avalon.bind(node, 'focus', function (e) { 7063 var dom = e.target; 7064 var field = dom._ms_duplex_; 7065 var validator = getValidate(e.target); 7066 validator && validator.onReset.call(dom, e, field); 7067 }); 7068 } 7069 } 7070 var rformat = /\\?{{([^{}]+)\}}/gm; 7071 7072 function getMessage() { 7073 var data = this.data || {}; 7074 return this.message.replace(rformat, function (_, name) { 7075 return data[name] == null ? '' : data[name]; 7076 }); 7077 } 7078 valiDir.defaults = { 7079 validate: valiDir.validate, 7080 onError: avalon.noop, 7081 onSuccess: avalon.noop, 7082 onComplete: avalon.noop, 7083 onManual: avalon.noop, 7084 onReset: avalon.noop, 7085 onValidateAll: avalon.noop, 7086 validateInBlur: true, //@config {Boolean} trueï¼å¨bluräºä»¶ä¸è¿è¡éªè¯,触åonSuccess, onError, onCompleteåè° 7087 validateInKeyup: true, //@config {Boolean} trueï¼å¨keyupäºä»¶ä¸è¿è¡éªè¯,触åonSuccess, onError, onCompleteåè° 7088 validateAllInSubmit: true, //@config {Boolean} trueï¼å¨submitäºä»¶ä¸æ§è¡onValidateAllåè° 7089 resetInFocus: true, //@config {Boolean}
7089 trueï¼å¨focusäºä»¶ä¸æ§è¡onResetåè°, 7090 deduplicateInValidateAll: false //@config {Boolean} falseï¼å¨validateAllåè°ä¸å¯¹reasonæ°ç»æ ¹æ®å ç´ èç¹è¿è¡å»é 7091 }; 7092 7093 /** 7094 * ä¸ä¸ªdirectiveè£ é¥°å¨ 7095 * @returns {directive} 7096 */ 7097 // DirectiveDecorator(scope, binding, vdom, this) 7098 // Decorator(vm, options, callback) 7099 function Directive(vm, binding, vdom, render) { 7100 var type = binding.type; 7101 var decorator = avalon.directives[type]; 7102 if (inBrowser) { 7103 var dom = avalon.vdom(vdom, 'toDOM'); 7104 if (dom.nodeType === 1) { 7105 dom.removeAttribute(binding.attrName); 7106 } 7107 vdom.dom = dom; 7108 } 7109 var callback = decorator.update ? function (value) { 7110 if (!render.mount && /css|visible|duplex/.test(type)) { 7111 render.callbacks.push(function () { 7112 decorator.update.call(directive$$1, directive$$1.node, value); 7113 }); 7114 } else { 7115 decorator.update.call(directive$$1, directive$$1.node, value); 7116 } 7117 } : avalon.noop; 7118 for (var key in decorator) { 7119 binding[key] = decorator[key]; 7120 } 7121 binding.node = vdom; 7122 var directive$$1 = new Action(vm, binding, callback); 7123 if (directive$$1.init) { 7124 //è¿éå¯è½ä¼éånode, callback, type, name 7125 directive$$1.init(); 7126 } 7127 directive$$1.update(); 7128 return directive$$1; 7129 } 7130 7131 var eventMap = avalon.oneObject('animationend,blur,change,input,' + 'click,dblclick,focus,keydown,keypress,keyup,mousedown,mouseenter,' + 'mouseleave,mousemove,mouseout,mouseover,mouseup,scan,scroll,submit', 'on'); 7132 function parseAttributes(dirs, tuple) { 7133 var node = tuple[0], 7134 uniq = {}, 7135 bindings = []; 7136 var hasIf = false; 7137 for (var name in dirs) { 7138 var value = dirs[name]; 7139 var arr = name.split('-'); 7140 // ms-click 7141 if (name in node.props) { 7142 var attrName = name; 7143 } else { 7144 attrName = ':' + name.slice(3); 7145 } 7146 if (eventMap[arr[1]]) { 7147 arr.splice(1, 0, 'on'); 7148 } 7149 //ms-on-click 7150 if (arr[1] === 'on') { 7151 arr[3] = parseFloat(arr[3]) || 0; 7152 } 7153 7154 var type = arr[1]; 7155 if (type === 'controller' || type === 'important') continue; 7156 if (directives[type]) { 7157 7158 var binding = { 7159 type: type, 7160 param: arr[2], 7161 attrName: attrName, 7162 name: arr.join('-'), 7163 expr: value, 7164 priority: directives[type].priority || type.charCodeAt(0) * 100 7165 }; 7166 if (type === 'if') { 7167 hasIf = true; 7168 } 7169 if (type === 'on') { 7170 binding.priority += arr[3]; 7171 } 7172 if (!uniq[binding.name]) { 7173 uniq[binding.name] = value; 7174 bindings.push(binding); 7175 if (type === 'for') { 7176 return [avalon.mix(binding, tuple[3])]; 7177 } 7178 } 7179 } 7180 } 7181 bindings.sort(byPriority); 7182 7183 if (hasIf) { 7184 var ret = []; 7185 for (var i = 0, el; el = bindings[i++];) { 7186 ret.push(el); 7187 if (el.type === 'if') { 7188 return ret; 7189 } 7190 } 7191 } 7192 return bindings; 7193 } 7194 function byPriority(a, b) { 7195 return a.priority - b.priority; 7196 } 7197 7198 var rimprovePriority = /[+-\?]/; 7199 var rinnerValue = /__value__\)$/; 7200 function parseInterpolate(dir) { 7201 var rlineSp = /\n\r?/g; 7202 var str = dir.nodeValue.trim().replace(rlineSp, ''); 7203 var tokens = []; 7204 do { 7205 //aaa{{@bbb}}ccc 7206 var index = str.indexOf(config.openTag); 7207 index = index === -1 ? str.length : index; 7208 var value = str.slice(0, index); 7209 if (/\S/.test(value)) { 7210 tokens.push(avalon.quote(avalon._decode(value))); 7211 } 7212 str = str.slice(index + config.openTag.length); 7213 if (str) { 7214 index = str.indexOf(config.closeTag); 7215 var value = str.slice(0, index); 7216 var expr = avalon.unescapeHTML(value); 7217 if (/\|\s*\w/.test(expr)) { 7218 //妿åå¨è¿æ»¤å¨ï¼ä¼åå¹²æ 7219 var arr = addScope(expr, 'expr'); 7220 if (arr[1]) { 7221 expr = arr[1].replace(rinnerValue, arr[0] + ')'); 7222 } 7223 } 7224 if (rimprovePriority) { 7225 expr = '(' + expr + ')'; 7226 } 7227 tokens.push(expr); 7228 7229 str = str.slice(index + config.closeTag.length); 7230 } 7231 } while (str.length); 7232 return [{ 7233 expr: tokens.join('+'), 7234 name: 'expr', 7235 type: 'expr' 7236 }]; 7237 } 7238 7239 function getChildren(arr) { 7240 var count = 0; 7241 for (var i = 0, el; el = arr[i++];) {
7242 if (el.nodeName === '#document-fragment') { 7243 count += getChildren(el.children); 7244 } else { 7245 count += 1; 7246 } 7247 } 7248 return count; 7249 } 7250 function groupTree(parent, children) { 7251 children && children.forEach(function (vdom) { 7252 if (!vdom) return; 7253 var vlength = vdom.children && getChildren(vdom.children); 7254 if (vdom.nodeName === '#document-fragment') { 7255 var dom = createFragment(); 7256 } else { 7257 dom = avalon.vdom(vdom, 'toDOM'); 7258 var domlength = dom.childNodes && dom.childNodes.length; 7259 if (domlength && vlength && domlength > vlength) { 7260 if (!appendChildMayThrowError[dom.nodeName]) { 7261 avalon.clearHTML(dom); 7262 } 7263 } 7264 } 7265 if (vlength) { 7266 groupTree(dom, vdom.children); 7267 if (vdom.nodeName === 'select') { 7268 var values = []; 7269 getSelectedValue(vdom, values); 7270 lookupOption(vdom, values); 7271 } 7272 } 7273 //é«çº§çæ¬å¯ä»¥å°è¯ querySelectorAll 7274 7275 try { 7276 if (!appendChildMayThrowError[parent.nodeName]) { 7277 parent.appendChild(dom); 7278 } 7279 } catch (e) {} 7280 }); 7281 } 7282 7283 function dumpTree(elem) { 7284 var firstChild; 7285 while (firstChild = elem.firstChild) { 7286 if (firstChild.nodeType === 1) { 7287 dumpTree(firstChild); 7288 } 7289 elem.removeChild(firstChild); 7290 } 7291 } 7292 7293 function getRange(childNodes, node) { 7294 var i = childNodes.indexOf(node) + 1; 7295 var deep = 1, 7296 nodes = [], 7297 end; 7298 nodes.start = i; 7299 while (node = childNodes[i++]) { 7300 nodes.push(node); 7301 if (node.nodeName === '#comment') { 7302 if (startWith(node.nodeValue, 'ms-for:')) { 7303 deep++; 7304 } else if (node.nodeValue === 'ms-for-end:') { 7305 deep--; 7306 if (deep === 0) { 7307 end = node; 7308 nodes.pop(); 7309 break; 7310 } 7311 } 7312 } 7313 } 7314 nodes.end = end; 7315 return nodes; 7316 } 7317 7318 function startWith(long, short) { 7319 return long.indexOf(short) === 0; 7320 } 7321 7322 var appendChildMayThrowError = { 7323 '#text': 1, 7324 '#comment': 1, 7325 script: 1, 7326 style: 1, 7327 noscript: 1 7328 }; 7329 7330 /** 7331 * çæä¸ä¸ªæ¸²æå¨,å¹¶ä½ä¸ºå®ç¬¬ä¸ä¸ªéå°çms-controller对åºçVMç$render屿§ 7332 * @param {String|DOM} node 7333 * @param {ViewModel|Undefined} vm 7334 * @param {Function|Undefined} beforeReady 7335 * @returns {Render} 7336 */ 7337 avalon.scan = function (node, vm, beforeReady) { 7338 return new Render(node, vm, beforeReady || avalon.noop); 7339 }; 7340 7341 /** 7342 * avalon.scan çå é¨å®ç° 7343 */
7344 function Render(node, vm, beforeReady) { 7345 this.root = node; //å¦æä¼ å ¥çå符串,ç¡®ä¿åªæä¸ä¸ªæ ç¾ä½ä¸ºæ ¹èç¹ 7346 this.vm = vm; 7347 this.beforeReady = beforeReady; 7348 this.bindings = []; //æ¶éå¾ å å·¥çç»å®å±æ§ 7349 this.callbacks = []; 7350 this.directives = []; 7351 this.init(); 7352 } 7353 7354 Render.prototype = { 7355 /** 7356 * å¼å§æ«ææå®åºå 7357 * æ¶éç»å®å±æ§ 7358 * çææä»¤å¹¶å»ºç«ä¸VMçå ³è 7359 */ 7360 init: function init() { 7361 var vnodes; 7362 if (this.root && this.root.nodeType > 0) { 7363 vnodes = fromDOM(this.root); //转æ¢èæDOM 7364 //å°æ«æåºåçæ¯ä¸ä¸ªèç¹ä¸å ¶ç¶èç¹å离,æ´å°æä»¤å¯¹DOMæä½æ¶,对é¦å±è¾åºé æçé¢ç¹éç» 7365 dumpTree(this.root); 7366 } else if (typeof this.root === 'string') { 7367 vnodes = fromString(this.root); //转æ¢èæDOM 7368 } else { 7369 return avalon.warn('avalon.scan first argument must element or HTML string'); 7370 } 7371 7372 this.root = vnodes[0]; 7373 this.vnodes = vnodes; 7374 this.scanChildren(vnodes, this.vm, true); 7375 }, 7376 scanChildren: function scanChildren(children, scope, isRoot) { 7377 for (var i = 0; i < children.length; i++) { 7378 var vdom = children[i]; 7379 switch (vdom.nodeName) { 7380 case '#text': 7381 scope && this.scanText(vdom, scope); 7382 break; 7383 case '#comment': 7384 scope && this.scanComment(vdom, scope, children); 7385 break; 7386 case '#document-fragment': 7387 this.scanChildren(vdom.children, scope, false); 7388 break; 7389 default: 7390 this.scanTag(vdom, scope, children, false); 7391 break; 7392 } 7393 } 7394 if (isRoot) { 7395 this.complete(); 7396 } 7397 }, 7398 7399 7400 /** 7401 * 仿æ¬èç¹è·åæä»¤ 7402 * @param {type} vdom 7403 * @param {type} scope 7404 * @returns {undefined} 7405 */ 7406 scanText: function scanText(vdom, scope) { 7407 if (config.rexpr.test(vdom.nodeValue)) { 7408 this.bindings.push([vdom, scope, { 7409 nodeValue: vdom.nodeValue 7410 }]); 7411 } 7412 }, 7413 7414 7415 /** 7416 * 仿³¨éèç¹è·åæä»¤ 7417 * @param {type} vdom 7418 * @param {type} scope 7419 * @param {type} parentChildren 7420 * @returns {undefined} 7421 */ 7422 scanComment: function scanComment(vdom, scope, parentChildren) { 7423 if (startWith(vdom.nodeValue, 'ms-for:')) { 7424 this.getForBinding(vdom, scope, parentChildren); 7425 } 7426 }, 7427 7428 7429 /** 7430 * ä»å ç´ èç¹çnodeNameä¸å±æ§ä¸è·åæä»¤ 7431 * @param {type} vdom 7432 * @param {type} scope 7433 * @param {type} parentChildren 7434 * @param {type} isRoot ç¨äºæ§è¡completeæ¹æ³ 7435 * @returns {undefined} 7436 */ 7437 scanTag: function scanTag(vdom, scope, parentChildren, isRoot) { 7438 var dirs = {}, 7439 attrs = vdom.props, 7440 hasDir, 7441 hasFor; 7442 for (var attr in attrs) { 7443 var value = attrs[attr]; 7444 var oldName = attr; 7445 if (attr.charAt(0) === ':') { 7446 attr = 'ms-' + attr.slice(1); 7447 } 7448 if (startWith(attr, 'ms-')) { 7449 dirs[attr] = value; 7450 var type = attr.match(/\w+/g)[1]; 7451 type = eventMap[type] || type; 7452 if (!directives[type]) { 7453 avalon.warn(attr + ' has not registered!'); 7454 } 7455 hasDir = true; 7456 } 7457 if (attr === 'ms-for') { 7458 hasFor = value; 7459 delete attrs[oldName]; 7460 } 7461 } 7462 var $id = dirs['ms-important'] || dirs['ms-controller']; 7463 if ($id) { 7464 /** 7465 * å端渲æ 7466 * serverTemplateså端ç»avalonæ·»å ç对象,éé¢é½æ¯æ¨¡æ¿,
7467 * å°åæ¥å端渲æå¥½çåºååè¿åæåå§æ ·å,åè¢«æ«æ 7468 */ 7469 var templateCaches = avalon.serverTemplates; 7470 var temp = templateCaches && templateCaches[$id]; 7471 if (temp) { 7472 avalon.log('åç«¯åæ¬¡æ¸²æåç«¯ä¼ è¿æ¥ç模æ¿'); 7473 var node = fromString(temp)[0]; 7474 for (var i in node) { 7475 vdom[i] = node[i]; 7476 } 7477 delete templateCaches[$id]; 7478 this.scanTag(vdom, scope, parentChildren, isRoot); 7479 return; 7480 } 7481 //æ¨ç®åºæä»¤ç±»å 7482 var type = dirs['ms-important'] === $id ? 'important' : 'controller'; 7483 //æ¨ç®åºç¨æ·å®ä¹æ¶å±æ§å,æ¯ä½¿ç¨ms-屿§è¿æ¯:屿§ 7484 var attrName = 'ms-' + type in attrs ? 'ms-' + type : ':' + type; 7485 7486 if (inBrowser) { 7487 delete attrs[attrName]; 7488 } 7489 var dir = directives[type]; 7490 scope = dir.getScope.call(this, $id, scope); 7491 if (!scope) { 7492 return; 7493 } else { 7494 var clazz = attrs['class']; 7495 if (clazz) { 7496 attrs['class'] = (' ' + clazz + ' ').replace(' ms-controller ', '').trim(); 7497 } 7498 } 7499 var render = this; 7500 scope.$render = render; 7501 this.callbacks.push(function () { 7502 //ç¨äºå é¤ms-controller 7503 dir.update.call(render, vdom, attrName, $id); 7504 }); 7505 } 7506 if (hasFor) { 7507 if (vdom.dom) { 7508 vdom.dom.removeAttribute(oldName); 7509 } 7510 return this.getForBindingByElement(vdom, scope, parentChildren, hasFor); 7511 } 7512 7513 if (/^ms\-/.test(vdom.nodeName)) { 7514 attrs.is = vdom.nodeName; 7515 } 7516 7517 if (attrs['is']) { 7518 if (!dirs['ms-widget']) { 7519 dirs['ms-widget'] = '{}'; 7520 } 7521 hasDir = true; 7522 } 7523 if (hasDir) { 7524 this.bindings.push([vdom, scope, dirs]); 7525 } 7526 var children = vdom.children; 7527 //妿åå¨åèç¹,å¹¶ä¸ä¸æ¯å®¹å¨å ç´ (script, stype, textarea, xmp...) 7528 if (!orphanTag[vdom.nodeName] && children && children.length && !delayCompileNodes(dirs)) { 7529 this.scanChildren(children, scope, false); 7530 } 7531 }, 7532 7533 7534 /** 7535 * å°ç»å®å±æ§è½¬æ¢ä¸ºæä»¤ 7536 * æ§è¡åç§åè°ä¸ä¼åæä»¤ 7537 * @returns {undefined} 7538 */ 7539 complete: function complete() { 7540 this.yieldDirectives(); 7541 this.beforeReady(); 7542 if (inBrowser) { 7543 var root$$1 = this.root; 7544 if (inBrowser) { 7545 var rootDom = avalon.vdom(root$$1, 'toDOM'); 7546 groupTree(rootDom, root$$1.children); 7547 } 7548 } 7549 7550 this.mount = true; 7551 var fn; 7552 while (fn = this.callbacks.pop()) { 7553 fn(); 7554 } 7555 this.optimizeDirectives(); 7556 }, 7557 7558 7559 /** 7560 * å°æ¶éå°çç»å®å±æ§è¿è¡æ·±å å·¥,æåè½¬æ¢æä»¤ 7561 * @returns {Array<tuple>} 7562 */ 7563 yieldDirectives: function yieldDirectives() { 7564 var tuple; 7565 while (tuple = this.bindings.shift()) { 7566 var vdom = tuple[0], 7567 scope = tuple[1], 7568 dirs = tuple[2], 7569 bindings = []; 7570 if ('nodeValue' in dirs) { 7571 bindings = parseInterpolate(dirs); 7572 } else if (!('ms-skip' in dirs)) { 7573 bindings = parseAttributes(dirs, tuple); 7574 } 7575 for (var i = 0, binding; binding = bindings[i++];) { 7576 var dir = directives[binding.type]; 7577 if (!inBrowser && /on|duplex|active|hover/.test(binding.type)) { 7578 continue; 7579 } 7580 if (dir.beforeInit) { 7581 dir.beforeInit.call(binding); 7582 } 7583 7584 var directive$$1 = new Directive(scope, binding, vdom, this); 7585 this.directives.push(directive$$1); 7586 } 7587 } 7588 }, 7589 7590 7591 /** 7592 * ä¿®æ¹æä»¤çupdateä¸callbackæ¹æ³,让å®ä»¬ä»¥åæ§è¡æ¶æ´å 髿 7593 * @returns {undefined} 7594 */ 7595 optimizeDirectives: function optimizeDirectives() { 7596 for (var i = 0, el; el = this.directives[i++];) { 7597 el.callback = directives[el.type].update; 7598 el.update = newUpdate; 7599 el._isScheduled = false;
7600 } 7601 }, 7602 7603 update: function update() { 7604 for (var i = 0, el; el = this.directives[i++];) { 7605 el.update(); 7606 } 7607 }, 7608 7609 /** 7610 * éæ¯æææä»¤ 7611 * @returns {undefined} 7612 */ 7613 dispose: function dispose() { 7614 var list = this.directives || []; 7615 for (var i = 0, el; el = list[i++];) { 7616 el.dispose(); 7617 } 7618 //鲿¢å ¶ä»å°æ¹çthis.innerRender && this.innerRender.disposeæ¥é 7619 for (var _i6 in this) { 7620 if (_i6 !== 'dispose') delete this[_i6]; 7621 } 7622 }, 7623 7624 7625 /** 7626 * å°å¾ªç¯åºå转æ¢ä¸ºforæä»¤ 7627 * @param {type} begin 注éèç¹ 7628 * @param {type} scope 7629 * @param {type} parentChildren 7630 * @param {type} userCb 循ç¯ç»æåè° 7631 * @returns {undefined} 7632 */ 7633 getForBinding: function getForBinding(begin, scope, parentChildren, userCb) { 7634 var expr = begin.nodeValue.replace('ms-for:', '').trim(); 7635 begin.nodeValue = 'ms-for:' + expr; 7636 var nodes = getRange(parentChildren, begin); 7637 var end = nodes.end; 7638 var fragment = avalon.vdom(nodes, 'toHTML'); 7639 parentChildren.splice(nodes.start, nodes.length); 7640 begin.props = {}; 7641 this.bindings.push([begin, scope, { 7642 'ms-for': expr 7643 }, { 7644 begin: begin, 7645 end: end, 7646 expr: expr, 7647 userCb: userCb, 7648 fragment: fragment, 7649 parentChildren: parentChildren 7650 }]); 7651 }, 7652 7653 7654 /** 7655 * å¨å¸¦ms-forå ç´ èç¹ææ·»å 两个注éèç¹,ç»æå¾ªç¯åºå 7656 * @param {type} vdom 7657 * @param {type} scope 7658 * @param {type} parentChildren 7659 * @param {type} expr 7660 * @returns {undefined} 7661 */ 7662 getForBindingByElement: function getForBindingByElement(vdom, scope, parentChildren, expr) { 7663 var index = parentChildren.indexOf(vdom); //忥另ms-forçå ç´ èç¹ 7664 var props = vdom.props; 7665 var begin = { 7666 nodeName: '#comment', 7667 nodeValue: 'ms-for:' + expr 7668 }; 7669 if (props.slot) { 7670 begin.slot = props.slot; 7671 delete props.slot; 7672 } 7673 var end = { 7674 nodeName: '#comment', 7675 nodeValue: 'ms-for-end:' 7676 }; 7677 parentChildren.splice(index, 1, begin, vdom, end); 7678 this.getForBinding(begin, scope, parentChildren, props['data-for-rendered']); 7679 } 7680 }; 7681 var viewID; 7682 7683 function newUpdate() { 7684 var oldVal = this.beforeUpdate(); 7685 var newVal = this.value = this.get(); 7686 if (this.callback && this.diff(newVal, oldVal)) { 7687 this.callback(this.node, this.value); 7688 var vm = this.vm; 7689 var $render = vm.$render; 7690 var list = vm.$events['onViewChange']; 7691 /* istanbul ignore if */ 7692 if (list && $render && $render.root && !avalon.viewChanging) { 7693 if (viewID) { 7694 clearTimeout(viewID); 7695 viewID = null; 7696 } 7697 viewID = setTimeout(function () { 7698 list.forEach(function (el) { 7699 el.callback.call(vm, { 7700 type: 'viewchange', 7701 target: $render.root, 7702 vmodel: vm 7703 }); 7704 }); 7705 }); 7706 } 7707 } 7708 this._isScheduled = false; 7709 } 7710 7711 var events = 'onInit,onReady,onViewChange,onDispose,onEnter,onLeave'; 7712 var componentEvents = avalon.oneObject(events); 7713 7714 function toObject(value) { 7715 var value = platform.toJson(value); 7716 if (Array.isArray(value)) { 7717 var v = {}; 7718 value.forEach(function (el) { 7719 el && avalon.shadowCopy(v, el); 7720 }); 7721 return v; 7722 } 7723 return value; 7724 } 7725 var componentQueue = []; 7726 avalon.directive('widget', { 7727 delay: true, 7728 priority: 4, 7729 deep: true,
7730 init: function init() { 7731 //cached屿§å¿ é¡»å®ä¹å¨ç»ä»¶å®¹å¨éé¢,䏿¯templateä¸ 7732 var vdom = this.node; 7733 this.cacheVm = !!vdom.props.cached; 7734 if (vdom.dom && vdom.nodeName === '#comment') { 7735 var comment = vdom.dom; 7736 } 7737 var oldValue = this.getValue(); 7738 var value = toObject(oldValue); 7739 //å¤é¨VMä¸å é¨VM 7740 // ï¼ï¼ï¼å建ç»ä»¶çVMï¼ï¼BEGINï¼ï¼ï¼ 7741 var is = vdom.props.is || value.is; 7742 this.is = is; 7743 var component = avalon.components[is]; 7744 //å¤é¨ä¼ å ¥çæ»å¤§äºå é¨ 7745 if (!('fragment' in this)) { 7746 if (!vdom.isVoidTag) { 7747 //æåç»ä»¶å®¹å¨å é¨çä¸è¥¿ä½ä¸ºæ¨¡æ¿ 7748 var text = vdom.children[0]; 7749 if (text && text.nodeValue) { 7750 this.fragment = text.nodeValue; 7751 } else { 7752 this.fragment = avalon.vdom(vdom.children, 'toHTML'); 7753 } 7754 } else { 7755 this.fragment = false; 7756 } 7757 } 7758 //妿ç»ä»¶è¿æ²¡ææ³¨åï¼é£ä¹å°åå ç´ åæä¸ä¸ªå ä½ç¨ç注éèç¹ 7759 if (!component) { 7760 this.readyState = 0; 7761 vdom.nodeName = '#comment'; 7762 vdom.nodeValue = 'unresolved component placeholder'; 7763 delete vdom.dom; 7764 avalon.Array.ensure(componentQueue, this); 7765 return; 7766 } 7767 7768 //妿æ¯é空å ç´ ï¼æ¯å¦è¯´xmp, ms-*, template 7769 var id = value.id || value.$id; 7770 var hasCache = avalon.vmodels[id]; 7771 var fromCache = false; 7772 // this.readyState = 1 7773 if (hasCache) { 7774 comVm = hasCache; 7775 this.comVm = comVm; 7776 replaceRoot(this, comVm.$render); 7777 fromCache = true; 7778 } else { 7779 if (typeof component === 'function') { 7780 component = new component(value); 7781 } 7782 var comVm = createComponentVm(component, value, is); 7783 this.readyState = 1; 7784 fireComponentHook(comVm, vdom, 'Init'); 7785 this.comVm = comVm; 7786 7787 // ï¼ï¼ï¼å建ç»ä»¶çVMï¼ï¼ENDï¼ï¼ï¼ 7788 var innerRender = avalon.scan(component.template, comVm); 7789 comVm.$render = innerRender; 7790 replaceRoot(this, innerRender); 7791 var nodesWithSlot = []; 7792 var directives$$1 = []; 7793 if (this.fragment || component.soleSlot) { 7794 var curVM = this.fragment ? this.vm : comVm; 7795 var curText = this.fragment || '{{##' + component.soleSlot + '}}'; 7796 var childBoss = avalon.scan('<div>' + curText + '</div>', curVM, function () { 7797 nodesWithSlot = this.root.children; 7798 }); 7799 directives$$1 = childBoss.directives; 7800 this.childBoss = childBoss; 7801 for (var i in childBoss) { 7802 delete childBoss[i]; 7803 } 7804 } 7805 Array.prototype.push.apply(innerRender.directives, directives$$1); 7806 7807 var arraySlot = [], 7808 objectSlot = {}; 7809 //ä»ç¨æ·åçå ç´ å é¨ æ¶éè¦ç§»å¨å° æ°å建çç»ä»¶å é¨çå ç´ 7810 if (component.soleSlot) { 7811 arraySlot = nodesWithSlot; 7812 } else { 7813 nodesWithSlot.forEach(function (el, i) { 7814 //è¦æ±å¸¦slot屿§ 7815 if (el.slot) { 7816 var nodes = getRange(nodesWithSlot, el); 7817 nodes.push(nodes.end); 7818 nodes.unshift(el); 7819 objectSlot[el.slot] = nodes; 7820 } else if (el.props) { 7821 var name = el.props.slot; 7822 if (name) { 7823 delete el.props.slot; 7824 if (Array.isArray(objectSlot[name])) { 7825 objectSlot[name].push(el); 7826 } else { 7827 objectSlot[name] = [el]; 7828 } 7829 } 7830 } 7831 }); 7832 }
7833 //å°åæ¥å ç´ çææå©åï¼å ¨é¨ç§»å¨æ°çå ç´ ç第ä¸ä¸ªslotçä½ç½®ä¸ 7834 if (component.soleSlot) { 7835 insertArraySlot(innerRender.vnodes, arraySlot); 7836 } else { 7837 insertObjectSlot(innerRender.vnodes, objectSlot); 7838 } 7839 } 7840 7841 if (comment) { 7842 var dom = avalon.vdom(vdom, 'toDOM'); 7843 comment.parentNode.replaceChild(dom, comment); 7844 comVm.$element = innerRender.root.dom = dom; 7845 delete this.reInit; 7846 } 7847 7848 //å¤çDOMèç¹ 7849 7850 dumpTree(vdom.dom); 7851 comVm.$element = vdom.dom; 7852 groupTree(vdom.dom, vdom.children); 7853 if (fromCache) { 7854 fireComponentHook(comVm, vdom, 'Enter'); 7855 } else { 7856 fireComponentHook(comVm, vdom, 'Ready'); 7857 } 7858 }, 7859 diff: function diff(newVal, oldVal) { 7860 if (cssDiff.call(this, newVal, oldVal)) { 7861 return true; 7862 } 7863 }, 7864 7865 update: function update(vdom, value) { 7866 //this.oldValue = value //â â 鲿¢éå½ 7867 7868 switch (this.readyState) { 7869 case 0: 7870 if (this.reInit) { 7871 this.init(); 7872 this.readyState++; 7873 } 7874 break; 7875 case 1: 7876 this.readyState++; 7877 break; 7878 default: 7879 this.readyState++; 7880 var comVm = this.comVm; 7881 avalon.viewChanging = true; 7882 avalon.transaction(function () { 7883 for (var i in value) { 7884 if (comVm.hasOwnProperty(i)) { 7885 if (Array.isArray(value[i])) { 7886 comVm[i] = value[i].concat(); 7887 } else { 7888 comVm[i] = value[i]; 7889 } 7890 } 7891 } 7892 }); 7893 7894 //è¦ä¿è¯è¦å 触åå©åçViewChange ç¶ååå°å®èªå·±çViewChange 7895 fireComponentHook(comVm, vdom, 'ViewChange'); 7896 delete avalon.viewChanging; 7897 break; 7898 } 7899 this.value = avalon.mix(true, {}, value); 7900 }, 7901 beforeDispose: function beforeDispose() { 7902 var comVm = this.comVm; 7903 if (!this.cacheVm) { 7904 fireComponentHook(comVm, this.node, 'Dispose'); 7905 comVm.$hashcode = false; 7906 delete avalon.vmodels[comVm.$id]; 7907 this.innerRender && this.innerRender.dispose(); 7908 } else { 7909 fireComponentHook(comVm, this.node, 'Leave'); 7910 } 7911 } 7912 }); 7913 7914 function replaceRoot(instance, innerRender) { 7915 instance.innerRender = innerRender; 7916 var root$$1 = innerRender.root; 7917 var vdom = instance.node; 7918 var slot = vdom.props.slot; 7919 for (var i in root$$1) { 7920 vdom[i] = root$$1[i]; 7921 } 7922 if (vdom.props && slot) { 7923 vdom.props.slot = slot; 7924 } 7925 innerRender.root = vdom; 7926 innerRender.vnodes[0] = vdom; 7927 } 7928 7929 function fireComponentHook(vm, vdom, name) { 7930 var list = vm.$events['on' + name]; 7931 if (list) { 7932 list.forEach(function (el) { 7933 setTimeout(function () { 7934 el.callback.call(vm, { 7935 type: name.toLowerCase(), 7936 target: vdom.dom, 7937 vmodel: vm 7938 }); 7939 }, 0); 7940 }); 7941 } 7942 } 7943 7944 function createComponentVm(component, value, is) { 7945 var hooks = []; 7946 var defaults = component.defaults; 7947 collectHooks(defaults, hooks); 7948 collectHooks(value, hooks); 7949 var obj = {}; 7950 for (var i in defaults) { 7951 var val = value[i]; 7952 if (val == null) { 7953 obj[i] = defaults[i]; 7954 } else { 7955 obj[i] = val; 7956 } 7957 } 7958 obj.$id = value.id || value.$id || avalon.makeHashCode(is); 7959 delete obj.id; 7960 var def = avalon.mix(true, {}, obj); 7961 var vm = avalon.define(def); 7962 hooks.forEach(function (el) { 7963 vm.$watch(el.type, el.cb); 7964 }); 7965 return vm; 7966 } 7967 7968 function collectHooks(a, list) { 7969 for (var i in a) { 7970 if (componentEvents[i]) { 7971 if (typeof a[i] === 'function' && i.indexOf('on') === 0) { 7972 list.unshift({ 7973 type: i, 7974 cb: a[i] 7975 }); 7976 } 7977 //delete a[i] è¿éä¸è½å é¤,ä¼å¯¼è´åæ¬¡åæ¢æ¶æ²¡æonReady 7978 } 7979 } 7980 } 7981 7982 function resetParentChildren(nodes, arr) { 7983 var dir = arr && arr[0] && arr[0].forDir; 7984 if (dir) { 7985 dir.parentChildren = nodes; 7986 } 7987 } 7988 7989 function insertArraySlot(nodes, arr) { 7990 for (var i = 0, el; el = nodes[i]; i++) {
7991 if (el.nodeName === 'slot') { 7992 resetParentChildren(nodes, arr); 7993 nodes.splice.apply(nodes, [i, 1].concat(arr)); 7994 break; 7995 } else if (el.children) { 7996 insertArraySlot(el.children, arr); 7997 } 7998 } 7999 } 8000 8001 function insertObjectSlot(nodes, obj) { 8002 for (var i = 0, el; el = nodes[i]; i++) { 8003 if (el.nodeName === 'slot') { 8004 var name = el.props.name; 8005 resetParentChildren(nodes, obj[name]); 8006 nodes.splice.apply(nodes, [i, 1].concat(obj[name])); 8007 continue; 8008 } else if (el.children) { 8009 insertObjectSlot(el.children, obj); 8010 } 8011 } 8012 } 8013 8014 avalon.components = {}; 8015 avalon.component = function (name, component) { 8016 8017 component.extend = componentExtend; 8018 return addToQueue(name, component); 8019 }; 8020 function addToQueue(name, component) { 8021 avalon.components[name] = component; 8022 for (var el, i = 0; el = componentQueue[i]; i++) { 8023 if (el.is === name) { 8024 componentQueue.splice(i, 1); 8025 el.reInit = true; 8026 delete el.value; 8027 el.update(); 8028 i--; 8029 } 8030 } 8031 return component; 8032 } 8033 8034 function componentExtend(child) { 8035 var name = child.displayName; 8036 delete child.displayName; 8037 var obj = { defaults: avalon.mix(true, {}, this.defaults, child.defaults) }; 8038 if (child.soleSlot) { 8039 obj.soleSlot = child.soleSlot; 8040 } 8041 obj.template = child.template || this.template; 8042 return avalon.component(name, obj); 8043 } 8044 8045 return avalon; 8046});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.