This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

重写框架组件机制;重写pages组件;优化request插件

old
宇天 2017-04-13 01:11:34 +08:00
parent b5d4ee1cc1
commit 9848dd63bd
14 changed files with 2657 additions and 590 deletions

BIN
js/lib/layer.tar.gz Normal file

Binary file not shown.

View File

@ -217,7 +217,7 @@ define(['yua', 'lib/drag', 'css!./skin/def'], function(yua){
layerObj[conf].show = true layerObj[conf].show = true
if(!yua.vmodels[conf]){ if(!yua.vmodels[conf]){
yua.define(layerObj[conf].obj.init) yua(layerObj[conf].obj.init)
} }
yua.scan(layerDom[conf][1]) yua.scan(layerDom[conf][1])
@ -386,13 +386,13 @@ define(['yua', 'lib/drag', 'css!./skin/def'], function(yua){
document.body.appendChild(layerDom[this.init.$id][0]) document.body.appendChild(layerDom[this.init.$id][0])
//仅在允许点击遮罩时,初始化控制器,减少资源消耗 //仅在允许点击遮罩时,初始化控制器,减少资源消耗
if(this.init.shadeClose){ if(this.init.shadeClose){
yua.define(this.cInit) yua(this.cInit)
yua.scan(layerDom[this.init.$id][0]) yua.scan(layerDom[this.init.$id][0])
} }
} }
document.body.appendChild(layerDom[this.init.$id][1]) document.body.appendChild(layerDom[this.init.$id][1])
yua.define(this.init) yua(this.init)
yua.scan(layerDom[this.init.$id][1]) yua.scan(layerDom[this.init.$id][1])
return this return this
}, },

1324
js/lib/marked/marked.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,57 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Examples-1</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="../css/base.min.css" rel="stylesheet">
<style>
.do-mod-test {width:800px;height:100px;margin:30px;padding:30px;border:1px solid #ddd;}
.do-mod-test .date-start {width:100%;height:35px;}
</style>
</head>
<body>
<div class="do-mod-test" ms-controller="test">
<div class="pages" ms-widget="pages" data-pages-skin="red"></div>
</div>
<script src="../avalon.modern.min.js"></script>
<script>
;(function(A){
require(['./pages/pages'], function(){
var test = A.define({
$id: 'test',
aa: '112233',
pages: {
callback: function(id){
console.log(id);
},
total: 30
}
});
A.scan();
})
})(avalon);
</script>
</body>
</html>

View File

@ -1,34 +1,10 @@
.widget-pages .do-ui-pages {width:100%;height:30px;text-align:center;} .do-pages {width:100%;height:auto;text-align:center;font-size:13px;}
.widget-pages.h20 .do-ui-pages {height:20px;} .do-pages a.normal,.do-pages a.disabled,.do-pages a.curr {display:inline-block;width:auto;height:30px;padding:0 10px;margin:0 3px;line-height:30px;text-decoration:none;border-radius:3px;cursor:pointer;background:#6bb294;color:#fff;}
.widget-pages .do-ui-pages a {display:inline-block;width:auto;min-width:20px;height:30px;padding:0 10px;margin:0 3px;line-height:28px;} .do-pages a.disabled,.do-pages a.curr {background:none;color:#666;cursor:default}
.widget-pages .do-ui-pages .curr,.widget-pages .do-ui-pages .more {line-height:30px;padding:0;border:none!important;background:none!important;color:#666!important;cursor:default} .do-pages a.disabled {padding:0;}
.widget-pages.h20 .do-ui-pages a {min-width:10px;height:20px;line-height:18px;} .do-pages a.curr {font-weight:bold;font-size:15px;color:#429572;}
.widget-pages.h20 .do-ui-pages .curr,.widget-pages.h20 .do-ui-pages .more {line-height:20px;}
.widget-pages .do-ui-pages .page-jump {display:inline-block;} .do-pages a.normal:hover{background:#429572;}
.widget-pages .do-ui-pages .page-jump span,.widget-pages .do-ui-pages .page-jump input{display:inline-block;} .do-pages a.normal:active{background:#64bf99;}
.widget-pages .do-ui-pages .page-jump input {width:25px;height:18px;padding:0 3px;background:none;border:1px solid #ddd;} .do-pages .input-box,.do-pages .input-box span,.do-pages .input-box input {display:inline-block}
.do-pages .input-box input {width:25px;height:20px;padding:0 3px;background:#fff;border:1px solid #ddd}
.widget-pages.skin-default .do-ui-pages a {border:1px solid #ddd;background:#f3f3f3;color:#666;}
.widget-pages.skin-default .do-ui-pages a:hover {border:1px solid #e3e3e3;background:#e3e3e3;color:#666;}
.widget-pages.skin-default .do-ui-pages a:active {border:1px solid #ccc;background:#ccc;color:#666;}
.widget-pages.skin-blue .do-ui-pages a {border:1px solid #1b9af7;background:#1b9af7;color:#fff;}
.widget-pages.skin-blue .do-ui-pages a:hover {border:1px solid #13b5ff;background:#13b5ff;color:#fff;}
.widget-pages.skin-blue .do-ui-pages a:active {border:1px solid #1682cf;background:#1682cf;color:#fff;}
.widget-pages.skin-red .do-ui-pages a {border:1px solid #ff4351;background:#ff4351;color:#fff;}
.widget-pages.skin-red .do-ui-pages a:hover {border:1px solid #ff7680;background:#ff7680;color:#fff;}
.widget-pages.skin-red .do-ui-pages a:active {border:1px solid #f64c59;background:#f64c59;color:#fff;}
.widget-pages.skin-yellow .do-ui-pages a {border:1px solid #feae1b;background:#feae1b;color:#fff;}
.widget-pages.skin-yellow .do-ui-pages a:hover {border:1px solid #fec04e;background:#fec04e;color:#fff;}
.widget-pages.skin-yellow .do-ui-pages a:active {border:1px solid #f3ab26;background:#f3ab26;color:#fff;}
.widget-pages.skin-green .do-ui-pages a {border:1px solid #a5de37;background:#a5de37;color:#fff;}
.widget-pages.skin-green .do-ui-pages a:hover {border:1px solid #b9e563;background:#b9e563;color:#fff;}
.widget-pages.skin-green .do-ui-pages a:active {border:1px solid #a1d243;background:#a1d243;color:#fff;}
.widget-pages.skin-purple .do-ui-pages a {border:1px solid #7b72e9;background:#7b72e9;color:#fff;}
.widget-pages.skin-purple .do-ui-pages a:hover {border:1px solid #a49ef0;background:#a49ef0;color:#fff;}
.widget-pages.skin-purple .do-ui-pages a:active {border:1px solid #827ae1;background:#827ae1;color:#fff;}

33
js/lib/pages/pages.htm Normal file
View File

@ -0,0 +1,33 @@
<div class="do-pages do-fn-noselect" :class="{{'skin-' + skin}}">
<a class="normal"
:if="curr > 1 && !simpleMode"
:attr="{href: $setUrl(1)}"
:text="btns.home"
:click="$jump($event, 1)"></a>
<a class="normal"
:if="curr > 1"
:attr="{href: $setUrl(curr - 1)}"
:text="btns.prev"
:click="$jump($event, curr - 1)"></a>
<a :if-loop="!simpleMode || curr === el"
:repeat="pageList"
:attr="{href: $setUrl(el)}"
:class="{normal: curr !== el && '...' !== el, disabled: '...' === el, curr: curr === el}"
:text="el"
:click="$jump($event, el)"></a>
<a class="normal"
:if="curr < total"
:attr="{href: $setUrl(curr + 1)}"
:click="$jump($event, curr + 1)">{{btns.next}}</a>
<a class="normal"
:if="curr < total && !simpleMode"
:attr="{href: $setUrl(total)}"
:click="$jump($event, total)">{{btns.end}}</a>
<div class="input-box" :if="inputJump && !simpleMode">
<span>共{{total}}页,跳转到第</span>
<input type="text" :duplex-number="input" :keyup="$jump($event)">
<span></span>
<a class="normal" :attr="{href: $setUrl(input)}" :click="$jump($event, input)">确定</a>
</div>
</div>

View File

@ -1,127 +1,111 @@
define(["avalon","text!./pages.tpl","css!./pages.css"], function (av, tpl) { "use strict";
define(["yua","text!./pages.htm", "css!./pages"], function(yua, tpl) {
var widget = av.ui.pages = function(ele, data, vms){ //计算页码列表
function calculate(vm){
if (vm.total < 2)
return vm.pageList.clear();
var opts = av.mix({}, data.pagesOptions); var arr = [],
var height = opts.height || '', mid = vm.curr < vm.max / 2 ? vm.max - vm.curr : Math.floor(vm.max / 2);
skin = opts.skin || 'default';
delete opts.skin; if(vm.curr - mid > 1){
delete opts.height; arr.push('...')
opts.pages = []; //无论是否定义,都会清掉,有点暴力 }
for (var i = vm.curr - mid; i < vm.curr + mid + 1 && i <= vm.total; i++){
if(i > 0){
arr.push(i)
}
}
if(vm.curr + mid < vm.total){
arr.push('...')
}
vm.pageList = arr
}
function update(pid, vm) {
if(pid < 1){
pid = vm.input = 1
}
if(pid > vm.total){
pid = vm.input = vm.total
}
if(pid !== vm.curr){
vm.curr = vm.input = pid
vm.$onJump(pid)
}
}
return yua.component('pages', {
$template: tpl,
$init: function(vm) {
calculate(vm)
vm.$setUrl = function(val) {
if(!vm.url
|| '...' === val
|| vm.curr === val
|| val > vm.total
|| 1 > val) {
opts.$id = data.pagesId;
opts.$init = function(scan){
ele.classList.add('widget-pages', 'skin-' + skin, 'do-fn-noselect');
height && ele.classList.add(height);//非空时才添加,避免报错
ele.innerHTML = tpl;
calPages(Pager);
scan()
};
opts.$remove = function() {
ele.innerHTML = ''
};
opts.setUrl = function(id){
if(!Pager.url || id === '...' || Pager.curr === id || id > Pager.total || id < 1)
return 'javascript:;' return 'javascript:;'
return Pager.url.replace('{id}', id) }else{
}; return vm.url.replace('{id}', val)
opts.onJump = function(event, id){ }
event.preventDefault()
id = id >> 0;
jump(id, Pager);
};
opts.jumpPage = function(event){
var pid = Pager.jumpTxt;
if(pid > Pager.total)
Pager.jumpTxt = Pager.total;
if(event.keyCode == 13)
return jump(pid, Pager);
} }
var Pager = av.define(opts); vm.$jump = function(ev, val) {
if ('...' !== val) {
var link = this.getAttribute('href') || this.getAttribute('xlink:href')
if (val !== void 0){
Pager.$watch('total', function(v, old){ if('javascript:;' !== link){
Pager.total = v >> 0 || 1; //自动转换成数字类型,防止传入的值为字符串时报错,如 '3' location.hash = link
old = old >> 0; }
(v !== old) && calPages(Pager); var pid = val >> 0;
update(pid, vm)
} else {
vm.input = vm.input >>> 0 || 1;
if(13 == ev.keyCode){
update(vm.input, vm)
}
}
}
}
vm.$watch('curr', function(val, old) {
val = (val >>> 0) || 1
old = old >>> 0
if(val !== old){
calculate(vm)
}
}) })
Pager.$watch('curr', function(v, old){ vm.$watch('total', function(val, old) {
v = v >> 0 || 1;//自动转换成数字类型 val = (val >>> 0) || 1
old = old >> 0; old = old >>> 0
Pager.curr = v; if(val !== old){
(v !== old) && calPages(Pager); calculate(vm)
}
}) })
return Pager;
}
/**
* [calPages 计算要显示的页码数组并赋值给pages]
* @param {[type]} Pager [分页vm对象]
*/
function calPages(Pager){
if(Pager.total < 2){
Pager.pages.clear();
return;
}
var pageArr = [], len = (Pager.curr < Pager.max / 2) ? Pager.max : Math.floor(Pager.max / 2);
if(Pager.curr - len > 1)
pageArr.push('...');
for(var i = Pager.curr - len; i < Pager.curr + len && i <= Pager.total; i++){
if(i > 0)
pageArr.push(i)
}
if(Pager.curr + len < Pager.total)
pageArr.push('...');
Pager.pages = pageArr;
}
/**
* [jump 内部跳转函数]
* @param {[type]} id [要跳转去的页码]
* @param {[type]} Pager [分页vm对象]
*/
function jump(id, Pager){
if(id < 1)
id = Pager.jumpTxt = 1;
if(id > Pager.total)
id = Pager.jumpTxt = Pager.total;
if(Pager.curr === id)
return;
Pager.curr = Pager.jumpTxt = id;
Pager.callback && Pager.callback(id);
calPages(Pager);
}
//默认参数
widget.defaults = {
curr: 1, //当前页
total: 1, // 总页数默认为1即页面上不会显示分页条
max: 5, // 最多显示页码数
url: 'javascript:;', //页码按钮上的url,如'#!/page-{id}.html',其中{id}会被替换成该页码
pageJump: !1, //是否显示跳转表单
simpleMode: !1, //简单模式,即只有上一页和下一页
jumpTxt: 1, //跳转输入框显示的页码
pages: [], //页码数组
btns: { //除页码本身外的按钮上的字符
prev: '<<',
next: '>>',
home: '首页',
end: '末页'
}, },
callback: null //点击页码/上/下/首/末页的回调,页码无效或者为当前页的时候不会触发 curr: 1,
} total: 1,
max: 5,
url: "javascript:;",
return av; inputJump: !1,
simpleMode: !1,
input: 1,
pageList: [],
btns: {
prev: "<<",
next: ">>",
home: "首页",
end: "末页"
},
$skipArray: ['max', 'btns', 'url'],
$setUrl: yua.noop,
$jump: yua.noop,
$onJump: yua.noop
}) })
});

View File

@ -1 +0,0 @@
.widget-pages .do-ui-pages{width:100%;height:30px;text-align:center}.widget-pages.h20 .do-ui-pages{height:20px}.widget-pages .do-ui-pages a{display:inline-block;width:auto;min-width:20px;height:30px;padding:0 10px;margin:0 3px;line-height:28px}.widget-pages .do-ui-pages .curr,.widget-pages .do-ui-pages .more{line-height:30px;padding:0;border:none!important;background:none!important;color:#666!important;cursor:default}.widget-pages.h20 .do-ui-pages a{min-width:10px;height:20px;line-height:18px}.widget-pages.h20 .do-ui-pages .curr,.widget-pages.h20 .do-ui-pages .more{line-height:20px}.widget-pages .do-ui-pages .page-jump,.widget-pages .do-ui-pages .page-jump input,.widget-pages .do-ui-pages .page-jump span{display:inline-block}.widget-pages .do-ui-pages .page-jump input{width:25px;height:18px;padding:0 3px;background:0 0;border:1px solid #ddd}.widget-pages.skin-default .do-ui-pages a{border:1px solid #ddd;background:#f3f3f3;color:#666}.widget-pages.skin-default .do-ui-pages a:hover{border:1px solid #e3e3e3;background:#e3e3e3;color:#666}.widget-pages.skin-default .do-ui-pages a:active{border:1px solid #ccc;background:#ccc;color:#666}.widget-pages.skin-blue .do-ui-pages a{border:1px solid #1b9af7;background:#1b9af7;color:#fff}.widget-pages.skin-blue .do-ui-pages a:hover{border:1px solid #13b5ff;background:#13b5ff;color:#fff}.widget-pages.skin-blue .do-ui-pages a:active{border:1px solid #1682cf;background:#1682cf;color:#fff}.widget-pages.skin-red .do-ui-pages a{border:1px solid #ff4351;background:#ff4351;color:#fff}.widget-pages.skin-red .do-ui-pages a:hover{border:1px solid #ff7680;background:#ff7680;color:#fff}.widget-pages.skin-red .do-ui-pages a:active{border:1px solid #f64c59;background:#f64c59;color:#fff}.widget-pages.skin-yellow .do-ui-pages a{border:1px solid #feae1b;background:#feae1b;color:#fff}.widget-pages.skin-yellow .do-ui-pages a:hover{border:1px solid #fec04e;background:#fec04e;color:#fff}.widget-pages.skin-yellow .do-ui-pages a:active{border:1px solid #f3ab26;background:#f3ab26;color:#fff}.widget-pages.skin-green .do-ui-pages a{border:1px solid #a5de37;background:#a5de37;color:#fff}.widget-pages.skin-green .do-ui-pages a:hover{border:1px solid #b9e563;background:#b9e563;color:#fff}.widget-pages.skin-green .do-ui-pages a:active{border:1px solid #a1d243;background:#a1d243;color:#fff}.widget-pages.skin-purple .do-ui-pages a{border:1px solid #7b72e9;background:#7b72e9;color:#fff}.widget-pages.skin-purple .do-ui-pages a:hover{border:1px solid #a49ef0;background:#a49ef0;color:#fff}.widget-pages.skin-purple .do-ui-pages a:active{border:1px solid #827ae1;background:#827ae1;color:#fff}

View File

@ -1 +0,0 @@
define(["avalon","text!./pages.tpl","css!./pages.css"],function(t,a){function e(t){if(t.total<2)return void t.pages.clear();var a=[],e=t.curr<t.max/2?t.max:Math.floor(t.max/2);t.curr-e>1&&a.push("...");for(var r=t.curr-e;r<t.curr+e&&r<=t.total;r++)r>0&&a.push(r);t.curr+e<t.total&&a.push("..."),t.pages=a}function r(t,a){1>t&&(t=a.jumpTxt=1),t>a.total&&(t=a.jumpTxt=a.total),a.curr!==t&&(a.curr=a.jumpTxt=t,a.callback&&a.callback(t),e(a))}var n=t.ui.pages=function(n,u){var c=t.mix({},u.pagesOptions),l=c.height||"",i=c.skin||"default";delete c.skin,delete c.height,c.pages=[],c.$id=u.pagesId,c.$init=function(t){n.classList.add("widget-pages","skin-"+i,"do-fn-noselect"),l&&n.classList.add(l),n.innerHTML=a,e(o),t()},c.$remove=function(){n.innerHTML=""},c.setUrl=function(t){return!o.url||"..."===t||o.curr===t||t>o.total||1>t?"javascript:;":o.url.replace("{id}",t)},c.onJump=function(t,a){t.preventDefault(),a>>=0,r(a,o)},c.jumpPage=function(t){var a=o.jumpTxt;return a>o.total&&(o.jumpTxt=o.total),13==t.keyCode?r(a,o):void 0};var o=t.define(c);return o.$watch("total",function(t,a){o.total=t>>0||1,a>>=0,t!==a&&e(o)}),o.$watch("curr",function(t,a){t=t>>0||1,a>>=0,o.curr=t,t!==a&&e(o)}),o};return n.defaults={curr:1,total:1,max:5,url:"javascript:;",pageJump:!1,simpleMode:!1,jumpTxt:1,pages:[],btns:{prev:"<<",next:">>",home:"首页",end:"末页"},callback:null},t});

View File

@ -1,13 +0,0 @@
<div class="do-ui-pages">
<a class="rd3" ms-if="curr > 1 && !simpleMode" ms-attr="{href: setUrl(1)}" ms-click="onJump($event, 1)">{{btns.home}}</a>
<a class="rd3" ms-if="curr > 1" ms-attr="{href: setUrl(curr - 1)}" ms-click="onJump($event, curr - 1)">{{btns.prev}}</a>
<a class="rd3" ms-if-loop="!simpleMode || curr === el" ms-repeat="pages" ms-attr="{href: setUrl(el)}" ms-class="curr: curr === el" ms-class-1="more: '...' === el" ms-click="onJump($event, el)">{{el}}</a>
<a class="rd3" ms-if="curr < total" ms-attr="{href: setUrl(curr + 1)}" ms-click="onJump($event, curr + 1)">{{btns.next}}</a>
<a class="rd3" ms-if="curr < total && !simpleMode" ms-attr="{href: setUrl(total)}" ms-click="onJump($event, total)">{{btns.end}}</a>
<div class="page-jump" ms-if="pageJump && !simpleMode">
<span>共{{total}}页,跳转到第</span>
<input type="text" ms-duplex-number="jumpTxt" ms-keyup="jumpPage($event)">
<span>页</span>
<a class="rd3" ms-attr="{href: setUrl(jumpTxt)}" ms-click="onJump($event, jumpTxt)">确定</a>
</div>
</div>

831
js/lib/prism/prism.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -15,6 +15,7 @@ define(function(){
url: (url + '').trim(), url: (url + '').trim(),
type: protocol || 'GET', type: protocol || 'GET',
form: '', form: '',
data: {},
headers: {}, headers: {},
timeoutID: 0, timeoutID: 0,
uuid: Math.random().toString(16).substr(2) uuid: Math.random().toString(16).substr(2)

View File

@ -8,12 +8,6 @@
(function(global, factory) { (function(global, factory) {
if (typeof module === "object" && typeof module.exports === "object") { if (typeof module === "object" && typeof module.exports === "object") {
// For CommonJS and CommonJS-like environments where a proper `window`
// is present, execute the factory and get yua.
// For environments that do not have a `window` with a `document`
// (such as Node.js), expose a factory as module.exports.
// This accentuates the need for the creation of a real `window`.
// e.g. var yua = require("yua")(window);
module.exports = global.document ? factory(global, true) : function(w) { module.exports = global.document ? factory(global, true) : function(w) {
if (!w.document) { if (!w.document) {
throw new Error("Yua只能运行在浏览器环境") throw new Error("Yua只能运行在浏览器环境")
@ -31,7 +25,7 @@
* 全局变量及方法 * * 全局变量及方法 *
**********************************************************************/ **********************************************************************/
var expose = Date.now() var expose = generateID()
//http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function //http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function
var DOC = window.document var DOC = window.document
var head = DOC.head //HEAD元素 var head = DOC.head //HEAD元素
@ -39,11 +33,9 @@ head.insertAdjacentHTML("afterBegin", '<yua :skip class="yua-hide"><style id="yu
var ifGroup = head.firstChild var ifGroup = head.firstChild
function log() { function log() {
if (yua.config.debug) {
// http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log // http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log
console.log.apply(console, arguments) console.log.apply(console, arguments)
} }
}
/** /**
* Creates a new object without a prototype. This object is useful for lookup without having to * Creates a new object without a prototype. This object is useful for lookup without having to
@ -64,7 +56,6 @@ var nullObject = {} //作用类似于noop只用于代码防御千万不要
var rword = /[^, ]+/g //切割字符串为一个个小块以空格或豆号分开它们结合replace实现字符串的forEach var rword = /[^, ]+/g //切割字符串为一个个小块以空格或豆号分开它们结合replace实现字符串的forEach
var rw20g = /\w+/g var rw20g = /\w+/g
var rsvg = /^\[object SVG\w*Element\]$/ var rsvg = /^\[object SVG\w*Element\]$/
var rwindow = /^\[object (?:Window|DOMWindow|global)\]$/
var oproto = Object.prototype var oproto = Object.prototype
var ohasOwn = oproto.hasOwnProperty var ohasOwn = oproto.hasOwnProperty
var serialize = oproto.toString var serialize = oproto.toString
@ -101,9 +92,9 @@ function oneObject(array, val) {
return result return result
} }
var generateID = function (mark) { function generateID(mark) {
mark = mark && (mark + '-') || 'yua-' mark = mark && (mark + '-') || 'yua-'
return mark + Math.floor(Date.now() / 1000).toString(16) + '-' + Math.random().toString(16).slice(2, 6) + '-' + Math.random().toString(16).slice(6, 10) return mark + Date.now().toString(16) + '-' + Math.random().toString(16).slice(2, 6)
} }
yua = function (el) { //创建jQuery式的无new 实例化结构 yua = function (el) { //创建jQuery式的无new 实例化结构
@ -148,11 +139,6 @@ yua.nextTick = new function () {// jshint ignore:line
* yua的静态方法定义区 * * yua的静态方法定义区 *
**********************************************************************/ **********************************************************************/
yua.init = function (el) {
this[0] = this.element = el
}
yua.fn = yua.prototype = yua.init.prototype
yua.type = function (obj) { //取得目标的类型 yua.type = function (obj) { //取得目标的类型
if (obj == null) { if (obj == null) {
return String(obj) return String(obj)
@ -167,9 +153,6 @@ yua.isFunction = function (fn) {
return serialize.call(fn) === "[object Function]" return serialize.call(fn) === "[object Function]"
} }
yua.isWindow = function (obj) {
return rwindow.test(serialize.call(obj))
}
/*判定是否是一个朴素的javascript对象Object不是DOM对象不是BOM对象不是自定义类的实例*/ /*判定是否是一个朴素的javascript对象Object不是DOM对象不是BOM对象不是自定义类的实例*/
yua.isPlainObject = function (obj) { yua.isPlainObject = function (obj) {
@ -177,6 +160,27 @@ yua.isPlainObject = function (obj) {
return serialize.call(obj) === "[object Object]" && Object.getPrototypeOf(obj) === oproto return serialize.call(obj) === "[object Object]" && Object.getPrototypeOf(obj) === oproto
} }
var VMODELS = yua.vmodels = {} //所有vmodel都储存在这里
yua.init = function (source) {
if(yua.isPlainObject(source)){
var $id = source.$id,vm;
if (!$id) {
log("warning: vm必须指定$id")
}
vm = modelFactory(source)
vm.$id = $id
return VMODELS[$id] = vm
}else{
this[0] = this.element = source
}
}
yua.fn = yua.prototype = yua.init.prototype
//与jQuery.extend方法可用于浅拷贝深拷贝 //与jQuery.extend方法可用于浅拷贝深拷贝
yua.mix = yua.fn.mix = function () { yua.mix = yua.fn.mix = function () {
var options, name, src, copy, copyIsArray, clone, var options, name, src, copy, copyIsArray, clone,
@ -491,8 +495,7 @@ if(!Date.prototype.format){
yua.mix({ yua.mix({
rword: rword, rword: rword,
subscribers: subscribers, subscribers: subscribers,
version: '1.0.0-touch', version: '1.0.0',
ui: {},
log: log, log: log,
slice: function (nodes, start, end) { slice: function (nodes, start, end) {
return aslice.call(nodes, start, end) return aslice.call(nodes, start, end)
@ -502,8 +505,6 @@ yua.mix({
error: function (str, e) { error: function (str, e) {
throw new (e || Error)(str)// jshint ignore:line throw new (e || Error)(str)// jshint ignore:line
}, },
/*将一个以空格或逗号隔开的字符串或数组,转换成一个键值都为1的对象*/
oneObject: oneObject,
/* yua.range(10) /* yua.range(10)
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
yua.range(1, 11) yua.range(1, 11)
@ -1079,7 +1080,6 @@ kernel.plugins = plugins
kernel.plugins['interpolate'](["{{", "}}"]) kernel.plugins['interpolate'](["{{", "}}"])
kernel.async = true kernel.async = true
kernel.debug = true
kernel.paths = {} kernel.paths = {}
kernel.shim = {} kernel.shim = {}
kernel.maxRepeatSize = 100 kernel.maxRepeatSize = 100
@ -1249,17 +1249,13 @@ function notifySubscribers(subs, args) {
//yua最核心的方法的两个方法之一另一个是yua.scan返回一个ViewModel(VM)
var VMODELS = yua.vmodels = {} //所有vmodel都储存在这里
yua.define = function (source) {
var $id = source.$id
if (!$id) {
log("warning: vm必须指定$id")
}
var vmodel = modelFactory(source)
vmodel.$id = $id
return VMODELS[$id] = vmodel
}
//一些不需要被监听的属性 //一些不需要被监听的属性
var $$skipArray = oneObject("$id,$watch,$fire,$events,$model,$skipArray,$active,$pathname,$up,$ups,$track,$accessors") var $$skipArray = oneObject("$id,$watch,$fire,$events,$model,$skipArray,$active,$pathname,$up,$ups,$track,$accessors")
@ -1628,8 +1624,13 @@ var $modelDescriptor = {
/********************************************************************* /*********************************************************************
* 监控数组:each, :repeat配合使用 * * 监控数组:repeat配合使用 *
**********************************************************************/ **********************************************************************/
var arrayMethods = ['push', 'pop', 'shift', 'unshift', 'splice'] var arrayMethods = ['push', 'pop', 'shift', 'unshift', 'splice']
@ -1941,6 +1942,23 @@ function getProxyIds(a, isArray) {
return ret.join(";") return ret.join(";")
} }
/********************************************************************* /*********************************************************************
* 定时GC回收机制 (基于1.6基于频率的GC) * * 定时GC回收机制 (基于1.6基于频率的GC) *
**********************************************************************/ **********************************************************************/
@ -2123,6 +2141,12 @@ yua.clearHTML = function(node) {
return node return node
} }
/********************************************************************* /*********************************************************************
* yua的原型方法定义区 * * yua的原型方法定义区 *
**********************************************************************/ **********************************************************************/
@ -3062,8 +3086,12 @@ function scanAttr(elem, vmodels, match) {
var rnoscanAttrBinding = /^if|widget|repeat$/ var rnoscanAttrBinding = /^if|widget|repeat$/
var rnoscanNodeBinding = /^html|include$/ var rnoscanNodeBinding = /^html|include$/
function scanNodeList(parent, vmodels) { function scanNodeList(elem, vmodels) {
var nodes = yua.slice(parent.childNodes) if(isWidget(elem)){
// elem = elem.content
log(elem)
}
var nodes = yua.slice(elem.childNodes)
scanNodeArray(nodes, vmodels) scanNodeArray(nodes, vmodels)
} }
@ -3078,21 +3106,18 @@ function scanNodeArray(nodes, vmodels) {
case 1: case 1:
var elem = node var elem = node
if (!elem.msResolved && elem.parentNode && elem.parentNode.nodeType === 1) { if (!elem.msResolved && elem.parentNode && elem.parentNode.nodeType === 1) {
var library = isWidget(elem) var widget = isWidget(elem)
if (library) {
var widget = elem.localName ? elem.localName.replace(library + ":", "") : elem.nodeName if (widget) {
var fullName = library + ":" + camelize(widget)
componentQueue.push({ componentQueue.push({
library: library,
element: elem, element: elem,
fullName: fullName,
widget: widget,
vmodels: vmodels, vmodels: vmodels,
name: "widget" name: widget
}) })
if (yua.components[fullName]) { if (yua.components[widget]) {
// log(widget, yua.components)
//确保所有:attr-name扫描完再处理 //确保所有:attr-name扫描完再处理
_delay_component(fullName) _delay_component(widget)
} }
} }
} }
@ -3263,6 +3288,19 @@ Buffer.prototype = {
var buffer = new Buffer() var buffer = new Buffer()
var componentQueue = [] var componentQueue = []
var widgetList = [] var widgetList = []
var componentHooks = { var componentHooks = {
@ -3274,34 +3312,31 @@ var componentHooks = {
$dispose: noop, $dispose: noop,
$container: null, $container: null,
$childReady: noop, $childReady: noop,
$replace: false,
$extend: null,
$$template: function (str) { $$template: function (str) {
return str return str
} }
} }
yua.components = {} yua.components = {}
yua.component = function (name, opts) { yua.component = function (name, opts) {
if (opts) { if (opts) {
yua.components[name] = yua.mix({}, componentHooks, opts) yua.components[name] = yua.mix({}, componentHooks, opts)
} }
for (var i = 0, obj; obj = componentQueue[i]; i++) { for (var i = 0, obj; obj = componentQueue[i]; i++) {
if (name === obj.fullName) { if (name === obj.name) {
componentQueue.splice(i, 1) componentQueue.splice(i, 1);
i--; i--;
(function (host, hooks, elem, widget) { (function (host, hooks, elem, widget) {
//如果elem已从Document里移除,直接返回 //如果elem已从Document里移除,直接返回
//issuse : https://github.com/RubyLouvre/yua2/issues/40
if (!yua.contains(DOC, elem) || elem.msResolved) { if (!yua.contains(DOC, elem) || elem.msResolved) {
yua.Array.remove(componentQueue, host) yua.Array.remove(componentQueue, host)
return return
} }
var dependencies = 1 var dependencies = 1
var library = host.library var global = componentHooks
var global = yua.libraries[library] || componentHooks
//===========收集各种配置======= //===========收集各种配置=======
if (elem.getAttribute(":attr-identifier")) { if (elem.getAttribute(":attr-identifier")) {
@ -3309,25 +3344,21 @@ yua.component = function (name, opts) {
return return
} }
var elemOpts = getOptionsFromTag(elem, host.vmodels) var elemOpts = getOptionsFromTag(elem, host.vmodels)
var vmOpts = getOptionsFromVM(host.vmodels, elemOpts.config || host.fullName) var vmOpts = getOptionsFromVM(host.vmodels, elemOpts.config || host.name)
var $id = elemOpts.$id || elemOpts.identifier || generateID(widget) var $id = elemOpts.$id || elemOpts.identifier || generateID(widget)
delete elemOpts.config delete elemOpts.config
delete elemOpts.$id delete elemOpts.$id
delete elemOpts.identifier delete elemOpts.identifier
var componentDefinition = {} var componentDefinition = {}
var parentHooks = yua.components[hooks.$extend]
if (parentHooks) {
yua.mix(true, componentDefinition, parentHooks)
componentDefinition = parentHooks.$construct.call(elem, componentDefinition, {}, {})
} else {
yua.mix(true, componentDefinition, hooks) yua.mix(true, componentDefinition, hooks)
}
componentDefinition = yua.components[name].$construct.call(elem, componentDefinition, vmOpts, elemOpts) componentDefinition = yua.components[name].$construct.call(elem, componentDefinition, vmOpts, elemOpts)
componentDefinition.$refs = {} componentDefinition.$refs = {}
componentDefinition.$id = $id componentDefinition.$id = $id
//==========构建VM========= //==========构建VM=========
var keepSlot = componentDefinition.$slot var keepSlot = componentDefinition.$slot
var keepReplace = componentDefinition.$replace var keepReplace = componentDefinition.$replace
@ -3338,44 +3369,21 @@ yua.component = function (name, opts) {
delete componentDefinition.$container delete componentDefinition.$container
delete componentDefinition.$construct delete componentDefinition.$construct
var vmodel = yua.define(componentDefinition) || {} var vmodel = yua(componentDefinition) || {}
vmodel.$ups = host.vmodels
vmodel.$up = host.vmodels[0]
elem.msResolved = 1 //防止二进扫描此元素 elem.msResolved = 1 //防止二进扫描此元素
vmodel.$init(vmodel, elem) vmodel.$init(vmodel, elem)
global.$init(vmodel, elem) global.$init(vmodel, elem)
var nodes = elem.childNodes var nodes = elem.childNodes
//收集插入点
var slots = {}, snode
for (var s = 0, el; el = nodes[s++]; ) {
var type = el.nodeType === 1 && el.getAttribute("slot") || keepSlot
if (type) {
if (slots[type]) {
slots[type].push(el)
} else {
slots[type] = [el]
}
}
}
if (vmodel.$$template) { if (vmodel.$$template) {
yua.clearHTML(elem) yua.clearHTML(elem)
elem.innerHTML = vmodel.$$template(keepTemplate) elem.innerHTML = vmodel.$$template(keepTemplate)
} }
for (s in slots) {
if (vmodel.hasOwnProperty(s)) { // 组件所使用的标签是temlate,所以必须要要用子元素替换掉
var ss = slots[s] var child = elem.content.firstChild
if (ss.length) {
var fragment = yuaFragment.cloneNode(true)
for (var ns = 0; snode = ss[ns++]; ) {
fragment.appendChild(snode)
}
vmodel[s] = fragment
}
slots[s] = null
}
}
slots = null
var child = elem.children[0] || elem.firstChild
if (keepReplace) {
elem.parentNode.replaceChild(child, elem) elem.parentNode.replaceChild(child, elem)
child.msResolved = 1 child.msResolved = 1
var cssText = elem.style.cssText var cssText = elem.style.cssText
@ -3385,15 +3393,15 @@ yua.component = function (name, opts) {
if (className) { if (className) {
yua(elem).addClass(className) yua(elem).addClass(className)
} }
} //指定了组件的容器的话,则把组件节点转过去
if (keepContainer) { if (keepContainer) {
keepContainer.appendChild(elem) keepContainer.appendChild(elem)
} }
yua.fireDom(elem, "datasetchanged", yua.fireDom(elem, "datasetchanged",
{library: library, vm: vmodel, childReady: 1}) {vm: vmodel, childReady: 1})
var children = 0 var children = 0
var removeFn = yua.bind(elem, "datasetchanged", function (e) { var removeFn = yua.bind(elem, "datasetchanged", function (e) {
if (e.childReady && e.library === library) { if (e.childReady) {
dependencies += e.childReady dependencies += e.childReady
if (vmodel !== e.vm) { if (vmodel !== e.vm) {
vmodel.$refs[e.vm.$id] = e.vm vmodel.$refs[e.vm.$id] = e.vm
@ -3433,15 +3441,15 @@ yua.component = function (name, opts) {
scanTag(elem, [vmodel].concat(host.vmodels)) scanTag(elem, [vmodel].concat(host.vmodels))
yua.vmodels[vmodel.$id] = vmodel yua.vmodels[vmodel.$id] = vmodel
if (!elem.childNodes.length) { if (!elem.childNodes.length) {
yua.fireDom(elem, "datasetchanged", {library: library, vm: vmodel, childReady: -1}) yua.fireDom(elem, "datasetchanged", {vm: vmodel, childReady: -1})
} else { } else {
var id2 = setTimeout(function () { var id2 = setTimeout(function () {
clearTimeout(id2) clearTimeout(id2)
yua.fireDom(elem, "datasetchanged", {library: library, vm: vmodel, childReady: -1}) yua.fireDom(elem, "datasetchanged", {vm: vmodel, childReady: -1})
}, 17) }, 17)
} }
})(obj, yua.components[name], obj.element, obj.widget)// jshint ignore:line })(obj, yua.components[name], obj.element, obj.name)// jshint ignore:line
} }
} }
@ -3461,20 +3469,14 @@ function getOptionsFromVM(vmodels, pre) {
return {} return {}
} }
yua.libraries = [] function isWidget(el) {//如果是组件,则返回组件的名字
yua.library = function (name, opts) { var name = el.nodeName.toLowerCase()
if (DOC.namespaces) { if(name === 'template' && el.getAttribute('name')){
DOC.namespaces.add(name, 'http://www.w3.org/1999/xhtml'); return el.getAttribute('name')
} }
yua.libraries[name] = yua.mix({ return null
$init: noop,
$ready: noop,
$dispose: noop
}, opts || {})
} }
yua.library("ms")
yua.library("do")
@ -3486,26 +3488,13 @@ yua.library("do")
/*
broswer nodeName scopeName localName
IE9 ONI:BUTTON oni button
IE10 ONI:BUTTON undefined oni:button
IE8 button oni undefined
chrome ONI:BUTTON undefined oni:button
*/
function isWidget(el) { //如果为自定义标签,返回UI库的名字
if (el.scopeName && el.scopeName !== "HTML") {
return el.scopeName
}
var fullName = el.nodeName.toLowerCase()
var index = fullName.indexOf(":")
if (index > 0) {
return fullName.slice(0, index)
}
}
//各种MVVM框架在大型表格下的性能测试
// https://github.com/RubyLouvre/yua/issues/859
var bools = ["autofocus,autoplay,async,allowTransparency,checked,controls", var bools = ["autofocus,autoplay,async,allowTransparency,checked,controls",
"declare,disabled,defer,defaultChecked,defaultSelected", "declare,disabled,defer,defaultChecked,defaultSelected",
@ -5728,7 +5717,7 @@ new function () {// jshint ignore:line
return "" return ""
}) })
if (res === "ready") { if (res === "ready") {
log("debug: ready!已经被废弃请使用domReady!") log("ready!已经被废弃请使用domReady!")
res = "domReady" res = "domReady"
} }
//2. 去掉querystring, hash //2. 去掉querystring, hash
@ -5806,6 +5795,7 @@ new function () {// jshint ignore:line
var requireQueue = [] var requireQueue = []
var isUserFirstRequire = false var isUserFirstRequire = false
innerRequire = yua.require = function (array, factory, parentUrl, defineConfig) { innerRequire = yua.require = function (array, factory, parentUrl, defineConfig) {
if (!isUserFirstRequire) { if (!isUserFirstRequire) {
requireQueue.push(yua.slice(arguments)) requireQueue.push(yua.slice(arguments))
if (arguments.length <= 2) { if (arguments.length <= 2) {
@ -5817,7 +5807,6 @@ new function () {// jshint ignore:line
} }
return return
} }
if (!Array.isArray(array)) { if (!Array.isArray(array)) {
yua.error("require方法的第一个参数应为数组 " + array) yua.error("require方法的第一个参数应为数组 " + array)
} }
@ -5841,10 +5830,11 @@ new function () {// jshint ignore:line
} }
var req = makeRequest(name, defineConfig) var req = makeRequest(name, defineConfig)
var url = fireRequest(req) //加载资源,并返回该资源的完整地址 var url = fireRequest(req) //加载资源,并返回该资源的完整地址
if (url) { if (url) {
if (!uniq[url]) { if (!uniq[url]) {
deps.push(url) deps.push(url)
uniq[url] = !0//去重 uniq[url] = !0
} }
} }
}) })
@ -6016,7 +6006,7 @@ new function () {// jshint ignore:line
head.removeChild(node) head.removeChild(node)
node = null // 处理旧式IE下的循环引用问题 node = null // 处理旧式IE下的循环引用问题
}) })
log("debug: 加载 " + id + " 失败" + onError + " " + (!modules[id].state)) log("加载 " + id + " 失败")
} else { } else {
return true return true
} }
@ -6089,13 +6079,12 @@ new function () {// jshint ignore:line
css: { css: {
load: function (name, req, onLoad) { load: function (name, req, onLoad) {
var url = req.url var url = req.url
head.insertAdjacentHTML("beforeend", '<link rel="stylesheet" href="' + url + '">') head.insertAdjacentHTML("afterBegin", '<link rel="stylesheet" href="' + url + '">')
onLoad() onLoad()
} }
}, },
text: { text: {
load: function (name, req, onLoad) { load: function (name, req, onLoad) {
var url = req.url
var xhr = getXHR() var xhr = getXHR()
xhr.onload = function () { xhr.onload = function () {
var status = xhr.status; var status = xhr.status;
@ -6105,13 +6094,7 @@ new function () {// jshint ignore:line
onLoad(xhr.responseText) onLoad(xhr.responseText)
} }
} }
var time = "_=" + (new Date() - 0) xhr.open("GET", req.url, true)
var _url = url.indexOf("?") === -1 ? url + "?" + time : url + "&" + time
xhr.open("GET", _url, true)
if ("withCredentials" in xhr) {//这是处理跨域
xhr.withCredentials = true
}
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")//告诉后端这是AJAX请求
xhr.send() xhr.send()
} }
} }
@ -6360,70 +6343,6 @@ new function () {// jshint ignore:line
/*********************************************************************
* DOMReady *
**********************************************************************/
var readyList = [],
isReady
var fireReady = function (fn) {
isReady = true
var require = yua.require
if (require && require.checkDeps) {
modules["domReady!"].state = 4
require.checkDeps()
}
while (fn = readyList.shift()) {
fn(yua)
}
}
if (DOC.readyState === "complete") {
setTimeout(fireReady) //如果在domReady之外加载
} else {
DOC.addEventListener("DOMContentLoaded", fireReady)
}
window.addEventListener("load", fireReady)
yua.ready = function (fn) {
if (!isReady) {
readyList.push(fn)
} else {
fn(yua)
}
}
yua.config({
loader: true
})
yua.ready(function () {
yua.scan(DOC.body)
})
@ -6986,6 +6905,95 @@ Recognizer.add('swipe', swipeRecognizer)
/*********************************************************************
* DOMReady *
**********************************************************************/
var readyList = [],
isReady
var fireReady = function (fn) {
isReady = true
var require = yua.require
if (require && require.checkDeps) {
modules["domReady!"].state = 4
require.checkDeps()
}
while (fn = readyList.shift()) {
fn(yua)
}
}
if (DOC.readyState === "complete") {
setTimeout(fireReady) //如果在domReady之外加载
} else {
DOC.addEventListener("DOMContentLoaded", fireReady)
}
window.addEventListener("load", fireReady)
yua.ready = function (fn) {
if (!isReady) {
readyList.push(fn)
} else {
fn(yua)
}
}
yua.config({
loader: true
})
yua.ready(function () {
yua.scan(DOC.body)
})

258
js/yua.js
View File

@ -8,12 +8,6 @@
(function(global, factory) { (function(global, factory) {
if (typeof module === "object" && typeof module.exports === "object") { if (typeof module === "object" && typeof module.exports === "object") {
// For CommonJS and CommonJS-like environments where a proper `window`
// is present, execute the factory and get yua.
// For environments that do not have a `window` with a `document`
// (such as Node.js), expose a factory as module.exports.
// This accentuates the need for the creation of a real `window`.
// e.g. var yua = require("yua")(window);
module.exports = global.document ? factory(global, true) : function(w) { module.exports = global.document ? factory(global, true) : function(w) {
if (!w.document) { if (!w.document) {
throw new Error("Yua只能运行在浏览器环境") throw new Error("Yua只能运行在浏览器环境")
@ -31,7 +25,7 @@
* 全局变量及方法 * * 全局变量及方法 *
**********************************************************************/ **********************************************************************/
var expose = Date.now() var expose = generateID()
//http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function //http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function
var DOC = window.document var DOC = window.document
var head = DOC.head //HEAD元素 var head = DOC.head //HEAD元素
@ -39,11 +33,9 @@ head.insertAdjacentHTML("afterBegin", '<yua :skip class="yua-hide"><style id="yu
var ifGroup = head.firstChild var ifGroup = head.firstChild
function log() { function log() {
if (yua.config.debug) {
// http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log // http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log
console.log.apply(console, arguments) console.log.apply(console, arguments)
} }
}
/** /**
* Creates a new object without a prototype. This object is useful for lookup without having to * Creates a new object without a prototype. This object is useful for lookup without having to
@ -64,7 +56,6 @@ var nullObject = {} //作用类似于noop只用于代码防御千万不要
var rword = /[^, ]+/g //切割字符串为一个个小块以空格或豆号分开它们结合replace实现字符串的forEach var rword = /[^, ]+/g //切割字符串为一个个小块以空格或豆号分开它们结合replace实现字符串的forEach
var rw20g = /\w+/g var rw20g = /\w+/g
var rsvg = /^\[object SVG\w*Element\]$/ var rsvg = /^\[object SVG\w*Element\]$/
var rwindow = /^\[object (?:Window|DOMWindow|global)\]$/
var oproto = Object.prototype var oproto = Object.prototype
var ohasOwn = oproto.hasOwnProperty var ohasOwn = oproto.hasOwnProperty
var serialize = oproto.toString var serialize = oproto.toString
@ -101,9 +92,9 @@ function oneObject(array, val) {
return result return result
} }
var generateID = function (mark) { function generateID(mark) {
mark = mark && (mark + '-') || 'yua-' mark = mark && (mark + '-') || 'yua-'
return mark + Math.floor(Date.now() / 1000).toString(16) + '-' + Math.random().toString(16).slice(2, 6) + '-' + Math.random().toString(16).slice(6, 10) return mark + Date.now().toString(16) + '-' + Math.random().toString(16).slice(2, 6)
} }
yua = function (el) { //创建jQuery式的无new 实例化结构 yua = function (el) { //创建jQuery式的无new 实例化结构
@ -148,11 +139,6 @@ yua.nextTick = new function () {// jshint ignore:line
* yua的静态方法定义区 * * yua的静态方法定义区 *
**********************************************************************/ **********************************************************************/
yua.init = function (el) {
this[0] = this.element = el
}
yua.fn = yua.prototype = yua.init.prototype
yua.type = function (obj) { //取得目标的类型 yua.type = function (obj) { //取得目标的类型
if (obj == null) { if (obj == null) {
return String(obj) return String(obj)
@ -167,9 +153,6 @@ yua.isFunction = function (fn) {
return serialize.call(fn) === "[object Function]" return serialize.call(fn) === "[object Function]"
} }
yua.isWindow = function (obj) {
return rwindow.test(serialize.call(obj))
}
/*判定是否是一个朴素的javascript对象Object不是DOM对象不是BOM对象不是自定义类的实例*/ /*判定是否是一个朴素的javascript对象Object不是DOM对象不是BOM对象不是自定义类的实例*/
yua.isPlainObject = function (obj) { yua.isPlainObject = function (obj) {
@ -177,6 +160,27 @@ yua.isPlainObject = function (obj) {
return serialize.call(obj) === "[object Object]" && Object.getPrototypeOf(obj) === oproto return serialize.call(obj) === "[object Object]" && Object.getPrototypeOf(obj) === oproto
} }
var VMODELS = yua.vmodels = {} //所有vmodel都储存在这里
yua.init = function (source) {
if(yua.isPlainObject(source)){
var $id = source.$id,vm;
if (!$id) {
log("warning: vm必须指定$id")
}
vm = modelFactory(source)
vm.$id = $id
return VMODELS[$id] = vm
}else{
this[0] = this.element = source
}
}
yua.fn = yua.prototype = yua.init.prototype
//与jQuery.extend方法可用于浅拷贝深拷贝 //与jQuery.extend方法可用于浅拷贝深拷贝
yua.mix = yua.fn.mix = function () { yua.mix = yua.fn.mix = function () {
var options, name, src, copy, copyIsArray, clone, var options, name, src, copy, copyIsArray, clone,
@ -492,7 +496,6 @@ yua.mix({
rword: rword, rword: rword,
subscribers: subscribers, subscribers: subscribers,
version: '1.0.0', version: '1.0.0',
ui: {},
log: log, log: log,
slice: function (nodes, start, end) { slice: function (nodes, start, end) {
return aslice.call(nodes, start, end) return aslice.call(nodes, start, end)
@ -502,8 +505,6 @@ yua.mix({
error: function (str, e) { error: function (str, e) {
throw new (e || Error)(str)// jshint ignore:line throw new (e || Error)(str)// jshint ignore:line
}, },
/*将一个以空格或逗号隔开的字符串或数组,转换成一个键值都为1的对象*/
oneObject: oneObject,
/* yua.range(10) /* yua.range(10)
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
yua.range(1, 11) yua.range(1, 11)
@ -1079,7 +1080,6 @@ kernel.plugins = plugins
kernel.plugins['interpolate'](["{{", "}}"]) kernel.plugins['interpolate'](["{{", "}}"])
kernel.async = true kernel.async = true
kernel.debug = true
kernel.paths = {} kernel.paths = {}
kernel.shim = {} kernel.shim = {}
kernel.maxRepeatSize = 100 kernel.maxRepeatSize = 100
@ -1249,17 +1249,13 @@ function notifySubscribers(subs, args) {
//yua最核心的方法的两个方法之一另一个是yua.scan返回一个ViewModel(VM)
var VMODELS = yua.vmodels = {} //所有vmodel都储存在这里
yua.define = function (source) {
var $id = source.$id
if (!$id) {
log("warning: vm必须指定$id")
}
var vmodel = modelFactory(source)
vmodel.$id = $id
return VMODELS[$id] = vmodel
}
//一些不需要被监听的属性 //一些不需要被监听的属性
var $$skipArray = oneObject("$id,$watch,$fire,$events,$model,$skipArray,$active,$pathname,$up,$ups,$track,$accessors") var $$skipArray = oneObject("$id,$watch,$fire,$events,$model,$skipArray,$active,$pathname,$up,$ups,$track,$accessors")
@ -1628,8 +1624,13 @@ var $modelDescriptor = {
/********************************************************************* /*********************************************************************
* 监控数组:each, :repeat配合使用 * * 监控数组:repeat配合使用 *
**********************************************************************/ **********************************************************************/
var arrayMethods = ['push', 'pop', 'shift', 'unshift', 'splice'] var arrayMethods = ['push', 'pop', 'shift', 'unshift', 'splice']
@ -1941,6 +1942,23 @@ function getProxyIds(a, isArray) {
return ret.join(";") return ret.join(";")
} }
/********************************************************************* /*********************************************************************
* 定时GC回收机制 (基于1.6基于频率的GC) * * 定时GC回收机制 (基于1.6基于频率的GC) *
**********************************************************************/ **********************************************************************/
@ -2123,6 +2141,12 @@ yua.clearHTML = function(node) {
return node return node
} }
/********************************************************************* /*********************************************************************
* yua的原型方法定义区 * * yua的原型方法定义区 *
**********************************************************************/ **********************************************************************/
@ -3062,8 +3086,12 @@ function scanAttr(elem, vmodels, match) {
var rnoscanAttrBinding = /^if|widget|repeat$/ var rnoscanAttrBinding = /^if|widget|repeat$/
var rnoscanNodeBinding = /^html|include$/ var rnoscanNodeBinding = /^html|include$/
function scanNodeList(parent, vmodels) { function scanNodeList(elem, vmodels) {
var nodes = yua.slice(parent.childNodes) if(isWidget(elem)){
// elem = elem.content
log(elem)
}
var nodes = yua.slice(elem.childNodes)
scanNodeArray(nodes, vmodels) scanNodeArray(nodes, vmodels)
} }
@ -3078,21 +3106,18 @@ function scanNodeArray(nodes, vmodels) {
case 1: case 1:
var elem = node var elem = node
if (!elem.msResolved && elem.parentNode && elem.parentNode.nodeType === 1) { if (!elem.msResolved && elem.parentNode && elem.parentNode.nodeType === 1) {
var library = isWidget(elem) var widget = isWidget(elem)
if (library) {
var widget = elem.localName ? elem.localName.replace(library + ":", "") : elem.nodeName if (widget) {
var fullName = library + ":" + camelize(widget)
componentQueue.push({ componentQueue.push({
library: library,
element: elem, element: elem,
fullName: fullName,
widget: widget,
vmodels: vmodels, vmodels: vmodels,
name: "widget" name: widget
}) })
if (yua.components[fullName]) { if (yua.components[widget]) {
// log(widget, yua.components)
//确保所有:attr-name扫描完再处理 //确保所有:attr-name扫描完再处理
_delay_component(fullName) _delay_component(widget)
} }
} }
} }
@ -3263,6 +3288,19 @@ Buffer.prototype = {
var buffer = new Buffer() var buffer = new Buffer()
var componentQueue = [] var componentQueue = []
var widgetList = [] var widgetList = []
var componentHooks = { var componentHooks = {
@ -3274,34 +3312,31 @@ var componentHooks = {
$dispose: noop, $dispose: noop,
$container: null, $container: null,
$childReady: noop, $childReady: noop,
$replace: false,
$extend: null,
$$template: function (str) { $$template: function (str) {
return str return str
} }
} }
yua.components = {} yua.components = {}
yua.component = function (name, opts) { yua.component = function (name, opts) {
if (opts) { if (opts) {
yua.components[name] = yua.mix({}, componentHooks, opts) yua.components[name] = yua.mix({}, componentHooks, opts)
} }
for (var i = 0, obj; obj = componentQueue[i]; i++) { for (var i = 0, obj; obj = componentQueue[i]; i++) {
if (name === obj.fullName) { if (name === obj.name) {
componentQueue.splice(i, 1) componentQueue.splice(i, 1);
i--; i--;
(function (host, hooks, elem, widget) { (function (host, hooks, elem, widget) {
//如果elem已从Document里移除,直接返回 //如果elem已从Document里移除,直接返回
//issuse : https://github.com/RubyLouvre/yua2/issues/40
if (!yua.contains(DOC, elem) || elem.msResolved) { if (!yua.contains(DOC, elem) || elem.msResolved) {
yua.Array.remove(componentQueue, host) yua.Array.remove(componentQueue, host)
return return
} }
var dependencies = 1 var dependencies = 1
var library = host.library var global = componentHooks
var global = yua.libraries[library] || componentHooks
//===========收集各种配置======= //===========收集各种配置=======
if (elem.getAttribute(":attr-identifier")) { if (elem.getAttribute(":attr-identifier")) {
@ -3309,25 +3344,21 @@ yua.component = function (name, opts) {
return return
} }
var elemOpts = getOptionsFromTag(elem, host.vmodels) var elemOpts = getOptionsFromTag(elem, host.vmodels)
var vmOpts = getOptionsFromVM(host.vmodels, elemOpts.config || host.fullName) var vmOpts = getOptionsFromVM(host.vmodels, elemOpts.config || host.name)
var $id = elemOpts.$id || elemOpts.identifier || generateID(widget) var $id = elemOpts.$id || elemOpts.identifier || generateID(widget)
delete elemOpts.config delete elemOpts.config
delete elemOpts.$id delete elemOpts.$id
delete elemOpts.identifier delete elemOpts.identifier
var componentDefinition = {} var componentDefinition = {}
var parentHooks = yua.components[hooks.$extend]
if (parentHooks) {
yua.mix(true, componentDefinition, parentHooks)
componentDefinition = parentHooks.$construct.call(elem, componentDefinition, {}, {})
} else {
yua.mix(true, componentDefinition, hooks) yua.mix(true, componentDefinition, hooks)
}
componentDefinition = yua.components[name].$construct.call(elem, componentDefinition, vmOpts, elemOpts) componentDefinition = yua.components[name].$construct.call(elem, componentDefinition, vmOpts, elemOpts)
componentDefinition.$refs = {} componentDefinition.$refs = {}
componentDefinition.$id = $id componentDefinition.$id = $id
//==========构建VM========= //==========构建VM=========
var keepSlot = componentDefinition.$slot var keepSlot = componentDefinition.$slot
var keepReplace = componentDefinition.$replace var keepReplace = componentDefinition.$replace
@ -3338,44 +3369,21 @@ yua.component = function (name, opts) {
delete componentDefinition.$container delete componentDefinition.$container
delete componentDefinition.$construct delete componentDefinition.$construct
var vmodel = yua.define(componentDefinition) || {} var vmodel = yua(componentDefinition) || {}
vmodel.$ups = host.vmodels
vmodel.$up = host.vmodels[0]
elem.msResolved = 1 //防止二进扫描此元素 elem.msResolved = 1 //防止二进扫描此元素
vmodel.$init(vmodel, elem) vmodel.$init(vmodel, elem)
global.$init(vmodel, elem) global.$init(vmodel, elem)
var nodes = elem.childNodes var nodes = elem.childNodes
//收集插入点
var slots = {}, snode
for (var s = 0, el; el = nodes[s++]; ) {
var type = el.nodeType === 1 && el.getAttribute("slot") || keepSlot
if (type) {
if (slots[type]) {
slots[type].push(el)
} else {
slots[type] = [el]
}
}
}
if (vmodel.$$template) { if (vmodel.$$template) {
yua.clearHTML(elem) yua.clearHTML(elem)
elem.innerHTML = vmodel.$$template(keepTemplate) elem.innerHTML = vmodel.$$template(keepTemplate)
} }
for (s in slots) {
if (vmodel.hasOwnProperty(s)) { // 组件所使用的标签是temlate,所以必须要要用子元素替换掉
var ss = slots[s] var child = elem.content.firstChild
if (ss.length) {
var fragment = yuaFragment.cloneNode(true)
for (var ns = 0; snode = ss[ns++]; ) {
fragment.appendChild(snode)
}
vmodel[s] = fragment
}
slots[s] = null
}
}
slots = null
var child = elem.children[0] || elem.firstChild
if (keepReplace) {
elem.parentNode.replaceChild(child, elem) elem.parentNode.replaceChild(child, elem)
child.msResolved = 1 child.msResolved = 1
var cssText = elem.style.cssText var cssText = elem.style.cssText
@ -3385,15 +3393,15 @@ yua.component = function (name, opts) {
if (className) { if (className) {
yua(elem).addClass(className) yua(elem).addClass(className)
} }
} //指定了组件的容器的话,则把组件节点转过去
if (keepContainer) { if (keepContainer) {
keepContainer.appendChild(elem) keepContainer.appendChild(elem)
} }
yua.fireDom(elem, "datasetchanged", yua.fireDom(elem, "datasetchanged",
{library: library, vm: vmodel, childReady: 1}) {vm: vmodel, childReady: 1})
var children = 0 var children = 0
var removeFn = yua.bind(elem, "datasetchanged", function (e) { var removeFn = yua.bind(elem, "datasetchanged", function (e) {
if (e.childReady && e.library === library) { if (e.childReady) {
dependencies += e.childReady dependencies += e.childReady
if (vmodel !== e.vm) { if (vmodel !== e.vm) {
vmodel.$refs[e.vm.$id] = e.vm vmodel.$refs[e.vm.$id] = e.vm
@ -3433,15 +3441,15 @@ yua.component = function (name, opts) {
scanTag(elem, [vmodel].concat(host.vmodels)) scanTag(elem, [vmodel].concat(host.vmodels))
yua.vmodels[vmodel.$id] = vmodel yua.vmodels[vmodel.$id] = vmodel
if (!elem.childNodes.length) { if (!elem.childNodes.length) {
yua.fireDom(elem, "datasetchanged", {library: library, vm: vmodel, childReady: -1}) yua.fireDom(elem, "datasetchanged", {vm: vmodel, childReady: -1})
} else { } else {
var id2 = setTimeout(function () { var id2 = setTimeout(function () {
clearTimeout(id2) clearTimeout(id2)
yua.fireDom(elem, "datasetchanged", {library: library, vm: vmodel, childReady: -1}) yua.fireDom(elem, "datasetchanged", {vm: vmodel, childReady: -1})
}, 17) }, 17)
} }
})(obj, yua.components[name], obj.element, obj.widget)// jshint ignore:line })(obj, yua.components[name], obj.element, obj.name)// jshint ignore:line
} }
} }
@ -3461,20 +3469,14 @@ function getOptionsFromVM(vmodels, pre) {
return {} return {}
} }
yua.libraries = [] function isWidget(el) {//如果是组件,则返回组件的名字
yua.library = function (name, opts) { var name = el.nodeName.toLowerCase()
if (DOC.namespaces) { if(name === 'template' && el.getAttribute('name')){
DOC.namespaces.add(name, 'http://www.w3.org/1999/xhtml'); return el.getAttribute('name')
} }
yua.libraries[name] = yua.mix({ return null
$init: noop,
$ready: noop,
$dispose: noop
}, opts || {})
} }
yua.library("ms")
yua.library("do")
@ -3486,26 +3488,13 @@ yua.library("do")
/*
broswer nodeName scopeName localName
IE9 ONI:BUTTON oni button
IE10 ONI:BUTTON undefined oni:button
IE8 button oni undefined
chrome ONI:BUTTON undefined oni:button
*/
function isWidget(el) { //如果为自定义标签,返回UI库的名字
if (el.scopeName && el.scopeName !== "HTML") {
return el.scopeName
}
var fullName = el.nodeName.toLowerCase()
var index = fullName.indexOf(":")
if (index > 0) {
return fullName.slice(0, index)
}
}
//各种MVVM框架在大型表格下的性能测试
// https://github.com/RubyLouvre/yua/issues/859
var bools = ["autofocus,autoplay,async,allowTransparency,checked,controls", var bools = ["autofocus,autoplay,async,allowTransparency,checked,controls",
"declare,disabled,defer,defaultChecked,defaultSelected", "declare,disabled,defer,defaultChecked,defaultSelected",
@ -5728,7 +5717,7 @@ new function () {// jshint ignore:line
return "" return ""
}) })
if (res === "ready") { if (res === "ready") {
log("debug: ready!已经被废弃请使用domReady!") log("ready!已经被废弃请使用domReady!")
res = "domReady" res = "domReady"
} }
//2. 去掉querystring, hash //2. 去掉querystring, hash
@ -6017,7 +6006,7 @@ new function () {// jshint ignore:line
head.removeChild(node) head.removeChild(node)
node = null // 处理旧式IE下的循环引用问题 node = null // 处理旧式IE下的循环引用问题
}) })
log("debug: 加载 " + id + " 失败" + onError + " " + (!modules[id].state)) log("加载 " + id + " 失败")
} else { } else {
return true return true
} }
@ -6090,13 +6079,12 @@ new function () {// jshint ignore:line
css: { css: {
load: function (name, req, onLoad) { load: function (name, req, onLoad) {
var url = req.url var url = req.url
head.insertAdjacentHTML("beforeend", '<link rel="stylesheet" href="' + url + '">') head.insertAdjacentHTML("afterBegin", '<link rel="stylesheet" href="' + url + '">')
onLoad() onLoad()
} }
}, },
text: { text: {
load: function (name, req, onLoad) { load: function (name, req, onLoad) {
var url = req.url
var xhr = getXHR() var xhr = getXHR()
xhr.onload = function () { xhr.onload = function () {
var status = xhr.status; var status = xhr.status;
@ -6106,13 +6094,7 @@ new function () {// jshint ignore:line
onLoad(xhr.responseText) onLoad(xhr.responseText)
} }
} }
var time = "_=" + (new Date() - 0) xhr.open("GET", req.url, true)
var _url = url.indexOf("?") === -1 ? url + "?" + time : url + "&" + time
xhr.open("GET", _url, true)
if ("withCredentials" in xhr) {//这是处理跨域
xhr.withCredentials = true
}
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")//告诉后端这是AJAX请求
xhr.send() xhr.send()
} }
} }