Skip to content

Instantly share code, notes, and snippets.

@xdimh
Created June 3, 2015 09:07
Show Gist options
  • Save xdimh/4ee185091b8e815f9b4c to your computer and use it in GitHub Desktop.
Save xdimh/4ee185091b8e815f9b4c to your computer and use it in GitHub Desktop.
This gist exceeds the recommended number of files (~10). To access all files, please clone this gist.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/lcode.iml" filepath="$PROJECT_DIR$/.idea/lcode.iml" />
</modules>
</component>
</project>
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
#kkpager{
clear:both;
color:#999;
padding:5px 0px 5px 0px;
font-size:13px;
}
#kkpager a{
float: left;
border: 1px solid #ccc;
display: inline;
padding: 3px 10px 3px 10px;
margin-right: 5px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
cursor: pointer;
background: #fff;
text-decoration:none;
color:#999;
}
#kkpager span.disabled{
float: left;
display: inline;
padding: 3px 10px 3px 10px;
margin-right: 5px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border:1px solid #DFDFDF;
background-color:#FFF;
color:#DFDFDF;
}
#kkpager span.curr{
float: left;
border: 1px solid #31ACE2;
display: inline;
padding: 3px 10px 3px 10px;
margin-right: 5px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background: #F0FDFF;
color: #31ACE2;
}
#kkpager a:hover{
border:1px solid #31ACE2;
background-color:#31ACE2;
color:#fff;
}
#kkpager span.normalsize{
}
#kkpager_gopage_wrap{
position:relative;
left:0px;
top:0px;
}
#kkpager_btn_go {
width:44px;
height:18px;
border:0px;
overflow:hidden;
line-height:140%;
padding:0px;
margin:0px;
text-align:center;
cursor:pointer;
background-color:#31ACE2;
color:#FFF;
position:absolute;
left:0px;
top:-2px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
display:none;
}
#kkpager_btn_go_input{
width:36px;
height:14px;
color:#999;
text-align:center;
margin-left:1px;
margin-right:1px;
border:1px solid #DFDFDF;
position:relative;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
left:0px;
top:0px;
outline:none;
}
#kkpager_btn_go_input.focus{
border-color:#31ACE2;
}
#kkpager .pageBtnWrap{
float:left;
}
#kkpager .infoTextAndGoPageBtnWrap{
float:right;
}
#kkpager .spanDot{
float:left;
margin-right:5px;
}
#kkpager .currPageNum{
color:#FD7F4D;
}
#kkpager .infoTextAndGoPageBtnWrap{
padding-top:5px;
}
#kkpager{
clear:both;
color:#999;
padding:5px 0px 5px 0px;
font-size:13px;
}
#kkpager a{
float: left;
border: 1px solid #ccc;
display: inline;
padding: 3px 10px 3px 10px;
margin-right: 5px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
cursor: pointer;
background: #fff;
text-decoration:none;
color:#999;
}
#kkpager span.disabled{
float: left;
display: inline;
padding: 3px 10px 3px 10px;
margin-right: 5px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border:1px solid #DFDFDF;
background-color:#FFF;
color:#DFDFDF;
}
#kkpager span.curr{
float: left;
border: 1px solid #FF6600;
display: inline;
padding: 3px 10px 3px 10px;
margin-right: 5px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background: #FFEEE5;
color: #FF6600;
}
#kkpager a:hover{
border:1px solid #FF6600;
background-color:#FF6600;
color:#fff;
}
#kkpager span.normalsize{
}
#kkpager_gopage_wrap{
position:relative;
left:0px;
top:0px;
}
#kkpager_btn_go {
width:44px;
height:18px;
border:0px;
overflow:hidden;
line-height:140%;
padding:0px;
margin:0px;
text-align:center;
cursor:pointer;
background-color:#FF6600;
color:#FFF;
position:absolute;
left:0px;
top:-2px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
display:none;
}
#kkpager_btn_go_input{
width:36px;
height:14px;
color:#999;
text-align:center;
margin-left:1px;
margin-right:1px;
border:1px solid #DFDFDF;
position:relative;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
left:0px;
top:0px;
outline:none;
}
#kkpager_btn_go_input.focus{
border-color:#FF6600;
}
#kkpager .pageBtnWrap{
float:left;
}
#kkpager .infoTextAndGoPageBtnWrap{
float:right;
}
#kkpager .spanDot{
float:left;
margin-right:5px;
}
#kkpager .currPageNum{
color:#FD7F4D;
}
#kkpager .infoTextAndGoPageBtnWrap{
padding-top:5px;
}
<!DOCTYPE html>
<html style="font-size:62.5%;">
<head lang="en">
<meta charset="UTF-8">
<title>chrome rem bug test</title>
<style>
.f10 {
font-size: 1.6rem;
}
</style>
</head>
<body>
<div class="f10">
<p>10px 10px 10px 10px 10px 10px 10px 10px 10px 10px 10px 10px </p>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Datepicker</title>
</head>
<body>
<div id="J-pickbd" class="m-pickbd">
<input type="text" id="input" class="w-dateipt"/>
</div>
<script src="../nej/src/define.js?pro=../javascript/"></script>
<script>
/**
* Created by hzzhu_zhenyu on 2015/5/18.
*/
NEJ.define([
'util/chain/chainable',
'base/klass',
'base/element',
'base/event',
'base/util',
'ui/datepick/datepick'
], function ($, _k, _e, _v, _u,_dp, _p, o, f, r) {
var _pro;
_p._$$DatePicker = _k._$klass();
_pro = _p._$$DatePicker.prototype;
_pro.__init = function () {
this.__initNode();
this.__bindEvent();
};
_pro.__initNode = function () {
this.$dateIpt = $('#input');
};
_pro.__bindEvent = function () {
this.$dateIpt._$addEvent('click',this.__onDateIptClick._$bind(this));
};
_pro.__onDateIptClick = function(_event) {
_v._$stop(_event);
var _datepick = _dp._$$DatePick._$allocate({
parent: 'J-pickbd',
clazz: 'm-dt',
onchange: this.__DatePickChange._$bind(this)
});
};
_pro.__DatePickChange = function(_date) {
this.$dateIpt._$val(_u._$format(_date,'yyyy-MM-dd'));
};
_pro.__trim = function (str) {
if (str.trim) {
return str.trim();
} else {
return str.replace(/^\s+|\s+$/g, '');
}
};
new _p._$$DatePicker;
return _p;
});
</script>
</body>
</html>
/*
kkpager V1.3
https://github.com/pgkk/kkpager
Copyright (c) 2013 [email protected]
Licensed under the GNU GENERAL PUBLIC LICENSE
*/
var kkpager = {
pagerid : 'kkpager', //divID
mode : 'link', //模式(link 或者 click)
pno : 1, //当前页码
total : 1, //总页码
totalRecords : 0, //总数据条数
isShowFirstPageBtn : true, //是否显示首页按钮
isShowLastPageBtn : true, //是否显示尾页按钮
isShowPrePageBtn : true, //是否显示上一页按钮
isShowNextPageBtn : true, //是否显示下一页按钮
isShowTotalPage : true, //是否显示总页数
isShowCurrPage : true,//是否显示当前页
isShowTotalRecords : false, //是否显示总记录数
isGoPage : true, //是否显示页码跳转输入框
isWrapedPageBtns : true, //是否用span包裹住页码按钮
isWrapedInfoTextAndGoPageBtn : true, //是否用span包裹住分页信息和跳转按钮
hrefFormer : '', //链接前部
hrefLatter : '', //链接尾部
gopageWrapId : 'kkpager_gopage_wrap',
gopageButtonId : 'kkpager_btn_go',
gopageTextboxId : 'kkpager_btn_go_input',
lang : {
firstPageText : '首页',
firstPageTipText : '首页',
lastPageText : '尾页',
lastPageTipText : '尾页',
prePageText : '上一页',
prePageTipText : '上一页',
nextPageText : '下一页',
nextPageTipText : '下一页',
totalPageBeforeText : '共',
totalPageAfterText : '页',
currPageBeforeText : '当前第',
currPageAfterText : '页',
totalInfoSplitStr : '/',
totalRecordsBeforeText : '共',
totalRecordsAfterText : '条数据',
gopageBeforeText : '&nbsp;转到',
gopageButtonOkText : '确定',
gopageAfterText : '页',
buttonTipBeforeText : '第',
buttonTipAfterText : '页'
},
//链接算法(当处于link模式),参数n为页码
getLink : function(n){
//这里的算法适用于比如:
//hrefFormer=http://www.xx.com/news/20131212
//hrefLatter=.html
//那么首页(第1页)就是http://www.xx.com/news/20131212.html
//第2页就是http://www.xx.com/news/20131212_2.html
//第n页就是http://www.xx.com/news/20131212_n.html
if(n == 1){
return this.hrefFormer + this.hrefLatter;
}
return this.hrefFormer + '_' + n + this.hrefLatter;
},
//页码单击事件处理函数(当处于mode模式),参数n为页码
click : function(n){
//这里自己实现
//这里可以用this或者kkpager访问kkpager对象
return false;
},
//获取href的值(当处于mode模式),参数n为页码
getHref : function(n){
//默认返回'#'
return '#';
},
//跳转框得到输入焦点时
focus_gopage : function (){
var btnGo = $('#'+this.gopageButtonId);
$('#'+this.gopageTextboxId).attr('hideFocus',true);
btnGo.show();
btnGo.css('left','10px');
$('#'+this.gopageTextboxId).addClass('focus');
btnGo.animate({left: '+=30'}, 50);
},
//跳转框失去输入焦点时
blur_gopage : function(){
var _this = this;
setTimeout(function(){
var btnGo = $('#'+_this.gopageButtonId);
btnGo.animate({
left: '-=25'
}, 100, function(){
btnGo.hide();
$('#'+_this.gopageTextboxId).removeClass('focus');
});
},400);
},
//跳转输入框按键操作
keypress_gopage : function(){
var event = arguments[0] || window.event;
var code = event.keyCode || event.charCode;
//delete key
if(code == 8) return true;
//enter key
if(code == 13){
kkpager.gopage();
return false;
}
//copy and paste
if(event.ctrlKey && (code == 99 || code == 118)) return true;
//only number key
if(code<48 || code>57)return false;
return true;
},
//跳转框页面跳转
gopage : function(){
var str_page = $('#'+this.gopageTextboxId).val();
if(isNaN(str_page)){
$('#'+this.gopageTextboxId).val(this.next);
return;
}
var n = parseInt(str_page);
if(n < 1) n = 1;
if(n > this.total) n = this.total;
if(this.mode == 'click'){
this._clickHandler(n);
}else{
window.location = this.getLink(n);
}
},
//不刷新页面直接手动调用选中某一页码
selectPage : function(n){
this._config['pno'] = n;
this.generPageHtml(this._config,true);
},
//生成控件代码
generPageHtml : function(config,enforceInit){
if(enforceInit || !this.inited){
this.init(config);
}
var str_first='',str_prv='',str_next='',str_last='';
if(this.isShowFirstPageBtn){
if(this.hasPrv){
str_first = '<a '+this._getHandlerStr(1)+' title="'
+(this.lang.firstPageTipText || this.lang.firstPageText)+'">'+this.lang.firstPageText+'</a>';
}else{
str_first = '<span class="disabled">'+this.lang.firstPageText+'</span>';
}
}
if(this.isShowPrePageBtn){
if(this.hasPrv){
str_prv = '<a '+this._getHandlerStr(this.prv)+' title="'
+(this.lang.prePageTipText || this.lang.prePageText)+'">'+this.lang.prePageText+'</a>';
}else{
str_prv = '<span class="disabled">'+this.lang.prePageText+'</span>';
}
}
if(this.isShowNextPageBtn){
if(this.hasNext){
str_next = '<a '+this._getHandlerStr(this.next)+' title="'
+(this.lang.nextPageTipText || this.lang.nextPageText)+'">'+this.lang.nextPageText+'</a>';
}else{
str_next = '<span class="disabled">'+this.lang.nextPageText+'</span>';
}
}
if(this.isShowLastPageBtn){
if(this.hasNext){
str_last = '<a '+this._getHandlerStr(this.total)+' title="'
+(this.lang.lastPageTipText || this.lang.lastPageText)+'">'+this.lang.lastPageText+'</a>';
}else{
str_last = '<span class="disabled">'+this.lang.lastPageText+'</span>';
}
}
var str = '';
var dot = '<span class="spanDot">...</span>';
var total_info='<span class="totalText">';
var total_info_splitstr = '<span class="totalInfoSplitStr">'+this.lang.totalInfoSplitStr+'</span>';
if(this.isShowCurrPage){
total_info += this.lang.currPageBeforeText + '<span class="currPageNum">' + this.pno + '</span>' + this.lang.currPageAfterText;
if(this.isShowTotalPage){
total_info += total_info_splitstr;
total_info += this.lang.totalPageBeforeText + '<span class="totalPageNum">'+this.total + '</span>' + this.lang.totalPageAfterText;
}else if(this.isShowTotalRecords){
total_info += total_info_splitstr;
total_info += this.lang.totalRecordsBeforeText + '<span class="totalRecordNum">'+this.totalRecords + '</span>' + this.lang.totalRecordsAfterText;
}
}else if(this.isShowTotalPage){
total_info += this.lang.totalPageBeforeText + '<span class="totalPageNum">'+this.total + '</span>' + this.lang.totalPageAfterText;;
if(this.isShowTotalRecords){
total_info += total_info_splitstr;
total_info += this.lang.totalRecordsBeforeText + '<span class="totalRecordNum">'+this.totalRecords + '</span>' + this.lang.totalRecordsAfterText;
}
}else if(this.isShowTotalRecords){
total_info += this.lang.totalRecordsBeforeText + '<span class="totalRecordNum">'+this.totalRecords + '</span>' + this.lang.totalRecordsAfterText;
}
total_info += '</span>';
var gopage_info = '';
if(this.isGoPage){
gopage_info = '<span class="goPageBox">'+this.lang.gopageBeforeText+'<span id="'+this.gopageWrapId+'">'+
'<input type="button" id="'+this.gopageButtonId+'" onclick="kkpager.gopage()" value="'
+this.lang.gopageButtonOkText+'" />'+
'<input type="text" id="'+this.gopageTextboxId+'" onfocus="kkpager.focus_gopage()" onkeypress="return kkpager.keypress_gopage(event);" onblur="kkpager.blur_gopage()" value="'+this.next+'" /></span>'+this.lang.gopageAfterText+'</span>';
}
//分页处理
if(this.total <= 8){
for(var i=1;i<=this.total;i++){
if(this.pno == i){
str += '<span class="curr">'+i+'</span>';
}else{
str += '<a '+this._getHandlerStr(i)+' title="'
+this.lang.buttonTipBeforeText + i + this.lang.buttonTipAfterText+'">'+i+'</a>';
}
}
}else{
if(this.pno <= 5){
for(var i=1;i<=7;i++){
if(this.pno == i){
str += '<span class="curr">'+i+'</span>';
}else{
str += '<a '+this._getHandlerStr(i)+' title="'+
this.lang.buttonTipBeforeText + i + this.lang.buttonTipAfterText+'">'+i+'</a>';
}
}
str += dot;
}else{
str += '<a '+this._getHandlerStr(1)+' title="'
+this.lang.buttonTipBeforeText + '1' + this.lang.buttonTipAfterText+'">1</a>';
str += '<a '+this._getHandlerStr(2)+' title="'
+this.lang.buttonTipBeforeText + '2' + this.lang.buttonTipAfterText +'">2</a>';
str += dot;
var begin = this.pno - 2;
var end = this.pno + 2;
if(end > this.total){
end = this.total;
begin = end - 4;
if(this.pno - begin < 2){
begin = begin-1;
}
}else if(end + 1 == this.total){
end = this.total;
}
for(var i=begin;i<=end;i++){
if(this.pno == i){
str += '<span class="curr">'+i+'</span>';
}else{
str += '<a '+this._getHandlerStr(i)+' title="'
+this.lang.buttonTipBeforeText + i + this.lang.buttonTipAfterText+'">'+i+'</a>';
}
}
if(end != this.total){
str += dot;
}
}
}
var pagerHtml = '<div>';
if(this.isWrapedPageBtns){
pagerHtml += '<span class="pageBtnWrap">' + str_first + str_prv + str + str_next + str_last + '</span>'
}else{
pagerHtml += str_first + str_prv + str + str_next + str_last;
}
if(this.isWrapedInfoTextAndGoPageBtn){
pagerHtml += '<span class="infoTextAndGoPageBtnWrap">' + total_info + gopage_info + '</span>';
}else{
pagerHtml += total_info + gopage_info;
}
pagerHtml += '</div><div style="clear:both;"></div>';
$("#"+this.pagerid).html(pagerHtml);
},
//分页按钮控件初始化
init : function(config){
this.pno = isNaN(config.pno) ? 1 : parseInt(config.pno);
this.total = isNaN(config.total) ? 1 : parseInt(config.total);
this.totalRecords = isNaN(config.totalRecords) ? 0 : parseInt(config.totalRecords);
if(config.pagerid){this.pagerid = config.pagerid;}
if(config.mode){this.mode = config.mode;}
if(config.gopageWrapId){this.gopageWrapId = config.gopageWrapId;}
if(config.gopageButtonId){this.gopageButtonId = config.gopageButtonId;}
if(config.gopageTextboxId){this.gopageTextboxId = config.gopageTextboxId;}
if(config.isShowFirstPageBtn != undefined){this.isShowFirstPageBtn=config.isShowFirstPageBtn;}
if(config.isShowLastPageBtn != undefined){this.isShowLastPageBtn=config.isShowLastPageBtn;}
if(config.isShowPrePageBtn != undefined){this.isShowPrePageBtn=config.isShowPrePageBtn;}
if(config.isShowNextPageBtn != undefined){this.isShowNextPageBtn=config.isShowNextPageBtn;}
if(config.isShowTotalPage != undefined){this.isShowTotalPage=config.isShowTotalPage;}
if(config.isShowCurrPage != undefined){this.isShowCurrPage=config.isShowCurrPage;}
if(config.isShowTotalRecords != undefined){this.isShowTotalRecords=config.isShowTotalRecords;}
if(config.isWrapedPageBtns){this.isWrapedPageBtns=config.isWrapedPageBtns;}
if(config.isWrapedInfoTextAndGoPageBtn){this.isWrapedInfoTextAndGoPageBtn=config.isWrapedInfoTextAndGoPageBtn;}
if(config.isGoPage != undefined){this.isGoPage=config.isGoPage;}
if(config.lang){
for(var key in config.lang){
this.lang[key] = config.lang[key];
}
}
this.hrefFormer = config.hrefFormer || '';
this.hrefLatter = config.hrefLatter || '';
if(config.getLink && typeof(config.getLink) == 'function'){this.getLink = config.getLink;}
if(config.click && typeof(config.click) == 'function'){this.click = config.click;}
if(config.getHref && typeof(config.getHref) == 'function'){this.getHref = config.getHref;}
if(!this._config){
this._config = config;
}
//validate
if(this.pno < 1) this.pno = 1;
this.total = (this.total <= 1) ? 1: this.total;
if(this.pno > this.total) this.pno = this.total;
this.prv = (this.pno<=2) ? 1 : (this.pno-1);
this.next = (this.pno >= this.total-1) ? this.total : (this.pno + 1);
this.hasPrv = (this.pno > 1);
this.hasNext = (this.pno < this.total);
this.inited = true;
},
_getHandlerStr : function(n){
if(this.mode == 'click'){
return 'href="'+this.getHref(n)+'" onclick="return kkpager._clickHandler('+n+')"';
}
//link模式,也是默认的
return 'href="'+this.getLink(n)+'"';
},
_clickHandler : function(n){
var res = false;
if(this.click && typeof this.click == 'function'){
res = this.click.call(this,n) || false;
}
return res;
}
};
window.util = {
addEvent: function(ele, eventType, callback) {
var newCb = function(event) {
var event = event || window.event,
target = event.target || event.srcElement;
callback.call(ele, event, target);
};
if (ele.addEventListener) {
ele.addEventListener(eventType, newCb, false);
} else if (ele.attachEvent) {
ele.attachEvent('on' + eventType, newCb);
} else if(!!ele['on' + eventType]){
ele['on' + eventType] = newCb;
} else {
throw new Error("can't add event listener on this element");
}
},
preventDefault : function(event) {
if(event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
cancelBubble : function(event) {
if(event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
getOffsetR2Doc: function(event) {
var pageX, pageY;
pageX = event.pageX || event.clientX + document.body.scrollTop || document.documentElement.scrollTop;
pageY = event.pageY || event.clientY + document.body.scrollTop || document.documentElement.scrollTop;
return {
x: pageX,
y: pageY
}
}
};
/**
* Created by hzzhu_zhenyu on 2015/5/12.
*/
!function(window,undefined){
var document = window.document,
navigator = window.navigator,
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
push = Array.prototype.push,
slice = Array.prototype.slice,
trim = String.prototype.trim,
indexOf = Array.prototype.indexOf;
var zQuery = function(selector,context) {
return new zQuery.fn.init(selector,context);
};
zQuery.fn = zQuery.prototype = {
consturctor : zQuery,
/**
@param : {'#id'|'.class'|'tag'|element|doument}
@return zQuery object
**/
init : function(selector,context) {
this.elements = [];
context = context ? context : document;
if(!selector) {
return this;
}
if(typeof selector === 'function') {
this._addEvent(window,'load',selector);
return this;
}
if(typeof selector === 'object' && selector.nodeType && (selector.nodeType == 1 || selector.nodeType == 9)) {
this.elements[0] = selector;
return this;
}
switch(selector.charAt(0)) {
case '#':
this.elements[0] = document.getElementById(selector.substring(1));
break;
case '.':
this.elements = this._getElementByClassName(selector.substring(1),context);
break;
default:
this.elements = this._toArray(context.getElementsByTagName(selector));
break;
}
},
/**
* covert to array-like list to real array
* @param : array-like list
* @return : javascript array
*/
_toArray : function(arrayLikeList) {
try {
return slice.call(arrayLikeList,0);
} catch(e) {
var arr = [];
for(var i = 0,len = arrayLikeList.length; i < len; i++){
arr[i] = arrayLikeList[i];
}
return arr;
}
},
/**
* @param : element,array,i
* @return : -1 or element position in array
*/
_inArray : function( elem, array, i ) {
var len;
if ( array ) {
if ( indexOf ) {
return indexOf.call( array, elem, i );
}
len = array.length;
i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
for ( ; i < len; i++ ) {
if ( i in array && array[ i ] === elem ) {
return i;
}
}
}
return -1;
},
/**
* @param : classname,context
* @return : elements in context
*/
_getElementByClassName : function(className,context) {
if(context.getElementsByClassName) {
return this._toArray(context.getElementsByClassName(className));
} else if(document.querySelectorAll) {
return this._toArray(context.querySelectorAll('.' + className));
} else {
var all = context.getElementsByTagName("*"),
elements = [],
i = 0;
for (; i < all.length; i++) {
if (all[i].className && (" " + all[i].className + " ").indexOf(" " + className + " ") > -1 && this._inArray(elements,all[i]) === -1) elements.push(all[i]);
}
return elements;
}
},
/**
* @param : target element,eventType,callback function
*/
_addEvent : function(target,eventType,fn) {
var newFn = function(event) {
var event = event || window.event,
tagit = event.target || event.srcElement;
fn.call(target,event,tagit);
};
if(target.addEventListener) {
target.addEventListener(eventType,newFn,false);
} else if(target.attachEvent) {
target.attachEvent('on' + eventType, newFn);
} else {
throw new Error("cant't bind event on this element");
}
},
_removeEvent : function(target,eventType,fn) {
if (target.removeEventListener) {
target.removeEventListener(eventType, fn,false);
} else if (target.detachEvent) {
target.detachEvent('on' + eventType, fn);
}
},
/**
* @param : eventType,function
* @return : current zQuery object
*/
bind : function(eventType,fn) {
var eles = this.elements,
i = eles.length;
while(i--) {
this._addEvent(eles[i],eventType,fn);
}
return this;
},
unbind : function(eventType,fn) {
var eles = this.elements,
i = eles.length;
while(i--) {
this._removeEvent(eles[i],eventType,fn);
}
return this;
},
each : function(array,fn) {
var result;
if(!fn) {
fn = array;
array = this.elements;
}
for(var i = 0; i < array.length; i++) {
result = fn.call(array[i],i);
if(result !== undefined && !result) {
break;
}
}
return this;
},
_trim : function(str) {
trimLeft = /^\s+/,
trimRight = /\s+$/;
return trim ? trim.call(str) : str.replace( trimLeft, "" ).replace( trimRight, "" );
},
removeClass : function(className) {
var eles = this.elements,
that = this;
this.each(eles,function(){
var oldClassNames = that._trim(this.className).split(/\s+/),
newClassNames = "";
for(var i = 0; i < oldClassNames.length; i++) {
if(oldClassNames[i] !== className) {
newClassNames += i ? " " + oldClassNames[i] : oldClassNames[i];
}
}
this.className = newClassNames;
});
return that;
},
/**
* add class to html element
* @param : className
* @return : current zQuery object
*/
addClass : function(className) {
var eles = this.elements,
that = this,
className = that._trim(className);
this.each(eles,function(){
var oldClassNames = that._trim(this.className);
if(oldClassNames.indexOf(className) < 0) {
this.className = oldClassNames ? oldClassNames + ' ' + className : className;
}
});
return that;
},
/**
* @return : first element in zQuery object
*/
firstEle : function() {
return this.elements[0];
},
/**
* get next sibling
*/
next : function() {
var ele = this.elements[0],
next;
if(ele.nextElementSibling) {
this.elements[0] = ele.nextElementSibling;
} else if(ele.nextSibling) {
next = ele.nextSibling;
while(next && next.nodeType != 1) {
next = next.nextSibling;
}
this.elements[0] = next;
}
return this;
},
/**
* get previous sibling
*/
prev : function() {
var ele = this.elements[0],
prev;
if(ele.previousElementSibling) {
this.elements[0] = ele.previousElementSibling;
} else if(ele.previousSibling) {
prev = ele.previousSibling;
while(prev && prev.nodeType != 1) {
prev = prev.previousSibling;
}
this.elements[0] = prev;
}
return this;
},
/**
* set or get css style
* @param : ruleName,ruleValue
* @return : cuurent zQuery object
*/
css : function(ruleName,ruleValue) {
var that = this,
ele = that.elements[0],
eles = that.elements;
if(ruleValue !== undefined) {
that.each(eles,function(){
this.style[ruleName] = ruleValue;
});
} else {
var style = ele.currentStyle? ele.currentStyle : window.getComputedStyle(ele, null);
return style.getAttribute ? style.getAttribute(ruleName) : style.getPropertyValue(ruleName);
}
return that;
},
//get element attribute or set element attribute may not compatible across browsers
attr : function(attrName,opt_value,opt_direct) {
var that = this,
ele = that.elements[0],
eles = that.elements;
if(opt_value !== undefined) {
that.each(eles,function(){
if(opt_direct) {
this[attrName] = opt_value;
} else {
this.setAttribute(attrName,opt_value);
}
});
return that;
} else {
return ele.getAttribute(attrName);
}
},
delAttr : function(attrName) {
var that = this,
eles = that.elements;
that.each(eles,function(){
this.removeAttribute(attrName);
});
return that;
},
//get direct children of element
getChildEles : function() {
var eles = this.elements,
childEles = [],
that = this;
that.each(eles, function(){
childEles = childEles.concat(that._toArray(this.children));
});
that.elements = childEles;
return that;
},
// get child elements
find : function(selector) {
var that = this,
eles = this.elements,
newEles = [];
that.each(eles,function(){
newEles = newEles.concat($(selector,this).elements);
});
this.elements = newEles;
return that;
},
hasClass : function(className) {
var ele = this.elements[0],
className = this._trim(className),
oldClassNames = this._trim(ele.className);
if(oldClassNames.indexOf(className) < 0) {
return false;
} else {
return true;
}
},
text : function(text) {
var ele = this.elements[0];
if(text) {
if(ele.innerText) {
ele.innerText = text;
} else {
ele.textContent = text;
}
} else {
return ele.innerText || ele.textContent;
}
return this;
},
html : function(html) {
var ele = this.elements[0];
if(html) {
ele.innerHTML = html;
} else {
return ele.innerHTML;
}
},
//remove this html element
remove : function() {
this.each(function(){
this.parentNode.removeChild(this);
});
return this;
},
empty : function() {
var that = this,
eles = that.elements;
that.each(eles,function(){
var childs = that._toArray(this.children),
len = childs.length,
i;
for(i = 0; i < len; i++) {
this.removeChild(childs[i]);
}
});
return that;
},
lastEle : function() {
var that = this,
eles = that.elements;
return $(eles[eles.length-1]);
},
child : function(tag) {
var that = this,
eles = that.elements,
newEles = [],
childs;
that.each(eles,function(){
childs = that._toArray(this.children);
for(var i = 0, len = childs.length; i < len; i++) {
if(childs[i].tagName.toLowerCase() !== tag) {
childs.splice(i,1);
len = childs.length;
}
}
newEles = newEles.concat(childs);
});
that.elements = newEles;
return that;
},
parent : function(selector) {
var that = this,
eles = that.elements,
newEles = [],
parent;
if(!selector) {
that.each(eles,function(){
parent = this.parentNode;
newEles.push(parent)
});
} else {
switch(selector.charAt(0)) {
case '#':
that.each(eles,function(){
parent = this.parentNode;
while(parent && $(parent).attr('id') !== selector.substring(1)) {
parent = parent.parentNode;
}
newEles.push(parent)
});
break;
case '.':
that.each(eles,function(){
parent = this.parentNode;
while(parent && !$(parent).hasClass(selector.substring(1))) {
parent = parent.parentNode;
}
newEles.push(parent)
});
break;
default:
that.each(eles,function(){
parent = this.parentNode;
while(parent && parent.tagName.toLowerCase() !== selector) {
parent = parent.parentNode;
}
newEles.push(parent)
});
break;
}
}
that.elements = newEles;
return that;
},
val : function(opt_val) {
if(opt_val !== undefined) {
this.each(function(){
this.value = opt_val;
});
return this;
} else {
return this._trim(this.elements[0].value);
}
},
get : function(id) {
return $(this.elements[id]);
},
length : function() {
return this.elements.length;
},
realVal : function() {
var val = this._trim(this.elements[0].value);
if(val == this.attr('data-placeholder')) {
val = "";
}
return val;
},
before : function(ele,opt_ele) {
this.each(function(){
if(!opt_ele) {
opt_ele = this.children[0];
}
this.insertBefore(ele,opt_ele);
});
return this;
},
after : function(ele) {
this.each(function(){
this.appendChild(ele);
});
return this;
},
ease : function(time) {
return Math.pow(time,1/2);
},
animate : function(attr,value,opt_stop,opt_fn) {
var begin,_animate,
that = this;
_animate = function(ele,start,end,duration) {
begin = (new Date()).getTime();
duration = duration || 1000;
var _realAnimate = function() {
var pos = (new Date().getTime() - begin ) / duration;
if(pos >= 1.0) {
if(opt_fn) {
opt_fn.call(that);
}
return false;
}
pos = that.ease(pos);
var newValue = (parseInt(start) + (end-start)*pos);
if(newValue <= opt_stop) {
newValue = 0;
}
return !!(ele.style[attr] = newValue + 'px');
};
var step = function() {
if(_realAnimate()) {
setTimeout(step,13);
}
};
setTimeout(step,13);
};
this.each(function(){
var oldValue = $(this).css(attr),
newValue;
if(oldValue.indexOf('px')) {
oldValue = oldValue.substring(0,oldValue.length-2);
}
switch(value.charAt(0)) {
case '-' :
newValue = oldValue - value.substring(1);
_animate(this,oldValue,newValue);
break;
case '+' :
newValue = value.substring(1)-0 + parseInt(oldValue,10);
_animate(this,oldValue,newValue);
break;
}
});
}
};
zQuery.animate = function(opts) {
var start = new Date(),timer;
timer = setInterval(function(){
var progress,delta,timePassed;
timePassed = new Date() - start;
progress = timePassed/opts.duration;
if(progress > 1) {
clearInterval(timer);
opts.complete();
return;
}
delta = opts.delta(progress);
opts.step(delta);
},opts.delay || 13);
};
zQuery.isIE6_7 = function() {
var uAgent = navigator.userAgent;
return uAgent.indexOf('MSIE 6.0') > 0 || uAgent.indexOf('MSIE 7.0') > 0;
};
zQuery.serialize = function(obj) {
var data = [];
for(prop in obj) {
if(hasOwn.call(obj,prop)) {
push.call(data,encodeURIComponent(prop) + '=' + encodeURIComponent(obj[prop]));
}
}
return data.join('&');
};
zQuery.addZero = function(d) {
return new String(d).length >= 2 ? d : '0' + d;
};
zQuery.getFormatDateStr = function(date) {
var y = date.getFullYear(),
m = date.getM4onth() + 1,
d = date.getDay() + 1,
h = date.getHours(),
mi = date.getMinutes();
return y + '-' + $.addZero(m) + '-' + $.addZero(d) + ' ' + $.addZero(h) + ':' + $.addZero(mi);
};
zQuery.createEle = function(tag) {
return $(document.createElement(tag));
};
zQuery.ajax = function(props) {
props.async = props.async === undefined ? true : props.async;
var createXHR = function() {
if(!window.XMLHttpRequest) {
try {
return new ActiveXObject('Msxml2.XMLHTTP.6.0');
} catch (e1) {
try {
return new ActiveXObject('Msxml2.XMLHTTP.3.0')
} catch (e2) {
throw new Error('XMLHttpRequest is not supported');
}
}
} else {
return new XMLHttpRequest();
}
};
var xhr = createXHR();
xhr.open(props.method,props.url,props.async);
if(props.method == "GET") {
xhr.send(null);
} else if (props.method == "POST") {
xhr.send($.serialize(props.data));
}
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if((xhr.status >= 200 && xhr.status < 300 )|| xhr.status == 304) {
if(window.JSON && JSON.parse) {
props.callback.call(null,JSON.parse(xhr.responseText));
} else {
props.callback.call(null,eval('(' + xhr.responseText +')'));
}
} else {
alert('failed');
}
}
};
};
zQuery.proxy = function(fn,context) {
var _object = context,
_function = fn,
_args = arguments;
return function(){
//todo 兼容性问题
// not use slice for chrome 10 beta and Array.apply for android
var _argc = slice.call(_args,2);
push.apply(_argc,arguments);
return _function.apply(_object||null,_argc);
};
};
zQuery.fn.init.prototype = zQuery.fn;
window.$ = window.zQuery = zQuery;
}(window,void(0));
基础库依赖关系
global <- klass
<- platform
<- config <- constant
<- util <- element <-> event
/*
* ------------------------------------------
* 可链式接口实现代理文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @namespace CHAINABLE */
/** @module base/chain */
NEJ.define([
'base/util'
],function(_u,_p){
var _cache = {};
/**
* 添加可链式调用的接口
*
* 添加可链式接口
* ```javascript
* NEJ.define([
* 'base/chain'
* ],function(_l){
* var _map = {};
*
* _map._$api1 = function(){
* // TODO
* }
*
* _map._$api2 = function(){
* // TODO
* }
*
* _l._$merge(_map);
* });
* ```
*
* 使用链式调用接口
* ```javascript
* NEJ.define([
* '/path/to/api.js',
* 'util/chain/chainable'
* ],function(_x,$){
* // 使用链式调用api
* $('body > p')._$api1()._$api2();
* });
* ```
*
* @method module:base/chain._$merge
* @param {Object} arg0 - 接口集合
* @return {Void}
*/
_p._$merge = function(_map){
_u._$merge(_cache,_map);
};
/**
* 导出链式接口列表
*
* @method module:base/chain._$dump
* @return {Object} 链式接口列表
*/
_p._$dump = function(){
return _cache;
};
/**
* 清除链式列表
*
* @method module:base/chain._$clear
* @return {Void}
*/
_p._$clear = function(){
_cache = {};
};
return _p;
});
/*
* ------------------------------------------
* 平台配置信息
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module base/config */
NEJ.define([
'./global.js',
'{platform}config.js'
],function(NEJ,_h,_p,_o,_f,_r){
/**
* 取Frame跨域Ajax代理文件,通过NEJ_CONF的p_frame配置给定域名的代理文件地址
*
* @method module:base/config._$getFrameProxy
* @see module:base/config._$get
* @param {String} arg0 - 请求地址或者域名
* @return {String} 代理文件地址
*/
_p._$getFrameProxy = function(_url){
var _host = _h.__url2host(_url);
return _p._$get('frames')[_host]||
(_host+'/res/nej_proxy_frame.html');
};
/**
* 取Flash跨域Ajax配置文件,通过NEJ_CONF的p_flash配置给定域名的代理文件地址
*
* @method module:base/config._$getFlashProxy
* @see module:base/config._$get
* @param {String} arg0 - 请求地址或者域名
* @return {String} 代理文件地址
*/
_p._$getFlashProxy = function(_url){
return _p._$get('flashs')[_h.__url2host(_url)];
};
/**
* 获取NEJ配置信息,通过NEJ_CONF配置相关信息
*
* ```javascript
* window.NEJ_CONF = {
* // resource root
* // defalut value -> '/res/'
* root : '/nej/'
* // blank image for ie6-ie7
* // default value -> $root+'nej_blank.gif'
* blank : '/res/nej_blank.gif'
* // localstorage flash
* // default value -> $root+'nej_storage.swf'
* storage : '/res/nej_storage.swf'
* // audio player flash
* // default value -> $root+'nej_player_audio.swf'
* audio : '/res/nej_player_audio.swf'
* // video player flash
* // default value -> $root+'nej_player_video.swf'
* video : '/res/nej_player_video.swf'
* // clipboard flash
* // default value -> $root+'nej_clipboard.swf'
* clipboard : '/res/nej_clipboard.swf'
* // https request proxy
* // default value -> $root+'nej_proxy_flash.swf'
* ajax : '/res/nej_proxy_flash.swf'
* // portrait root
* // default value -> $root+'portrait/'
* portrait : '/res/portrait/'
* // cross domain xhr request for ie6-ie9
* // if path not start with http[s]://
* // will use /res/nej_proxy_frame.html as default
* p_frame:['http://c.d.com/html/nej_proxy_frame.html']
* // flash crossdomain.xml file path
* // default value -> http://a.b.com/crossdomain.xml
* p_flash:['http://a.b.com/proxy/crossdomain.xml']
* // CSRF cookie name and parameter name
* // set p_csrf:true to use URS config {cookie:'AntiCSRF',param:'AntiCSRF'}
* // default value -> {cookie:'',param:''}
* p_csrf:{cookie:'AntiCSRF',param:'AntiCSRF'}
* };
* ```
*
* 配置标识支持
*
* | 标识 | 说明 |
* | :-- | :-- |
* | portrait | 表情根路径 |
* | blank.png | 空白图片文件地址 |
* | ajax.swf | Ajax代理Flash文件地址 |
* | chart.swf | 图标Flash文件地址 |
* | audio.swf | 实现Audio功能的Flash文件地址 |
* | video.swf | 实现Video功能的Flash文件地址 |
* | clipboard.swf | 实现剪切板功能的Flash文件地址 |
* | upload.image.swf | 实现图片上传功能的Flash文件地址 |
* | storage.swf | 实现本地存储功能的Flash文件地址 |
*
* @method module:base/config._$get
* @param {String} arg0 - 配置标识
* @return {Variable} 配置信息
*/
_p._$get = function(_key){
return _h.__get(_key);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.c'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 常量定义文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module base/constant */
NEJ.define([
'./global.js',
'./config.js'
],function(NEJ,_c,_p,_o,_f,_r){
var _seed = +new Date;
/**
* 找不到指定内容的错误码
*
* @const {Number} module:base/constant._$CODE_NOTFUND
*/
_p._$CODE_NOTFUND = 10000-_seed;
/**
* 需要指定的参数未指定的错误码
*
* @const {Number} module:base/constant._$CODE_NOTASGN
*/
_p._$CODE_NOTASGN = 10001-_seed;
/**
* 不支持操作的错误码
*
* @const {Number} module:base/constant._$CODE_NOTSPOT
*/
_p._$CODE_NOTSPOT = 10002-_seed;
/**
* 操作超时的错误码
*
* @const {Number} module:base/constant._$CODE_TIMEOUT
*/
_p._$CODE_TIMEOUT = 10003-_seed;
/**
* 字符串作为脚本执行异常的错误码
*
* @const {Number} module:base/constant._$CODE_ERREVAL
*/
_p._$CODE_ERREVAL = 10004-_seed;
/**
* 回调执行异常的错误码
*
* @const {Number} module:base/constant._$CODE_ERRCABK
*/
_p._$CODE_ERRCABK = 10005-_seed;
/**
* 服务器返回异常的错误码
*
* @const {Number} module:base/constant._$CODE_ERRSERV
*/
_p._$CODE_ERRSERV = 10006-_seed;
/**
* 异常终止的错误码
*
* @const {Number} module:base/constant._$CODE_ERRABRT
*/
_p._$CODE_ERRABRT = 10007-_seed;
/**
* 请求头content-type统一名称
*
* @const {Number} module:base/constant._$HEAD_CT
*/
_p._$HEAD_CT = 'Content-Type';
/**
* 文本请求头content-type值
*
* @const {String} module:base/constant._$HEAD_CT_PLAN
*/
_p._$HEAD_CT_PLAN = 'text/plain';
/**
* 文件请求头content-type值
*
* @const {String} module:base/constant._$HEAD_CT_FILE
*/
_p._$HEAD_CT_FILE = 'multipart/form-data';
/**
* 表单请求头content-type值
*
* @const {String} module:base/constant._$HEAD_CT_FORM
*/
_p._$HEAD_CT_FORM = 'application/x-www-form-urlencoded';
/**
* 空图片BASE64编码地址,低版本浏览器使用图片地址
*
* @const {String} module:base/constant._$BLANK_IMAGE
*/
_p._$BLANK_IMAGE = _c._$get('blank.png')||'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
if (CMPT){
NEJ.copy(NEJ.P('nej.g'),_p);
}
return _p;
});
{
"a":"aaaaaaaaa",
"b":"bbbbbbbbbb"
}
<!DOCTYPE html>
<html>
<head>
<title>define demo</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script src="../../../define.js"></script>
<script>
define(['./a.js']);
define(['json!./a.json'],function(_json){
log(_json);
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>element demo</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script src="../../define.js"></script>
<script>
NEJ.define([
'base/element'
],function(_e){
// create element and get by id
var _div = _e._$create('div');
_div.innerHTML = '<p id="a">aaaa</p>';
log(_e._$get('a'));
// get element after set element id in memory
var _div = document.createElement('div');
var _id = _e._$id(_div);
log(_e._$get(_id));
// parse element
log(_e._$html2node('<TR><td>col1</td><td>col2</td></TR>'));
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>element demo</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<div>
<p id="abc">aaaaaaaaaaaaa</p>
</div>
<input type="button" value="aaaa" onclick="document.title=+new Date;"/>
<script src="../../define.js"></script>
<script>
NEJ.define([
'base/event'
],function(_v){
_v._$addEvent(
document,'click',function(event){
log('document '+(this==document));
}
);
_v._$addEvent(
document.body,'click',function(event){
log('body '+(this==document.body));
}
);
_v._$addEvent(
'abc','click',function(event){
log('abc '+(this.id=='abc'));
}
);
_v._$addEvent(
document,'propertychange',function(event){
console.log(event.propertyName+'->'+document.title);
}
);
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>util demo</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<form id="abc">
<input type="text" name="a"/>
<select name="b"><option>aaa</option></select>
</form>
<script src="../../define.js"></script>
<script>
NEJ.define([
'base/element',
'base/util'
],function(_e,_u){
_u._$forEach(
_e._$get('abc').elements,function(e){
log(e.name);
}
);
});
</script>
</body>
</html>
/*
* ------------------------------------------
* 节点接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module base/element */
NEJ.define([
'./global.js',
'./constant.js',
'./util.js',
'./event.js',
'./chain.js',
'{platform}element.js'
],function(NEJ,_g,_u,_v,_x,_h,_p,_o,_f,_r){
// variables
var _y = {}, // chainable methods
_cspol, // css text pool
_empol = {}, // elements without id property, eg. document,window
_dirty = {}, // temporary element with id
_fragment = document.createDocumentFragment(); // node in memory
// init
if (!document.head){
document.head = document.getElementsByTagName('head')[0]||document.body;
}
/**
* 为节点设置一个唯一的标识
*
* 结构举例
* ```html
* <div id="abc">aaaaa</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 如果有id,返回原来的id,否则返回auto-id-12345678(8位随机字符串)
* var _id = _e._$id(_node||"abc");
* });
* ```
*
* @method module:base/element._$id
* @param {String|Node} arg0 - 节点标识或者对象
* @return {String} 节点标识
*/
/**
* @method CHAINABLE._$id
* @see module:base/element._$id
*/
_p._$id =
_y._$id = function(_element){
_element = _p._$get(_element);
if (!_element) return;
var _id = !!_element.id ? _element.id
: 'auto-id-'+_u._$uniqueID();
if (!('id' in _element)){
_empol[_id] = _element;
}
_element.id = _id;
// check if element can be getted
if (!_p._$get(_id)){
_dirty[_id] = _element;
}
return _id;
};
/**
* 根据标识取节点对象,包括在内存中的节点
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 先根据id从内存中取,再从页面取
* var _node = _e._$get("abc");
* });
* ```
*
* @method module:base/element._$get
* @param {String|Node} arg0 - 节点标识或者对象
* @return {Node} 节点对象
*/
_p._$get = function(_element){
// for document/window
var _node = _empol[''+_element];
if (!!_node){
return _node;
}
// element is node
if (!_u._$isString(_element)&&
!_u._$isNumber(_element)){
return _element;
}
// element is id
// check node in page first
var _node = document.getElementById(_element);
if (!_node){
_node = _h.__getElementById(_fragment,_element);
}
// remove dirty element
if (!!_node){
delete _dirty[_element];
}
return _node||_dirty[_element];
};
/**
* 取节点的子节点列表
*
* 结构举例
* ```html
* <div id="abc">
* <p>1</p>
* <p><span>2</span></p>
* <p>3</p>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 取直接的3个子节点(p标签)
* var _childs = _e._$getChildren('abc');
*
* // 使用类名过滤,去带a或者b样式类的子节点
* var _childs = _e._$getChildren('abc','a b');
* });
* ```
*
* @method module:base/element._$getChildren
* @param {String|Node} arg0 - 节点标识或者对象
* @param {String} arg1 - 样式标识
* @return {Array} 子节点列表
*/
/**
* @method CHAINABLE._$getChildren
* @see module:base/element._$getChildren
*/
_p._$getChildren =
_y._$getChildren = function(_element,_clazz){
_element = _p._$get(_element);
if (!_element) return null;
var _list = _h.__getChildren(_element);
if (!!_clazz){
_u._$reverseEach(
_list,function(_node,_index,_list){
if (!_p._$hasClassName(_node,_clazz)){
_list.splice(_index,1);
}
}
);
}
return _list;
};
/**
* 根据类名取节点列表
*
* 结构举例
* ```html
* <div id="abc">
* <p class="item">1</p>
* <div><p class="item">2</p></div>
* <p class="item">3</p>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 获取abc节点下样式带有"item"的节点列表,如果没有父节点,返回null
* var _list = _e._$getByClassName('abc','item');
* });
* ```
*
* @method module:base/element._$getByClassName
* @param {String|Node} arg0 - 节点标识或者对象
* @param {String} arg1 - 类名
* @return {Array} 节点列表
*/
/**
* @method CHAINABLE._$getByClassName
* @see module:base/element._$getByClassName
*/
_p._$getByClassName =
_y._$getByClassName = function(_element,_class){
_element = _p._$get(_element);
return !_element ? null :
_h.__getElementsByClassName(
_element,_class.trim()
);
};
/**
* 根据从兄弟节点中搜索符合条件的节点
*
* 结构举例
* ```html
* <div>
* <p class="item" id="a1">1</p>
* <p class="item" id="a2">2</p>
* <p class="item" id="a3">3</p>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 取a2的后一个兄弟节点a3
* var _node = _e._$getSibling('a2');
*
* // 取a2的前一个兄弟节点a1
* var _node = _e._$getSibling('a2',{backward:true});
*
* // 过滤搜索,从a2向后搜索找id为a4的节点
* var _node = _e._$getSibling('a2',function(_element){
* return _element.id=='a4'
* });
*
* // 过滤搜索,从a2向前搜索找id为a0的节点
* var _node = _e._$getSibling('a2',{
* backward:true,
* filter:function(_element){
* return _element.id=='a0'
* }
* });
* });
* ```
*
* @method module:base/element._$getSibling
* @param {String|Node} arg0 - 节点标识或者对象
* @param {Function|Object} arg1 - 如果是函数则表示过滤器,否则为配置信息
* @property {Boolean} backward - 是否后向搜索,默认前向搜索
* @property {Function} filter - 节点过滤器,返回true表示需要返回的节点,找到第一个即返回
* @return {Node} 符合条件的节点
*/
/**
* @method CHAINABLE._$getSibling
* @see module:base/element._$getSibling
*/
_p._$getSibling =
_y._$getSibling = (function(){
var _doFilter = function(){
return !0;
};
return function(_element,_filter){
_element = _p._$get(_element);
if (!_element){
return null;
}
var _conf = {
backward:!1,
filter:_doFilter
};
if (_u._$isFunction(_filter)){
_conf.filter = _filter;
}else{
_conf = _u._$fetch(_conf,_filter);
}
var _next = _conf.backward
? _h.__previousSibling
: _h.__nextSibling;
while(_element=_next(_element)){
if (_conf.filter(_element)){
break;
}
}
return _element;
};
})();
/**
* 取节点所在的滚动容器,
* 从当前节点开始往上遍历,直到出现滚动条的节点
*
* 结构举例
* ```html
* <div id="efg">
* <div id="abc">123</div>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 加入efg节点出现滚动条,则这里找到的是efg节点
* var _sbody = _e._$getScrollViewPort('abc');
*
* // 不带任何参数取页面滚动条所在节点
* var _sbody = _e._$getScrollViewPort();
* });
* ```
*
* @method module:base/element._$getScrollViewPort
* @param {String|Node} arg0 - 节点标识或者对象
* @return {Node} 视窗节点
*/
_p._$getScrollViewPort = function(_element){
_element = _p._$get(_element);
if (!!_element){
_element = _element.parentNode;
while(!!_element){
if (_element.scrollHeight>
_element.clientHeight){
break;
}
_element = _element.parentNode;
}
if (!!_element){
return _element;
}
}
var _tmp1 = document.body.scrollHeight,
_tmp2 = document.documentElement.scrollHeight;
return _tmp2>=_tmp1?document.documentElement:document.body;
};
/**
* 盒模型结构
*
* @typedef {Object} module:base/element~BoxModel
* @property {Number} scrollTop - 滚动垂直偏移
* @property {Number} scrollLeft - 滚动水平偏移
* @property {Number} clientWidth - 页面可视宽度
* @property {Number} clientHeight - 页面可视高度
* @property {Number} scrollWidth - 页面滚动宽度
* @property {Number} scrollHeight - 页面滚动高度
*/
/**
* 取页面盒信息,返回盒信息内容:
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 返回信息见说明
* var _box = _e._$getPageBox();
* });
* ```
*
* @method module:base/element._$getPageBox
* @param {Document} arg0 - 文档对象
* @return {module:base/element~BoxModel} 盒信息
*/
_p._$getPageBox = (function(){
// get min value but not zero
var _getClientBox = function(_list){
var _result = 0;
_u._$forEach(
_list,function(_size){
if (!_size) return;
if (!_result){
_result = _size;
}else{
_result = Math.min(_result,_size);
}
}
);
return _result;
};
var _farr = [
{
main:'scroll',
sub:['Top','Left'],
func:function(_key,_body0,_body1){
return Math.max(
_body0['scroll'+_key],
_body1['scroll'+_key]
);
}
},
{
main:'client',
sub:['Width','Height'],
func:function(_key,_body0,_body1){
return _getClientBox([
_body0['client'+_key],
_body0['offset'+_key],
_body1['client'+_key],
_body1['offset'+_key]
]);
}
},
{
main:'scroll',
sub:['Width','Height'],
func:function(_key,_body0,_body1,_result){
return Math.max(
_result['client'+_key],
_body0['scroll'+_key],
_body1['scroll'+_key]
);
}
}
];
return function(_document){
var _result = {},
_doc = _document||document,
_body0 = _doc.body,
_body1 = _doc.documentElement;
_u._$forEach(
_farr,function(_item){
var _main = _item.main;
_u._$forEach(
_item.sub,function(_key){
_result[_main+_key] = _item.func(
_key,_body0,_body1,_result
);
}
);
}
);
return _result;
};
})();
/**
* 按比例将给定大小缩放至限制区域内
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 限制区域大小 100*10
* var _limit = {width:100,height:10};
*
* // 给定200*10的大小,由于宽度超出,缩放后为{width:100,height:5}
* var _box = _e._$getMaxBox({width:200,height:10},_limit);
*
* // 给定100*20的大小,由于高度超出,缩放后为{width:50,height:10}
* var _box = _e._$getMaxBox({width:100,height:20},_limit);
*
* // 给定 50*5,没有超出限制,返回{width:50,height:5}
* var _box = _e._$getMaxBox({width:50,height:5},_limit);
* });
* ```
*
* @method module:base/element._$getMaxBox
* @param {module:base/element~SizeModel} arg0 - 原始大小
* @param {module:base/element~SizeModel} arg1 - 最大限制大小
* @return {module:base/element~SizeModel} 按比例计算出的最大值信息
*/
_p._$getMaxBox = function(_org,_max){
var _result = _u._$merge({},_org),
_mrto = _max.width/_max.height,
_orto = _org.width/_org.height;
// height overflow
if (_mrto>_orto&&
_org.height>_max.height){
_result.height = _max.height;
_result.width = _result.height*_orto;
}
// width overflow
if (_mrto<_orto&&
_org.width>_max.width){
_result.width = _max.width;
_result.height = _result.width/_orto;
}
return _result;
};
/**
* 滚动到指定节点
*
* 结构举例
* ```html
* <div id="a" style="padding:5px 0 0 10px;"></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 滚动到页面上a这节点的位置
* _e._$scrollTo('a');
* });
* ```
*
* @method module:base/element._$scrollTo
* @param {Node|String} arg0 - 节点
* @return {Void}
*/
/**
* @method CHAINABLE._$scrollTo
* @see module:base/element._$scrollTo
*/
_p._$scrollTo =
_y._$scrollTo = function(_element){
var _offset = _p._$offset(_element);
window.scrollTo(_offset.x,_offset.y);
};
/**
* 大小信息对象
* @typedef {Object} module:base/element~SizeModel
* @property {Number} width - 宽度
* @property {Number} height - 高度
*/
/**
* 位置信息对象
* @typedef {Object} module:base/element~PositionModel
* @property {Number} top - 垂直位置
* @property {Number} left - 水平位置
*/
/**
* 计算在容器中对齐时的位置信息
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 容器大小
* var _box = {width:100,height:40};
*
* // 默认居中对齐返回 {top:15,left:40}
* var _pos = _e._$align(_box,{width:20,height:10});
*
* // 左下对齐返回 {top:30,left:0}
* var _pos = _e._$align(_box,{width:20,height:10},'left bottom');
* });
* ```
*
* @method module:base/element._$align
* @param {module:base/element~SizeModel} arg0 - 容器大小
* @param {module:base/element~SizeModel} arg1 - 原始大小
* @param {String} arg2 - 对齐方式,水平+空格+垂直,如left top,默认为 center middle,
* 水平:left/center/right,
* 垂直:top/middle/bottom
* @return {module:base/element~PositionModel} 位置信息
*/
_p._$align = (function(){
var _reg = /\s+/;
var _fmap = {
left:function(){
return 0;
},
center:function(_box,_org){
return (_box.width-_org.width)/2;
},
right:function(_box,_org){
return _box.width-_org.width;
},
top:function(){
return 0;
},
middle:function(_box,_org){
return (_box.height-_org.height)/2;
},
bottom:function(_box,_org){
return _box.height-_org.height;
}
};
return function(_box,_org,_align){
var _result = {},
_arr = (_align||'').split(_reg),
_top = _fmap[_arr[1]]||_fmap.middle,
_left = _fmap[_arr[0]]||_fmap.center;
_result.top = _top(_box,_org);
_result.left = _left(_box,_org);
return _result;
};
})();
/**
* 计算两个节点之间的偏移量
*
* 结构举例
* ```html
* <div id="a" style="position:relative;padding:5px 0 0 10px;">
* <span id="b">123</span>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 计算节点b到节点a(外层需要定位属性)的距离,如果没有指定节点,默认计算的根节点
* // _result : {x:10,y:5}
* var _result = _e._$offset('b','a');
* });
* ```
*
* @method module:base/element._$offset
* @param {String|Node} arg0 - 起始节点
* @param {String|Node} arg1 - 结束节点,没有该参数则计算到根节点
* @return {Object} 偏移量,如{x:234,y:987}
*/
/**
* @method CHAINABLE._$offset
* @see module:base/element._$offset
*/
_p._$offset =
_y._$offset = (function(){
var _isRoot = function(_element){
return _element==document.body||
_element==document.documentElement;
};
return function(_from,_to){
_from = _p._$get(_from);
if (!_from){
return null;
}
_to = _p._$get(_to)||null;
var _node = _from,
_result = {x:0,y:0},
_isroot,_delta,_border;
while(!!_node&&_node!=_to){
_isroot = _isRoot(_node)||_node==_from;
_delta = _isroot?0:_node.scrollLeft;
_border = parseInt(_p._$getStyle(_node,'borderLeftWidth'))||0;
_result.x += _node.offsetLeft+_border-_delta;
_delta = _isroot?0:_node.scrollTop;
_border = parseInt(_p._$getStyle(_node,'borderTopWidth'))||0;
_result.y += _node.offsetTop+_border-_delta;
_node = _node.offsetParent;
}
return _result;
};
})();
/**
* 节点占全屏
*
* @method module:base/element._$fullScreen
* @param {Node} arg0 - 节点
* @return {Void}
*/
/**
* @method CHAINABLE._$fullScreen
* @see module:base/element._$fullScreen
*/
_p._$fullScreen =
_y._$fullScreen = function(_element){
_element = _p._$get(_element);
if (!!_element){
_h.__fullScreen(
_element,
_p._$getPageBox()
);
}
};
/**
* 为节点增加用于盖select/flash等控件的层
*
* @method module:base/element._$mask
* @see module:base/element._$unmask
* @param {Node} arg0 - 节点
* @return {Node} 盖层节点
*/
/**
* @method CHAINABLE._$mask
* @see module:base/element._$mask
*/
_p._$mask =
_y._$mask = function(_element){
_element = _p._$get(_element);
if (!!_element){
_p._$id(_element);
return _h.__mask(_element);
}
return null;
};
/**
* 为节点移除用于盖select/flash等控件的层
*
* @method module:base/element._$unmask
* @see module:base/element._$mask
* @param {Node} arg0 - 节点
* @return {Node} 盖层节点
*/
/**
* @method CHAINABLE._$unmask
* @see module:base/element._$unmask
*/
_p._$unmask =
_y._$unmask = function(_element){
_element = _p._$get(_element);
if (!!_element){
_p._$id(_element);
return _h.__unmask(_element);
}
return null;
};
/**
* 创建节点,使用该接口创建的结构后续可通过_$get接口根据ID取到节点
*
* 结构举例
* ```javascript
* <div id="abc">1</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 创建一个节点,挂到body上
* _e._$create("div","m-body",document.body);
*
* // 创建一个节点挂到id是abc的节点上
* // 结果:<div id="abc">1<p class="m-list"></p></div>
* _e._$create("p","m-list","abc");
*
* // 创建一个节点放在内存中
* var _node = _e._$create('div');
* _node.innerHTML = '<p id="a">aaaaaa</p><p id="b">bbbbbb</p>';
* // 后续可以通过id取id为a的节点
* var _pa = _e._$get('a');
* });
* ```
*
* @method module:base/element._$create
* @param {String} arg0 - 标签
* @param {String} arg1 - 样式
* @param {String|Node} arg2 - 父节点标识或者对象
* @return {Node} 节点
*/
_p._$create = (function(){
var _map = {
a:{href:'#',hideFocus:!0},
style:{type:'text/css'},
link:{type:'text/css',rel:'stylesheet'},
iframe:{frameBorder:0},
script:{defer:!0,type:'text/javascript'}
};
return function(_tag,_class,_parent){
var _element = document.createElement(_tag),
_config = _map[_tag.toLowerCase()];
_u._$merge(_element,_config);
if (!!_class) _element.className = _class;
_parent = _p._$get(_parent);
if (!!_parent){
_parent.appendChild(_element);
}else{
// append to documentfragment for get by id
if (!_config){
_fragment.appendChild(_element);
}
}
return _element;
};
})();
/**
* 创建可交互框架
*
* 结构举例
* ```html
* <div id="frameCnt"></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* var _xFrame = _e._$createXFrame({
* src:'http://www.baidu.com',
* name:'百度',
* parent:'frameCnt',
* visible:false,
* onload:function(){
* // 加载frame成功后,name设置成功,为百度
* // 加载frame成功后,显示效果正确,display:none
* }
* });
* });
* ```
*
* @method module:base/element._$createXFrame
* @param {Object} arg0 - 可选配置参数
* @property {String} src - 框架地址
* @property {String} name - 框架名称
* @property {String|Node|Function} parent - 父节点或者框架加入父容器的执行函数
* @property {Boolean} visible - 是否可见
* @property {Function} onload - 框架载入回调
* @return {Node} 框架节点
*/
_p._$createXFrame = (function(){
var _getFrameSrc = function(){
if (location.hostname==document.domain){
return 'about:blank';
}
return 'javascript:(function(){document.open();document.domain="'+document.domain+'";document.close();})();';
};
var _getFrameWithName = function(_name){
_name = _name.trim();
if (!_name){
return _p._$create('iframe');
}
// pass name to frame
var _iframe;
try{
_iframe = document.createElement(
'<iframe name="'+_name+'"></iframe>');
_iframe.frameBorder = 0;
}catch(e){
_iframe = _p._$create('iframe');
_iframe.name = _name;
}
return _iframe;
};
return function(_options){
_options = _options||_o;
var _iframe = _getFrameWithName(_options.name||'');
if (!_options.visible){
_iframe.style.display = 'none';
}
if (_u._$isFunction(_options.onload)){
_v._$addEvent(_iframe,'load',function(_event){
if (!_iframe.src) return;
_v._$clearEvent(_iframe,'load');
_options.onload(_event);
});
}
// will trigger onload
var _parent = _options.parent;
if (_u._$isFunction(_parent)){
try{_parent(_iframe);}catch(e){}
}else{
(_p._$get(_parent)||document.body).appendChild(_iframe);
}
// ensure trigger onload async
var _src = _options.src||_getFrameSrc();
window.setTimeout(function(){
_iframe.src = _src;
},0);
return _iframe;
};
})();
/**
* 删除节点
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 移除节点前先清理节点上的事件
* _e._$remove('abc',false);
* // 移除节点前不清理节点上的事件
* _e._$remove('abc',true);
* });
* ```
*
* @method module:base/element._$remove
* @see module:base/element._$removeByEC
* @param {String|Node} arg0 - 节点标识或者对象
* @param {Boolean} arg1 - 是否禁止事件清理
* @return {Void}
*/
/**
* @method CHAINABLE._$remove
* @see module:base/element._$remove
*/
_p._$remove =
_y._$remove = (function(){
var _fmap = {
img:function(_node){
_node.src = _g._$BLANK_IMAGE;
},
iframe:function(_node){
_node.src = 'about:blank';
}
};
var _doClear = function(_node,_tag){
if (!_tag){
var _xtag = (_node.tagName||'').toLowerCase(),
_func = _fmap[_xtag];
if (!!_func){
_func(_node);
}
return;
}
if (!!_node.getElementsByTagName){
_u._$forEach(
_node.getElementsByTagName(_tag),
_doClear
);
}
};
return function(_element){
_element = _p._$get(_element);
if (!!_element){
// clear events
if (!arguments[1]){
_v._$clearEvent(_element);
}
// clear elements
_doClear(_element);
_doClear(_element,'img');
_doClear(_element,'iframe');
// remove node
if (!!_element.parentNode){
_element.parentNode.removeChild(_element);
}
}
};
})();
/**
* 节点移至内存
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 先生成一个节点加到body下
* var _node = _e._$create('div','js-div',document.body);
* // 把节点移动到内存中
* _e._$removeByEC(_node);
* // 从body上没有取到节点,结果为[]
* _e._$getByClassName(document.body,'js-div');
* });
* ```
*
* @method module:base/element._$removeByEC
* @see module:base/element._$remove
* @param {String|Node} arg0 - 节点标识或者对象
* @return {Void}
*/
/**
* @method CHAINABLE._$removeByEC
* @see module:base/element._$removeByEC
*/
_p._$removeByEC =
_y._$removeByEC = function(_element){
_element = _p._$get(_element);
if (!!_element){
try{
_fragment.appendChild(_element);
}catch(ex){
// ignore
console.error(ex);
}
}
};
/**
* 清除所有子节点
*
* 结构举例
* ```html
* <ul id="abc">
* <li>aaaaaaaaaaaaa</li>
* <li>bbbbbbbbbbbbb</li>
* <li>ccccccccccccc</li>
* </ul>
*
* <table id="efg">
* <tr><td>1111</td><td>1111</td></tr>
* <tr><td>2222</td><td>2222</td></tr>
* <tr><td>3333</td><td>3333</td></tr>
* </table>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 清除ul下的子节点
* _e._$clearChildren('abc');
*
* // 清除table下的子节点
* _e._$clearChildren('efg');
* });
* ```
*
* @method module:base/element._$clearChildren
* @see module:base/element._$remove
* @param {String|Node} arg0 - 容器节点
* @return {Void}
*/
/**
* @method CHAINABLE._$clearChildren
* @see module:base/element._$clearChildren
*/
_p._$clearChildren =
_y._$clearChildren = function(_element){
_element = _p._$get(_element);
if (!!_element){
_u._$reverseEach(
_element.childNodes,
function(_node){
_p._$remove(_node);
}
);
}
};
/**
* 内联元素增加定位封装
*
* 结构举例
* ```html
* <input type="text" id="abc"/>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 包装定位的span
* _e._$wrapInline('abc');
* });
* ```
*
* 生成结构如下
* ```html
* <span style="position:relative;zoom:1">
* <input type="text" id="abc"/>
* <!-- 此api返回以下这个节点 -->
* <span style="position:absolute;top:0;left:0;"></span>
* </span>
* ```
*
* 应用举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 返回容器的样式名称
* // 通过这个样式名称可以取到一个绝对定位的样式名 class+'-show'
* var _node = _e._$wrapInline('abc',{
* tag:'label',
* clazz:'js-xxx'
* });
* // 可以在返回的节点里添加想要显示的结构
* _node.innerHTML = '<span>aaa</span><span>aaa</span>';
* });
* ```
*
* @method module:base/element._$wrapInline
* @param {String|Node} arg0 - 内联节点
* @param {Object} arg1 - 绝对定位节点配置信息
* @property {String} tag - 标记名称,默认span
* @property {String} nid - 节点识别样式名,这个会被添加到样式中作为标识
* @property {String} clazz - 样式名称
* @return {Node} 绝对定位的节点
*/
/**
* @method CHAINABLE._$wrapInline
* @see module:base/element._$wrapInline
*/
_p._$wrapInline =
_y._$wrapInline = (function(){
var _clazz,
_reg0 = /\s+/;
var _doInitStyle = function(){
if (!!_clazz) return;
_clazz = _p._$pushCSSText('.#<uispace>{position:relative;zoom:1;}.#<uispace>-show{position:absolute;top:0;left:100%;cursor:text;white-space:nowrap;overflow:hidden;}');
_p._$dumpCSSText();
};
return function(_element,_options){
_element = _p._$get(_element);
if (!_element){
return null;
}
// init style
_doInitStyle();
_options = _options||_o;
// check relative parent
var _parent = _element.parentNode;
if (!_p._$hasClassName(_parent,_clazz)){
// build wrapper box
_parent = _p._$create('span',_clazz);
_element.insertAdjacentElement('beforeBegin',_parent);
_parent.appendChild(_element);
}
// check absolute node
var _nid = _options.nid||'',
_node = _p._$getByClassName(
_parent,_nid||
(_clazz+'-show')
)[0];
if (!_node){
var _klass = ((_options.clazz||'')+' '+_nid).trim();
_klass = _clazz+'-show'+(!_klass?'':' ')+_klass;
_node = _p._$create(_options.tag||'span',_klass);
_parent.appendChild(_node);
}
// append class to parent node
var _klass = _options.clazz;
if (!!_klass){
_klass = (_klass||'').trim().split(_reg0)[0]+'-parent';
_p._$addClassName(_parent,_klass);
}
return _node;
};
})();
/**
* 设置或者获取指定标识的数据
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 设置值操作
* // <div id="abc" data-img="http://a.b.com/a.png">123</div>
* // 返回value值: http://a.b.com/a.png
* var _src = _e._$dataset('abc','img','http://a.b.com/a.png');
* // 取值操作
* var _src = _e._$dataset('abc','img');
*
* // 批量设置
* var _map = _e._$dataset('abc',{
* a:'aaaaa',
* b:'bbbbbbbb',
* c:'ccccccccc'
* });
*
* // 批量取值
* // 返回:{a:'aaaaa',b:'bbbbbbbb',c:'ccccccccc'}
* var _map = _e._$dataset('abc',['a','b','c']);
* });
* ```
*
* @method module:base/element._$dataset
* @see module:base/element._$attr
* @param {String} arg0 - 数据标识
* @param {String|Object|Array} arg1 - 属性名
* @return {String|Object} 数据值
*/
/**
* @method CHAINABLE._$dataset
* @see module:base/element._$dataset
*/
_p._$dataset =
_y._$dataset = function(_element,_key,_value){
// check element
var _id = _p._$id(_element);
if (!_id){
return null;
}
// check single key-value
if (_u._$isString(_key)){
return _h.__dataset(
_p._$get(_element),
_key,_value
);
}
// check map set
// ignore argument _value
if (_u._$isObject(_key)){
var _ret = {};
_u._$forIn(_key,function(_v,_k){
_ret[_k] = _p._$dataset(_id,_k,_v);
});
return _ret;
}
// check array get
// ignore argument _value
if (_u._$isArray(_key)){
var _ret = {};
_u._$forEach(_key,function(_k){
_ret[_k] = _p._$dataset(_id,_k);
});
return _ret;
}
return null;
};
/**
* 取某个节点的属性值
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 设置成 <div id="abc" data-img="http://a.b.com/a.png">123</div>
* // 返回value值: http://a.b.com/a.png
* var _src = _e._$attr('abc','data-img','http://a.b.com/a.png');
*
* // 如果设置了img的值返回data-img,否则放回空字符串
* var _src = _e._$attr('abc','data-img');
* });
* ```
*
* @method module:base/element._$attr
* @see module:base/element._$dataset
* @param {String|Node} arg0 - 节点标识或者对象
* @param {String} arg1 - 属性名称
* @param {String} arg2 - 属性值,如果没有设置此参数则表示取值
* @return {String} 属性值
*/
/**
* @method CHAINABLE._$attr
* @see module:base/element._$attr
*/
_p._$attr =
_y._$attr = function(_element,_name,_value){
_element = _p._$get(_element);
if (!_element){
return '';
}
if (_value!==undefined&&!!_element.setAttribute){
_element.setAttribute(_name,_value);
}
return _h.__getAttribute(_element,_name);
};
/**
* html代码转节点对象,
* 如果转换出来的节点数量超过[包含]2个,
* 则最外面增加一个容器节点,即返回的始终是一个节点
*
* 结构举例
* ```html
* <div id="abc">
* <span>123</span>
* </div>
* ```
*
* 代码举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* var _node = _e._$html2node('<div>1</div><div><span>2</span></div>');
* });
* ```
*
* 返回结果
* ```html
* <div> <!-- 返回此节点 -->
* <div>1</div>
* <div><span>2</span></div>
* </div>
* ```
*
* @method module:base/element._$html2node
* @param {String} arg0 - 代码
* @return {Node} 节点
*/
_p._$html2node = (function(){
var _reg = /<(.*?)(?=\s|>)/i, // first tag name
_tmap = {li:'ul',tr:'tbody',td:'tr',th:'tr',option:'select'};
return function(_html){
var _tag;
if (_reg.test(_html)){
_tag = _tmap[(RegExp.$1||'').toLowerCase()]||'';
}
var _div = _p._$create(_tag||'div');
_div.innerHTML = _html;
var _list = _p._$getChildren(_div);
return _list.length>1?_div:_list[0];
};
})();
/**
* 将dom节点转为xml串
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_p){
* // 生成<div id="abc">123</div>字符串
* var _xml = _p._$dom2xml('abc'));
* });
* ```
*
* @see module:base/element._$xml2dom
* @method module:base/element._$dom2xml
* @param {String|Node} arg0 - 节点
* @return {String} XML代码
*/
/**
* @method CHAINABLE._$dom2xml
* @see module:base/element._$dom2xml
*/
_p._$dom2xml =
_y._$dom2xml = function(_element){
_element = _p._$get(_element);
return !_element?'':_h.__serializeDOM2XML(_element);
};
/**
* 将xml转为dom节点
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 生成<div id="abc">123</div>节点
* var _node = _e._$xml2dom('<div id="abc">123</div>');
* });
* ```
*
* @method module:base/element._$xml2dom
* @see module:base/element._$dom2xml
* @param {String} arg0 - xml文本
* @return {Node} DOM节点
*/
_p._$xml2dom = function(_xml){
_xml = (_xml||'').trim();
return !_xml?null:_h.__parseDOMFromXML(_xml);
};
/**
* dom节点转对象,多用于XML DOM转数据对象
*
* 结构举例
* ```html
* <div id="abc">123</div>
*
* <div id="efg">
* <p>aaaa</p>
* <span>bbbb</span>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_p){
* // 返回对象{div:'123'}
* var _obj = _p._$dom2object('abc');
*
* // 返回对象{div:{p:'aaaa',span:'bbbb'}}
* var _obj = _p._$dom2object('efg');
* });
* ```
*
* @method module:base/element._$dom2object
* @see module:base/element._$xml2object
* @param {String|Node} arg0 - 节点
* @return {Object} 转换完成的对象
*/
/**
* @method CHAINABLE._$dom2object
* @see module:base/element._$dom2object
*/
_p._$dom2object =
_y._$dom2object = function(_dom,_obj){
_obj = _obj||{};
_dom = _p._$get(_dom);
if (!_dom) return _obj;
var _name = _dom.tagName.toLowerCase(),
_list = _p._$getChildren(_dom);
if (!_list||!_list.length){
_obj[_name] = _dom.textContent||_dom.text||'';
return _obj;
}
var _tmp = {};
_obj[_name] = _tmp;
_u._$forEach(
_list,function(_node){
_p._$dom2object(_node,_tmp);
}
);
return _obj;
};
/**
* XML转对象
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 返回 {user:{id:'1',username:'aaa',password:'123456'}}
* var _obj = _e._$xml2object('\
* <?xml version="1.0" encoding="utf-8" ?>\
* <user>\
* <id>1</id>\
* <username>aaa</username>\
* <password>123456</password>\
* </user>\
* ');
* });
* ```
*
* @method module:base/element._$xml2object
* @see module:base/element._$dom2object
* @param {String} arg0 - xml代码
* @return {Object} 对象
*/
_p._$xml2object = function(_xml){
try{
return _p._$dom2object(_p._$xml2dom(_xml));
}catch(ex){
return null;
}
};
/**
* 文本转指定类型的数据
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 转成dom节点
* var _dom = _e._$text2type('<div id="abc">123</div>',"xml");
* // 转成json字符串
* var _json = _e._$text2type('{"a":"aaaaaaaaaaaaa"}',"json");
* // 原样返回
* var _text = _e._$text2type('<div id="abc">123</div>');
* });
* ```
*
* @method module:base/element._$text2type
* @param {String} arg0 - 文本内容
* @param {String} arg1 - 类型,如xml/json/text
* @return {Variable} 指定类型的数据
*/
_p._$text2type = (function(){
var _fmap = {
xml:function(_text){
return _p._$xml2dom(_text);
},
json:function(_text){
try{
return JSON.parse(_text);
}catch(ex){
return null;
}
},
dft:function(_text){
return _text;
}
};
return function(_text,_type){
_type = (_type||'').toLowerCase();
return (_fmap[_type]||_fmap.dft)(_text||'');
};
})();
/**
* 批量设置节点样式
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* _e._$style('abc',{color:'red',width:'100px'});
* });
* ```
*
* 输出结果
* ```html
* <div id="abc" style="color:red;width:100px;">123</div>
* ```
*
* @method module:base/element._$style
* @see module:base/element._$setStyle
* @param {String|Node} arg0 - 节点
* @param {Object} arg1 - 样式信息{color:'red',width:'100px'}
* @return {Void}
*/
/**
* @method CHAINABLE._$style
* @see module:base/element._$style
*/
_p._$style =
_y._$style = function(_element,_map){
_element = _p._$get(_element);
if (!!_element){
_u._$loop(_map,function(_value,_name){
_p._$setStyle(_element,_name,_value);
});
}
};
/**
* 设置单个样式
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* _e._$setStyle('abc','color','red');
* });
* ```
*
* 输出结果
* ```html
* <div id="abc" style="color:red;">123</div>
* ```
*
* @method module:base/element._$setStyle
* @see module:base/element._$getStyle
* @param {String|Node} arg0 - 节点
* @param {String} arg1 - 样式名称
* @param {String} arg2 - 样式值
* @return {Void}
*/
/**
* @method CHAINABLE._$setStyle
* @see module:base/element._$setStyle
*/
_p._$setStyle =
_y._$setStyle = function(_element,_name,_value){
_element = _p._$get(_element);
if (!!_element){
_h.__setStyleValue(
_element,_name,
_h.__processCSSText(_value)
);
}
};
/**
* 取样式值
*
* 结构举例
* ```html
* <div id="abc" style="color:red;">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 返回节点的颜色值red(高版本浏览器返回rgb值),如果没有返回空字符串
* var _value = _e._$getStyle('abc','color');
* });
* ```
*
* @method module:base/element._$getStyle
* @see module:base/element._$setStyle
* @param {String|Node} arg0 - 节点
* @param {String} arg1 - 样式名称
* @return {String} 样式值
*/
/**
* @method CHAINABLE._$getStyle
* @see module:base/element._$getStyle
*/
_p._$getStyle =
_y._$getStyle = function(_element,_name){
_element = _p._$get(_element);
return !_element ? '' :
_h.__getStyleValue(
_element,_name
);
};
/**
* 页面注入脚本
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 注入脚本,全局执行环境
* _e._$addScript('\
* document.getElementById("abc").style.color = "green"\
* ');
* });
* ```
*
* 输出结果
* ```html
* <div id="abc" style="color:green;">123</div>
* ```
*
* @method module:base/element._$addScript
* @param {String} arg0 - 脚本内容
* @return {Void}
*/
_p._$addScript = function(_script){
try{
_script = _script.trim();
if (!!_script){
return (new Function(_script))();
}
}catch(ex){
// ignore
console.error(ex.message);
console.error(ex.stack);
}
};
/**
* 注入页面内联样式,
* 样式支持前缀标记$&lt;vendor&gt; ,
* 如下样式值支持3D/2D切换,优先选用3D,格式:$&lt;NAME|VALUE&gt;
*
* * NAME支持:scale/rotate/translate/matrix
* * VALUE格式:x=1&y=2&z=3&a=30
*
*
* 范例如$&lt;scale|a=30&gt;,各名称支持的参数列表
*
* | 名称 | 参数 |
* | :-- | :-- |
* | scale | x,y,z |
* | rotate | x,y,z,a |
* | translate | x,y,z |
* | matrix | m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 |
*
*
* 结构举例
* ```html
* <html>
* <head>
* <title>test</title>
* </head>
* </html>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 注入样式
* _e._$addStyle('body{font-size:20px}');
*
* // 注入样式支持变量
* _e._$addStyle('\
* .a{$<vendor>transform-origin:0 0;}\
* .b{$<vendor>transform:$<translate|x=0&y=1&z=1>}\
* ');
* });
* ```
*
* 输出结果
* ```html
* <html>
* <head>
* <title>test</title>
* <style>body{font-size:20px;}</style>
* <style>
* .a{-webkit-transform-origin:0 0;}\
* .b{-webkit-transform:translate3d(0,1,1);}\
* </style>
* </head>
* </html>
* ```
*
* @method module:base/element._$addStyle
* @param {String} arg0 - 样式内容
* @return {Node} 样式节点
*/
_p._$addStyle = (function(){
var _reg = /[\s\r\n]+/gi;
return function(_css){
_css = (_css||'').replace(_reg,' ').trim();
var _node = null;
if (!!_css){
_node = _p._$create('style');
document.head.appendChild(_node);
_h.__injectCSSText(
_node,_h.__processCSSText(_css)
);
}
return _node;
};
})();
/**
* 缓存待激活样式
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 设置样式到缓存中,自动生成样式名,返回自动生成的类名#<class>
* var _class = _e._$pushCSSText('.#<uispace>{width:300px;}');
*
* // 把缓存中的样式内联到页面
* _e._$dumpCSSText();
* });
* ```
*
* @method module:base/element._$pushCSSText
* @see module:base/element._$dumpCSSText
* @param {String} arg0 - 样式
* @return {String} 样式标识
*/
_p._$pushCSSText = (function(){
var _reg = /#<(.*?)>/g,
_seed = +new Date;
return function(_css,_data){
if (!_cspol){
_cspol = [];
}
var _class = 'auto-'+_u._$uniqueID(),
_dmap = _u._$merge({uispace:_class},_data);
_cspol.push(
_css.replace(_reg,function($1,$2){
return _dmap[$2]||$1;
})
);
return _class;
};
})();
/**
* 激活缓存中的样式
*
* 结构举例
* ```html
* <div id="abc" class="item">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 设置样式.item{width:300px;}到缓存中
* _e._$pushCSSText('.item{width:300px;}');
*
* // 把缓存中的样式内联到页面
* _e._$dumpCSSText();
* });
* ```
*
* @method module:base/element._$dumpCSSText
* @see module:base/element._$pushCSSText
* @return {Void}
*/
_p._$dumpCSSText = function(){
if (!!_cspol){
_p._$addStyle(_cspol.join(' '));
_cspol = null;
}
};
/**
* 追加CSS规则
*
* 结构举例
* ```html
* <style id="abc"></style>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 设置样式.item{width:300px;}到缓存中
* _e._$appendCSSText('node-id','.item{width:300px;}');
* });
* ```
*
* @method module:base/element._$appendCSSText
* @see module:base/element._$addStyle
* @param {Node} arg0 - 样式节点
* @param {String} arg1 - 单条样式规则
* @return {CSSRule} 样式规则对象
*/
/**
* @method CHAINABLE._$appendCSSText
* @see module:base/element._$appendCSSText
*/
_p._$appendCSSText =
_y._$appendCSSText = function(_element,_css){
_element = _p._$get(_element);
return !_element ? null :
_h.__appendCSSText(
_element,
_h.__processCSSText(_css)
);
};
/**
* 新增样式类,多个样式用空格分开
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 添加样式 fc01 fc03
* _e._$addClassName('abc','fc01 fc03');
* });
* ```
*
* 输出结果
* ```html
* <div id="abc" class="fc01 fc03">123</div>
* ```
*
* @method module:base/element._$addClassName
* @see module:base/element._$delClassName
* @see module:base/element._$replaceClassName
* @param {String|Node} arg0 - 要操作的节点标识或者节点对象
* @param {String} arg1 - 要新增的样式类名称
* @return {Void}
*/
/**
* @method CHAINABLE._$addClassName
* @see module:base/element._$addClassName
*/
_p._$addClassName =
_y._$addClassName = function(_element,_class){
_element = _p._$get(_element);
if (!!_element){
_h.__processClassName(
_element,'add',_class
);
}
};
/**
* 删除样式类,多个样式用空格分开
*
* 结构举例
* ```html
* <div id="abc" class="fc01 fc03">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 删除fc02 fc03样式名
* _e._$delClassName('abc','fc02 fc03');
* });
* ```
*
* 输出结果
* ```html
* <div id="abc" class="fc01">123</div>
* ```
*
* @method module:base/element._$delClassName
* @see module:base/element._$addClassName
* @see module:base/element._$replaceClassName
* @param {String|Node} arg0 - 要操作的节点标识或者节点对象
* @param {String} arg1 - 要删除的样式类名称
* @return {Void}
*/
/**
* @method CHAINABLE._$delClassName
* @see module:base/element._$delClassName
*/
_p._$delClassName =
_y._$delClassName = function(_element,_class){
_element = _p._$get(_element);
if (!!_element){
_h.__processClassName(
_element,'remove',_class
);
}
};
/**
* 替换节点的样式类名称,多个样式用空格分隔,
* 操作过程为先删除待删样式,再添加待添样式,因此不需要删除样式存在才添加样式
*
* 结构举例
* ```html
* <div id="abc" class="fc01 fc03">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 替换fc02为fc05
* // 这里不需要fc02存在
* _e._$replaceClassName('abc','fc02','fc05');
* });
* ```
*
* 输出结果
* ```html
* <div id="abc" class="fc01 fc03 fc05">123</div>
* ```
*
* @method module:base/element._$replaceClassName
* @see module:base/element._$addClassName
* @see module:base/element._$delClassName
* @param {String|Node} arg0 - 要操作的节点标识或者节点对象
* @param {String} arg1 - 要删除的样式类名称
* @param {String} arg2 - 要新增的样式类名称
* @return {Void}
*/
/**
* @method CHAINABLE._$replaceClassName
* @see module:base/element._$replaceClassName
*/
_p._$replaceClassName =
_y._$replaceClassName = function(_element,_del,_add){
_element = _p._$get(_element);
if (!!_element){
_h.__processClassName(
_element,'replace',
_del,_add
);
}
};
/**
* 检测节点是否包含指定样式,多个样式用空格分隔,检测时包含其中之一即表示包含
*
* 结构举例
* ```html
* <div id="abc" class="fc01 fc03">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 如果有fc01样式返回true,否则返回false
* _e._$hasClassName('abc',"fc01");
* });
* ```
*
* @method module:base/element._$hasClassName
* @param {String|Node} arg0 - 节点标识或者对象
* @param {String} arg1 - 样式串
* @return {Boolean} 是否含指定样式
*/
/**
* @method CHAINABLE._$hasClassName
* @see module:base/element._$hasClassName
*/
_p._$hasClassName =
_y._$hasClassName = function(_element,_class){
_element = _p._$get(_element);
if (!!_element){
return _h.__hasClassName(_element,_class);
}
return !1;
};
/**
* 取样式变换矩阵对象
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 生成下面矩阵的对象
* // |a:1,b:0,c:0,d:1,e:0:f:0|
* // |m11:1,m12:0,m13:0,m14:0|
* // |m21:0,m22:1,m23:0,m24:0|
* // |m31:0,m32:0,m33:1,m34:0|
* // |m41:0,m42:0,m43:0,m44:1|
* var _matrix = _e._$matrix("matrix(1,0,0,1,0,0)");
* });
* ```
*
* @method module:base/element._$matrix
* @param {String} arg0 - 变化信息
* @return {CSSMatrix} 变换矩阵对象
*/
_p._$matrix = function(_matrix){
_matrix = (_matrix||'').trim();
return _h.__getCSSMatrix(_matrix);
};
/**
* 设置3D变换,对于不支持3D的系统自动切换为2D变换
*
* 结构举例
* ```html
* <div id="abc"></div>
* ```
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element'
* ],function(_e){
* // 进行css3d变换,对应css样式为-webkit-transform:rotate3d( 2, 1, 1, -75deg);
* _e._$css3d('abc','rotate',{x:2,y:1,z:1,a:'-75deg'});
* });
* ```
*
* @method module:base/element._$css3d
* @see module:base/element._$addStyle
* @param {String|Node} arg0 - 节点标识或者对象
* @param {String} arg1 - 变换类型,matrix/translate/scale/rotate
* @param {Object} arg2 - 变换值,{x:1,y:2,z:3,a:'30deg'}
* @return {Void}
*/
/**
* @method CHAINABLE._$css3d
* @see module:base/element._$css3d
*/
_p._$css3d =
_y._$css3d = function(_element,_name,_map){
_element = _p._$get(_element);
if (!!_element){
var _value = _h.__processTransformValue(_name,_map);
if (!!_value){
_p._$setStyle(_element,'transform',_value);
}
}
};
// for chainable
_x._$merge(_y);
if (CMPT){
NEJ.copy(NEJ.P('nej.e'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 事件接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module base/event */
NEJ.define([
'./global.js',
'./element.js',
'./util.js',
'./chain.js',
'{platform}event.js'
],function(NEJ,_e,_u,_x,_h,_p,_o,_f,_r){
// {id:{type:[{type:'click',func:function,sfun:function,capt:true},...]}}
// id - element id
// type - event name, no on prefix
// func - event after wrapper
// capt - capture flag
// sfun - event before wrapper
// link - events link to this event [[element,type,handler,capture],...]
var _xcache = {},
_y = {}; // chainable methods
/*
* 取事件类型列表
* @param {String} 事件类型
* @return {Array} 事件列表
*/
var _getTypeList = (function(){
var _reg = /[\s,;]+/;
return function(_type){
var _type = (_type||'').trim().toLowerCase();
return !_type?null:_type.split(_reg);
};
})();
/*
* 取鼠标相对于BODY的偏移
* @param {Event} 事件对象
* @param {String} 类型,X/Y
* @param {String} 滚动偏移名称,Left/Top
* @return {Void}
*/
var _getClientOffset = function(_event,_type,_name){
var _key1 = 'page'+_type;
return _event[_key1]!=null?_event[_key1]:(
_event['client'+_type]+
_e._$getPageBox()['scroll'+_name]
);
};
/*
* 取鼠标相对于页面的偏移
* @param {Event} 事件对象
* @param {String} 类型,X/Y
* @param {String} 滚动偏移名称,Left/Top
* @return {Void}
*/
var _getPageOffset = function(_event,_type,_name){
var _key3 = 'scroll'+_name;
_node = _p._$getElement(_event),
_xret = _getClientOffset(_event,_type,_name);
while(!!_node&&
_node!=document.body&&
_node!=document.documentElement){
_xret += _node[_key3]||0;
_node = _node.parentNode;
}
return _xret;
};
/*
* 格式化添加删除事件接口参数
* @param {String|Node} 节点ID或者对象
* @param {String} 事件类型,不带on前缀,不区分大小写,多个事件用空格分隔
* @param {Function} 事件处理函数
* @param {Boolean} 是否捕获阶段事件,IE低版本浏览器忽略此参数
* return {Object} 格式化后参数
*/
var _doFormatArgs = function(_element,_type,_handler,_capture){
var _result = {};
// check element
_element = _e._$get(_element);
if (!_element){
return null;
}
_e._$id(_element);
_result.element = _element;
// check event handler
if (!_u._$isFunction(_handler)){
return null;
}
_result.handler = _handler;
// check type
var _type = _getTypeList(_type);
if (!_type){
return null;
}
// save info
_result.type = _type;
_result.capture = !!_capture;
return _result;
};
/**
* 节点添加事件,
* 支持添加自定义事件,
* 对于自定义事件的实现逻辑由其他模块负责实现
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 添加系统预定义事件
* _v._$addEvent(
* 'abc','mouseover',function(_event){
* // TODO something
* },false
* );
*
* // 添加自定义事件,回车事件
* _v._$addEvent(
* 'abc','enter',function(_event){
* // TODO something
* },false
* );
*
* // 添加多个事件,用空格分隔
* _v._$addEvent(
* 'abc','mouseover click mousedown',
* function(_event){
* // TODO something
* },false
* );
* });
* ```
*
* 带自定义事件的类构造或者对象
* ```javascript
* NEJ.define([
* 'base/klass',
* 'base/event',
* 'util/event',
* 'util/event/event'
* ],function(_k,_v,_t0,_t1,_p){
* // 定义类
* _p._$$Klass = _k._$klass();
* var _pro = _p._$$Klass._$extend(_t0._$$EventTarget);
*
* // TODO
*
* // 添加自定义事件支持
* // 对节点的事件同样支持此自定义事件
* _t1._$$CustomEvent._$allocate({
* element:_p._$$Klass,
* event:['ok','fail']
* });
*
* // 使用事件接口添加/删除/调度事件
* var _handler = function(_event){
* // TODO
* };
* _v._$addEvent(_p._$$Klass,'ok',_handler);
* _v._$delEvent(_p._$$Klass,'ok',_handler);
* });
* ```
*
* @method module:base/event._$addEvent
* @see module:base/event._$delEvent
* @param {String|Node|Object} arg0 - 节点或者类构造或者对象
* @param {String} arg1 - 事件类型,不带on前缀,不区分大小写,多个事件用空格分隔
* @param {Function} arg2 - 事件处理函数
* @param {Boolean} arg3 - 是否捕获阶段事件,IE低版本浏览器忽略此参数
* @return {Void}
*/
/**
* @method CHAINABLE._$addEvent
* @see module:base/event._$addEvent
*/
_p._$addEvent =
_y._$addEvent = (function(){
// cache event
// type/handler/link
var _doCacheEvent = function(_type,_source,_real){
var _id = _e._$id(_source.element),
_cch_id = _xcache[_id]||{},
_cch_tp = _cch_id[_type]||[];
_cch_tp.push({
type:_real.type||_type,
func:_real.handler||_source.handler,
sfun:_source.handler,
capt:_source.capture,
link:_real.link
});
_cch_id[_type] = _cch_tp;
_xcache[_id] = _cch_id;
};
return function(){
var _args = _doFormatArgs.apply(null,arguments);
if (!_args) return;
_u._$forEach(
_args.type,function(_name){
var _argc = _h.__checkEvent(
_args.element,
_name,_args.handler
);
// add event
_h.__addEvent(
_args.element,_argc.type,
_argc.handler,_args.capture
);
// add event link
_u._$forIn(
_argc.link,function(_item){
_item[3] = !!_item[3];
_h.__addEvent.apply(_h,_item);
_item[0] = _e._$id(_item[0]);
}
);
// cache event
_doCacheEvent(_name,_args,_argc);
}
);
};
})();
/**
* 节点删除事件,输入参数必须保证与添加接口_$addEvent输入参数完全一致
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 事件回调业务逻辑
* var _doCallback = function(_event){
* // TODO something
* alert('0');
* };
*
* // 添加事件
* _v._$addEvent('abc','mouseover',_doCallback,false);
* // 删除事件,这里参数必须保持完全一致
* _v._$delEvent('abc','mouseover',_doCallback,false);
*
* // 比如以下方式虽然回调的业务逻辑一致,但是无法删除之前添加的事件
* _v._$delEvent(
* 'abc',"mouseover",function(_event){
* // TODO something
* alert('0');
* },false
* );
*
* // 删除多个事件
* _v._$delEvent(
* 'abc','mouseover click mouseup',
* _doCallback,false
* );
* });
* ```
*
* @method module:base/event._$delEvent
* @see module:base/event._$addEvent
* @param {String|Node} arg0 - 节点ID或者对象
* @param {String} arg1 - 事件类型,不带on前缀,不区分大小写,多个事件用空格分隔
* @param {Function} arg2 - 事件处理函数
* @param {Boolean} arg3 - 是否捕获阶段事件
* @return {Void}
*/
/**
* @method CHAINABLE._$delEvent
* @see module:base/event._$delEvent
*/
_p._$delEvent =
_y._$delEvent = (function(){
var _unCacheEvent = function(_type,_conf){
var _id = _e._$id(_conf.element),
_cch_id = _xcache[_id]||_o,
_cch_tp = _cch_id[_type],
_index = _u._$indexOf(
_cch_tp,function(_item){
// check handler and capture
return _item.sfun===_conf.handler&&
_item.capt===_conf.capture;
}
);
// check result
var _result = null;
if (_index>=0){
var _item = _cch_tp.splice(_index,1)[0];
_result = [[
_conf.element,_item.type,
_item.func,_conf.capture
]];
if (!!_item.link){
_result.push.apply(_result,_item.link);
}
// clear cache
if (!_cch_tp.length){
delete _cch_id[_type];
}
if (!_u._$hasProperty(_cch_id)){
delete _xcache[_id];
}
}
return _result;
};
return function(){
var _args = _doFormatArgs.apply(null,arguments);
if (!_args) return;
_u._$forEach(
_args.type,function(_name){
_u._$forEach(
_unCacheEvent(_name,_args),
function(_item){
_h.__delEvent.apply(_h,_item);
}
);
}
);
};
})();
/**
* 清除节点事件
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 添加事件
* _v._$addEvent(
* 'abc','mouseover',function(_event){
* // TODO something
* }
* );
* _v._$addEvent(
* 'abc','mouseover',function(_event){
* // TODO something
* },true
* );
* _v._$addEvent(
* 'abc','custom',function(_event){
* // TODO something
* }
* );
*
* // 清除节点所有事件,包括两个mouseover事件和一个custom事件
* _v._$clearEvent('abc');
*
* // 清除节点指定类型事件,只清除两个mouseover事件
* _v._$clearEvent('abc','mouseover');
*
* // 清除多个事件,用空格分隔
* _v._$clearEvent('abc','mouseover custom');
* });
* ```
*
* @method module:base/event._$clearEvent
* @see module:base/event._$delEvent
* @param {String|Node} arg0 - 节点ID或者对象
* @param {String} arg1 - 事件类型,不带on前缀,不区分大小写,多个事件用空格分隔
* @return {Void}
*/
/**
* @method CHAINABLE._$clearEvent
* @see module:base/event._$clearEvent
*/
_p._$clearEvent =
_y._$clearEvent = (function(){
var _doClearEvent = function(_id,_name,_list){
_u._$reverseEach(
_list,function(_item){
_p._$delEvent(
_id,_name,_item.sfun,_item.capt
);
}
);
};
return function(_element,_type){
var _id = _e._$id(_element);
if (!_id) return;
var _cch_id = _xcache[_id];
if (!!_cch_id){
_type = _getTypeList(_type);
if (!!_type){
// clear event by type
_u._$forEach(
_type,function(_name){
_doClearEvent(_id,_name,_cch_id[_name]);
}
);
}else{
// clear all event
_u._$loop(
_cch_id,function(_value,_name){
_p._$clearEvent(_element,_name);
}
);
}
}
};
})();
/**
* 触发对象的某个事件,注:对于IE浏览器该接口节点事件有以下限制
*
* * 捕获阶段支持需要浏览器IE9+
* * 节点上自定义事件支持需要浏览器IE9+
*
*
* 结构举例
* ```html
* <div id="abc">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 注册鼠标事件
* _v._$addEvent(
* 'abc','click',function(_event){
* // 获取鼠标事件触发的垂直位置
* var _y = _v._$pageY(_event);
* }
* );
* // 触发鼠标事件
* _v._$dispatchEvent('abc','click');
*
* // 注册自定义事件
* _v._$addEvent(
* 'abc','ok',function(_event){
* // TODO something
* }
* );
* // 触发自定义事件
* _v._$dispatchEvent('abc','ok');
* });
* ```
*
* @method module:base/event._$dispatchEvent
* @param {String|Node} arg0 - 节点ID或者对象
* @param {String} arg1 - 鼠标事件类型,不区分大小写,多个事件用空格分隔
* @param {Object} arg2 - 传递的参数信息
* @return {Void}
*/
/**
* @method CHAINABLE._$dispatchEvent
* @see module:base/event._$dispatchEvent
*/
_p._$dispatchEvent =
_y._$dispatchEvent = function(_element,_type,_options){
var _element = _e._$get(_element);
if (!!_element){
_u._$forEach(
_getTypeList(_type),function(_name){
var _result = _h.__checkEvent(
_element,_name
);
_h.__dispatchEvent(
_element,_result.type,_options
);
}
);
}
};
/**
* 获取触发事件的节点,可以传入过滤接口来遍历父节点找到符合条件的节点
*
* 结构举例
* ```html
* <div id="a">
* <p>
* <span id="b">123</span>
* <span link="a">123</span>
* <span class="a link">123</span>
* <span data-link="a">123</span>
* <label>aaaaa</label>
* </p>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 取事件触发节点
* _v._$addEvent(
* 'b','click',function(_event){
* // id为b的节点
* var _node = _v._$getElement(_event);
* // TODO something
* }
* );
*
* // 事件触发,取id是a的节点
* _v._$addEvent(
* 'b','click',function(_event){
* // id为a的节点
* var _node = _v._$getElement(
* _event,function(_element){
* return _element.id=='a';
* }
* );
* // TODO something
*
* // class含link或者属性含link或者data-link的节点
* var _node = _v._$getElement(_event,'link');
*
* // 仅匹配class即 class="link xx xxx"
* var _node = _v._$getElement(_event,'c:link');
*
* // 仅匹配dataset即 data-link="aaaa"
* var _node = _v._$getElement(_event,'d:link');
*
* // 仅匹配attributer即 link="aaa"
* var _node = _v._$getElement(_event,'a:link');
*
* // 仅匹配tag即 <label>
* var _node = _v._$getElement(_event,'t:label');
* }
* );
* });
* ```
*
* @method module:base/event._$getElement
* @param {Event} arg0 - 事件对象
* @param {Function} arg1 - 过滤接口
* @return {Node} 符合条件的节点
*/
_p._$getElement = (function(){
// element filter
var _exmap;
var _doFilter = function(_name,_element){
var _arr = _name.split(':');
if (_arr.length>1){
if (!_exmap){
_exmap = {
a:_e._$attr,
d:_e._$dataset,
c:_e._$hasClassName,
t:function(n,v){return (n.tagName||'').toLowerCase()===v;}
};
}
var _check = _exmap[_arr[0]];
if (!!_check){
return !!_check(_element,_arr[1]);
}
_name = _arr[1];
}
return !!_e._$attr(_element,_name)||
!!_e._$dataset(_element,_name)||
_e._$hasClassName(_element,_name);
};
return function(_event){
if (!_event) return null;
var _element = _event.target||
_event.srcElement,
_filter = arguments[1];
if (!_filter){
return _element;
}
if (_u._$isString(_filter)){
_filter = _doFilter._$bind(null,_filter);
}
if (_u._$isFunction(_filter)){
while(_element){
if (!!_filter(_element)){
return _element;
}
_element = _element.parentNode;
}
return null;
}
return _element;
};
})();
/**
* 阻止事件,包括默认事件和传递事件
*
* 结构举例
* ```html
* <div id="a">
* <a href="xxx.html" id="b">123</a>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 事件回调中阻止事件冒泡
* _v._$addEvent(
* 'b','click',function(_event){
* // 阻止事件继续传播
* // 阻止链接打开的默认事件
* _v._$stop(_event);
* }
* );
*
* // a节点上的点击事件不会触发
* _v._$addEvent(
* 'a','click',function(_event){
* alert(0);
* // TODO something
* }
* );
* });
* ```
*
* @method module:base/event._$stop
* @see module:base/event._$stopBubble
* @see module:base/event._$stopDefault
* @param {Event} arg0 - 要阻止的事件对象
* @return {Void}
*/
_p._$stop = function(_event){
_p._$stopBubble(_event);
_p._$stopDefault(_event);
};
/**
* 阻止事件的冒泡传递
*
* 结构举例
* ```html
* <div id="a">
* <a href="xxx.html" id="b">123</a>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 事件回调中阻止事件冒泡
* _v._$addEvent(
* 'b','click',function(_event){
* // 阻止事件继续传播
* // 链接仍然会被打开
* _v._$stopBubble(_event);
* }
* );
*
* // a节点上的点击事件不会触发
* _v._$addEvent(
* 'a','click',function(_event){
* alert(0);
* // TODO something
* }
* );
* });
* ```
*
* @see module:base/event._$stop}
* @method module:base/event._$stopBubble
* @param {Event} arg0 - 要阻止的事件对象
* @return {Void}
*/
_p._$stopBubble = function(_event){
if (!!_event){
!!_event.stopPropagation
? _event.stopPropagation()
: _event.cancelBubble = !0;
}
};
/**
* 阻止标签的默认事件
*
* 结构举例
* ```html
* <div id="a">
* <a href="xxx.html" id="b">123</a>
* </div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 事件回调中阻止链接默认事件
* _v._$addEvent(
* 'b','click',function(_event){
* // 阻止链接打开页面的默认行为
* _v._$stopDefault(_event);
* }
* );
*
* // a节点上的点击事件仍然会触发
* _v._$addEvent(
* 'a','click',function(_event){
* alert(0);
* // TODO something
* }
* );
* });
* ```
*
* @method module:base/event._$stopDefault
* @see module:base/event._$stop
* @param {Event} arg0 - 要阻止的事件对象
* @return {Void}
*/
_p._$stopDefault = function(_event) {
if (!!_event){
!!_event.preventDefault
? _event.preventDefault()
: _event.returnValue = !1;
}
};
/**
* 取事件相对于页面的位置
*
* 结构举例
* ```html
* <div id="abc" style="width:100%;height:100%;">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 回调中取鼠标位置
* _v._$addEvent(
* 'abc','click',function(_event){
* // 获取鼠标事件触发的水平、垂直位置
* var _pos = _v._$page(_event);
* }
* );
* });
* ```
*
* @method module:base/event._$page
* @see module:base/event._$pageX
* @see module:base/event._$pageY
* @param {Event} arg0 - 事件对象
* @return {Object} 位置信息,{x:10,y:10}
*/
_p._$page = function(_event){
return {
x:_p._$pageX(_event),
y:_p._$pageY(_event)
};
};
/**
* 取事件相对于页面左侧的位置,累加所有内部滚动高度
*
* 结构举例
* ```html
* <div id="abc" style="width:100%;height:100%;">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 回调中取鼠标位置
* _p._$addEvent(
* 'abc','click',function(_event){
* // 获取鼠标事件触发的水平位置
* var _x = _v._$pageX(_event);
* }
* );
* });
* ```
*
* @method module:base/event._$pageX
* @see module:base/event._$clientX
* @param {Event} arg0 - 事件对象
* @return {Number} 水平位置
*/
_p._$pageX = function(_event){
return _getPageOffset(_event,'X','Left');
};
/**
* 取事件相对于页面顶部的位置,累加所有内部滚动高度
*
* 结构举例
* ```html
* <div id="abc" style="width:100%;height:100%;">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 回调中取鼠标位置
* _v._$addEvent(
* 'abc','click',function(_event){
* // 获取鼠标事件触发的垂直位置
* var _y = _v._$pageY(_event);
* }
* );
* });
* ```
*
* @method module:base/event._$pageY
* @see module:base/event._$clientY
* @param {Event} arg0 - 事件对象
* @return {Number} 垂直位置
*/
_p._$pageY = function(_event){
return _getPageOffset(_event,'Y','Top');
};
/**
* 取事件相对于页面左侧的位置,仅累加页面滚动高度
*
* 结构举例
* ```html
* <div id="abc" style="width:100%;height:100%;">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 回调中取鼠标位置
* _p._$addEvent(
* 'abc','click',function(_event){
* // 获取鼠标事件触发的水平位置
* var _x = _v._$clientX(_event);
* }
* );
* });
* ```
*
* @method module:base/event._$clientX
* @see module:base/event._$pageX
* @param {Event} arg0 - 事件对象
* @return {Number} 水平位置
*/
_p._$clientX = function(_event){
return _getClientOffset(_event,'X','Left');
};
/**
* 取事件相对于页面顶部的位置,仅累加页面滚动高度
*
* 结构举例
* ```html
* <div id="abc" style="width:100%;height:100%;">123</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* ],function(_v){
* // 回调中取鼠标位置
* _v._$addEvent(
* 'abc','click',function(_event){
* // 获取鼠标事件触发的垂直位置
* var _y = _v._$pageY(_event);
* }
* );
* });
* ```
*
* @method module:base/event._$clientY
* @see module:base/event._$pageY
* @param {Event} arg0 - 事件对象
* @return {Number} 垂直位置
*/
_p._$clientY = function(_event){
return _getClientOffset(_event,'Y','Top');
};
// for chainable method
_x._$merge(_y);
if (CMPT){
NEJ.copy(NEJ.P('nej.v'),_p);
}
return _p;
});
/*
* --------------------------------------------
* 原生对象扩展接口
* @version 1.0
* @author genify([email protected])
* --------------------------------------------
*/
/**
* 全局window对象
* @external window
*/
/**
* 全局页面文档对象
* @external document
*/
/**
* 全局location对象
* @external location
*/
/**
* 全局history对象
* @external history
*/
/**
* 内置函数对象扩展
* @external Function
*/
NEJ.define(function(_p,_o,_f,_r){
var _extpro = Function.prototype;
/**
* AOP增强操作,增强操作接受一个输入参数包含以下信息
*
* | 参数名称 | 参数类型 | 参数描述 |
* | :-- | :-- | :-- |
* | args | Array | 函数调用时实际输入参数,各增强操作中可以改变值后将影响至后续的操作 |
* | value | Variable | 输出结果 |
* | stopped | Boolean | 是否结束操作,终止后续操作 |
*
* @method external:Function#_$aop
* @param {Function} arg0 - 前置操作,接受一个输入参数,见描述信息
* @param {Function} arg1 - 后置操作,接受一个输入参数,见描述信息
* @return {Function} 增强后操作函数
*/
_extpro._$aop = function(_before,_after){
var _after = _after||_f,
_before = _before||_f,
_handler = this;
return function(){
var _event = {args:_r.slice.call(arguments,0)};
_before(_event);
if (!_event.stopped){
_event.value = _handler.apply(this,_event.args);
_after(_event);
}
return _event.value;
};
};
/**
* 绑定接口及参数,使其的调用对象保持一致
*
* ```javascript
* var scope = {a:0};
*
* var func = function(a,b){
* // 第一个参数 :1
* console.log(a);
* // 第二个参数 : 2
* consoel.log(b);
* // 当前this.a : 0
* console.log(this.a);
* };
*
* func._$bind(scope,"1")(2);
* ```
*
* @method external:Function#_$bind
* @see external:Function#_$bind2
* @param {Object} arg0 - 需要保持一致的对象,null表示window对象,此参数外的其他参数作为绑定参数
* @return {Function} 返回绑定后的函数
*/
_extpro._$bind = function() {
var _args = arguments,
_object = arguments[0],
_function = this;
return function(){
// not use slice for chrome 10 beta and Array.apply for android
var _argc = _r.slice.call(_args,1);
_r.push.apply(_argc,arguments);
return _function.apply(_object||null,_argc);
};
};
/**
* 绑定接口及参数,使其的调用对象保持一致,
* 该接口与_$bind接口的差别在于绑定时参数和调用时参数的顺序不一样,
* _$bind优先传入绑定时参数,_$bind2优先传入调用时参数
*
* ```javascript
* var scope = {a:0};
*
* var func = function(a,b){
* // 第一个参数 :2
* console.log(a);
* // 第二个参数 : 1
* consoel.log(b);
* // 当前this.a : 0
* console.log(this.a);
* };
*
* func._$bind(scope,"1")(2);
* ```
*
* @method external:Function#_$bind2
* @see external:Function#_$bind
* @param {Object} arg0 - 需要保持一致的对象,null表示window对象,此参数外的其他参数作为绑定参数
* @return {Function} 返回绑定后的事件函数
*/
_extpro._$bind2 = function() {
var _args = arguments,
_object = _r.shift.call(_args),
_function = this;
return function(){
_r.push.apply(arguments,_args);
return _function.apply(_object||null,arguments);
};
};
// for compatiable
var _extpro = String.prototype;
if (!_extpro.trim){
_extpro.trim = (function(){
var _reg = /(?:^\s+)|(?:\s+$)/g;
return function(){
return this.replace(_reg,'');
};
})();
}
if (!this.console){
this.console = {
log:_f,
error:_f
};
}
if (CMPT){
NEJ = this.NEJ||{};
// copy object properties
// only for nej compatiable
NEJ.copy = function(a,b){
a = a||{};
b = b||_o;
for(var x in b){
if (b.hasOwnProperty(x)){
a[x] = b[x];
}
}
return a;
};
// NEJ namespace
NEJ = NEJ.copy(
NEJ,{
O:_o,R:_r,F:_f,
P:function(_namespace){
if (!_namespace||!_namespace.length){
return null;
}
var _package = window;
for(var a=_namespace.split('.'),
l=a.length,i=(a[0]=='window')?1:0;i<l;
_package=_package[a[i]]=_package[a[i]]||{},i++);
return _package;
}
}
);
return NEJ;
}
return _p;
});
/*
* --------------------------------------------
* NEJ类模型
* @version 1.0
* @author genify([email protected])
* --------------------------------------------
*/
/** @module base/klass */
NEJ.define([
'./global.js',
'{platform}util.js'
],function(NEJ,_u,_p,_o,_f,_r){
/**
* 定义类,通过此api定义的类具有以下特性:
*
* * {@link external:Function#_$extend|_$extend}作为类的静态扩展方法
* * __init作为类的初始化函数
* * __super作为子类调用父类的同名函数
*
* ```javascript
* NEJ.define([
* 'base/klass'
* ],function(k,p){
* // 定义类A
* p.A = k._$klass();
* var pro = A.prototype;
* // 初始化
* pro.__init = function(){
* // do init
* };
* // 类接口
* pro.__doSomething = function(a){
* // TODO something
* };
*
* return p;
* });
* ```
*
* ```javascript
* NEJ.define([
* 'base/klass',
* '/path/to/class/a.js'
* ],function(k,a,p){
* // 定义类B,并继承自A
* p.B = k._$klass();
* var pro = B._$extend(a.A);
* // 初始化
* pro.__init = function(){
* // 调用A的初始化逻辑
* this.__super();
* // TODO B的初始化逻辑
* };
* // 类接口
* pro.__doSomething = function(a){
* // 调用A的__doSomething接口
* this.__super(a);
* // TODO B的逻辑
* };
*
* return p;
* });
* ```
*
* @method module:base/klass._$klass
* @see external:Function#_$extend
* @return {Function} 返回定义的类
*/
_p._$klass = (function(){
var _isNotFunction = function(){
return _o.toString.call(arguments[0])!=='[object Function]';
};
var _doFindIn = function(_method,_klass){
while(!!_klass){
var _pro = _klass.prototype,
_key = _u.__forIn(_pro,function(v){
return _method===v;
});
if (_key!=null){
return {
name:_key,
klass:_klass
};
}
_klass = _klass._$super;
}
};
return function(){
// class constructor
var _Klass = function(){
return this.__init.apply(this,arguments);
};
_Klass.prototype.__init = _f;
/**
* 子类继承父类
*
* ```javascript
* NEJ.define([
* 'base/klass'
* ],function(k,p){
* // 定义类A
* p.A = k._$klass();
* var pro = A.prototype;
* // 初始化
* pro.__init = function(){
* // do init
* };
* // 类接口
* pro.__doSomething = function(a){
* // TODO something
* };
*
* return p;
* });
* ```
*
* ```javascript
* NEJ.define([
* 'base/klass',
* '/path/to/class/a.js'
* ],function(k,a,p){
* // 定义类B,并继承自A
* p.B = k._$klass();
* var pro = B._$extend(a.A);
* // 初始化
* pro.__init = function(){
* // 调用A的初始化逻辑
* this.__super();
* // TODO B的初始化逻辑
* };
* // 类接口
* pro.__doSomething = function(a){
* // 调用A的__doSomething接口
* this.__super(a);
* // TODO B的逻辑
* };
*
* return p;
* });
* ```
*
* @method external:Function#_$extend
* @see module:base/klass._$klass
* @param {Function} arg0 - 父类
* @param {Boolean} arg1 - 是否拷贝父类的静态方法,默认拷贝父类静态方法
* @return {Object} 扩展类的prototype对象
*/
_Klass._$extend = function(_super,_static){
if (_isNotFunction(_super)){
return;
}
// for static method
var _this = this;
if (_static!==!1){
_u.__forIn(_super,function(v,k){
if (!_isNotFunction(v)){
_this[k] = v;
}
});
}
// do inherit
this._$super = _super;
var _parent = function(){};
_parent.prototype = _super.prototype;
this.prototype = new _parent();
this.prototype.constructor = this;
// for super method call
var _stack = [],
_phash = {};
var _doUpdateCache = function(_method,_klass){
var _result = _doFindIn(_method,_klass);
if (!_result) return;
// save state
if (_stack[_stack.length-1]!=_result.name){
_stack.push(_result.name);
}
_phash[_result.name] = _result.klass._$super;
return _result.name;
};
this.prototype.__super = function(){
var _name = _stack[_stack.length-1],
_method = arguments.callee.caller;
if (!_name){
_name = _doUpdateCache(_method,this.constructor);
}else{
var _parent = _phash[_name].prototype;
// switch caller name
if (!_parent.hasOwnProperty(_method)||
_method!=_parent[_name]){
_name = _doUpdateCache(_method,this.constructor);
}else{
_phash[_name] = _phash[_name]._$super;
}
}
// call parent method
var _ret = _phash[_name].prototype[_name].apply(this,arguments);
// exit super
if (_name==_stack[_stack.length-1]){
_stack.pop();
delete _phash[_name];
}
return _ret;
};
if (CMPT){
var _pro = this.prototype;
_pro.__supInit = _pro.__super;
_pro.__supReset = _pro.__super;
_pro.__supDestroy = _pro.__super;
_pro.__supInitNode = _pro.__super;
_pro.__supDoBuild = _pro.__super;
_pro.__supOnShow = _pro.__super;
_pro.__supOnHide = _pro.__super;
_pro.__supOnRefresh = _pro.__super;
this._$supro = _super.prototype;
}
return this.prototype;
};
return _Klass;
};
})();
if (CMPT){
NEJ.C = _p._$klass;
NEJ.copy(this.NEJ,NEJ);
}
return _p;
});
/*
* ------------------------------------------
* 平台接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module base/platform */
NEJ.define([
'./global.js'
],function(NEJ,_p,_o,_f,_r){
var _platform = this.navigator.platform,
_useragent = this.navigator.userAgent;
/**
* 平台判断信息
*
* ```javascript
* NEJ.define([
* 'base/platform'
* ],function(_m){
* var _is = _m._$IS;
* // 是否MAC系统
* console.log(_is.mac);
* // 是否IPhone
* console.log(_is.iphone);
* // ...
* });
* ```
*
* @const module:base/platform._$IS
* @see module:base/platform._$is
* @type {Object}
* @property {Boolean} mac - 是否Mac系统
* @property {Boolean} win - 是否windows系统
* @property {Boolean} linux - 是否linux系统
* @property {Boolean} ipad - 是否Ipad
* @property {Boolean} iphone - 是否IPhone
* @property {Boolean} android - 是否Android系统
* @property {Boolean} ios - 是否IOS系统
* @property {Boolean} tablet - 是否平板
* @property {Boolean} desktop - 是否桌面系统
*/
var _is = {
mac : _platform,
win : _platform,
linux : _platform,
ipad : _useragent,
ipod : _useragent,
iphone : _platform,
android : _useragent
};
_p._$IS = _is;
for(var x in _is){
_is[x] = new RegExp(x,'i').test(_is[x]);
}
_is.ios = _is.ipad||_is.iphone||_is.ipod;
_is.tablet = _is.ipad;
_is.desktop = _is.mac||_is.win||(_is.linux&&!_is.android);
/**
* 判断是否指定平台
*
* ```javascript
* NEJ.define([
* 'base/platform'
* ],function(_m){
* // 是否MAC系统
* console.log(_m._$is('mac'));
* // 是否iphone
* console.log(_m._$is('iphone'));
* // ...
* });
* ```
*
* @method module:base/platform._$is
* @see module:base/platform._$IS
* @param {String} arg0 - 平台名称
* @return {Boolean} 是否指定平台
*/
_p._$is = function(_platform){
return !!_is[_platform];
};
// parse kernel information
/**
* 引擎内核信息
*
* ```javascript
* NEJ.define([
* 'base/platform'
* ],function(_m){
* var _kernel = _m._$KERNEL;
* // 打印平台信息
* console.log(_kernel.engine);
* console.log(_kernel.release);
* console.log(_kernel.browser);
* console.log(_kernel.version);
* });
* ```
*
* @const module:base/platform._$KERNEL
* @type {Object}
* @property {String} engine - 布局引擎,trident/webkit/gecko/presto...
* @property {Number} release - 布局引擎版本
* @property {String} browser - 浏览器名称,ie/chrome/safari/opera/firefox/maxthon...
* @property {Number} version - 浏览器版本
* @property {Object} prefix - 平台前缀,html5/css3 attribute/method/constructor
*/
var _kernel = {
engine:'unknow',
release:'unknow',
browser:'unknow',
version:'unknow',
prefix:{css:'',pro:'',clz:''}
};
_p._$KERNEL = _kernel;
if (/msie\s+(.*?);/i.test(_useragent)||
/trident\/.+rv:([\d\.]+)/i.test(_useragent)){
_kernel.engine = 'trident';
_kernel.browser = 'ie';
_kernel.version = RegExp.$1;
_kernel.prefix = {css:'ms',pro:'ms',clz:'MS',evt:'MS'};
// 4.0-ie8 5.0-ie9 6.0-ie10 7.0-ie11
// adjust by document mode setting in develop toolbar
var _test = {6:'2.0',7:'3.0',8:'4.0',9:'5.0',10:'6.0',11:'7.0'};
_kernel.release = _test[document.documentMode]||
_test[parseInt(_kernel.version)];
}else if(/webkit\/?([\d.]+?)(?=\s|$)/i.test(_useragent)){
_kernel.engine = 'webkit';
_kernel.release = RegExp.$1||'';
_kernel.prefix = {css:'webkit',pro:'webkit',clz:'WebKit'};
}else if(/rv\:(.*?)\)\s+gecko\//i.test(_useragent)){
_kernel.engine = 'gecko';
_kernel.release = RegExp.$1||'';
_kernel.browser = 'firefox';
_kernel.prefix = {css:'Moz',pro:'moz',clz:'Moz'};
if (/firefox\/(.*?)(?=\s|$)/i.test(_useragent))
_kernel.version = RegExp.$1||'';
}else if(/presto\/(.*?)\s/i.test(_useragent)){
_kernel.engine = 'presto';
_kernel.release = RegExp.$1||'';
_kernel.browser = 'opera';
_kernel.prefix = {css:'O',pro:'o',clz:'O'};
if (/version\/(.*?)(?=\s|$)/i.test(_useragent))
_kernel.version = RegExp.$1||'';
}
if (_kernel.browser=='unknow'){
var _test = ['chrome','maxthon','safari'];
for(var i=0,l=_test.length,_name;i<l;i++){
_name = _test[i]=='safari'?'version':_test[i];
if (new RegExp(_name+'/(.*?)(?=\\s|$)','i').test(_useragent)){
_kernel.browser = _test[i];
_kernel.version = RegExp.$1.trim();
break;
}
}
}
/**
* 引擎特性支持信息
*
* ```javascript
* NEJ.define([
* 'base/platform'
* ],function(_m){
* var _support = _m._$SUPPORT;
* // 打印平台是否支持CSS3 3D特效
* console.log(_support.css3d);
* });
* ```
* @const module:base/platform._$SUPPORT
* @see module:base/platform._$support
* @type {Object}
* @property {Boolean} css3d - 是否支持CSS3 3D
*/
_p._$SUPPORT = {};
/**
* 判断平台是否支持指定特性
*
* ```javascript
* NEJ.define([
* 'base/platform'
* ],function(_m){
* // 是否支持CSS3 3D特效
* console.log(_m._$support('css3d'));
* });
* ```
*
* @method module:base/platform._$support
* @see module:base/platform._$SUPPORT
* @param {String} arg0 - 特性标识
* @return {Boolean} 是否支持指定特性
*/
_p._$support = function(_feature){
return !!_p._$SUPPORT[_feature];
};
if (CMPT){
NEJ.copy(NEJ.P('nej.p'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'base/global',
'base/util'
],function(NEJ,_u,_p,_o,_f,_r){
var _cache = {};
/*
* URL地址转源信息
* http://a.b.com:8080/a/bc/ -> http://a.b.com:8080
* @param {String} URL地址
* @return {String} 源信息
*/
_p.__url2host = (function(){
var _reg = /^([\w]+?:\/\/.*?(?=\/|$))/i;
return function(_url){
_url = _url||'';
if (_reg.test(_url))
return RegExp.$1;
return location.protocol+'//'+location.host;
};
})();
/**
* 设置NEJ配置信息
* @param {String} 配置标识
* @param {Variable} 配置信息
* @return {Void}
*/
_p.__set = function(_key,_value){
_cache[_key] = _value;
};
/**
* 获取NEJ配置信息
* @param {String} 配置标识
* @return {Variable} 配置信息
*/
_p.__get = function(_key){
return _cache[_key];
};
// init
/*
* 初始化配置信息
* @param {Object} 配置信息
* @return {Void}
*/
var _doInit = (function(){
var _conf = {
'portrait':{name:'portrait',dft:'portrait/'},
'ajax.swf':{name:'ajax',dft:'nej_proxy_flash.swf'},
'chart.swf':{name:'chart',dft:'nej_flex_chart.swf'},
'audio.swf':{name:'audio',dft:'nej_player_audio.swf'},
'video.swf':{name:'video',dft:'nej_player_video.swf'},
'clipboard.swf':{name:'clipboard',dft:'nej_clipboard.swf'},
'upload.image.swf':{name:'uploadimage',dft:'nej_upload_image.swf'}
};
var _doInitProxy = function(_list){
var _map = {};
if (!_list||!_list.length){
return _map;
}
for(var i=0,l=_list.length,_path;i<l;i++){
_path = _list[i];
if (_path.indexOf('://')>0)
_map[_p.__url2host(_path)] = _path;
}
return _map;
};
return function(_config){
// check path config
_p.__set('root',_config.root||'/res/');
var _root = _p.__get('root');
_u._$loop(_conf,function(v,k,m){
_p.__set(k,_config[v.name]||(_root+v.dft));
});
// csrf config
var _csrf = _config.p_csrf;
if (_csrf===!0){
_csrf = {
cookie:'AntiCSRF',
param:'AntiCSRF'
};
}
_csrf = _csrf || _o;
_p.__set('csrf',{
param:_csrf.param||'',
cookie:_csrf.cookie||''
});
// ajax by frame proxy
_p.__set('frames',_doInitProxy(_config.p_frame));
// ajax by flash proxy
_p.__set('flashs',_doInitProxy(_config.p_flash));
};
})();
_doInit(this.NEJ_CONF||_o);
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./config.js',
'base/platform'
],function(_h,_m,_p,_o,_f,_r){
// for ie
NEJ.patch('TR',function(){
_h.__set(
'storage.swf',
(this.NEJ_CONF||_o).storage||
(_h.__get('root')+'nej_storage.swf')
);
});
// for ie7- data uri not available
NEJ.patch('TR<=3.0',function(){
_h.__set(
'blank.png',
(this.NEJ_CONF||_o).blank||
(_h.__get('root')+'nej_blank.gif')
);
});
return _h;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'base/util',
'base/platform'
],function(_u,_m,_p,_o,_f,_r){
/**
* 从DocumentFragment中取指定ID的节点
* @param {Document} 文档对象
* @param {String} 节点标识
* @return {Node} 指定标识的节点
*/
_p.__getElementById = function(_fragment,_id){
if (!!_fragment.getElementById){
return _fragment.getElementById(''+_id);
}
try{
return _fragment.querySelector('#'+_id);
}catch(e){
return null;
}
};
/**
* 取节点的子节点列表
* @param {Node} 节点ID或者对象
* @return {Array} 子节点列表
*/
_p.__getChildren = function(_element){
return _u._$object2array(_element.children);
};
/**
* 根据类名取节点列表
* @param {Node} 节点ID或者对象
* @param {String} 类名
* @return {Array} 节点列表
*/
_p.__getElementsByClassName = function(_element,_class){
return _u._$object2array(_element.getElementsByClassName(_class));
};
/**
* 取下一个兄弟节点
* @param {Node} 节点对象
* @return {Node} 节点
*/
_p.__nextSibling = function(_element){
return _element.nextElementSibling;
};
/**
* 取上一个兄弟节点
* @param {Node} 节点对象
* @return {Node} 节点
*/
_p.__previousSibling = function(_element){
return _element.previousElementSibling;
};
/**
* 设置、获取数据
* @param {Node} 节点
* @param {String} 标识
* @param {Variable} 值
*/
_p.__dataset = function(_element,_name,_value){
_element.dataset = _element.dataset||{};
if (_value!==undefined){
_element.dataset[_name] = _value;
}
return _element.dataset[_name];
};
/**
* 取节点属性值
* @param {Node} 节点
* @param {String} 属性名
* @return {String} 属性值
*/
_p.__getAttribute = function(_element,_name){
return _element.getAttribute(_name);
};
/**
* 将dom节点转为xml串
* @param {Node} 节点
* @return {String} XML代码
*/
_p.__serializeDOM2XML = function(_dom){
return new XMLSerializer().serializeToString(_dom)||'';
};
/**
* 将xml转为dom节点
* @param {String} XML代码
* @return {Node} 节点
*/
_p.__parseDOMFromXML = function(_xml){
var _root = new DOMParser()
.parseFromString(_xml,'text/xml')
.documentElement;
return _root.nodeName=='parsererror'?null:_root;
};
/**
* 节点占全屏
* @param {Node} 节点
* @param {Object} 视窗模型
* @return {Void}
*/
_p.__fullScreen = function(){
// use css fixed position
};
/**
* 为节点增加用于盖select/flash等控件的层
* @param {Node} 节点
* @return {Void}
*/
_p.__mask = function(){
// do nothing
};
/**
* 去除用于盖select/flash等控件的层
* @param {Node} 节点
* @return {Void}
*/
_p.__unmask = function(){
// do nothing
};
// variables
var _ospt = _m._$SUPPORT,
_opfx = _m._$KERNEL.prefix;
/**
* 指定名称是否在配置表中
* @param {String} 名称
* @param {Object} 配置表
* @return {Boolean} 是否命中
*/
_p.__isMatchedName = (function(){
var _reg = /^([a-z]+?)[A-Z]/;
return function(_name,_map){
return !!(_map[_name]||(_reg.test(_name)&&_map[RegExp.$1]));
};
})();
/**
* 样式名称做前缀增强
* @param {String} 名称
* @return {Boolean} 是否需要前缀增强
*/
_p.__isNeedPrefixed = (function(){
var _pmap = _u._$array2object([
'animation','transform','transition',
'appearance','userSelect','box','flex','column'
]);
return function(_name){
return _p.__isMatchedName(_name,_pmap);
};
})();
/**
* 格式化样式属性名称
* border-width -> borderWidth
* @param {String} 样式样式名
* @return {String} 格式化后样式名
*/
_p.__fmtStyleName = (function(){
var _reg = /-([a-z])/g;
return function(_name){
_name = _name||'';
return _name.replace(_reg,function($1,$2){
return $2.toUpperCase();
});
};
})();
/**
* 针对样式名称做格式化及前缀增强
* @param {String} 样式名
* @return {String} 增强后的样式名
*/
_p.__getStyleName = (function(){
var _reg = /^[a-z]/,
_prefix = _opfx.css||'';
return function(_name){
_name = _p.__fmtStyleName(_name);
if (!_p.__isNeedPrefixed(_name)){
return _name;
}
// add prefix
// userSelect -> webkitUserSelect
return _prefix+_name.replace(_reg,function($1){
return $1.toUpperCase();
});
};
})();
/**
* 取样式值
* @param {String|Node} 节点
* @param {String} 样式名称
* @return {Variable} 样式值
*/
_p.__getStyleValue = function(_element,_name){
var _current = window.getComputedStyle(_element,null);
return _current[_p.__getStyleName(_name)]||'';
};
/**
* 设置样式
* @param {String|Node} 节点
* @param {String} 样式名称
* @param {String} 样式值
* @return {Void}
*/
_p.__setStyleValue = function(_element,_name,_value){
_element.style[_p.__getStyleName(_name)] = _value;
};
/**
* 取样式变换矩阵对象
* @param {String} 变换信息
* @return {CSSMatrix} 变换矩阵对象
*/
_p.__getCSSMatrix = (function(){
var _reg0 = /\((.*?)\)/,
_reg1 = /\s*,\s*/,
_klss = ['CSSMatrix',_opfx.clz+'CSSMatrix'],
_list = ['m11','m12','m21','m22','m41','m42'];
// matrix(1,2,3,4,5,6)
// -> {m11:1,m12:2,m21:3,m22:4,m41:5,m42:6}
var _doParse = function(_matrix){
var _obj = {};
if (_reg0.test(_matrix||'')){
// 11,12,21,22,41,42
_u._$forEach(
RegExp.$1.split(_reg1),
function(_value,_index){
_obj[_list[_index]] = _value;
}
);
}
return _obj;
};
return function(_matrix){
var _mtrx;
_u._$forIn(_klss,function(_name){
if (!!this[_name]){
_mtrx = new this[_name](_matrix||'');
return !0;
}
});
return !_mtrx?_doParse(_matrix):_mtrx;
};
})();
/**
* 注入样式
* @param {Node} 样式节点
* @param {String} 样式内容
* @return {Void}
*/
_p.__injectCSSText = function(_style,_css){
_style.textContent = _css;
};
/**
* 对样式进行预处理
* @param {String} 待处理样式内容
* @return {String} 处理后样式内容
*/
_p.__processCSSText = (function(){
var _reg0 = /\$<(.*?)>/gi,
_reg1 = /\{(.*?)\}/g,
_pfx = '-'+_opfx.css.toLowerCase()+'-',
_2dmap = {
scale:'scale({x|1},{y|1})',
rotate:'rotate({a})',
translate:'translate({x},{y})',
matrix:'matrix({m11},{m12},{m21},{m22},{m41},{m42})'
},
_3dmap = {
scale:'scale3d({x|1},{y|1},{z|1})',
rotate:'rotate3d({x},{y},{z},{a})',
translate:'translate3d({x},{y},{z})',
matrix:'matrix3d({m11},{m12},{m13},{m14},{m21},{m22},{m23},{m24},{m31},{m32},{m33|1},{m34},{m41},{m42},{m43},{m44|1})'
};
// merge template and data
var _getTransformValue = function(_tpl,_map){
_map = _map||_o;
return _tpl.replace(_reg1,function($1,$2){
var _arr = $2.split('|');
return _map[_arr[0]]||_arr[1]||'0';
});
};
// process transform value
_p.__processTransformValue = function(_name,_data){
var _tpl = (!_ospt.css3d?_2dmap:_3dmap)[_name.trim()];
if (!!_tpl){
return _getTransformValue(_tpl,_data);
}
return '';
};
return function(_css){
if (!_css.replace){
return _css;
}
return _css.replace(_reg0,function($1,$2){
// prefix for css3
if ($2==='vendor'){
return _pfx;
}
// parse 3D value
var _arr = ($2||'').split('|');
return _p.__processTransformValue(
_arr[0],_u._$query2object(_arr[1])
)||$1;
});
};
})();
/**
* 追加CSS规则
* @param {Node} 样式节点
* @param {String} 单条样式规则
* @return {CSSRule} 样式规则对象
*/
_p.__appendCSSText = function(_element,_css){
var _sheet = _element.sheet,
_length = _sheet.cssRules.length;
_sheet.insertRule(_css,_length);
return _sheet.cssRules[_length];
};
/**
* 取待验证的样式列表
* @param {String} 样式,多个以空格分隔
* @return {Array} 样式列表
*/
_p.__getClassList = (function(){
var _reg = /\s+/;
return function(_class){
_class = (_class||'').trim();
return !!_class?_class.split(_reg):null;
};
})();
/**
* 操作样式
* @param {Node} 节点
* @param {String} 操作
* @param {String} 样式
* @return {Void}
*/
_p.__processClassName = function(_element,_type,_class){
if (_type=='replace'){
_p.__processClassName(
_element,'remove',_class
);
_p.__processClassName(
_element,'add',arguments[3]
);
return;
}
_u._$forEach(
_p.__getClassList(_class),
function(_clazz){
_element.classList[_type](_clazz);
}
);
};
/**
* 检测节点是否包含指定样式,多个样式用空格分隔,检测时包含其中之一即表示包含
* @param {Node} 节点ID或者对象
* @param {String} 样式串
* @return {Boolean} 是否含指定样式
*/
_p.__hasClassName = function(_element,_class){
var _list = _element.classList;
if (!_list||!_list.length){
return !1;
}
return _u._$indexOf(
_p.__getClassList(_class),
function(_clazz){
return _list.contains(_clazz);
}
)>=0;
};
// for init
(function(){
if (!_ospt.css3d){
var _matrix = _p.__getCSSMatrix();
_ospt.css3d = !!_matrix&&_matrix.m41!=null;
}
})();
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./element.js',
'base/platform',
'base/util'
],function(_h,_m,_u,_p,_o,_f,_r){
// for ie
NEJ.patch('TR',function(){
/**
* 取节点的子节点列表
* @param {Node} _element 节点ID或者对象
* @return {Array} 子节点列表
*/
_h.__getChildren = _h.__getChildren._$aop(
function(_event){
var _element = _event.args[0];
if (!!_element.children) return;
// hack children
_event.stopped = !0;
var _result = [];
_u._$forEach(
_element.childNodes,
function(_node){
if (_node.nodeType==1){
_result.push(_node);
}
}
);
_event.value = _result;
}
);
});
// for ie10-
NEJ.patch('TR<=6.0',function(){
/**
* 设置、获取数据
* @param {Node} 节点
* @param {String} 标识
* @param {Variable} 值
*/
_h.__dataset = (function(){
var _dataset = {},
_tag = 'data-',
_reg = /\-(.{1})/gi;
// init element dataset
var _init = function(_element){
var _id = _element.id;
if (!!_dataset[_id]) return;
var _map = {};
_u._$forEach(
_element.attributes,
function(_node){
var _key = _node.nodeName;
if (_key.indexOf(_tag)!=0) return;
_key = _key.replace(_tag,'')
.replace(_reg,function($1,$2){
return $2.toUpperCase();
});
_map[_key] = _node.nodeValue||'';
}
);
_dataset[_id] = _map;
};
return function(_element,_key,_value){
_init(_element);
var _set = _dataset[_element.id];
if (_value!==undefined){
_set[_key] = _value;
}
return _set[_key];
};
})();
});
// for ie9-
NEJ.patch('TR<=5.0',function(){
// cache background image
try{document.execCommand('BackgroundImageCache',!1,!0);}catch(e){}
/**
* 注入样式
* @param {Node} 样式节点
* @param {String} 样式内容
* @return {Void}
*/
_h.__injectCSSText = (function(){
var _max = 30;
return _h.__injectCSSText._$aop(function(_event){
var _element = _event.args[0];
if (!_element.styleSheet) return;
_event.stopped = !0;
var _css = _event.args[1];
// ie9- has 31 style/link limitation
var _list = document.styleSheets;
if (_list.length>_max){
// bad performance
_element = _list[_max];
_css = _element.cssText + _css;
}else{
_element = _element.styleSheet;
}
_element.cssText = _css;
});
})();
/**
* 取待验证的样式正则表达式
* @param {String} 样式,多个以空格分隔
* @return {RegExp} 正则表达式
*/
_h.__getClassRegExp = (function(){
var _reg = /\s+/g;
return function(_class){
_class = (_class||'').trim().replace(_reg,'|');
return !_class?null:new RegExp('(\\s|^)(?:'+_class+')(?=\\s|$)','g');
};
})();
/**
* 操作样式
* @param {Node} 节点
* @param {String} 操作
* @param {String} 样式
* @return {Void}
*/
_h.__processClassName = function(_element,_type,_class){
_class = _class||'';
var _name = _element.className||'',
_xreg = _h.__getClassRegExp(
_class+' '+(arguments[3]||'')
);
// remove all calss
var _result = _name;
if (!!_xreg){
_result = _result.replace(_xreg,'');
}
// parse added class
switch(_type){
case 'remove':
_class = '';
break;
case 'replace':
_class = arguments[3]||'';
break;
}
// generate class result
_result = (_result+' '+_class).trim();
if (_name!=_result){
_element.className = _result;
}
};
/**
* 检测节点是否包含指定样式,多个样式用空格分隔,检测时包含其中之一即表示包含
* @param {Node} 节点ID或者对象
* @param {String} 样式串
* @return {Boolean} 是否含指定样式
*/
_h.__hasClassName = function(_element,_class){
var _xreg = _h.__getClassRegExp(_class);
if (!!_xreg){
return _xreg.test(_element.className||'');
}
return !1;
};
});
// for ie8-
NEJ.patch('TR<=4.0',function(){
/**
* 根据类名取节点列表
* @param {Node} 节点ID或者对象
* @param {String} 类名
* @return {Array} 节点列表
*/
_h.__getElementsByClassName = function(_element,_class){
var _result = [],
_regexp = new RegExp('(\\s|^)(?:'+_class.replace(/\s+/g,'|')+')(?=\\s|$)');
_u._$forEach(
_element.getElementsByTagName('*'),
function(_node){
if (_regexp.test(_node.className)){
_result.push(_node);
}
}
);
return _result;
};
/**
* 取下一个兄弟节点
* @param {Node} 节点对象
* @return {Node} 节点
*/
_h.__nextSibling = function(_element){
while(_element=_element.nextSibling){
if (_element.nodeType==1){
return _element;
}
}
};
/**
* 取上一个兄弟节点
* @param {Node} 节点对象
* @return {Node} 节点
*/
_h.__previousSibling = function(_element){
while(_element=_element.previousSibling){
if (_element.nodeType==1){
return _element;
}
}
};
/**
* 将dom节点转为xml串
* @param {Node} 节点
* @return {String} XML代码
*/
_h.__serializeDOM2XML = function(_dom){
return ('xml' in _dom)?_dom.xml:_dom.outerHTML;
};
/**
* 将xml转为dom节点
* @param {String} XML代码
* @return {Node} 节点
*/
_h.__parseDOMFromXML = (function(){
// http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
var _msxml = [
'Msxml2.DOMDocument.6.0',
'Msxml2.DOMDocument.3.0'
];
var _getParser = function(){
try{
for(var i=0,l=_msxml.length;i<l;i++){
return new ActiveXObject(_msxml[i]);
}
}catch(ex){
return null;
}
};
return function(_xml){
var _parser = _getParser();
if (!!_parser&&
_parser.loadXML(_xml)&&
!_parser.parseError.errorCode){
return _parser.documentElement;
}
return null;
};
})();
/**
* 取样式值
* @param {String|Node} 节点
* @param {String} 样式名称
* @return {Variable} 样式值
*/
_h.__getStyleValue = (function(){
var _reg0 = /opacity\s*=\s*([\d]+)/i;
var _fmap = {
// get opacity from filter:alpha(opacity=50)
opacity:function(_style){
var _result = 0;
if (_reg0.test(_style.filter||'')){
_result = parseFloat(RegExp.$1)/100;
}
return _result;
}
};
return function(_element,_name){
var _current = _element.currentStyle,
_func = _fmap[_name];
if (!!_func){
return _func(_current);
}
return _current[_h.__getStyleName(_name)]||'';
};
})();
/**
* 设置样式
* @param {String|Node} 节点
* @param {String} 样式名称
* @param {String} 样式值
* @return {Void}
*/
_h.__setStyleValue = (function(){
var _fmap = {
// opacity -> filter:alpha(opacity=50)
opacity:function(_element,_value){
_element.style.filter = 'alpha(opacity='+_value*100+')';
}
};
return function(_element,_name,_value){
var _func = _fmap[_name];
if (!!_func){
_func(_element,_value);
}else{
_element.style[_h.__getStyleName(_name)] = _value;
}
};
})();
/**
* 追加CSS规则
* @param {Node} 样式节点
* @param {String} 单条样式规则
* @return {CSSRule} 样式规则对象
*/
_h.__appendCSSText = function(_element,_css){
var _sheet = _element.styleSheet,
_length = _sheet.rules.length,
_arr = _css.split(/[\{\}]/);
_sheet.addRule(_arr[0],_arr[1],_length);
return _sheet.rules[_length];
};
});
// for ie7-
NEJ.patch('TR<=3.0',function(){
/**
* 取节点属性值
* @param {Node} 节点
* @param {String} 属性名
* @return {String} 属性值
*/
_h.__getAttribute =
_h.__getAttribute._$aop(null,function(_event){
// fix ie7 maxlength default value 2147483647
var _args = _event.args;
if (_args[1]=='maxlength'&&
_event.value==2147483647){
_event.value = null;
}
});
});
// for ie6-
NEJ.patch('TR<=2.0',function(){
/**
* 节点占全屏
* @param {Node} 节点
* @param {Object} 视窗模型
* @return {Void}
*/
_h.__fullScreen = function(_element,_viewport){
var _style = _element.style;
_style.width = _viewport.scrollWidth+'px';
_style.height = _viewport.scrollHeight+'px';
};
/**
* 为节点增加用于盖select/flash等控件的层
* @param {Node} 节点
* @return {Void}
*/
_h.__mask = (function(){
var _cache = {};
// remove mask
_h.__unmask = function(_element){
var _id = _element.id,
_mask = _cache[_id];
if (!!_mask){
delete _cache[_id];
_mask.parentNode.removeChild(_mask);
}
};
// append mask
return function(_element){
var _id = _element.id,
_mask = _cache[_id];
// create mask
if (!_mask){
_mask = document.createElement('iframe');
_mask.style.position = 'absolute';
_cache[_id] = _mask;
}
// sync mask size
var _style1 = _mask.style,
_style0 = _element.style;
_style1.top = (parseInt(_style0.top)||0)+'px';
_style1.left = (parseInt(_style0.left)||0)+'px';
_style1.width = _element.offsetWidth+'px';
_style1.height = _element.offsetHeight+'px';
_element.insertAdjacentElement('beforeBegin',_mask);
return _mask;
};
})();
});
// for firefox
NEJ.patch('GR',function(){
if (!_m._$SUPPORT.css3d){
_m._$SUPPORT.css3d = 'MozPerspective' in document.body.style;
}
if (!('insertAdjacentElement' in document.body)){
HTMLElement.prototype.insertAdjacentElement = function(_where,_element){
if (!_where||!_element) return;
switch(_where){
case 'beforeEnd' :
this.appendChild(_element);
return;
case 'beforeBegin':
this.parentNode.insertBefore(_element,this);
return;
case 'afterBegin' :
!this.firstChild
?this.appendChild(_element)
:this.insertBefore(_element,this.firstChild);
return;
case 'afterEnd' :
!this.nextSibling
?this.parentNode.appendChild(_element)
:this.parentNode.insertBefore(_element,this.nextSibling);
return;
}
};
}
if (!('innerText' in document.body)){
HTMLElement.prototype['__defineGetter__']("innerText",function(){return this.textContent;});
HTMLElement.prototype['__defineSetter__']("innerText",function(_content){this.textContent = _content;});
}
});
return _h;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'base/util',
'base/platform'
],function(_u,_m,_p,_o,_f,_r){
/**
* 验证事件信息
* @param {Node} 节点
* @param {String} 事件类型
* @param {Function} 处理函数
* @return {Object} 验证后事件信息 type/handler
*/
_p.__checkEvent = (function(){
// need change event name
var _tmap = {
touchstart:'mousedown',
touchmove:'mousemove',
touchend:'mouseup'
},
// need prefix
_pfix = _m._$KERNEL.prefix,
_emap = {
transitionend:'TransitionEnd',
animationend:'AnimationEnd',
animationstart:'AnimationStart',
animationiteration:'AnimationIteration',
visibilitychange:'visibilitychange'
};
var _fmap = {
enter:function(_element,_type,_handler){
var _result = {
type:'keypress'
};
if (!!_handler){
_result.handler = function(_event){
if (_event.keyCode===13){
_handler.call(_element,_event);
}
};
}
return _result;
}
};
var _doPrefix = function(_name){
return (_pfix.evt||_pfix.pro)+_name;
};
return function(_element,_type,_handler){
var _result = {
type:_type,
handler:_handler
};
if (!(('on'+_type) in _element)){
// check name convert
var _name = _tmap[_type];
if (!!_name){
_result.type = _name;
return _result;
}
// check prefix complete
var _name = _emap[_type];
if (!!_name){
_result.type = _doPrefix(_name);
return _result;
}
// check event update
var _func = _fmap[_type];
if (!!_func){
return _func.apply(null,arguments);
}
}
return _result;
};
})();
/**
* 添加事件
* @param {Node} 节点
* @param {String} 事件
* @param {Function} 处理函数
* @param {Boolean} 是否捕捉阶段
* @return {Void}
*/
_p.__addEvent = function(){
var _args = arguments;
if (DEBUG){
if (!(('on'+_args[1]) in _args[0])){
console.log('not support event['+_args[1]+'] for '+_args[0]);
}
}
_args[0].addEventListener(
_args[1],_args[2],_args[3]
);
};
/**
* 删除事件
* @param {Node} 节点
* @param {String} 事件
* @param {Function} 处理函数
* @param {Boolean} 是否捕捉阶段
* @return {Void}
*/
_p.__delEvent = function(){
var _args = arguments;
_args[0].removeEventListener(
_args[1],_args[2],_args[3]
);
};
/**
* 触发对象的某个事件
* @param {String|Node} 节点ID或者对象
* @param {String} 鼠标事件类型
* @return {Void}
*/
_p.__dispatchEvent = function(_element,_type,_options){
var _event = document.createEvent('Event');
_event.initEvent(_type,!0,!0);
_u._$merge(_event,_options);
_element.dispatchEvent(_event);
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./event.js',
'base/util'
],function(_h,_u,_p,_o,_f,_r){
// for ie10+
NEJ.patch('TR>=6.0',function(){
/**
* 验证事件信息
* @param {Node} 节点
* @param {String} 事件类型
* @param {Function} 处理函数
* @return {Object} 验证后事件信息 type/handler
*/
_h.__checkEvent = (function(){
var _emap = {
touchcancel:'MSPointerCancel',
touchstart:'MSPointerDown',
touchmove:'MSPointerMove',
touchend:'MSPointerUp'
};
return _h.__checkEvent._$aop(function(_event){
var _args = _event.args;
// check event convert
var _name = _emap[_args[1]];
if (!!_name){
_event.stopped = !0;
_event.value = {
type:_name,
handler:_args[2]
};
}
});
})();
});
// for ie9
NEJ.patch('TR==5.0',function(){
/**
* 验证事件信息
* @param {Node} 节点
* @param {String} 事件类型
* @param {Function} 处理函数
* @return {Object} 验证后事件信息 type/handler
*/
_h.__checkEvent = (function(){
var _vmap = {};
var _fmap = {
input:function(_element,_type,_handler){
// for check type only
if (!_handler){
return {type:_type};
}
// fix input backspace/delete/ctrl+x bug
return {
type:_type,
handler:function(_event){
var _id = _element.id;
_vmap[_id] = _element.value;
_handler.call(_element,_event);
},
link:[[
document,'selectionchange',
function(_event){
var _id = _element.id;
if (_element!=document.activeElement){
delete _vmap[_id];
return;
}
if (_vmap[_id]!==_element.value){
_vmap[_id] = _element.value;
_handler.call(_element,_event);
}
}
]]
};
}
};
return _h.__checkEvent._$aop(function(_event){
var _args = _event.args;
// check event update
var _func = _fmap[_args[1]];
if (!!_func){
_event.stopped = !0;
_event.value = _func.apply(null,_args);
}
});
})();
});
// for ie9+
NEJ.patch('TR>=5.0',function(){
// must use attach/detach for event
var _attached = {
'propertychange':1
};
/**
* 添加事件
* @param {Node} 节点
* @param {String} 事件
* @param {Function} 处理函数
* @param {Boolean} 是否捕捉阶段
* @return {Void}
*/
_h.__addEvent =
_h.__addEvent._$aop(function(_event){
var _args = _event.args;
if (_attached[_args[1]]!=null&&!!_args[0].attachEvent){
_event.stopped = !0;
_args[0].attachEvent('on'+_args[1],_args[2]);
}
});
/**
* 删除事件
* @param {Node} 节点
* @param {String} 事件
* @param {Function} 处理函数
* @param {Boolean} 是否捕捉阶段
* @return {Void}
*/
_h.__delEvent =
_h.__delEvent._$aop(function(_event){
var _args = _event.args,
_alias = _attached[_args[1]];
if (_attached[_args[1]]!=null&&!!_args[0].detachEvent){
_event.stopped = !0;
_args[0].detachEvent('on'+_args[1],_args[2]);
}
});
});
// for ie8-
NEJ.patch('TR<=4.0',function(){
/**
* 验证事件信息
* @param {Node} 节点
* @param {String} 事件类型
* @param {Function} 处理函数
* @return {Object} 验证后事件信息 type/handler
*/
_h.__checkEvent = (function(){
var _lmap = {};
var _fmap = {
input:function(_element,_type,_handler){
var _result = {
type:'propertychange'
};
if (!!_handler){
_result.handler = function(_event){
// for input.value or textarea.value
if (('value' in _element)&&
_event.propertyName=='value'){
var _id = _element.id;
// lock cycle trigger
if (!!_lmap[_id]){
return;
}
_lmap[_id] = !0;
_handler.call(_element,_event);
delete _lmap[_id];
}
};
}
return _result;
},
load:function(_element,_type,_handler){
var _result = {
type:'readystatechange'
};
if (!!_handler){
_result.handler = function(_event){
if (_element.readyState=='loaded'||
_element.readyState=='complete'){
_handler.call(_element,_event);
}
};
}
return _result;
}
};
return _h.__checkEvent._$aop(function(_event){
var _args = _event.args;
// check event update
var _func = _fmap[_args[1]];
if (!!_func){
_event.stopped = !0;
_event.value = _func.apply(null,_args);
}
// use element for this in handler
if (!!_args[2]){
_args[2] = _args[2]._$bind(_args[0]);
}
});
})();
/**
* 添加事件
* @param {Node} 节点
* @param {String} 事件
* @param {Function} 处理函数
* @param {Boolean} 是否捕捉阶段
* @return {Void}
*/
_h.__addEvent = function(){
var _args = arguments;
if (DEBUG){
if (!(('on'+_args[1]) in _args[0])){
console.log('not support event['+_args[1]+'] for '+_args[0]);
}
}
_args[0].attachEvent('on'+_args[1],_args[2]);
};
/**
* 删除事件
* @param {Node} 节点
* @param {String} 事件
* @param {Function} 处理函数
* @param {Boolean} 是否捕捉阶段
* @return {Void}
*/
_h.__delEvent = function(){
var _args = arguments;
_args[0].detachEvent('on'+_args[1],_args[2]);
};
/**
* 触发对象的某个事件
* @param {String|Node} 节点ID或者对象
* @param {String} 鼠标事件类型
* @return {Void}
*/
_h.__dispatchEvent = (function(){
var _omap = {
propertychange:{propertyName:'value'}
};
return function(_element,_type,_options){
var _event = document.createEventObject();
try{
_u._$merge(_event,_omap[_type],_options);
_element.fireEvent('on'+_type,_event);
}catch(ex){
// ignore unrecognized event name
console.error(ex.message);
console.error(ex.stack);
}
};
})();
});
// for firefox
NEJ.patch('GR',function(){
/**
* 验证事件信息
* @param {Node} 节点
* @param {String} 事件类型
* @param {Function} 处理函数
* @return {Object} 验证后事件信息 type/handler
*/
_h.__checkEvent = (function(){
var _nreg = /^(?:transitionend|animationend|animationstart|animationiteration)$/i;
var _fmap = {
mousewheel:function(_element,_type,_handler){
var _result = {
type:'MozMousePixelScroll'
};
if (!!_handler){
_result.handler = function(_event){
var _delta = _event.detail;
_event.wheelDelta = -_delta;
_event.wheelDeltaY = -_delta;
_event.wheelDeltaX = 0;
_handler.call(_element,_event);
};
}
return _result;
}
};
return _h.__checkEvent._$aop(function(_event){
var _args = _event.args;
// check animation event
if (_nreg.test(_args[1])){
_event.stopped = !0;
_event.value = {
type:_args[1],
handler:_args[2]
};
}
// check event update
var _func = _fmap[_args[1]];
if (!!_func){
_event.stopped = !0;
_event.value = _func.apply(null,_args);
}
});
})();
});
return _h;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define(function(_p,_o,_f,_r){
/**
* 遍历对象
* @param {Object} 对象
* @param {Function} 迭代回调
* @param {Object} 回调执行对象
* @return {String} 循环中断时的key值
*/
_p.__forIn = function(_obj,_callback,_this){
if (!_obj||!_callback){
return null;
}
var _keys = Object.keys(_obj);
for(var i=0,l=_keys.length,_key,_ret;i<l;i++){
_key = _keys[i];
_ret = _callback.call(
_this||null,
_obj[_key],_key,_obj
);
if (!!_ret){
return _key;
}
}
return null;
};
/**
* 遍历列表
* @param {Array} 列表
* @param {Function} 迭代回调
* @param {Object} 回调执行对象
* @return {Void}
*/
_p.__forEach = function(_list,_callback,_this){
_list.forEach(_callback,_this);
};
/**
* 集合转数组
* @param {Object} 集合
* @return {Array} 数组
*/
_p.__col2array = function(_list){
return _r.slice.call(_list,0);
};
/**
* YYYY-MM-DDTHH:mm:ss.sssZ格式时间串转时间戳
* @param {String} 时间串
* @return {Number} 时间戳
*/
_p.__str2time = function(_str){
return Date.parse(_str);
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./util.js',
'base/platform'
],function(_h,_m,_p,_o,_f,_r){
// for ie8-
NEJ.patch('TR<=4.0',function(){
/**
* 遍历对象
* @param {Object} 对象
* @param {Function} 迭代回调
* @param {Object} 回调执行对象
* @return {String} 循环中断时的key值
*/
_h.__forIn = function(_obj,_callback,_this){
if (!_obj||!_callback){
return;
}
// iterate
var _ret;
for(var x in _obj){
if (!_obj.hasOwnProperty(x)) continue;
_ret = _callback.call(_this,_obj[x],x,_obj);
if (!!_ret){
return x;
}
}
};
/**
* 遍历列表
* @param {Array} 列表
* @param {Function} 迭代回调
* @param {Object} 回调执行对象
* @return {Void}
*/
_h.__forEach = function(_list,_callback,_this){
for(var i=0,l=_list.length;i<l;i++){
_callback.call(_this,_list[i],i,_list);
}
};
/**
* 集合转数组
* @param {Object} 集合
* @return {Array} 数组
*/
_h.__col2array = function(_list){
var _result = [];
if (!!_list&&!!_list.length){
for(var i=0,l=_list.length;i<l;i++){
_result.push(_list[i]);
}
}
return _result;
};
/**
* YYYY-MM-DDTHH:mm:ss.sssZ格式时间串转时间戳
* @param {String} 时间串
* @return {Number} 时间戳
*/
_h.__str2time = (function(){
var _reg = /-/g;
return function(_str){
// only support YYYY/MM/DDTHH:mm:ss
return Date.parse(_str.replace(_reg,'/').split('.')[0]);
};
})();
});
return _h;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>config测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit config test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./config.test.js"></script>
</body>
</html>
window.NEJ_CONF = {
'root':'/res/',
'p_frame':['http://nei.netease.com/html/nej_proxy_frame.html'],
'p_flash':['http://nei.netease.com/proxy/crossdomain.xml']
}
var f = function(){
//定义测试模块
module("config");
var _c = NEJ.P('nej.c'),
_p = NEJ.P('nej.p');
//开始单元测试
test('NEJ配置文件测试', function() {
var _uri = _c._$getFrameProxy('http://nei.netease.com');
equal(_uri,'http://nei.netease.com/html/nej_proxy_frame.html','代理文件地址');
var _flash = _c._$getFlashProxy('http://nei.netease.com');
equal(_flash,'http://nei.netease.com/proxy/crossdomain.xml','http://nei.netease.com/proxy/crossdomain.xml');
equal(_c._$get('portrait'),'/res/portrait/','NEJ各文件配置portrait');
equal(_c._$get('ajax.swf'),'/res/nej_proxy_flash.swf','NEJ各文件配置ajax');
equal(_c._$get('chart.swf'),'/res/nej_flex_chart.swf','NEJ各文件配置chart');
equal(_c._$get('audio.swf'),'/res/nej_player_audio.swf','NEJ各文件配置audio');
equal(_c._$get('video.swf '),undefined,'NEJ各文件配置video');
equal(_c._$get('clipboard.swf'),'/res/nej_clipboard.swf','NEJ各文件配置clipboard');
equal(_c._$get('upload.image.swf'),'/res/nej_upload_image.swf','NEJ各文件配置upload');
if (_p._$KERNEL.browser == 'ie' && _p._$KERNEL.release <= 3.0){
equal(_c._$get('storage.swf'),'/res/nej_storage.swf','NEJ各文件配置storage');
}else{
ok(true,'高版本不需要 storage');
}
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}config.test.js',
['{lib}base/config.js'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>constant测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit constant test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./constant.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("constant");
var _p = NEJ.P('nej.g'),
_g = NEJ.P('nej.p');
//开始单元测试
test('测试静态变量', function() {
equal(typeof(_p._$CODE_NOTASGN),'number','需要指定的参数未指定');
equal(typeof(_p._$CODE_NOTSPOT),'number','不支持操作');
equal(typeof(_p._$CODE_TIMEOUT),'number','操作超时');
equal(typeof(_p._$CODE_ERREVAL),'number','字符串作为脚本执行异常');
equal(typeof(_p._$CODE_ERRCABK),'number','回调执行异常');
equal(typeof(_p._$CODE_ERRSERV),'number','服务器返回异常');
equal(typeof(_p._$CODE_ERRABRT),'number','异常终止的错误码');
equal(_p._$HEAD_CT,'Content-Type','请求头content-type统一名称');
equal(_p._$HEAD_CT_PLAN,'text/plain','文本请求头content-type值');
equal(_p._$HEAD_CT_FILE,'multipart/form-data','文件请求头content-type值');
equal(_p._$HEAD_CT_FORM,'application/x-www-form-urlencoded','表单请求头content-type值');
if (_g._$KERNEL.browser == 'ie' && _g._$KERNEL.release<=3.0){
equal(_p._$BLANK_IMAGE,'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==','空图片BASE64编码地址');
}else{
equal(_p._$BLANK_IMAGE,'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==','空图片BASE64编码地址');
}
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}constant.test.js',
['{lib}base/constant.js'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>element测试页面</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style id='style-id' type="text/css">
#js-node{position: relative;}
#bottom{margin:1200px 0 0 2200px;}
</style>
</head>
<body>
<h1 id="qunit-header">nej element.js test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div class="node" id="js-node">
<span>node</span>
<span class='node2'>node2</span>
</div>
<div id="ele" style="position:relative;padding:5px 0 0 10px;">
<div id="ele2">123</div>
</div>
<textarea id="cursor-area">请选中我,3秒后测试开始</textarea>
<div id='css3d' class='css3d'>
设置css3d属性
</div>
<div id='ul'><ul>ul</ul><p>p</p><h1>h1</h1></div>
<div id='frameCnt'>
</div>
<div id='bottom'>
bottom
</div>
<div id="full-div">full-div</div>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./element.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module('element');
var p = NEJ.P('nej.p');
var e = NEJ.P('nej.e');
var v = NEJ.P('nej.v');
//开始单元测试
test('判断平台',function(){
equal(typeof(p._$KERNEL),'object','浏览器是'+p._$KERNEL.browser+'----前缀是'+p._$KERNEL.prefix.css+'----scc3d='+p._$SUPPORT.css3d);
});
test('xml2object',function(){
var _xml = '<?xml version="1.0" encoding="UTF-8" ?>\
<netease>\
<albums>\
<p><id><code><id>id</id>\
<code>code</code>\
<name>name</name>\</code></id></p>\
<album>\
<id>id</id>\
<code>code</code>\
<name>name</name>\
</album>\
</albums>\
</netease>';
var _xml2 = '<?xml version="1.0" encoding="UTF-8"?>\
<netease>\
<albums>\
<code>1</code>\
<album>\
<id>198114001</id>\
<name></name>\
<desc></desc>\
<auth>2</auth>\
<privacy>2</privacy>\
<count>110</count>\
<tcover>4/zxeW5iOfq3ppXe1etviJwg==/611645124409898904.jpg</tcover>\
<coverurl>1/_0CvRVkR39uuLIIEHVSAJQ==/1278740819214249961.jpg</coverurl>\
<coverurl160>5/eoc7HI1101yikVJnzbBADg==/3082713944952843165.jpg</coverurl160>\
</album>\
</albums>\
</netease>';
equal(e._$xml2object(_xml2).netease.albums.album.auth,'2','XML转对象');
});
QUnit.test('textarea光标测试',function(){
QUnit.stop();
var _cursor = e._$get('cursor-area');
setTimeout(function(){
equal(e._$cursor(_cursor),{start:100,end:2000},'请人工检查光标起始位置和结束位置');
QUnit.start();
},2000);
});
QUnit.test('fullScreen测试',function(){
QUnit.stop();
var _cursor = e._$get('full-div');
setTimeout(function(){
e._$fullScreen(_cursor);
equal(_cursor.style.width,document.body.offsetWidth + 'px','节点占全屏');
QUnit.start();
},3000);
});
test('element',function(){
var _node = document.getElementById('js-node');
e._$setStyle(_node,'z-index',888);
equal(e._$getStyle(_node,'z-index'),888,'设置z-index样式');
equal(e._$get('js-node'),_node,'取节点对象,通过ID');
equal(e._$get(_node),_node,'取节点对象,通过对象');
//需要重复测试
equal(typeof(e._$id(_node)),'string','为节点设置一个唯一的ID');//返回本身id,没有id生成一个auto-id-xxxxxxxx
/**
* <div class="node" id="js-node">
* <span>node</span>
* <span>node2</span>
* </div>
*/
equal(e._$getSibling('ele').id,'cursor-area','根据从兄弟节点中搜索符合条件的节点')
equal(e._$getChildren(_node)[0].innerHTML,'node','取节点的子节点列表');
equal(e._$getChildren(_node,'node2')[0].innerHTML,'node2','根据样式标识取子节点列表');
equal(e._$getByClassName(document,'node')[0],_node,'根据类名取节点列表');
/**
* 创建<div id='js-div'></div>节点
* 追加到document.body下
*/
equal(e._$create('div','js-div',document.body),e._$getByClassName(document,'js-div')[0],'创建一个节点');
//xFrame
stop();
var _xFrame = e._$createXFrame({
src:'http://www.baidu.com',
name:'百度',
parent:'frameCnt',
visible:false,
onload:function(){
ok(true,'框架载入成功');
equal(_xFrame.name,'百度','name设置');
equal(_xFrame.style.display,'none','visible设置');
start();
}
});
var _id = e._$id(e._$getByClassName(document,'js-div')[0]);
var _ele = e._$get(_id);
//css3D
var _css3d = e._$get('css3d');
e._$css3d(_css3d,'translate',{x:'100px',y:'20px',z:'30px'});
equal(_css3d.style['-webkit-transform'],'translate3d(100px, 20px, 30px)','设置translate3d属性,仅safari和chrome支持');
e._$css3d(_css3d,'translate',{x:'100px',y:'20px',z:'40px'});
equal(_css3d.style['-webkit-transform'],'translate3d(100px, 20px, 40px)','重新设置translate3d属性,仅safari和chrome支持');
e._$css3d(_css3d,'scale',{x:1,y:2,z:2});
equal(_css3d.style['-webkit-transform'],'scale3d(1, 2, 2)','设置scale3d属性,仅safari和chrome支持');
e._$css3d(_css3d,'scale',{x:2,y:3,z:3});
equal(_css3d.style['-webkit-transform'],'scale3d(2, 3, 3)','重新设置scale3d属性,仅safari和chrome支持');
e._$css3d(_css3d,'rotate',{x:1,y:2,z:2,a:'45deg'});
equal(_css3d.style['-webkit-transform'],'rotate3d(1, 2, 2, 45deg)','设置rotate3d属性,仅safari和chrome支持');
e._$css3d(_css3d,'rotate',{x:2,y:1,z:1,a:'-75deg'});
equal(_css3d.style['-webkit-transform'],'rotate3d(2, 1, 1, -75deg)','重新设置rotate3d属性,仅safari和chrome支持');
e._$style(_css3d,{color:'red',background:'black'});
equal(_css3d.style['color'],'red','通过_$style设置样式');
equal(e._$getStyle(_css3d,'color'),'rgb(255, 0, 0)','去节点的color样式');
/**
* |a:1,b:0,c:0,d:1,e:0:f:0|
* |m11:1,m12:0,m13:0,m14:0|
* |m21:0,m22:1,m23:0,m24:0|
* |m31:0,m32:0,m33:1,m34:0|
* |m41:0,m42:0,m43:0,m44:1|
*/
var _matrix = e._$matrix("matrix(1,0,0,1,0,0)");
//移除节点
e._$remove(_ele,true);
equal(e._$get(_id),null,'删除节点,是否在删除节点前移除事件,要测试v._$clearEvent(_element)接口');
var _ele = e._$create('div','js-div',document.body);
_ele.innerText = 'hello';
e._$removeByEC(_ele);
/* */ equal(e._$getByClassName(document,'js-div').length,0,'节点移除到内存中');
var _ele = e._$create('div','js-div',document.body);
//设置data
var _a = e._$dataset(_ele,'img','就是一个值');
equal(_a,'就是一个值','给对象设置属性值');
/** _$dom2xml&&_$xml2dom
var _d2m = e._$dom2xml(_css3d);
var _m2d = e._$xml2dom(_d2m);
equal(_css3d,_m2d,'dom转xml,xml转dom,转后结果一致');
var _d2m = e._$dom2xml(_css3d);
var _t2t = e._$text2type(_d2m,"xml");
equal(_css3d,_css3d,'dom转xml字符串,再转成dom节点');
*/
var _text = '<div id="abc">xxxx</div>';
var _t2t = e._$text2type(_text,"xml");
equal(typeof(_t2t),'object','text2type');
var _text = '{"a":"b"}';
var _t2t = e._$text2type(_text,"json");
propEqual(_t2t,{"a":"b"},'text2type');
//_$html2node
var _ele = e._$html2node('<div id="testnode"><img src="" /></div>');
equal(_ele.id,'testnode','html代码转节点对象');
var _ele = e._$html2node('<div id="testnode"></div><div id="testnode1"></div><div id="testnode2"></div>');
equal(e._$getChildren(_ele).length,3,'html代码转节点对象');
//_$pushCSSText
e._$pushCSSText('.css3d{width:300px;}');
equal(_css3d.style.width,'','未激活样式');
e._$dumpCSSText();
equal(_css3d.offsetWidth,300,'激活样式');
//_$getPageBox
var _pb = e._$getPageBox();
equal(typeof(_pb.scrollTop),'number','取盒子的信息');
equal(typeof(_pb.scrollLeft),'number','取盒子的信息');
equal(typeof(_pb.clientWidth),'number','取盒子的信息');
equal(typeof(_pb.clientHeight),'number','取盒子的信息');
equal(typeof(_pb.scrollWidth),'number','取盒子的信息');
equal(typeof(_pb.scrollHeight),'number','取盒子的信息');
notEqual(_pb.scrollTop,NaN,'取盒子的信息');
notEqual(_pb.scrollLeft,NaN,'取盒子的信息');
notEqual(_pb.clientWidth,NaN,'取盒子的信息');
notEqual(_pb.clientHeight,NaN,'取盒子的信息');
notEqual(_pb.scrollWidth,NaN,'取盒子的信息');
notEqual(_pb.scrollHeight,NaN,'取盒子的信息');
var _limit = {width:100,height:10};
var _box = e._$getMaxBox({width:250,height:10},_limit);
propEqual(_box,{width:100,height:4},'给定大小缩放至限制区域内');
var _box = e._$getMaxBox({width:100,height:50},_limit);
propEqual(_box,{width:20,height:10},'给定大小缩放至限制区域内');
var _bottom = e._$get('bottom');
e._$scrollTo(_bottom);
notEqual(e._$getPageBox().scrollTop,0,'scrollTo指定节点');
notEqual(e._$getPageBox().scrollLeft,0,'scrollTo指定节点');
var _align = e._$align({width:200,height:200},{width:100,height:100});
propEqual(_align,{top:50,left:50},'获取滚动视窗');
var _align = e._$align({width:200,height:200},{width:100,height:100},'left bottom');
propEqual(_align,{top:100,left:0},'获取滚动视窗');
/**_$query
var _qdom = e._$query('.css3d',document);
equal(_qdom[0],_css3d,'通过选择器取节点');
*/
var _bd = e._$getScrollViewPort(_node);
equal(typeof(_bd),'object','获取滚动视窗');
//equal(_bd,document.documentElement,'获取滚动视窗');
//_$offset,没有to参数就计算到根节点
equal(typeof(e._$offset(_node).x),'number','计算两个节点之间的偏移量');
equal(typeof(e._$offset(_node).y),'number','计算两个节点之间的偏移量');
notEqual(typeof(e._$offset(_node).x),NaN,'计算两个节点之间的偏移量');
notEqual(typeof(e._$offset(_node).y),NaN,'计算两个节点之间的偏移量');
var _result = e._$offset(e._$get('ele2'),e._$get('ele'));
equal(_result.x,10,"计算两个节点之间的偏移量,指定了2个节点");
e._$setStyle(_node,'color','#f00');
equal(e._$getStyle(_node,'color'),'rgb(255, 0, 0)','设置color样式');
e._$setStyle(_node,'color2','red2');
equal(_node.style.color2,'red2','非标准属性一样设置成功,但是节点上没有显示,设置样式');
equal(e._$getStyle(_node,'color'),'rgb(255, 0, 0)','取样式值');
notEqual(e._$getStyle(_node,'color'),'red','样式值跟存的不一样,取的时候按照标准属性');
equal(e._$getStyle(_node,'color2'),'','非标准属性返回空字符串');
e._$addStyle('body{font-size:20px}');
equal(e._$getStyle(_node,'fontSize'),'20px','添加样式');
e._$addScript('document.getElementById("js-node").style.color = "green"');
equal(e._$getStyle(_node,'color'),'rgb(0, 128, 0)','脚本添加颜色');
e._$addClassName(_node,'fc01 fc03');
equal(_node.className,'node fc01 fc03','新增样式类,多个样式用空格分开');
e._$delClassName(_node,'node');
equal(_node.className,'fc01 fc03','删除样式类,多个样式用空格分开');
e._$replaceClassName(_node,'fc01 fc03','node');
equal(_node.className,'node','替换节点的样式类名称,多个样式用空格分隔');
e._$addClassName(_node,'node');
equal(e._$hasClassName(_node,'node'),true,'检测节点是否包含指定样式,多个样式用空格分隔,检测时包含其中之一即表示包含');
equal(typeof(e._$appendCSSText('style-id','#bottom{color:red;}')),'object','appendCSSText');
});
QUnit.test('clearChildren',function(){
var _ul = e._$get('ul');
e._$clearChildren(_ul);
equal(e._$getChildren(_ul).length,0,'子节点被清空了');
});
QUnit.test('wrapInline',function(){
var _ul = e._$get('js-node');
// equal(e._$wrapInline(_ul),0,'wrapInline-default');
equal(e._$wrapInline(_ul,{tag:'label',clazz:'label-class'}),0,'wrapInline-p');
});
QUnit.test('attr',function(){
var _src = e._$attr('js-node','data-img','xxx');
equal(_src,'xxx','attr');
})
QUnit.test('mask and unmask',function(){
ok('没有做测试')
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}element.test.js',
['{lib}base/element.js','{lib}util/encode/json.js'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>event.js测试页面</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
.node{width:100px;height:50px;-webkit-transition:3s;-moz-transition:3s;}
.box{width:950px;height:950px;background:green;}
</style>
</head>
<body>
<h1 id="qunit-header">nej event.js test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div class="node" id="js-node">
<span>点击我</span>
</div>
<div id='js-box' class='box'>touch测试</div>
<input id='js-input' type='text' />
<textarea id='js-textarea'></textarea>
<iframe id='js-iframe'></iframe>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./event.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module('event');
var p = NEJ.P('nej.p');
var e = NEJ.P('nej.e');
var v = NEJ.P('nej.v');
var func = function(_eventType,_node){
_node = _node || e._$get('js-node');
var _num = 0,_ele,_ele2,_pageX,_pageY;
var _dispatch = function(_node){
v._$dispatchEvent(_node,_eventType);
}
var _f = function(e){
_num = 10;
_ele = v._$getElement(e);
//带过滤器
_ele2 = v._$getElement(e,function(_element){
return _element.id != 'js-node';
});
};
v._$addEvent(_node,_eventType,_f);
_dispatch(_node);
equal(_ele.id,'js-node','获取触发事件的节点');
notEqual(_ele2.id,'js-node','获取触发事件的节点,过滤接口是id不能为js-node');
equal(_num,10,'事件添加成功,并且触发了');
_num = 0;
v._$delEvent(_node,_eventType,_f);
_dispatch(_node);
equal(_num,0,'事件已经被删除了,所以值不变');
v._$addEvent(_node,_eventType,_f);
v._$clearEvent(_node,_eventType);
v._$clearEvent(_node);
_dispatch(_node);
equal(_num,0,'所有事件已经被清理了,所以值不变');
v._$addEvent(_node,_eventType,_f);
v._$clearEvent(_node,'xxx');
_dispatch(_node);
notEqual(_num,0,'清理的类型不对,所以值变了');
v._$clearEvent(_node);
v._$addEvent(_node,_eventType,_f);
v._$clearEvent(_node,'function');
_dispatch(_node);
notEqual(_num,0,'清理的类型用关键字试试');
v._$clearEvent(_node);
_num = 0;
v._$addEvent(_node,_eventType,_f);
_dispatch(_node.children[0]);
equal(_num,10,'事件冒泡了');
v._$clearEvent(_node);
_num = 0;
var _f = function(e){
v._$stop(e);
_num = 10;
_ele = v._$getElement(e);
_ele2 = v._$getElement(e,function(_element){
return _element.id != 'js-node';
});
};
var _f2 = function(e){
v._$stop(e);
if(e.type == _eventType){
_pageX = v._$pageX(e);
_pageY = v._$pageY(e);
equal(_pageX,NaN,'结果是事件触发的pageX');
equal(_pageY,NaN,'结果是事件触发的pageY');
}
_num = 20;
_ele = v._$getElement(e);
_ele2 = v._$getElement(e,function(_element){
return _element.id != 'js-node';
});
};
v._$addEvent(_node,_eventType,_f);
v._$addEvent(_node.children[0],_eventType,_f2);
_dispatch(_node.children[0]);
equal(_num,20,'阻止掉事件冒泡');
_num = 0;
v._$clearEvent(_node);
v._$clearEvent(_node.children[0]);
v._$addEvent(_node,_eventType,_f,true);
//是否捕获阶段 IE没有
v._$addEvent(_node.children[0],_eventType,_f2,true);
_dispatch(_node.children[0]);
equal(_num,10,'阻止掉事件捕获');
};
// 开始单元测试
test('event mouseover',function(){
var _eventType = 'mouseover';
func(_eventType);
});
test('event click',function(){
var _eventType = 'click';
func(_eventType);
});
test('event change',function(){
var _eventType = 'change';
func(_eventType,e._$get('js-input'));
});
module('event常规测试');
test('null',function(){
expect(0);
var _node = e._$get('js-node');
var _f = function(){};
v._$addEvent(_node,'click',_f);
v._$delEvent(null,'click',_f);
});
test('input event',function(){
stop();
var _input = e._$get('js-input');
v._$addEvent(_input,'input',function(_event){
ok(true,'input text 成功触发input 事件');
start();
});
v._$dispatchEvent(_input,'input');
});
test('textarea event',function(){
stop();
var _textarea = e._$get('js-textarea');
v._$addEvent(_textarea,'input',function(_event){
ok(true,'textarea 成功触发input 事件');
start();
});
v._$dispatchEvent(_textarea,'input');
});
test('load event',function(){
stop();
var _iframe = e._$get('js-iframe');
v._$addEvent(_iframe,'load',function(_event){
ok(true,'ifram load事件成功触发');
start();
});
_iframe.src = 'http://www.baidu.com';
});
if (p._$support('css3d')){
test('transitionend event',function(){
stop();
var _node = e._$get('js-node');
e._$setStyle(_node,'transition-duration','1s');
v._$addEvent(_node,'transitionend',function(_event){
ok(true,'transitionend 事件成功触发');
start();
});
e._$css3d(_node,'rotate',{x:2,y:1,z:0,a:'105deg'});
});
}
module('user helper test');
test("检测事件触发点", function(){
stop();
var _pageX,_pageY;
var _f2 = function(_e){
if(_e.type == 'click'){
_pageX = v._$pageX(_e);
_pageY = v._$pageY(_e);
equal(typeof(_pageX),'number','检测事件触发点pageX'+_pageX);
equal(typeof(_pageY),'number','检测事件触发点pageY'+_pageY);
start();
}
};
var _node = e._$get('js-node');
v._$addEvent(_node,'click',_f2);
v._$dispatchEvent(_node,'click');
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}event.test.js',
['{lib}base/event.js','{lib}base/element.js'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>global测试页面</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">nej global.js test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./global.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module('global');
//开始单元测试
test('Function prototype',function(){
equal(typeof(Function.prototype._$bind),'function','函数对象加入了_$bind方法');
equal(typeof(Function.prototype._$bind2),'function','函数对象加入了_$bind2方法');
});
test('window.MWF', function() {
deepEqual(NEJ.O,{},'只读空对象实例');
deepEqual(NEJ.R,[],'只读空数组实例');
notEqual(NEJ.F,function(){return !1;},'空函数实例每个都不equal');
notDeepEqual(NEJ.F,function(){return !1;},'空函数实例每个都不DeepEqual');
});
// test('NEJ.X after window.MWF',function(){
// var _obj ={},_obj2 = {};
// _obj.num = 2;
// NEJ.X(_obj2,_obj,function(_num){
// if(_num == 3)
// return false;
// });
// equal(_obj.num,_obj2.num,'拷贝对象属性');
// var _obj = {},_obj2 = {};
// _obj.num1 = 3;
// _obj.num2 = 4;
// NEJ.X(_obj2,_obj,function(_num){
// if(_num == 3)
// return true;
// });
// notEqual(_obj.num1,_obj2.num1,'拷贝对象通过过滤接口属性');
// equal(_obj.num2,_obj2.num2,'拷贝对象通过过滤接口属性');
// });
// test('NEJ.EX after window.MWF',function(){
// /**
// * 以下代码从_obj2取_obj中对应的属性值
// * 拷贝结束后_obj->{num:1,num1:aa}
// */
// var _obj ={},_obj2 = {};
// _obj.num = 1;
// _obj.num1 = 'aa';
// _obj2.num = 2;
// NEJ.EX(_obj,_obj2);
// equal(_obj.num,_obj2.num,'拷贝对象属性');
// var _obj = {},_obj2 = {};
// _obj.num = '3';
// _obj2.num = '4';
// NEJ.EX(_obj,_obj2);
// equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性');
// _obj.num = 'aaa';
// _obj2.num = 'null';
// NEJ.EX(_obj,_obj2);
// equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试字符串null');
// _obj.num = 'aaa';
// _obj2.num = null;
// NEJ.EX(_obj,_obj2);
// notEqual(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试null');
// _obj.num = 'aaa';
// _obj2.num = undefined;
// NEJ.EX(_obj,_obj2);
// notEqual(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试undefined');
// _obj.num = 'aaa';
// _obj2.num = 'undefined';
// NEJ.EX(_obj,_obj2);
// equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试字符串undefined');
// _obj.num = 'aaa';
// _obj2.num = Number.NaN;
// NEJ.EX(_obj,_obj2);
// notEqual(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试Number.NaN值');
// _obj.num = 'aaa';
// _obj2.num = Number.MAX_VALUE;
// NEJ.EX(_obj,_obj2);
// equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试Number.MAX_VALUE值');
// _obj.num = 'aaa';
// _obj2.num = Number.MIN_VALUE;
// NEJ.EX(_obj,_obj2);
// equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试Number.MIN_VALUE');
// });
test('NEJ.P',function(){
equal(NEJ.P('a.b.c'),a.b.c,'字符串a.b.c生成命名空间');
equal(NEJ.P('window.a.b.c'),window.a.b.c,'字符串window.a.b.c生成命名空间');
deepEqual(NEJ.P('0.2.3'),{},'字符串0.2.3不能生成正确命名空间');
deepEqual(NEJ.P('function.for'),{},'关键字不能生成正确命名空间');
});
// test('NEJ.C',function(){
// var _f = NEJ.C();
// var _num = 0;
// _f.__static = function(){
// return 'static';
// };
// _f.prototype.__init = function(){
// _num = 10;
// };
// var _f2 = NEJ.C();
// //_fn2==_f2.prototype
// var _fn2 = _f2._$extend(_f);
// _fn2.__init = function(){
// this.__super();
// _num--;
// }
// var _xf = new _f();
// equal(typeof(_f),'function','返回一个函数对象');
// equal(typeof(_f._$bind),'function','返回的对象有_$bind方法,继承自Function');
// equal(typeof(_f._$bind2),'function','返回的对象有_$bind2方法,继承自Function');
// var _x2f = new _f2();
// equal(_num,9,'父类__init后,子类__init会被调用');
// equal(_f2.__static(),'static','默认继承了静态方法,如不继承传入false参数');
// });
// test('_$bind接口',function(){
// var _f = NEJ.C();
// _f.prototype.__init = function(){
// };
// var _f2 = NEJ.C();
// var _obj = {num:3};
// var _fn2 = _f2._$extend(_f);
// _fn2.__print = function(_obj,_obj2){
// return arguments[0]+arguments[1];
// };
// _fn2.__init = function(){
// this.__super();
// this.num = 33;
// var _fun = this.__print._$bind(this,'obj');
// var _fun2 = this.__print._$bind2(this,'obj');
// equal(_fun('aaa'),'objaaa','测试_$bind方法,参数的顺序调用');
// equal(_fun2('bbb'),'bbbobj','测试_$bind2方法,参数的倒序调用');
// };
// var _f22 = new _f2();
// });
test('trim接口',function(){
equal(' dfdf @$#%^ dfdf '.trim(),'dfdf @$#%^ dfdf','测试trim接口前后去空格');
equal(' function '.trim(),'function','关键字');
equal(' function(){return 0;} '.trim(),'function(){return 0;}','函数');
equal(' \\\*function()\*\\{return 0;} '.trim(),'\\\*function()\*\\{return 0;}','转义字符');
equal(' &lt; '.trim(),'&lt;','转义字符');
});
test('aop增强接口',function(){
var _obj = {a:0};
var _f = function(){
_obj.a = 1;
return 'aop增强操作1';
};
var _f2 = function(_event){
_obj.a = 2;
_event.value = 'aop增强操作2';
};
var _f3 = function(_event){
_obj.a = 3;
_event.value = 'aop增强操作3';
}
var _f = _f._$aop(_f2,_f3);
var _value = _f();
equal(_obj.a,3,'aop增强操作');
equal(_value,'aop增强操作3','aop增强操作返回值是某个增强操作的返回值');
});
test('aop增强接口,stopped',function(){
var _obj = {a:0};
var _f = function(){
_obj.a = 1;
return 'aop增强操作';
};
var _f2 = function(_event){
_event.stopped = true;
_obj.a = 2;
_event.value = 'aop增强操作2';
};
var _f3 = function(_event){
_obj.a = 3;
_event.value = 'aop增强操作3';
}
var _f = _f._$aop(_f2,_f3);
_f();
equal(_obj.a,2,'aop增强操作');
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}global.test.js',['{lib}base/global.js'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>klass测试页面</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">nej klass.js test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./klass.test.js"></script>
</body>
</html>
var f = function(_k){
//定义测试模块
module('global');
//开始单元测试
test('NEJ.C',function(){
var _f = _k._$klass();
var _num = 0;
_f.__static = function(){
return 'static';
};
_f.prototype.__init = function(){
_num = 10;
};
var _f2 = _k._$klass();
//_fn2==_f2.prototype
var _fn2 = _f2._$extend(_f);
_fn2.__init = function(){
this.__super();
_num--;
}
var _xf = new _f();
equal(typeof(_f),'function','返回一个函数对象');
equal(typeof(_f._$bind),'function','返回的对象有_$bind方法,继承自Function');
equal(typeof(_f._$bind2),'function','返回的对象有_$bind2方法,继承自Function');
var _x2f = new _f2();
equal(_num,9,'父类__init后,子类__init会被调用');
equal(_f2.__static(),'static','默认继承了静态方法,如不继承传入false参数');
});
test('_$bind接口',function(){
var _f = _k._$klass();
_f.prototype.__init = function(){
};
var _f2 = _k._$klass();
var _obj = {num:3};
var _fn2 = _f2._$extend(_f);
_fn2.__print = function(_obj,_obj2){
return arguments[0]+arguments[1];
};
_fn2.__init = function(){
this.__super();
this.num = 33;
var _fun = this.__print._$bind(this,'obj');
var _fun2 = this.__print._$bind2(this,'obj');
equal(_fun('aaa'),'objaaa','测试_$bind方法,参数的顺序调用');
equal(_fun2('bbb'),'bbbobj','测试_$bind2方法,参数的倒序调用');
};
var _f22 = new _f2();
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}global.test.js',['{lib}base/klass.js'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>platform测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit platform test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./platform.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("platform");
var _p = NEJ.P('nej.p');
//开始单元测试
test('NEJ配置文件测试', function() {
var _isWindows = _p._$is('desktop');
equal(_isWindows,true,'判断是否指定平台');
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}platform.test.js',
['{lib}base/platform.js'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>util测试页面</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">nej util.js test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="js-node">node</div>
<script src="../../define.js?pro=./"></script>
<script type="text/javascript" src="./util.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module('util');
var _util = NEJ.P('nej.u');
//开始单元测试
test('util',function(){
//判断
equal(_util._$isFunction(function(){}),true,'判断函数类型');
equal(_util._$isFunction(),false,'判断函数类型');
equal(_util._$isFunction(null),false,'判断函数类型');
equal(_util._$isString('abc'),true,'判断字符串类型');
equal(_util._$isString(),false,'判断字符串类型');
equal(_util._$isString(null),false,'判断字符串类型');
equal(_util._$isNumber("123"),false,'判断数字类型');
equal(_util._$isNumber(),false,'判断数字类型');
equal(_util._$isNumber(null),false,'判断数字类型');
equal(_util._$isNumber(0),true,'判断数字类型');
equal(_util._$isNumber(-0),true,'判断数字类型');
equal(_util._$isNumber(+0),true,'判断数字类型');
equal(_util._$isNumber(-1),true,'判断数字类型');
equal(_util._$isNumber(NaN),true,'判断数字类型');
equal(_util._$isNumber(Number.NEGATIVE_INFINITY),true,'判断数字类型');
equal(_util._$isNumber(Number.MAX_VALUE),true,'判断数字类型');
equal(_util._$isNumber(Number.MIN_VALUE),true,'判断数字类型');
equal(_util._$isBoolean(0),false,'判断布尔类型');
equal(_util._$isBoolean(),false,'判断布尔类型');
equal(_util._$isBoolean(null),false,'判断布尔类型');
equal(_util._$isBoolean(false),true,'判断布尔类型');
equal(_util._$isBoolean(true),true,'判断布尔类型');
equal(_util._$isDate(),false,'判断date类型');
equal(_util._$isDate(null),false,'判断date类型');
equal(_util._$isDate(new Date()),true,'判断date类型');
equal(_util._$isArray(),false,'判断Array类型');
equal(_util._$isArray(null),false,'判断Array类型');
equal(_util._$isArray([1,'a',{a:1}]),true,'判断Array类型');
equal(_util._$isObject(function(){}),false,'判断Object类型');
equal(_util._$isObject(),false,'判断Object类型');
equal(_util._$isObject(null),false,'判断Object类型');
equal(_util._$isObject({}),true,'判断Object类型');
equal(_util._$isObject({a:1}),true,'判断Object类型');
//功能
var _node = document.getElementById('js-node');
equal(_util._$indexOf([1,2,3],3),2,'查找列表中的某一项');
//常用来编码html结构,比如:<div> - > &lt;div&gt;
equal(_util._$encode({r:/\<|\>/g,'<':'&lt;','>':'&gt;'},'<div>'),'&lt;div&gt;','根据正则编码字符串');
equal(_util._$encode({r:/\d/g,'9':'t'},'99999'),'ttttt','编码字符串');
equal(_util._$escape('<a>util</a>&'),'&lt;a&gt;util&lt;/a&gt;&amp;','编码html代码');
equal(_util._$unescape('&lt;&amp;a&gt;util&lt;/a&gt;'),'<&a>util</a>','反编码html代码');
notEqual(_util._$format(new Date(),'yyyy-MM-dd'),'2012-01-11','格式化时间');
equal(_util._$fixed(3.1415926,2),'3.14','浮点数值保留指定位数小数点');
// equal(_util._$dom2xml(_node),'<div xmlns=\"http://www.w3.org/1999/xhtml\" id=\"js-node\">node</div>','将dom节点转为xml串');
// equal(document.body.appendChild(_util._$xml2dom('<div xmlns="http://www.w3.org/1999/xhtml" id="js-node2">node</div>')),document.getElementById('js-node2'),'将xml串转为dom节点然后加到页面上,自己跟自己做比较');
var _obj = {"div":"node"};
// equal(_util._$dom2object(_node,{}).div,_obj.div,'拷贝页面节点到空对象,跟现有节点比较');
//返回的对象为{div:'node'}
var _xml = '<?xml version="1.0" encoding="UTF-8" ?>\
<netease>\
<albums>\
<p><id><code><id>id</id>\
<code>code</code>\
<name>name</name>\</code></id></p>\
<album>\
<id>id</id>\
<code>code</code>\
<name>name</name>\
</album>\
</albums>\
</netease>';
var _xml2 = '<?xml version="1.0" encoding="UTF-8"?>\
<netease>\
<albums>\
<code>1</code>\
<album>\
<id>198114001</id>\
<name></name>\
<desc></desc>\
<auth>2</auth>\
<privacy>2</privacy>\
<count>110</count>\
<tcover>4/zxeW5iOfq3ppXe1etviJwg==/611645124409898904.jpg</tcover>\
<coverurl>1/_0CvRVkR39uuLIIEHVSAJQ==/1278740819214249961.jpg</coverurl>\
<coverurl160>5/eoc7HI1101yikVJnzbBADg==/3082713944952843165.jpg</coverurl160>\
</album>\
</albums>\
</netease>';
var _obj2 = {123:"123",abc:"abc"};
equal(_util._$string2object('abc=abc,123=123',',').abc,_obj2.abc,'key-value字符串转对象');
equal(_util._$object2string(_obj2),'123=123,abc=abc','key-value对象转成key=value对后用分隔符join');
equal(_util._$query2object('abc=abc&123=123').abc,_obj2.abc,'查询串转对象');
equal(_util._$query2object('abc=abc&123=123')['123'],_obj2['123'],'查询串转对象');
equal(_util._$object2query(_obj2),'123=123&abc=abc','查询串转对象');
var _map = {0:'0',1:'1',2:'2',length:3};
equal(_util._$object2array(_map)[1],'1','对象转数组');
equal(typeof(_util._$randString()),'string','随机一个字符串');
var _str = _util._$randNumberString();
var _isNumber = function(_str){
try{
if(/[^\d]/.test(_str))
return false;
return true;
}catch(e){
return false;
}
};
equal(_isNumber(_str),true,'随机生成一个全部为数字的字符串,可指定长度');
var _num = _util._$randNumber(0,1000);
equal(typeof(_num) == 'number' && _num > 0 && _num < 1000,true,'随机生成一个数字,可指定范围');
var _obj = {a:0};
var _f2 = function(){
_obj.a = 2;
}._$aop(
function(){
_obj.a = 1;
}
,function(){
_obj.a = 3;
})
_f2();
equal(_obj.a,3,'AOP增强操作');
var _list = [0,1,2];
_util._$forEach(_list,function(_item,_index,_list){
equal(_index == _item,true,'foreach回调方法');
});
var _obj = {a:'1',b:'2',c:'3'};
var _value = _util._$forIn(_obj,function(_item,_index,_list){
if(_item == '2')
return true;
});
equal(_value,'b','遍历列表或对象');
var _list = [0,1,2,3];
var _value = _util._$reverseEach(_list,function(_item,_index,_list){
_list[_index] = _item+1;
return false;
});
equal(_list[0],1,'逆序遍历列表或对象');
var _obj = [1,2,3];
var _value = _util._$forIn(_obj,function(_item,_index,_list){
if(_item == 2)
return true;
});
equal(_value,1,'forIn找到符合条件的项的索引或标识');
var _list = [1,2,3];
var _index = _util._$indexOf(_list,function(_value){return _value==2});
equal(_index , 1,'线性查找指定项');
});
test('安全删除对象属性',function(){
var _obj = {"a":"a","b":"b"};
_util._$safeDelete(_obj,["a","b"]);
equal(_obj.a,undefined,"安全删除对象属性");
})
test('安全删除对象属性',function() {
_obj = {"a":1,"b":2};
_util._$safeDelete(_obj,"b");
equal(_obj.b,undefined,"安全删除对象属性");
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}util.test.js',
['{lib}base/util.js'],f);
});
/*
* ------------------------------------------
* 通用接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module base/util */
NEJ.define([
'./global.js',
'{platform}util.js'
],function(NEJ,_h,_p,_o,_f,_r){
/*
* 查看数据是否指定类型
* @param {Variable} 数据
* @param {String} 类型
* @return {Boolean} 是否指定类型
*/
var _isTypeOf = function(_data,_type){
try{
_type = _type.toLowerCase();
if (_data===null) return _type=='null';
if (_data===undefined) return _type=='undefined';
return _o.toString.call(_data).toLowerCase()=='[object '+_type+']';
}catch(e){
return !1;
}
};
/**
* 判断是否函数类型
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回false
* var is = _u._$isFunction(123);
* // 返回true
* var is = _u._$isFunction(function(){});
* });
* ```
*
* @method module:base/util._$isFunction
* @param {Variable} arg0 - 待检测类型的数据
* @return {Boolean} 是否函数类型
*/
_p._$isFunction = function(_data){
return _isTypeOf(_data,'function');
};
/**
* 判断是否字符串
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回false
* var is = _u._$isString(123);
* // 返回true
* var is = _u._$isString("123");
* });
* ```
*
* @method module:base/util._$isString
* @param {Variable} arg0 - 待检测类型的数据
* @return {Boolean} 是否字符串
*/
_p._$isString = function(_data){
return _isTypeOf(_data,'string');
};
/**
* 判断是否数字
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回false
* var is = _u._$isNumber("123");
* // 返回true
* var is = _u._$isNumber(123);
* var is = _u._$isNumber(-123);
* var is = _u._$isNumber(Number.MAX_VALUE);
* });
* ```
*
* @method module:base/util._$isNumber
* @param {Variable} arg0 - 待检测类型的数据
* @return {Boolean} 是否数值类型
*/
_p._$isNumber = function(_data){
return _isTypeOf(_data,'number');
};
/**
* 判断是否布尔值
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回false
* var is = _u._$isBoolean(0);
* // 返回true
* var is = _u._$isBoolean(false);
* });
* ```
*
* @method module:base/util._$isBoolean
* @param {Variable} arg0 - 待检测类型的数据
* @return {Boolean} 是否布尔值
*/
_p._$isBoolean = function(_data){
return _isTypeOf(_data,'boolean');
};
/**
* 判断是否日期
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回false
* var is = _u._$isDate(0);
* // 返回true
* var is = _u._$isDate(new Date());
* });
* ```
*
* @method module:base/util._$isDate
* @param {Variable} arg0 - 待检测类型的数据
* @return {Boolean} 是否日期
*/
_p._$isDate = function(_data){
return _isTypeOf(_data,'date');
};
/**
* 判断是否数组
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回false
* var is = _u._$isArray(0);
* // 返回true
* var is = _u._$isArray([1,2]);
* });
* ```
*
* @method module:base/util._$isArray
* @param {Variable} arg0 - 待检测类型的数据
* @return {Boolean} 是否数组
*/
_p._$isArray = function(_data){
return _isTypeOf(_data,'array');
};
/**
* 判断是否对象
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回false
* var is = _u._$isObject(function(){});
* // 返回true
* var is = _u._$isObject({});
* var is = _u._$isObject({a:"a"});
* });
* ```
*
* @method module:base/util._$isObject
* @param {Variable} arg0 - 待检测类型的数据
* @return {Boolean} 是否对象
*/
_p._$isObject = function(_data){
return _isTypeOf(_data,'object');
};
/**
* 计算字符串长度,中文算两个字符
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 字符串长度为5
* var len = _u._$length('你i他');
* });
* ```
*
* @method module:base/util._$length
* @param {String} arg0 - 待计算长度字符串
* @return {Number} 字符串长度
*/
_p._$length = (function(){
var _reg = /[^\x00-\xff]/g;
return function(_content){
return (''+(_content||'')).replace(_reg,'**').length;
};
})();
/**
* 遍历对象
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* var obj = {a:{id:1,name:'a'},b:{id:2,name:'b'},...};
*
* // 遍历对象
* _u._$loop(obj,function(_item,_key){
* // TODO
* });
*
* // 从对象里查找id为2的元素,如果有返回KEY,没有返回null
* var key = _u._$loop(obj,function(_item){
* return _item.id==2;
* });
* });
* ```
*
* @method module:base/util._$loop
* @see module:base/util._$forIn
* @param {Object} arg0 - 对象
* @param {Function} arg1 - 回调,如果返回true,则中断遍历
* @param {Object} arg2 - 回调函数调用时this对象
* @return {String} 返回中断时的标识,没有中断则统一返回null
*/
_p._$loop = function(_obj,_callback,_this){
if (_p._$isObject(_obj)&&
_p._$isFunction(_callback)){
return _h.__forIn.apply(_h,arguments);
}
return null;
};
/**
* 线性查找指定项
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* var list = ["你","我","他"];
* // 返回下标1
* var index = _u._$indexOf(list,"我");
* // 没有找到,返回-1
* var index = _u._$indexOf(list,"他们");
* // 如果第二个参数是过滤接口,根据接口的规则查找
* // 以下规则排除第一个下标
* var index = _u._$indexOf(list,function(_item,_index,_list){
* return _item==='他';
* });
* });
* ```
*
* @method module:base/util._$indexOf
* @param {Array} arg0 - 待搜索列表
* @param {Variable} arg1 - 指定项,如果为function则表示过滤接口
* @return {Number} 给定项所在的位置索引,以0开始,没有项返回-1
*/
_p._$indexOf = function(_list,_item){
var _filter = _p._$isFunction(_item) ? _item
: function(_value){return _value===_item;},
_index = _p._$forIn(_list,_filter);
return _index!=null?_index:-1;
};
/**
* 二分法查找指定项
*
* 验证函数输入输出说明
*
* | | 类型 | 结果说明 |
* | :-- | :-- | :-- |
* | 输入 | Variable | 中间项元素 |
* | 输出 | Number | < 0 目标元素在低位区间 |
* | | | = 0 匹配到目标元素 |
* | | | > 0 目标元素在高位区间 |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 二分查找id为2的项的索引值
* var list = [{id:1,name:'aaa'},{id:2,name:'bbbb'},...];
* var index = _u._$binSearch(list,function(_item){
* return _item.id-2;
* });
* });
* ```
*
* @method module:base/util._$binSearch
* @param {Array} arg0 - 待查找列表
* @param {Function} arg1 - 验证函数
* @return {Number} 找到匹配项索引,找不到返回-1
*/
_p._$binSearch = (function(){
var _docheck;
// do binary search
var _doSearch = function(_list,_low,_high){
if (_low>_high) return -1;
var _middle = Math.ceil((_low+_high)/2),
_result = _docheck(_list[_middle],_middle,_list);
if (_result==0)
return _middle;
if (_result<0)
return _doSearch(_list,_low,_middle-1);
return _doSearch(_list,_middle+1,_high);
};
return function(_list,_check){
_docheck = _check||_f;
return _doSearch(_list,0,_list.length-1);
};
})();
/**
* 逆序遍历列表,支持中断
*
* 回调函数输入输出说明
*
* | | 类型 | 说明 |
* | :-- | :-- | :-- |
* | 输入 | Variable | 值 |
* | | Number | 下标 |
* | | Array | 列表对象 |
* | 输出 | Boolean | 是否匹配 |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 删除id为3的项,并退出循环
* var list = [{id:1,name:'aaa'},{id:2,name:'bbbb'},...];
* _u._$reverseEach(list,function(_item,_index,_list){
* if (_item.id==3){
* _list.splice(_index,1);
* return !0;
* }
* });
* });
* ```
*
* @method module:base/util._$reverseEach
* @see module:base/util._$forEach
* @param {Array} arg0 - 列表
* @param {Function} arg1 - 回调,如果返回true,则中断遍历
* @param {Object} arg2 - 回调函数调用时this对象
* @return {Number} 返回遍历中断时的索引值,没有中断则返回null
*/
_p._$reverseEach = function(_list,_callback,_this){
if (!!_list&&!!_list.length&&_p._$isFunction(_callback)){
for(var i=_list.length-1;i>=0;i--){
if (!!_callback.call(_this,_list[i],i,_list)){
return i;
}
}
}
return null;
};
/**
* 正序遍历列表,不支持中断
*
* 回调函数输入输出说明
*
* | | 类型 | 说明 |
* | :-- | :-- | :-- |
* | 输入 | Variable | 值 |
* | | Number | 下标 |
* | | Array | 列表对象 |
* | 输出 | Boolean | 是否匹配 |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* var list = [1,2,3];
* _u._$forEach(list,function(_item,_index,_list){
* // TODO somthing
* });
* });
* ```
*
* @method module:base/util._$forEach
* @see module:base/util._$reverseEach
* @param {Array} arg0 - 列表
* @param {Function} arg1 - 回调,如果返回true,则中断遍历
* @param {Object} arg2 - 回调函数调用时this对象
* @return {Void}
*/
_p._$forEach = function(_list,_callback,_this){
if (!!_list&&!!_list.length&&
_p._$isFunction(_callback)){
if (!_list.forEach){
_p._$forIn.apply(_p,arguments);
}else{
_h.__forEach(_list,_callback,_this);
}
}
};
/**
* 遍历列表或对象,如果带length属性,则作为数组遍历,如果要遍历带length属性的对象用_$loop接口,支持中断退出
*
* 回调函数输入输出说明
*
* | | 类型 | 说明 |
* | :-- | :-- | :-- |
* | 输入 | Variable | 值 |
* | | Number | 下标 |
* | | Object_Array | 列表或者集合对象 |
* | 输出 | Boolean | 是否匹配 |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 从有序列表里查找id为2的元素,如果有则返回索引,没有返回null
* var list = [{id:1,name:'a'},{id:2,name:'b'},...];
* var index = _u._$forIn(list,function(_item){
* return _item.id==2;
* });
*
* // 从对象里查找id为2的元素,如果有返回KEY,没有返回null
* var obj = {a:{id:1,name:'a'},b:{id:2,name:'b'},...};
* var key = _u._$forIn(obj,function(_item){
* return _item.id==2;
* });
* });
* ```
*
* @method module:base/util._$forIn
* @param {Object|Array} arg0 - 列表或者对象
* @param {Function} arg1 - 回调,如果返回true,则中断遍历
* @param {Object} arg2 - 回调函数调用时this对象
* @return {String|Number} 返回中断时的索引或者标识,没有中断则统一返回null
*/
_p._$forIn = function(_list,_callback,_this){
if (!_list||!_p._$isFunction(_callback)){
return null;
}
if (_p._$isNumber(_list.length)){
// list see as array
for(var i=0,l=_list.length;i<l;i++){
if (!!_callback.call(_this,_list[i],i,_list)){
return i;
}
}
}else if (_p._$isObject(_list)){
// list is object
return _p._$loop(_list,_callback,_this);
}
return null;
};
/**
* 编码字符串,
* 编码规则对象中r正则表达式参数提取字符串需要编码的内容,
* 然后使用编码规则对象中的映射表进行替换
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 把字符串99999根据规则9替换成t,结果:ttttt
* var str = _u._$encode({r:/\d/g,'9':'t'},'99999');
* });
* ```
*
* @method module:base/util._$encode
* @param {Object} arg0 - 编码规则
* @param {String} arg1 - 待编码的字串
* @return {String} 编码后的字串
*/
_p._$encode = function(_map,_content){
_content = ''+_content;
if (!_map||!_content){
return _content||'';
}
return _content.replace(_map.r,function($1){
var _result = _map[!_map.i?$1.toLowerCase():$1];
return _result!=null?_result:$1;
});
};
/**
* 编码html代码,'<' -> '&amp;lt;'
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 编码,结果:&amp;lt;a&amp;gt;util&amp;lt;/a&amp;gt;&amp;amp;
* var str = _u._$escape('<a>util</a>&');
* });
* ```
*
* @method module:base/util._$escape
* @see module:base/util._$unescape
* @param {String} arg0 - 待编码串
* @return {String} 编码后的串
*/
_p._$escape = (function(){
var _reg = /<br\/?>$/,
_map = {
r:/\<|\>|\&|\r|\n|\s|\'|\"/g,
'<':'&lt;','>':'&gt;','&':'&amp;',' ':'&nbsp;',
'"':'&quot;',"'":'&#39;','\n':'<br/>','\r':''
};
return function(_content){
_content = _p._$encode(_map,_content);
return _content.replace(_reg,'<br/><br/>');
};
})();
/**
* 反编码html代码,'&amp;lt;' -> '<'
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 反编码,结果:<&a>util</a>
* var str = _u._$unescape('&amp;lt;&amp;amp;a&amp;gt;util&amp;lt;/a&amp;gt;');
* });
* ```
*
* @method module:base/util._$unescape
* @see module:base/util._$escape
* @param {String} arg0 - 待反编码串
* @return {String} 反编码后的串
*/
_p._$unescape = (function(){
var _map = {r:/\&(?:lt|gt|amp|nbsp|#39|quot)\;|\<br\/\>/gi,'&lt;':'<','&gt;':'>','&amp;':'&','&nbsp;':' ','&#39;':"'",'&quot;':'"','<br/>':'\n'};
return function(_content){
return _p._$encode(_map,_content);
};
})();
/**
* 格式化时间,yyyy|yy|MM|cM|eM|M|dd|d|HH|H|mm|ms|ss|m|s|w
*
* 各标识说明:
*
* | 标识 | 说明 |
* | :-- | :-- |
* | yyyy | 四位年份,如2001 |
* | yy | 两位年费,如01 |
* | MM | 两位月份,如08 |
* | M | 一位月份,如8 |
* | dd | 两位日期,如09 |
* | d | 一位日期,如9 |
* | HH | 两位小时,如07 |
* | H | 一位小时,如7 |
* | mm | 两位分钟,如03 |
* | m | 一位分钟,如3 |
* | ss | 两位秒数,如09 |
* | s | 一位秒数,如9 |
* | ms | 毫秒数,如234 |
* | w | 中文星期几,如一 |
* | ct | 12小时制中文后缀,上午/下午 |
* | et | 12小时制英文后缀,A.M./P.M. |
* | cM | 中文月份,如三 |
* | eM | 英文月份,如Mar |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 根据格式输出时间,比如:2012-01-11,连接符可自定义
* var str = _u._$format(new Date(),'yyyy-MM-dd');
* });
* ```
*
* @method module:base/util._$format
* @param {Number|String|Date} arg0 - 时间
* @param {String} arg1 - 格式
* @return {String} 指定格式的时间串
*/
_p._$format = (function(){
var _map = {i:!0,r:/\byyyy|yy|MM|cM|eM|M|dd|d|HH|H|mm|ms|ss|m|s|w|ct|et\b/g},
_12cc = ['上午','下午'],
_12ec = ['A.M.','P.M.'],
_week = ['日','一','二','三','四','五','六'],
_cmon = ['一','二','三','四','五','六','七','八','九','十','十一','十二'],
_emon = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sept','Oct','Nov','Dec'];
var _fmtnmb = function(_number){
_number = parseInt(_number)||0;
return (_number<10?'0':'')+_number;
};
var _fmtclc = function(_hour){
return _hour<12?0:1;
};
return function(_time,_format,_12time){
if (!_time||!_format)
return '';
_time = _p._$var2date(_time);
_map.yyyy = _time.getFullYear();
_map.yy = (''+_map.yyyy).substr(2);
_map.M = _time.getMonth()+1;
_map.MM = _fmtnmb(_map.M);
_map.eM = _emon[_map.M-1];
_map.cM = _cmon[_map.M-1];
_map.d = _time.getDate();
_map.dd = _fmtnmb(_map.d);
_map.H = _time.getHours();
_map.HH = _fmtnmb(_map.H);
_map.m = _time.getMinutes();
_map.mm = _fmtnmb(_map.m);
_map.s = _time.getSeconds();
_map.ss = _fmtnmb(_map.s);
_map.ms = _time.getMilliseconds();
_map.w = _week[_time.getDay()];
var _cc = _fmtclc(_map.H);
_map.ct = _12cc[_cc];
_map.et = _12ec[_cc];
if (!!_12time){
_map.H = _map.H%12;
}
return _p._$encode(_map,_format);
};
})();
/**
* 日期字符串转日期对象
*
* 字符串日期格式同ECMA规范定义:YYYY-MM-DDTHH:mm:ss.sssZ
*
* 各标识说明:
*
* | 标识 | 说明 |
* | :-- | :-- |
* | YYYY | 四位年份,0000-9999,如2001 |
* | - | 年月日分隔符 |
* | MM | 两位月份,01-12,如03 |
* | DD | 两位日期,01-31,如07 |
* | T | 时间起始标识 |
* | HH | 两位小时,00-24,如05 |
* | : | 时分秒分隔符 |
* | mm | 两位分钟,00-59,如30 |
* | ss | 两位秒数,00-59,如08 |
* | . | 秒/毫秒分隔符 |
* | sss | 三位毫秒数,000-999,如004 |
* | Z | 时区偏移 |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 输入YYYY-MM-DDTHH:mm:ss.sssZ格式字符串,生成日期对象
* var date = _u._$var2date('2013-07-29T13:12:45.300');
*
* // 输入YYYY-MM-DDTHH:mm:ss格式字符串,生成日期对象
* var date = _u._$var2date('2013-07-29T13:12:45');
*
* // 输入YYYY-MM-DD格式字符串,生成日期对象
* var date = _u._$var2date('2013-07-29');
* });
* ```
*
* @method module:base/util._$var2date
* @param {String} arg0 - 日期串
* @return {Date} 日期对象
*/
_p._$var2date = function(_time){
var _date = _time;
if (_p._$isString(_time)){
_date = new Date(
_h.__str2time(_time)
);
}
if (!_p._$isDate(_date)){
_date = new Date(_time);
}
return _date;
};
/**
* 浮点数值保留指定位数小数点
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 保留2位小数,返回3.14
* var value = _u._$fixed(3.14159,2);
* });
* ```
*
* @method module:base/util._$fixed
* @param {Float} arg0 - 浮点数
* @param {Number} arg1 - 小数位
* @return {Number} 浮点数
*/
_p._$fixed = function(_float,_fraction){
return parseFloat(new Number(_float).toFixed(_fraction));
};
/**
* 相对路径转绝对路径
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 相对路径../a/b.html转绝对路径http://a.b.com:8010/a/b.html
* var url = _u._$absolute(
* '../a/b.html',
* 'http://a.b.com:8010/z/'
* );
* });
* ```
*
* @method module:base/util._$absolute
* @param {String} arg0 - 相对路径
* @param {String} arg1 - 绝对路径ROOT,必须以http://开始,默认为location目录
* @return {String} 绝对路径地址
*/
_p._$absolute = (function(){
var _reg0 = /([^\/:])\/.*$/,
_reg1 = /\/[^\/]+$/,
_reg2 = /[#\?]/,
_base = location.href.split(/[?#]/)[0],
_anchor = document.createElement('a');
var _isAbsolute = function(_uri){
return (_uri||'').indexOf('://')>0;
};
var _doFormat = function(_uri){
return (_uri||'').split(_reg2)[0]
.replace(_reg1,'/');
};
var _doMergeURI = function(_uri,_root){
// for /a/b/c
if (_uri.indexOf('/')==0)
return _root.replace(_reg0,'$1')+_uri;
// for a/b or ./a/b or ../a/b
return _doFormat(_root)+_uri;
};
_base = _doFormat(_base);
return function(_uri,_root){
_uri = (_uri||'').trim();
if (!_isAbsolute(_root))
_root = _base;
if (!_uri) return _root;
if (_isAbsolute(_uri))
return _uri;
_uri = _doMergeURI(_uri,_root);
_anchor.href = _uri;
_uri = _anchor.href;
return _isAbsolute(_uri) ? _uri :
_anchor.getAttribute('href',4); // ie6/7
};
})();
/**
* 从URL地址中提取源信息
*
* * http://a.b.com:8080/a/b/ -> http://a.b.com:8080
* * /a/b ->
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 提取url地址的源信息
* // 返回http://a.b.com:8080
* var origin = _u._$url2origin("http://a.b.com:8080/a/b/");
* });
* ```
*
* @method module:base/util._$url2origin
* @param {String} arg0 - URL地址
* @return {String} 源信息
*/
_p._$url2origin = (function(){
var _reg = /^([\w]+?:\/\/.*?(?=\/|$))/i;
return function(_url){
if (_reg.test(_url||''))
return RegExp.$1.toLowerCase();
return '';
};
})();
/**
* key-value字符串转对象
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* var str = "abc=abc,123=123";
* // 返回对象{abc:"abc",123:"123"}
* var obj = _u._$string2object(_str,",");
* });
* ```
*
* @method module:base/util._$string2object
* @see module:base/util._$object2string
* @param {String} arg0 - 待处理数据
* @param {String|RegExp} arg1 - 分隔符
* @return {Object} 转换后对象
*/
_p._$string2object = function(_string,_split){
var _obj = {};
_p._$forEach(
(_string||'').split(_split),
function(_name){
var _brr = _name.split('=');
if (!_brr||!_brr.length) return;
var _key = _brr.shift();
if (!_key) return;
_obj[decodeURIComponent(_key)] =
decodeURIComponent(_brr.join('='));
}
);
return _obj;
};
/**
* key-value对象转成key=value对后用分隔符join
*
* 对象中不同类型的取值规则如下:
*
* | 类型 | 取值规则 |
* | :-- | :-- |
* | Function | 过滤掉,不输出 |
* | Date | 转成时间戳,getTime取值 |
* | Array | 值用逗号分隔,如[1,2,3] -> 1,2,3 |
* | Object | 使用JSON转成字符串 |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回字符串 abc=abc,123=123
* var obj = {
* abc:"abc",
* 123:"123"
* };
* var str = _u._$object2string(obj);
*
* // 返回字符串
* // a=1871406603152186&b=1,2,3&d={"a":"a","b":"b"}&e=e&f=1&g=true
* var obj = {
* a:new Date,
* b:[1,2,3],
* c:function(){},
* d:{a:'a',b:'b'},
* e:'e',
* f:1,
* g:true
* };
* var str = _u._$object2string(obj,'&');
* });
* ```
*
* @method module:base/util._$object2string
* @see module:base/util._$string2object
* @param {Object} arg0 - 对象
* @param {String} arg1 - 分隔符,默认为逗号
* @param {Boolean} arg2 - 是否编码
* @return {String} key-value串
*/
_p._$object2string = function(_object,_split,_encode){
if (!_object) return '';
var _arr = [];
_p._$loop(
_object,function(_value,_key){
if (_p._$isFunction(_value)){
return;
}
if (_p._$isDate(_value)){
_value = _value.getTime();
}else if(_p._$isArray(_value)){
_value = _value.join(',');
}else if(_p._$isObject(_value)){
_value = JSON.stringify(_value);
}
if (!!_encode){
_value = encodeURIComponent(_value);
}
_arr.push(encodeURIComponent(_key)+'='+_value);
}
);
return _arr.join(_split||',');
};
/**
* 查询串转对象
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回对象{abc:"abc",123:"123"}
* var obj = _u._$query2object("abc=abc&123=123");
* });
* ```
*
* @method module:base/util._$query2object
* @see module:base/util._$object2query
* @see module:base/util._$string2object
* @param {String} arg0 - 查询串
* @return {Object} 转换出来的对象
*/
_p._$query2object = function(_query){
return _p._$string2object(_query,'&');
};
/**
* 对象转查询串
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回对象123=123&abc=abc
* var query = _u._$object2query({abc:"abc",123:"123"});
* });
* ```
*
* @method module:base/util._$object2query
* @see module:base/util._$query2object
* @see module:base/util._$object2string
* @param {Object} arg0 - 对象
* @return {String} 查询串
*/
_p._$object2query = function(_object){
return _p._$object2string(_object,'&',!0);
};
/**
* 集合转数组,集合具有length属性
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 返回数组['1','2','3']
* var map = {0:'0',1:'1',2:'2',length:3};
* var arr = _u._$object2array(map);
*
* // 多用于对节点集合的转换
* var nodes = document.body.childNodes;
* var arr = _u._$object2array(nodes);
* });
* ```
*
* @method module:base/util._$object2array
* @see module:base/util._$array2object
* @param {Object} arg0 - 集合,必须有length属性
* @return {Array} 数组
*/
_p._$object2array = function(_object){
return _h.__col2array(_object);
};
/**
* 数组转对象,将列表中元素按照指定KEY组成对象<br/>
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 输出结果为 {2:{id:2,name:'b'},...}
* var arr = [{id:1,name:'a'},{id:2,name:'b'},...];
* var obj = _u._$array2object(
* arr,function(_item){
* // 过滤name为a的项
* if (_item.name=='a'){
* return;
* }
* // 组对象的KEY用每项的id
* return _item.id;
* }
* );
*
* // 默认使用每项的值组对象
* var brr = ['a','b','c',...];
* // 输出 {a:'a',b:'b',c:'c',...}
* var obj = _u._$array2object(brr);
* });
* ```
*
* @method module:base/util._$array2object
* @see module:base/util._$object2array
* @param {Array} arg0 - 列表
* @param {Function} arg1 - 过滤函数,返回每一项的KEY,没有返回则过滤当前项
* @return {Object} 对象
*/
_p._$array2object = function(_list,_filter){
var _result = {};
_p._$forEach(
_list,function(_item){
var _key = _item;
if (!!_filter){
_key = _filter(_item);
}
if (_key!=null){
_result[_key] = _item;
}
}
);
return _result;
};
/**
* 格式化数字为指定位数,不足位数前面用0补足
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 2 -> 002
* // 22 -> 022
* // 222 -> 222
* // 2222 -> 2222
* var str = _u._$number2string(2,3);
* });
* ```
*
* @method module:base/util._$number2string
* @param {Number} arg0 - 数值
* @param {Number} arg1 - 位数,至少1位
* @return {String} 格式化后字符串
*/
_p._$number2string = function(_number,_limit){
var _len1 = (''+_number).length,
_len2 = Math.max(1,parseInt(_limit)||0),
_delta = _len2-_len1;
if (_delta>0){
_number = new Array(_delta+1).join('0')+_number;
}
return ''+_number;
};
/**
* 安全删除属性,
* 部分浏览器(如低版本IE)禁止直接delete节点上的属性
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 节点上保存的数据
* _node.data = {a:'aaaaa',b:'bbbbb'};
* _node.test = 'aaaaa';
*
* // 删除单个属性
* _u._$safeDelete(_node,'test');
* // 批量删除
* _u._$safeDelete(_node,['test','data']);
* });
* ```
*
* @method module:base/util._$safeDelete
* @param {Object} arg0 - 对象
* @param {String|Array} arg1 - 属性
* @return {Void}
*/
_p._$safeDelete = function(_object,_name){
if (!_p._$isArray(_name)){
try{
delete _object[_name];
}catch(e){
_object[_name] = undefined;
}
}else{
_p._$forEach(
_name,function(_item){
_p._$safeDelete(_object,_item);
}
);
}
};
/**
* 随机一个字符串
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 可能返回"13d1r1dt2"
* var seed = _u._$randString(9);
* });
* ```
*
* @method module:base/util._$randString
* @param {String} arg0 - 字符串长度
* @return {String} 随机字符串
*/
_p._$randString = (function(){
var _chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
return function(_length){
_length = _length||10;
var _result = [];
for(var i=0,_rnum;i<_length;++i){
_rnum = Math.floor(Math.random()*_chars.length);
_result.push(_chars.charAt(_rnum));
}
return _result.join('');
};
})();
/**
* 随机生成一个给定范围的整数
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 可能返回3
* var seed = _u._$randNumber(0,9);
* });
* ```
*
* @method module:base/util._$randNumber
* @see module:base/util._$randNumberString
* @param {Number} arg0 - 小区间,包含
* @param {Number} arg1 - 大区间,不包含
* @return {Number} 随机整数
*/
_p._$randNumber = function(_min,_max){
return Math.floor(Math.random()*(_max-_min)+_min);
};
/**
* 随机生成一个全部为数字的字符串
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 可能返回123456789
* var seed = _u._$randNumberString(9);
* });
* ```
*
* @deprecated
* @method module:base/util._$randNumberString
* @see module:base/util._$randNumber
* @see module:base/util._$uniqueID
* @param {Number} arg0 - 随机字符串的长度[1,30]
* @return {String} 随机生成的字符串
*/
_p._$randNumberString = function(_length){
_length = Math.max(0,Math.min(_length||8,30));
var _min = Math.pow(10,_length-1),_max = _min*10;
return _p._$randNumber(_min,_max).toString();
};
/**
* 生成系统中的唯一标识,每次调用均生成一个新的标识
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_p){
* // 可能返回123456789
* var _id1 = _p._$uniqueID(),
* _id2 = _p._$uniqueID();
* // _id1 != _id2
* });
* ```
*
* @method module:base/util._$uniqueID
* @return {String} 唯一标识
*/
_p._$uniqueID = (function(){
var _seed = +new Date;
return function(){
return ''+(_seed++);
};
})();
/**
* 读取上下文中指定名字空间的值
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* var obj = {
* a:{
* b:{
* c:{
* d:'ddddd'
* }
* }
* }
* };
* // 输出 ddddd
* var value = _u._$query(obj,'a.b.c.d');
* // 输出 undefined
* var value = _u._$query(null,'a.b.c.d');
* });
* ```
*
* @method module:base/util._$query
* @param {Object} arg0 - 上下文
* @param {String} arg1 - 名字空间
* @return {Varaible} 查询到的值
*/
_p._$query = function(_context,_namespace){
_context = _context||_o;
var _arr = (_namespace||'').split('.');
for(var i=0,l=_arr.length;i<l;i++){
_context = _context[_arr[i]];
if (!_context) break;
}
return _context;
};
/**
* 合并数据,同名属性右侧覆盖左侧,
* 最后一个如果是函数则用做数据过滤,
* 第一个参数作为合并数据结果集对象,如果为空则新建对象
*
* 过滤接口输入输出说明
*
* | | 类型 | 说明 |
* | :-- | :-- | :-- |
* | 输入 | Variable | 值 |
* | | String | 键 |
* | 输出 | Boolean | 是否过滤 |
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 合并多个数据至obj0中
* var obj0 = {a:0,b:1},
* obj1 = {a:"a",b:"b",c:"c"},
* obj2 = {c:"c",d:"d",e:"f"},
* ... ;
* var obj = _u._$merge(obj0,obj1,obj2,...);
*
* // 带过滤接口合并
* // 阻止a属性的覆盖
* var obj = _u._$merge(
* obj0,obj1,obj2,...,
* function(_value,_key){
* return _key=='a';
* }
* );
* });
* ```
*
* @method module:base/util._$merge
* @see module:base/util._$fetch
* @param {Object} arg0 - 原始对象
* @param {Object} arg1 - 待拷贝对象
* @param {Function} arg2 - 过滤接口
* @return {Object} 拷贝后对象
*/
_p._$merge = function(){
var _last = arguments.length-1,
_filter = arguments[_last];
// check filter function for last args
if (_p._$isFunction(_filter)){
_last -= 1;
}else{
_filter = _f;
}
// args0 as result
var _result = arguments[0]||{};
// merge
for(var i=1;i<=_last;i++){
_p._$loop(arguments[i],function(v,k){
if (!_filter(v,k)){
_result[k] = v;
}
});
}
return _result;
};
/**
* 根据原始对象属性,从目标对象提取非空值
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* var obj0 = {a:0,b:1},
* obj1 = {a:"a",b:"b",c:"c"};
* // 根据obj0的属性,从obj1拷贝非null属性到obj0中
* // 结果是obj0.a = "a",obj.b = "b",没有拷贝c属性;
* var obj = _u._$fetch(obj0,obj1);
* });
* ```
*
* @method module:base/util._$fetch
* @see module:base/util._$merge
* @param {Object} arg0 - 原始对象
* @param {Object} arg1 - 目标对象
* @return {Object} 合并后的对象
*/
_p._$fetch = function(_object,_config){
if (!!_config){
_p._$loop(_object,function(v,k,m){
var _value = _config[k];
if (_value!=null){
m[k] = _value;
}
});
}
return _object;
};
/**
* 判断对象自生是否包含元素
*
* ```javascript
* NEJ.define([
* 'base/util'
* ],function(_u){
* // 判断空对象是否有属性
* // 输出 false
* var has = _u._$hasProperty({});
*
* // 判断非空对象是否有属性
* // 输出 true
* var has = _u._$hasProperty({a:'a',b:'b',c:'c'});
*
* // 判断空数组是否有属性
* // 输出 false
* var has = _u._$hasProperty([]);
*
* // 判断非空数组是否有属性
* // 输出 true
* var has = _u._$hasProperty([1,2,3]);
* });
* ```
*
* @method module:base/util._$hasProperty
* @param {Object|Array} arg0 - 对象
* @return {Boolean} 是否有元素
*/
_p._$hasProperty = function(_obj){
// for null
if (!_obj){
return !1;
}
// for object with length
if (_obj.length!=null){
return _obj.length>0;
}
// for object
var _length = 0;
_p._$loop(_obj,function(){
_length++;
return _length>0;
});
return _length>0;
};
if (CMPT){
NEJ.Q = _p._$query;
NEJ.X = _p._$merge;
NEJ.EX = _p._$fetch;
NEJ.copy(this.NEJ,NEJ);
NEJ.copy(NEJ.P('nej.u'),_p);
}
return _p;
});
(function(d,p){
var __config = {root:{/*lib,pro,platform*/}/*native,charset,global,platform*/},
__xqueue = [], // item:{n:'filename',d:[/* dependency list */],p:[/* platform list */],h:[/* patch list */],f:function}
__scache = {}, // uri:STATE 0-loading 1-waiting 2-defined
__rcache = {}, // uri:RESULT
__stack = [], // for define stack
__platform;
/*
* 显示日志
* @param {String} _msg 日志内容
* @return {Void}
*/
var _doLog = (function(){
var _div,_div1,_css1 = {cursor:'pointer',textAlign:'center',backgroundColor:'#ddd'},
_css = {display:'none',position:'absolute',top:0,right:0,boder:'1px solid #aaa',overflow:'auto',height:'300px',width:'400px',zIndex:'1000',fontSize:'12px',color:'#fff',backgroundColor:'#000',lineHeight:'20px',textAlign:'left'};
return function(_msg){
if (!_div){
_div = document.createElement('div');
var _style = _div.style;
for(var x in _css)
_style[x] = _css[x];
document.body.appendChild(_div);
_div1 = document.createElement('div');
_div1.title = '关闭控制台信息';
_div1.innerHTML = '×';
_style = _div1.style;
for(var x in _css1)
_style[x] = _css1[x];
_div.appendChild(_div1);
_div1.onclick = function(){_div.style.display='none';};
document.attachEvent('onkeypress',function(_event){
// press ~ to show console
if (_event.keyCode==96)
_div.style.display = 'block';
});
}
var p = document.createElement('div');
p.innerHTML = _msg;
_div1.insertAdjacentElement('afterEnd',p);
};
})();
/*
* 文件初始化
* @return {Void}
*/
var _doInit = function(){
if (!p.console)
p.console = {log:_doLog,warn:_doLog};
// do init add loaded script and remove node
var _list = d.getElementsByTagName('script');
if (!_list||!_list.length) return;
var _reg = /\/define(?:\.cmp)?\.js(?=\?|#|$)/;
for(var i=_list.length-1,_script;i>=0;i--){
_script = _list[i];
_script.xxx = !0;
_reg.test(_script.src)
? _doParseConfig(_script.src)
: _doScriptLoaded(_script,!0);
}
if (!__config.global&&!p.define){
p.define = NEJ.define;
}
};
/*
* 解析地址
* @param {String}
* @return {Void}
*/
var _doParseConfig = function(_uri){
_uri = _doFormatURI(_uri);
if (!_uri) return;
var _arr = _uri.split(/[?#]/),
_brr = _arr[0].split('/');
_brr.pop(); // splice define.js
__config.root.lib = _brr.join('/')+'/';
var _obj = _doStr2Obj(_arr[1]);
__config.charset = _obj.c||'utf-8';
__config.global = _obj.g=='true';
delete _obj.c;
delete _obj.g;
_doParsePlatform(_obj.p);
delete _obj.p;
var _deps = _obj.d;
delete _obj.d;
var _root = __config.root;
for(var x in _obj){
_root[x] = _obj[x];
}
_root.platform = './platform/';
if (!_root.pro){
_root.pro = '../javascript/';
}
if (!!_deps){
document.write('<script src="'+_deps+'"></scr'+'ipt>');
}
};
/*
* 解析列表依赖关系
* @return {Array} 列表
*/
var _doParseDependency = (function(){
var _dependency = function(_list,_dmap,_test){
if (!_list||!_list.length)
return null;
var _result = [];
for(var i=0,l=_list.length,_file,_files;i<l;i++){
_file = _list[i];
if (!!_test[_file])
continue;
_test[_file] = !0;
_files = _dependency(_dmap[_file],_dmap,_test);
if (!!_files&&_files.length>0)
_result.push.apply(_result,_files);
_result.push(_file);
}
return _result;
};
return function(_list,_dmap){
return _dependency(_list,_dmap,{});
};
})();
/*
* 序列化配置依赖关系
* @return {Void}
*/
var _doSerializeDepList = function(_map){
if (!_map) return;
// format url
var _xlist = [],
_result = {};
for(var x in _map){
var _list = _map[x],
_file = _doFormatURI(x);
_xlist.push(_file);
_result[_file] = _list;
if (!_list||!_list.length) continue;
for(var i=0,l=_list.length;i<l;i++){
_list[i] = _doFormatURI(_list[i]);
}
}
// merge result
return _doParseDependency(_xlist,_result);
};
/*
* 解析插件信息
* @param {String} _uri 地址
* @return {Array} 插件信息
*/
var _doParsePlugin = (function(){
var _pmap = {
text:function(_uri){
_doLoadText(_uri);
},
json:function(_uri){
_doLoadJSON(_uri);
},
regular:function(_uri){
_doLoadText(_uri);
}
};
return function(_uri){
var _brr = [],
_type = null,
_arr = _uri.split('!'),
_fun = _pmap[_arr[0].toLowerCase()];
if (!!_fun){
_type = _arr.shift();
}
_brr.push(_arr.join('!'));
_brr.push(_fun||_doLoadScript);
_brr.push(_type);
return _brr;
};
})();
/*
* 初始化平台信息
* @param {String} _config 平台配置信息
* @return {Void}
*/
var _doParsePlatform = (function(){
var _reg0 = /(cef|ios|win|android)/,
_emap = {gk:'G',wk:'W',td:'T'};
return function(_config){
_config = _config||'td|gk|wk';
var _root = __config;
// hybrid development
if (_reg0.test(_config)){
var _name = RegExp.$1;
_root.platform = _name=='win'?/T/i:/W/i;
_root.native = '{lib}native/'+_name+'/';
return;
}
// parse platform
var _reg = [];
for(var x in _emap){
if (_config.indexOf(x)>=0){
_reg.push(_emap[x]);
}
}
_root.platform = new RegExp(_reg.join('|'),'i');
};
})();
/*
* 解析平台识别表达式
* @param {String} 平台识别串
* @return {Object} 平台信息,{pkey:'engine',isEngOK:function(_engine){},vkey:'release',isVerOK:function(version){}}
*/
var _doParsePatchExp = (function(){
var _reg0 = /\s/g,
_reg1 = /(TR|WR|GR|TV|WV|GV)/i,
_reg2 = /([<>=]=?)/,
_pkey = '[VERSION]',
_emap = {T:'trident',W:'webkit',G:'gecko'},
_vmap = {R:'release',V:'version'};
var _doParseVersion = function(_exp){
return _exp.replace(_reg2,"'$1'");
};
return function(_exp){
_exp = (_exp||'').replace(_reg0,'');
if (!_reg1.test(_exp)){
return null;
}
var _key = RegExp.$1,
_brr = _key.split(''),
_result = {
pkey:'engine',
vkey:_vmap[_brr[1]]
},
_pstr = _emap[_brr[0]];
_result.isEngOK = function(_platform){
return _platform==_pstr;
};
var _arr = _exp.split(_key),
_left = "'"+_doParseVersion(_arr[0])+_pkey+"'",
_right = "'"+_pkey+_doParseVersion(_arr[1])+"'";
_result.isVerOK = function(_version){
var _arr = ['true'];
if (!!_left){
_arr.push(_left.replace(_pkey,_version));
}
if (!!_right){
_arr.push(_right.replace(_pkey,_version));
}
return eval(_arr.join('&&'));
};
return _result;
};
})();
/*
* 根据给定地址指定请求编码
* @param {String} _uri 地址
* @return {String} 编码方式
*/
var _doParseCharset = function(_uri){
return _uri.indexOf(__config.root.lib)>=0?'utf-8':__config.charset;
};
/*
* 解析平台依赖的文件
* @param {Array} 依赖列表
* @return {Array} 合并了平台信息后的依赖列表
*/
var _doMergePlatform = (function(){
var _reg0 = /\\|\//;
// {platform}xxx -> ['./platform/xxx','./platform/xxx.patch']
// {platform}xxx.yy -> ['./platform/xxx.yy','./platform/xxx.patch.yy']
var _doParsePlatformURI = function(_uri){
_uri = (_uri||'').replace(
'{platform}',
__config.root.platform
);
var _arr = _uri.split(_reg0),
_name = _arr.pop(),
_path = _arr.join('/')+'/',
_patch = _name.split('.'),
_sufix = '';
if (_patch.length>1){
_sufix = '.'+_patch.pop();
}
return [
_path+_name,
_path+_patch.join('.')+'.patch'+_sufix
];
};
return function(_deps){
var _ret = {};
for(var i=0,_it;_it=_deps[i];i++){
if (_it.indexOf('{platform}')>=0){
_it = _doParsePlatformURI(_it);
_deps[i] = _it[0];
_ret[_it[0]] = _it[1];
}
}
return _ret;
};
})();
/*
* 从NEJ.patch中提取依赖列表合并至define依赖列表中
* @param {Array} define中的依赖列表
* @param {Function} define执行函数
* @return {Array} 合并了patch后的依赖列表
*/
var _doMergePatched = function(_callback){
var _func = _callback.toString();
if (_func.indexOf('NEJ.patch')<0){
return;
}
var _ret = [],
_map = {},
_tmp = NEJ.patch,
_reg = __config.platform;
NEJ.patch = function(){
var _args = _doFormatARG.apply(
null,arguments
);
// check platform
if (!_args[0]||!_args[1]||
!_reg.test(_args[0])){
return;
}
// merge dependency
for(var i=0,l=_args[1].length,_it;i<l;i++){
_it = _args[1][i];
if (!_map[_it]){
_map[_it] = !0;
_ret.push(_it);
}
}
};
try{
_callback();
}catch(e){
// ignore
}
NEJ.patch = _tmp;
return _ret;
};
/*
* 判断是否字符串
* @param {Varable} _data 数据
* @param {String} _type 类型
* @return {Boolean} 是否字符串
*/
var _isTypeOf = function(_data,_type){
return Object.prototype.toString.call(_data)==='[object '+_type+']';
};
/*
* 取事件触发元素
* @param {Event} _event 事件对象
* @return {Void}
*/
var _getElement = function(_event){
return !_event?null:(_event.target||_event.srcElement);
};
/*
* 查询串转对象
* @param {String} _query 查询串
* @return {Object} 对象
*/
var _doStr2Obj = function(_query){
var _result = {},
_list = (_query||'').split('&');
if (!!_list&&!!_list.length)
for(var i=0,l=_list.length,_brr,_key;i<l;i++){
_brr = _list[i].split('=');
_key = _brr.shift();
if (!_key) continue;
_result[decodeURIComponent(_key)] =
decodeURIComponent(_brr.join('='));
}
return _result;
};
/*
* 格式化地址,取绝对路径
* @param {String} _uri 待格式化地址
* @return {String} 格式化后地址
*/
var _doFormatURI = (function(){
var _xxx = !1,
_reg = /{(.*?)}/gi,
_reg1= /([^:])\/+/g,
_reg3= /[^\/]*$/,
_reg4= /\.js$/i,
_reg5= /^[{\/\.]/,
_anchor = d.createElement('a');
var _absolute = function(_uri){
return _uri.indexOf('://')>0;
};
var _slash = function(_uri){
return _uri.replace(_reg1,'$1/');
};
var _append = function(){
if (_xxx) return;
_xxx = !0;
_anchor.style.display = 'none';
document.body.appendChild(_anchor);
};
var _root = function(_uri) {
return _uri.replace(_reg3,'');
};
var _format = function(_uri){
_append();
_anchor.href = _uri;
_uri = _anchor.href;
return _absolute(_uri)&&_uri.indexOf('./')<0 ?
_uri : _anchor.getAttribute('href',4); // ie6/7
};
var _amdpath = function(_uri,_type){
// start with {xx} or /xx/xx or ./ or ../
// end with .js
// absolute uri
if (_reg4.test(_uri)||
_reg5.test(_uri)||
_absolute(_uri)){
return _uri;
}
// lib/base/klass -> {lib}base/klass.js
// pro/util/a -> {pro}util/a.js
var _arr = _uri.split('/'),
_path = __config.root[_arr[0]],
_sufx = !_type?'.js':'';
if (!!_path){
_arr.shift();
return _path+_arr.join('/')+_sufx;
}
// for base/klass -> {lib}base/klass.js
return '{lib}'+_arr.join('/')+_sufx;
};
return function(_uri,_base,_type){
if(_isTypeOf(_uri,'Array')){
var _list = [];
for(var i = 0; i < _uri.length; i++){
_list.push(
_doFormatURI(_uri[i],_base,_type)
);
}
return _list;
}
if (!_uri) return '';
if (_absolute(_uri)){
return _format(_uri);
}
if (_base&&_uri.indexOf('.')==0){
_uri = _root(_base)+_uri;
}
_uri = _slash(_amdpath(_uri,_type));
var _uri = _uri.replace(
_reg,function($1,$2){
return __config.root[$2]||$2;
}
);
return _format(_uri);
};
})();
/*
* 格式化输入参数
* @param {String} 字符串
* @param {Array} 数组
* @param {Function} 函数
* @return {Array} 格式化后的参数列表
*/
var _doFormatARG = function(_str,_arr,_fun){
var _args = [null,null,null],
_kfun = [
function(_arg){return _isTypeOf(_arg,'String');},
function(_arg){return _isTypeOf(_arg,'Array');},
function(_arg){return _isTypeOf(_arg,'Function');}
];
for(var i=0,l=arguments.length,_it;i<l;i++){
_it = arguments[i];
for(var j=0,k=_kfun.length;j<k;j++){
if (_kfun[j](_it)){
_args[j] = _it;
break;
}
}
}
return _args;
};
/*
* 侦测脚本载入情况
* @param {Node} _script 脚本节点
* @return {Void}
*/
var _doAddListener = (function(){
var _statechange = function(_event){
var _element = _getElement(_event)||this;
if (!_element) return;
var _state = _element.readyState;
if (_state==='loaded'||
_state==='complete')
_doScriptLoaded(_element,!0);
};
return function(_script){
_script.onload = function(e){_doScriptLoaded(_getElement(e),!0);};
_script.onerror = function(e){_doScriptLoaded(_getElement(e),!1);};
_script.onreadystatechange = _statechange;
};
})();
/*
* 页面已存在的script节点添加事件检测
* @return {Void}
*/
var _doAddAllListener = function(){
var _list = document.getElementsByTagName('script');
for(var i=_list.length-1,_script;i>=0;i--){
_script = _list[i];
if (!_script.xxx){
_script.xxx = !0;
!_script.src ? _doClearStack()
: _doAddListener(_list[i]);
}
}
};
/*
* 清理脚本节点
* @param {Node} _script 脚本节点
* @return {Void}
*/
var _doClearScript = function(_script){
if (!_script||!_script.parentNode) return;
_script.onload = null;
_script.onerror = null;
_script.onreadystatechange = null;
_script.parentNode.removeChild(_script);
};
/*
* 检查所有文件是否都载入
* @return {Boolean} 是否都载入
*/
var _isFinishLoaded = function(){
for(var x in __scache)
if (__scache[x]===0)
return !1;
return !0;
};
/*
* 检查列表是否都载入完成
* @param {Array} 列表
* @return {Void}
*/
var _isListLoaded = function(_list){
if (!!_list&&!!_list.length){
for(var i=_list.length-1;i>=0;i--){
if (__scache[_list[i]]!==2){
return !1;
}
}
}
return !0;
};
/*
* 检查集合是否都载入完成
* @param {Object} 集合
* @return {Void}
*/
var _isMapLoaded = function(_map){
if (!!_map){
for(var x in _map){
if (__scache[_map[x]]!==2){
return !1;
}
}
}
return !0;
};
/*
* 载入依赖文本
* @param {String} _uri 文本地址
* @return {Void}
*/
var _doLoadText = (function(){
var _msid,
_msxml = [
'Msxml2.XMLHTTP.6.0',
'Msxml2.XMLHTTP.3.0',
'Msxml2.XMLHTTP.4.0',
'Msxml2.XMLHTTP.5.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP'
];
var _getXHR = function(){
if (!!p.XMLHttpRequest){
return new p.XMLHttpRequest();
}
if (!!_msid){
return new ActiveXObject(_msid);
}
for(var i=0,l=_msxml.length,_it;i<l;i++){
try{
_it = _msxml[i];
var _xhr = new ActiveXObject(_it);
_msid = _it;
return _xhr;
}catch(e){
// ignore
}
}
};
return function(_uri,_callback){
if (!_uri) return;
var _state = __scache[_uri];
if (_state!=null) return;
// load text
__scache[_uri] = 0;
var _xhr = _getXHR();
_xhr.onreadystatechange = function(){
if (_xhr.readyState==4){
var _text = _xhr.responseText||'';
__scache[_uri] = 2;
__rcache[_uri] = _text;
if (!!_callback){
_callback(_text);
}
_doCheckLoading();
}
};
_xhr.open('GET',_uri,!0);
_xhr.send(null);
};
})();
/*
* 载入依赖JSON
* @param {String} _uri JSON地址
* @return {Void}
*/
var _doLoadJSON = function(_uri){
_doLoadText(_uri,function(_text){
var _data;
try{
if (!!p.JSON&&!!JSON.parse){
_data = JSON.parse(_text);
}else{
_data = eval('('+_text+')');
}
}catch(ex){
_data = null;
}
__rcache[_uri] = _data;
});
};
/*
* 载入依赖脚本
* @param {String} _uri 脚本地址
* @return {Void}
*/
var _doLoadScript = function(_uri){
if (!_uri) return;
var _state = __scache[_uri];
if (_state!=null) return;
// load file
__scache[_uri] = 0;
var _script = d.createElement('script');
_script.xxx = !0;
_script.type = 'text/javascript';
_script.charset = _doParseCharset(_uri);
_doAddListener(_script);
_script.src = _uri;
(d.getElementsByTagName('head')[0]||document.body).appendChild(_script);
};
/*
* 脚本载入完成回调
* @param {Node} _script 脚本节点对象
* @param {Boolean} _isok 脚本载入是否成功
* @return {Void}
*/
var _doScriptLoaded = function(_script,_isok){
var _uri = _doFormatURI(_script.src);
if (!_uri) return;
var _arr = __stack.pop();
if (!!_arr){
_arr.unshift(_uri);
_doDefine.apply(p,_arr);
}
// 404 is ok for platform
if (!!_uri&&__scache[_uri]!=1){
__scache[_uri] = 2;
}
_doClearScript(_script);
_doCheckLoading();
};
/*
* 搜索循环引用
* @return {Object} 需解环项
*/
var _doFindCircularRef = (function(){
var _result;
var _index = function(_array,_name){
for(var i=_array.length-1;i>=0;i--)
if (_array[i].n==_name)
return i;
return -1;
};
var _loop = function(_item){
if (!_item) return;
var i = _index(_result,_item.n);
if (i>=0) return _item;
_result.push(_item);
var _deps = _item.d;
if (!_deps||!_deps.length) return;
for(var i=0,l=_deps.length,_citm;i<l;i++){
_citm = _loop(__xqueue[_index(__xqueue,_deps[i])]);
if (!!_citm) return _citm;
}
};
var _exec = function(_list,_pmap){
if (!_pmap) return;
// find platform patch list
var _arr = [];
for(var i=0,l=_list.length,_it;i<l;i++){
_it = _list[i];
if (_pmap[_it]){
_arr.push(_it);
}
}
// index queue by file name
var _map = {};
for(var i=0,l=__xqueue.length,_it;i<l;i++){
_it = __xqueue[i];
_map[_it.n] = _it;
}
// execute platform patch
for(var i=0,l=_arr.length,_it,_item;i<l;i++){
_it = _arr[i];
// exec hack.js
_item = _map[_it];
if (!!_item){
_doExecFunction(_item);
}
// exec hack.patch.js
_item = _map[_pmap[_it]];
if (!!_item){
_doExecFunction(_item);
}
}
};
return function(){
_result = [];
// check from begin to end
var _item = _loop(__xqueue[0]);
// must do platform before excute
if (!!_item){
_exec(_item.d,_item.p);
}
return _item;
};
})();
/*
* 执行文件脚本
* @param {Object} 缓存信息
* @return {Void}
*/
var _doExecFunction = (function(){
// dependency inject param
var _o = {},
_r = [],
_f = function(){return !1;};
// merge inject param
var _doMergeDI = function(_dep,_map){
var _arr = [];
if (!!_dep){
// merge dependency list result
for(var i=0,l=_dep.length,_it;i<l;i++){
_it = _dep[i];
// except for 404 platform
if (!__rcache[_it]&&!_map[_it]){
__rcache[_it] = {};
}
// result of (platform.js || platform.patch.js)
_arr.push(__rcache[_it]||__rcache[_map[_it]]||{});
}
}
_arr.push({},_o,_f,_r);
return _arr;
};
var _doMergeResult = function(_uri,_result){
var _ret = __rcache[_uri],
_iso = {}.toString.call(_result)=='[object Object]';
if (!!_result){
if (!_ret||!_iso){
// for other type of return
_ret = _result;
}else{
// for namespace return
_ret = _ret||{};
for(var x in _result){
_ret[x] = _result[x];
}
}
}
__rcache[_uri] = _ret;
// save platform information
var _puri = __config.root.lib+'base/platform.js';
if (_uri===_puri){
__platform = _ret;
}
};
return function(_item){
var _args = _doMergeDI(
_item.d,_item.p
);
if (!!_item.f){
var _result = _item.f.apply(p,_args)||
_args[_args.length-4];
_doMergeResult(_item.n,_result);
}
__scache[_item.n] = 2;
console.log('do '+_item.n);
};
})();
/*
* 检查依赖载入情况
* @return {Void}
*/
var _doCheckLoading = function(){
if (!__xqueue.length) return;
for(var i=__xqueue.length-1,_item;i>=0;){
_item = __xqueue[i];
if (__scache[_item.n]!==2&&
(!_isMapLoaded(_item.p)||
!_isListLoaded(_item.h)||
!_isListLoaded(_item.d))){
i--; continue;
}
// for loaded
__xqueue.splice(i,1);
if (__scache[_item.n]!==2){
_doExecFunction(_item);
}
i = __xqueue.length-1;
}
// check circular reference
if (__xqueue.length>0&&_isFinishLoaded()){
var _item = _doFindCircularRef()||__xqueue.pop();
console.warn('try to unlock circular reference -> '+_item.n);
_doExecFunction(_item);
_doCheckLoading();
}
};
/*
* 清理函数定义缓存栈
* @return {Void}
*/
var _doClearStack = function(){
var _args = __stack.pop();
while(!!_args){
_doDefine.apply(p,_args);
_args = __stack.pop();
}
};
/*
* 查找当前执行的脚本
* @return {Node} 当前执行脚本
*/
var _doFindScriptRunning = function(){
var _list = document.getElementsByTagName('script');
for(var i=_list.length-1,_script;i>=0;i--){
_script = _list[i];
if (_script.readyState=='interactive')
return _script;
}
};
/*
* 执行模块定义
* @param {String} _uri 当前所在文件,确定文件中模块不会被其他文件依赖时可以不用传此参数,比如入口文件
* @param {Array} _deps 模块依赖的其他模块文件,没有依赖其他文件可不传此参数
* @param {Function} _callback 模块定义回调【必须】
* @return {Void}
*/
var _doDefine = (function(){
var _seed = +new Date,
_keys = ['d','h'];
var _doComplete = function(_list,_base){
if (!_list||!_list.length) return;
for(var i=0,l=_list.length,_it;i<l;i++){
_it = _list[i]||'';
if(_it.indexOf('.')!=0) continue;
_list[i] = _doFormatURI(_it,_base);
}
};
return function(_uri,_deps,_callback){
// check input
var _args = _doFormatARG.apply(
p,arguments
);
_uri = _args[0]||
_doFormatURI('./'+(_seed++)+'.js');
_deps = _args[1];
_callback = _args[2];
// check module defined in file
_uri = _doFormatURI(_uri);
if (__scache[_uri]===2){
return; // duplication
}
// for {platform}
var _plts;
if (!!_deps){
_plts = _doMergePlatform(_deps);
}
// for NEJ.patch
var _pths;
if (!!_callback){
_pths = _doMergePatched(_callback);
}
// complete relative uri
_doComplete(_deps,_uri);
__scache[_uri] = 1;
// push to load queue
var _xmap = {
n:_uri,d:_deps,
h:_pths,f:_callback
};
__xqueue.push(_xmap);
// load dependence
for(var i=0,l=_keys.length,_it,_list;i<l;i++){
_it = _keys[i];
_list = _xmap[_it];
if (!!_list&&!!_list.length){
var _kmap = {};
for(var k=0,j=_list.length,_itt,_itm,_arr,_type;k<j;k++){
_itt = _list[k];
if (!_itt){
console.warn('empty dep uri for '+_uri);
}
// 0 - url
// 1 - load function
// 2 - resource type
_arr = _doParsePlugin(_itt);
_itm = _doFormatURI(_arr[0],_uri,_arr[2]);
_kmap[_itt] = _itm;
_list[k] = _itm;
// load resource
_arr[1](_itm);
}
if (_it==='h'&&!!_xmap.f){
_xmap.f.kmap = _kmap;
}
}
}
if (!!_plts){
var _pmap = {};
for(var x in _plts){
_it = _doFormatURI(_plts[x],_uri);
_pmap[_doFormatURI(x,_uri)] = _it;
_doLoadScript(_it);
}
_xmap.p = _pmap;
}
// check state
_doCheckLoading();
};
})();
// exports
/**
* NEJ名字空间
* @namespace NEJ
*/
p.NEJ = {};
/**
* 模块定义,单个文件只允许定义一个模块,即只允许执行一次NEJ.define,模块执行函数支持依赖列表注入和名字空间两种方式
*
* 文件路径遵循以下规则
*
* * 完整的文件路径,如 http://a.b.com/patch/to/file.js
* * 使用{}标识配置参数,如{root}file.js
* * 直接使用非{}标识配置参数,此时不能加.js后缀,系统自动加.js后缀,如 root/file
* * NEJ库文件可以省略lib标识,如base/element,等价于 lib/base/element,等价于 {lib}base/element.js
* * 其他文本资源采用text!前缀标识,如text!/path/to/file.css,注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持
* * JSON资源采用json!前缀标识,如json!/path/to/data.json,注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持
* * Regular模板资源采用regular!前缀标识,如regular!/path/to/file.html,注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持
* * 路径以 ./ 或者 ../ 开始的相对路径则相对于当前脚本文件的路径,如 ./util.js
*
* ```javascript
* // 依赖base/global和base/util
* NEJ.define([
* 'base/global',
* 'base/util'
* ],function(NEJ,u,p,o,f,r){
* // u - {lib}base/util.js文件返回的api集合
* // p - 允许外界调用的类或者API均定义在p空间下
* // o - 注入的空对象 {}
* // f - 注入的空函数 function(){return !1;}
* // r - 注入的空数组 []
*
* // TODO something
*
* // 返回允许外界使用的对象
* return p;
* });
* ```
*
* ```javascript
* // 不依赖其他文件,等价于直接执行
* NEJ.define(function(p,o,f,r){
* // TODO something
*
* return p;
* });
* ```
*
* ```javascript
* // 仅用于引入依赖文件列表而不执行业务逻辑
* NEJ.define(['base/global']);
* ```
*
* @method NEJ.define
* @param {String} arg0 - 当前文件路径标识,不传自动解析,建议不传此参数
* @param {Array} arg1 - 模块依赖的其他模块文件,没有依赖其他文件可不传此参数
* @param {Function} arg2 - 模块定义回调,依赖列表中文件返回的执行结果会依次注入此回调中,回调返回的结果可被其他文件依赖时注入
* @return {Void}
*/
NEJ.define = function(_uri,_deps,_callback){
// has uri
if (_isTypeOf(_uri,'String'))
return _doDefine.apply(p,arguments);
// without uri
var _args = [].slice.call(arguments,0),
_script = _doFindScriptRunning();
// for ie check running script
if (!!_script){
var _src = _script.src;
if (!!_src)
_args.unshift(_doFormatURI(_src));
return _doDefine.apply(p,_args);
}
// for other
__stack.push(_args);
_doAddAllListener();
};
/**
* 根据条件判断是否在当前平台执行,
* 平台支持TR|WR|GR,没有比较操作符表示支持当前内核所有release版本
*
* | 标识符 | 说明 |
* | :-- | :-- |
* | T | Trident引擎,如ie |
* | W | Webkit引擎,如chrome |
* | G | Gecko引擎,如firefox |
*
* 平台内置的Trident引擎版本对应的IE版本关系:
*
* | Trident版本 | IE版本 |
* | :-- | :-- |
* | 2.0 | 6 |
* | 3.0 | 7 |
* | 4.0 | 8 |
* | 5.0 | 9 |
* | 6.0 | 10 |
* | 7.0 | 11 |
*
* patch文件必须符合以下规则:
* * 只允许执行若干NEJ.patch
* * NEJ.patch中只允许修改hack.js注入的对象里的API
* * 定义函数必须返回hack.js注入的对象
*
* ```javascript
* NEJ.define([
* './hack.js'
* ],function(h,p,o,f,r){
* // 针对trident平台的处理逻辑
* NEJ.patch('TR',function(){
* // TODO
* console.log('from inline ie');
* h.api = function(){
* // TODO
* };
* });
*
* // 针对webkit平台的处理逻辑
* NEJ.patch('WR',['./hack.chrome.js'],function(wk){
* // TODO
* console.log('from inline chrome');
* });
*
* // 针对gecko平台的处理逻辑
* NEJ.patch('GR',['./hack.firefox.js'],function(gk){
* // TODO
* console.log('from inline firefox');
* });
*
* // 针对IE6平台的处理逻辑
* NEJ.patch('TR==2.0',['./hack.ie6.js']);
*
* // 针对IE7-IE9的处理逻辑
* NEJ.patch('3.0<=TR<=5.0',function(){
* // TODO
* console.log('from inline ie7-ie9');
* });
*
* // 必须返回hack.js注入的对象
* return h;
* });
* ```
*
* @method NEJ.patch
* @param {String} arg0 - 平台识别条件,如:6<=TR<=9
* @param {Array} arg1 - 依赖文件列表
* @param {Function} arg2 - 执行函数
* @return {Void}
*/
NEJ.patch = function(_exp,_deps,_callback){
var _args = _doFormatARG.apply(
null,arguments
);
if (!_args[0]) return;
// check platform
var _kernel = __platform._$KERNEL,
_result = _doParsePatchExp(_args[0]);
if (!!_result&&!!_args[2]&&
_result.isEngOK(_kernel[_result.pkey])&&
_result.isVerOK(_kernel[_result.vkey])){
var _argc = [],
_deps = _args[1];
if (!!_deps){
var _xmap = arguments.callee.caller.kmap||{};
for(var i=0,l=_deps.length;i<l;i++){
_argc.push(__rcache[_xmap[_deps[i]]]||{});
}
}
_args[2].apply(p,_argc);
}
};
/**
* 载入依赖配置,对于老项目或者使用第三方框架的项目,可以使用此接口配置
*
* 项目某个页面加载的脚本列表
*
* ```html
* <script src="./a.js"></script>
* <script src="./b.js"></script>
* <script src="./c.js"></script>
* <script src="./d.js"></script>
* <script src="./e.js"></script>
* <script src="./f.js"></script>
* ```
*
* 根据脚本规则提取文件的依赖关系,没有依赖其他文件可不配置,假设页面入口文件为f.js
*
* ```javascript
* var deps = {
* '{pro}f.js':['{pro}d.js'],
* '{pro}e.js':['{pro}a.js','{pro}b.js','{pro}c.js'],
* '{pro}c.js':['{pro}b.js'],
* '{pro}b.js':['{pro}a.js']
* };
* ```
*
* 通过NEJ.deps配置依赖关系,假设以下配置文件的路径为./deps.js
*
* ```javascript
* NEJ.deps(deps,['{pro}f.js']);
* ```
*
* 修改页面使用文件依赖管理,使用d参数配置依赖文件地址
*
* ```html
* <script src="http://nej.netease.com/nej/src/define.js?d=./deps.js&pro=./"></script>
* <script src="./f.js"></script>
* ```
*
* 之后项目只需要维护deps.js中的依赖配置信息即可
*
* 说明:开发阶段deps.js中配置的文件均会被载入页面中,发布上线时仅提取页面使用到的脚本,比如上例中页面只用到f.js,通过配置文件可以发现f.js只依赖了d.js,因此这个页面最终发布时只会导出d.js和f.js
*
* @method NEJ.deps
* @param {Object} arg0 - 依赖映射表,如'{pro}a.js':['{pro}b.js','{pro}c.js']
* @param {Array} arg1 - 入口屏蔽文件列表,页面载入依赖配置文件中的文件时不载入此列表中的文件,多为页面入口文件
* @return {Void}
*/
NEJ.deps = function(_map,_entry){
var _list = _doSerializeDepList(_map);
if (!_list||!_list.length) return;
// ignore entry list
var _map = {};
if (!!_entry&&_entry.length>0){
for(var i=0,l=_entry.length;i<l;i++){
_map[_doFormatURI(_entry[i])] = !0;
}
}
for(var i=_list.length-1;i>=0;i--){
if (!!_map[_list[i]]){
_list.splice(i,1);
}
}
// load script
var _arr = [];
for(var i=0,l=_list.length,_it;i<l;i++){
_it = _list[i];
_arr.push('<script src="'+_it+'"></scr'+'ipt>');
__scache[_it] = 2;
}
document.writeln(_arr.join(''));
};
/**
* 是否兼容模式,兼容模式下支持用全局名字空间使用API和控件
*
* ```javascript
* if (CMPT){
* // TODO something
* // 此中的代码块在打包配置文件中将OBF_COMPATIBLE设置为false情况下打包输出时将被忽略
* }
* ```
*
* @name external:window.CMPT
* @constant {Boolean}
*/
p.CMPT = !0;
/**
* 是否调试模式,打包时调试模式下的代码将被过滤
*
* ```javascript
* if (DEBUG){
* // TODO something
* // 此中的代码块在打包发布后被过滤,不会输出到结果中
* }
* ```
*
* @name external:window.DEBUG
* @constant {Boolean}
*/
p.DEBUG = !0;
// init
_doInit();
})(document,window);
.#<uispace>{display:$<box>;$<box-pack>:end;width:150px;height:30px;line-height:30px;overflow:hidden;text-align:left;}
.#<uispace> .z-ttl{display:block;$<box-flex>:1;overflow-x:$<marquee>;border:2px solid #aaa;background:#fdc;}
.#<uispace> .z-act{width:30px;background:none center center no-repeat;background-size:30px 30px;cursor:default;}
.#<uispace> .js-play{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAV4AAAFeCAYAAADNK3caAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABoMSURBVHhe7d3Pi1VnnsfxXjU0DDQ09KpXA/MHDMy2oWFWveqV0jsTY1GUERFbB8SWQpAshCBDIhJhQBjThbgoFFukFooYCQot4ohBJBQWRsSWiBgRi0TOnKfHO11t1Fv3nnOee57vfRVIAnXPr+/zft7nU8+553l+8hM/KqACKqACKqACKqACKqACKqACKqACKlBeBTZv3vybDz744D/qf0fr//9L+lf//w/1v8o/NcAABjIy8MMaBx1NXkp+Ks+qbzjjDRs2/Ky+oN/VF3Ss/u9fMxaVyN3MMICBcRj46ytf/S75qygRv/fee/9aS3ax/vecbKUYDGCgUAaSvxaTz3ot4JmZmX+u7xb/XWiRx7k72kaqwsAUMJC8lvzWKwFv2bLlF/WJ/Wct3FXSlW4wgIGgDKwmzyXfTVzA9Un8tj6ZJ0ELLc1MQZrBrhvFKAwk3yXvTUy+9cnu8K0E0I4Crc/iJQgD6dtYO7LKd+PGjT999eRPIpQIMYCBqWUgeTD5sHMB1wf6ZW36L4LctaYWGO0neWKgNQa+SF7sTL6zs7M/rw9wVYO11mDELy1iIAADyYvJj63LN8XpWrjnSZd0MYABDLyRgfOtDzvURv9UsXU4DGAAA29nIHmytdRb72yDYutwGMAABoYzkHzZWL6bNm36le/pDi82INUIAxhIDCRfJm82km+9kz8BClAYwAAG1s9A8ubY4q03/rVir7/YaqVWGMDAgIHkz7Hk6/u6ICISDGBgbAa+GFm80u7Yxfa9zADfyyQb/LfBwMipt97gdBsHtg8AYwAD08pA8ui6U++r14ItySO5Se8YwEAzBtISQ+t7nbi+O6VZxxRcDTCAAQw0Z2B9s5h5qOam48aLAQy0xsDwh2yvFqi0Vlrzu5ykoIYYwEBiYHXowplpZnV3utbudDqejocBDFRDV6yoB4L/SLzEiwEMYKA9BpJX3/nthrrYJxS8vYKrpVpiAAPJq+8Ur4nOQUIUGMBAuwwkrw5LvN8oertFV0/1xMDUM/DNsMT7HUimHhIPhDwQwkCLDNSJ97thiVfBWyy4m5ibGAYwkBggXmJ1c8UABjIzQLyZCy7xSDwYwADxEq+0gwEMZGaAeDMXXNqRdjCAAeIlXmkHAxjIzADxZi64tCPtYAADxEu80g4GMJCZAeLNXHBpR9rBAAaIl3ilHQxgIDMDxJu54NKOtIMBDBAv8Uo7GMBAZgaIN3PBpR1pBwMYIF7ilXYwgIHMDBBv5oJLO9IOBjBAvMQr7WAAA5kZIN7MBZd2pB0MYIB4iVfawQAGMjNAvJkLLu1IOxjAAPESr7SDAQxkZoB4Mxdc2pF2MIAB4iVeaQcDGMjMAPFmLri0I+1gAAPES7zSDgYwkJkB4s1ccGlH2sEABoiXeKUdDGAgMwPEm7ng0o60gwEMEC/xSjsYwEBmBog3c8GlHWkHAxggXuKVdjCAgcwMEG/mgks70g4GMEC8xCvtYAADmRkg3swFl3akHQxggHiJV9rBAAYyM0C8mQsu7Ug7GMAA8RKvtIMBDGRmgHgzF1zakXYwgAHiJV5pBwMYyMwA8WYuuLQj7WAAA8RLvNIOBjCQmQHizVxwaUfawQAGiJd4pR0MYCAzA8SbueDSjrSDAQwQL/FKOxjAQGYGiDdzwaUdaQcDGCBe4pV2MICBzAwQb+aCSzvSDgYwQLzEK+1gAAOZGSDezAWXdqQdDGCAeIlX2sEABjIzQLyZCy7tSDsYwADxEq+0gwEMZGaAeDMXXNqRdjCAAeIlXmkHAxjIzADxZi64tCPtYAADxEu80g4GMJCZAeLNXHBpR9rBAAaIl3ilHQxgIDMDxJu54LnSzv79+6uzZ89W9+7dqwY/jx8/rr7++utqYWGh2rZtm84WtO1zMeY44yd34g3W+bZu3VpdunTp/2X7tv9ZXV2tLly4UG3fvp2AgzFAiOMLMVftiDdQp9u1a9c/JNyh9q0/8Pz58+rEiRPV7OwsAQdiIZdAHGc8yRNvkM6WxJmGEcb9efDgQXXo0CHyDcIDIY4nxFx1I94gHe306dPjOvcftrt582a1b98+Ag7CRS6ROM5ooifeAB1sx44d1YsXL1oRb9rJ999/Xy0tLXkAF4ANQhxNiLnqRbwBOtfx48dbk+7aHT179qxK+84Fo+P0UxLapf12Id4A4r127Von4h3sdGVlpTp48CABB2CFRNuX6Dg1Jd4Anenu3budinew8yT43bt3E3AAZsaRhW3akzbxBuhE3377bRbxpoOk7/+eOXOmSt8X1hHb64hqOV21JF7iHUvaT548qY4ePUq+Afgh/fzSJ94AHSdn4n3d0svLy9WBAwcIOABHBJxPwMQboMNMUrwDEV++fLnauXMnAQfgiYC7FzDxBugofRBvEnD6LvHi4mI1NzdHwAG4IuDuBEy8ATpIX8Q7SL8PHz6sDh8+TL4B2CLfbuRLvAE6R9/EOxDw7du3q/n5eQIOwBgBtytg4g3QKfoq3iTgly9fmn4yAGPES7wS1Gsduc/iHaTfNP1kmoB9ZmZG+xHx1DMg8QboBCWIdyDg+/fvm34yAHMScLMETLwBOkFJ4h0I+MaNG9WePXumPvkQWDOBlVo/4iXesd5ca2Mj009Op3RKlWWb5028xNuGQxvt4+nTp9WxY8ek3wAstimnyPsi3gCwlzjU8CZTm35SAo4s27XXRrzE2yitdrHxlStXTD8ZgMtpkeg410m8AQCPknjXSnww/aTXj6XgccTW922Il3i7CK2t7TPdVEw/Sb59F+mo50e8xNuaJLvcUZp+cv/+/R7ABeB1VElF/DzxBgA54lDD2yR+6dIl008GYDaiTEe5JuINAPE0iXcw/eTJkyer2dlZCTgAv6MIK8pniTcAuNMmXtNPGvMtXcDES7xdDs1m2fetW7eqffv2Sb8BWC5dqOs9f+INAOu0Jt61Vjf9pBS8Xun14XPES7xZUmmugzx79qw6fvy46ScDcN0HQXZ1DsQbAFCJ98daT9NPfvzxx4YfAvDdlfwmuV/iDQAm8b49T1+7ds30kwEYn6Qkuzg28QaAknjfPZCRpp88d+5ctXXrVgk4AO9diDD3Pok3AIjEu74R5CdPnph+MgDvuSXZxfGINwCIxLs+8Q4+laafPHDggPQbgP0upJhjn8QbAD7iHU28g0+bftJX0HJI9k3HIF7iHc9aQbZK00+eOnWqMv0kCeeUMPESbxCFNrsM008SL/EGkGHORjTU0Ey6a7e+c+eO6Sf1v87H/yXeAJARb3viHezJ9JMScJfhiXiJt31rBdnj8+fPqxMnTph+MkAf6VKi4+ybeANAJfF2a/qHDx9Wn3zySed/fo7TgW1TZjInXuLt1lqB9n7z5k3TTwboL324WRFvAJAk3nx2T9NPnj9/vtq2bZsEHKDvTErCxBsAHuLNJ97BkUw/Weaf+JMS7evHJV7izW+tQEdM008ePHhQ+g3Qj3JKmXgDACPxTt7kpp+UgEcRN/ES7+StFeQM0vSTZ86cMf1kgD41ikTH+SzxBoBE4u2XuU0/Kf0OkzHxEm+/rBXobJaXl00/GaB/DZPoOL8n3gBgSLz9tnWafnLXrl0ewAXoa+NI1rSQQRueePst3nR2L168qBYXF00/GbQPjipkiTcACMTbf/EOzjC11ZEjR6TfAP1uVNmu/TzxBgCAeMsR7+BMb9++bfrJAH1vXPkSb4DGJ97yxDs444sXL1bbt2+XgAP0w1EkTLwBGpx4yxVvOnPTT07f18+Il3jLtlags3/w4EF16NAh6TdAnxyWfok3QCNLvIHsW1+K6SfjJ2DiJd5Y1gpyNen146WlJdNPBuifvscbtBEl3iC2fcNlDKafHPanq9+XlZIl3gAyJt644h1c2crKiuknA/TVwQ2SeAM0JvHGF+/gCtP0k7t37/YArvB+S7yFN2C6gxLv9Ig3Xenq6qrpJwvvt8RbeAMS73RJd+3Vpuknjx49Kv0W2IeJt8BGe/1BisQ7vfJNV276ybIerKX+S7zEO93WCnT1ly9frnbu3CkBF9CnibeARhr2VSGJN5A9G16K6SfLSL/ES7wNu7rN+1iBhw8fVocPH5Z+e9q/ibenDTMs5a79vcTbR/X145zS9JPz8/ME3LN+Trw9a5BRhDv4LPH2Q3J9PYuXL19WFy5cMP1kj/o68faoMcaRrq+T9VV3/TuvNP3kwsJCNTMzIwFPuN8T74QbYFzZGmron9hKOaP79++bfnLC/Z54J9wAxFuKruKd540bN6o9e/ZIvxNwAPFOoOhtyFbijSfCSVxRmn7y9OnThh8ye4B4Mxe8beka452EruId86uvvvLyRUYXEG/GYnchXeKNJ8FJXVFaemjbtm2GHjI4gXgzFLkr4fo62aQUFfe4V69eJd4MTiDeDEUm3riiinhlXrjo/rVj4iXeiO5wTQ0qcP78eam3Yy8Qb8cF7jrtGuNtYBibvrECaZ7fHNxO8zGIl3jpRwV+VAEP2bodbiBe4qUdFfhRBazrRrz+7BlyczBJDnO2XQGJl3iJl3jb9or9vaMCxni7la6lfwIMM3i4xqFtV2BpaUnY6dgNxng7LnCOJ7eGGtpWz3Tvb+/evcTbsReIt+MCE+90S6y0q7948SLpZnAC8WYoctfylXhL01s/z3dlZaWanZ0l3gxOIN4MRSbeforGWf29AmltNkvDd/9QbeAC4iVe/pniCqT12M6dO2c+3sweIN7MBe8i/RpqmGJzNrh0KxDnS7iv93viJd4GXdemJVbg0aNH1eHDh43lTrDvE+8Ei99W+pV4S9Rf/nN+8eJFtbi4WM3NzZHuhPs98U64AdqQL/Hml1hpR7xy5YqHZz3q68Tbo8YYV8LEW5oG853v8vJydeDAAQm3Z/2ceHvWIOPIl3jziayUI6X5Fo4dO0a4Pe3fxNvThhlFwMRbig67P8+0XHv6etjWrVtJt8d9m3h73DjrlS/xdi+0Eo5w7dq1as+ePYRbQJ8m3gIaaZiAibcELXZ3jvfv368OHTpEuAX1ZeItqLHeJmDi7U5qfd7z8+fPq88//9xbZwX2YeItsNFeFzDx9lmP7Z9bes33woUL1fbt26XcQvsv8RbacGvlS7zty62ve/Sa7+Re8x025DfK74mXePvqGOe1pgLp5uo13xjStfRPAOla+ie2n73mG0e2axOxxBtAvoYaYso3vea7a9cu47gB+qjZyQI2IvHGEu/du3e95huwn0q8wRqVeGOI12u+MYcV3vTQzVBDAAkTb9niTa/5piXVveZLvH8T8ihfj/DZyUFDvOWK9/r1617zDRB+RvWfxBug0Ym3PPF6zXdyQWVUSXbxeeIl3vKsVfAZp9d8FxYWvOYboN81ETLxBgBA4u2/ib3mO90J19fJAojWXA39F+3aM0yv+e7fv9/3cQP2vXFTr8QbAAaJt58iTu1y5MgRwg3Qx8YV7Nu2I94AUBBvv8TrNV/DCsNETbzE2y9rFX426TXf3bt3S7kB+tUweTb5PfEGAETinbytV1ZWvOYboC81keko2xJvAFiId3Li9ZqvYYVRhDv4LPES7+SsVfCRB6/5btu2zbBCgD40jjybbEO8AaCRePMa/MaNG17zDdBvmoiz6bbEGwAg4s0jXq/5GlZoKlxDDQGEO2hE4u1WvOk13xMnTnjNN1CfaUug4+5H4g0AE/F2J16r+Uq548r1XdsRL/F2Z62C9+w1X8LtQriGGgII11BD+2ZPfz189tlnvqkQqH90KdBx9y3xBgDMUENzAa+urlaLi4vV3Nwc6QboE+MKMdd2xBsAMuJtJl6v+RpWyCVcQw0BhGuooZlw02u+H330kYQbqC/kFui4x5N4A0An8Y4mYK/5SrjjCrOt7YiXeEezVsGfTq/5nj171mq+AZhvS4CT2g/xBoBQ4h1+N7h27ZrXfAOwPilRtn1c4g0AI/G+Xbz37t2rDh48aBw3AOdty2+S+yPeAEAS74/F++zZs+r48eNe8w3A9yQF2dWxiTcAmMT7d/Gm1XyXlpYq0zV6gNaVNNvYL/ES7/AB0kI+cfPmzWrfvn2GFQIw3Ybc+rwP4g0A6bQnXtM1Srd9luybzo14ibeQPPvj0xxM1zg7OyvlBuC4NHk2OV/iDQDstCXeNI5rukYpt4n4Jr0t8RJvUYk3Tdc4Pz8v4QbgdtLym+TxiTcAwNOQeB8+fFgdPnyYcAPwOknh9eXYxBsA5MjiffHixd+mazSOa2ihL9Js4zyIl3h7O9Rw6dKlaufOnVJuAEbbkFWkfRBvAKijJd7l5eVq//79hBuAzUiybPNaiDcA3FHEm67j6NGjhBuAyTYlFXFfxBsA8tLFm5bdOXXqlGV3ArAYUZJdXBPxBoC9ZPFadsdDsy7E1vd9Ei/xTuTh2t27d6sDBw4YVgjAX98l18fzI94A4JeUeC27I+H2UYS5z4l4iTdL4k3L7pw5c8ayOwF4yy2piMcj3gAdoe+J17I7Um5EeTa5JuIl3s4Sb1o+3bI7pNtEUFG3JV7ibV28lt0h26jCbOu6iJd4WxNvGse17A7ptiWnyPshXuJtRbxp2Z29e/f6elgAniILry/XRrwBOsokH65ZdkfC7YvMSjoP4iXesRJvWnZnYWHB8ukB+ClJWFHOlXgDdJycideyOxJuFPlN8jqIN4B4Hz16NFZqHXWjtOyO5dOJd5LCinJs4g0g3iTELn8su0O2UYTXl+sg3gDiTVMqdvGTlt05efKkZXcCMNIX4TiP/7uJE2+ATpX+/G/7x7I7Ui5JdscA8QYQb+ogaV7bNn7u3Llj2Z0gTBBnd+JsWlviDdLJ0qKQjx8/Htu9lt3pbydt2slt37+2Jd4g4k2da35+vnr69OlI8h0snz43N+ets0AskG3/ZLu2TYg3WGfbtWtXdevWrXXJ98svv6x2795NuMEYIN1+S9fDtcAdLk3HmMSaVnwY/KSXH9KSO2lC8iRoHbT/HVQbxWwjiTewfHXamJ1Wu5bfrsRLvJIvBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQl4HVd4p38+bN37m7ln931YbaEAP9YaD26rfDEu83Gqw/DaYttAUGymegFu/KsMR7VUOX39DaUBtioD8M1OK9OizxntBg/WkwbaEtMBCCgRPDEu8fNXSIhvbwJO/DE/VW77cyUCfe+XeKd8uWLb8lXuLFAAYw0B4DyavvFO+GDRt+Vhf8uaK3V3S1VEsMTDUDq8mr7xRv+mUNyRdAmWpQ/Nnsz2YMtMfAF0Ol+0q8O4iXeDGAAQy0wsCOdYm3Hgj+ZV3wHxS9laJLDu0lB7VUy9IY+CH5dF3iTR+qP/xn4iVeDGAAA+MzUHv09Lqlmz74/vvv/7uCj19wtVM7DGCgFu9vRhKvh2ygIQ4MYKARA+t7qPa6mWtb/1rhGxW+tPEo52sMFQMtMZD8OXLaHWxQb/wn8iVfDGAAA+tnIHlzbOmmDTdt2vSreidPFH39RVcrtcLA9DKQfJm82Ui8rx60/R5I0wuSttf2GFg/A/UXE37fWLprhhw+Vfz1F1+t1AoD08dAnXY/bU26aUcbN278aQ3SeTBNH0zaXJtjYF0MnE+ebFW8aWezs7M/rxvgfzTCuhrB0+GWng7jDW8FMHA9+bF16a4ZckivE18voBDER3wYwEAOBq6P9FrwuHb+8MMP/6kW70XylUQwgIEpZ+Bi8uG4Lh15u1djvkemvOg57qaOIbVhoJ8MHOlkTHc9Nq4j9gZLwks9bsAYmBYGku+S99bjx04/Uy9r8Yv0NYq68KvTUnzXSTQYmDoGVpPnku86FeqoO69P6F+8Yjx1MPozuJ9/BmuXFtsleS35bVQnZv38zMzMv6V5KCUCEsYABkpmIHks+SyrQJse7NVKFn949Q0IK1q0eAcuGWbnTsY9ZiB5Kn1j6w9ZviLWVLLDtk+rbKYljuuL2VNf1H/V//1L/d9bPW4Af6q5UWAgNgO3Xnko+WhP8tO6VgMeJju/VwEVUAEVUAEVUAEVUAEVUAEVUAEVUAEVUAEVUAEVCF+B/wWXI359gAoiZAAAAABJRU5ErkJggg==");}
.#<uispace> .js-pause{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAV4AAAFeCAYAAADNK3caAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABU/SURBVHhe7d3Ph6VXHsfxrEIYQsgqq2H+gGG2Icwqq6y6ZddJ/9CLbJowhDB/QRZNIkSGYQhZhTCbiCb0KoQwhOhFGLIKQwiRoqPmnJlqutNJ3edWPfdzvvWcV9ES6lad53zv+/s+n/rep+o+8YQPFVABFVABFVABFVABFVABFVABFVABFbh4Fbh69eoL165d+0v79177/y/6v/b/99u/Y//UAAMYCDJw/yEHvde91P108az6K1d86dKlp9qGXmob+nv773fBohK5wwwDGDgLA9+d+Oql7q8LJeJXXnnlj02yH7V/P5KtFIMBDFxQBrq/Puo+Ky3gGzdu/L6dFv+4oEU+y+noa6QqDEzAQPda91spAV+/fv2ZdmG3m3CPSFe6wQAGNsrAUfdc991wAbeLeLFdzPcbLbQ0M0Gawa6DYh8Guu+694bJt13sLXclgHYfaD0WLxthoN+NdSsq38uXLz958sqfRCgRYgAD0zLQPdh9eHABt4Webaa/u5FTa1pgPH+SJwZWY+Bu9+LB5Hvz5s2n2wKfe8JWe8KIX1rEwAYY6F7sflxdvj1ON+HeIV3SxQAGMPCrDNxZfezQjP62Yms4DGAAA7/NQPfkaqm3fbNLiq3hMIABDOxmoPvy3PK9cuXKc+7T3V1sQKoRBjDQGei+7N48l3zbN/kAUIDCAAYwsJyB7s0zi7d98fOKvbzYaqVWGMDAAwa6P88kX/frgohIMICBMzNwd2/xSrtnLrb7MjdwXybZ4H8NBvZOve0LPl5jYd8DwBjAwKwMdI8uTr0nvxbsLXkkN+kdAxg4HwP9LYaW/TpxO536Xx1TcDXAAAYwcH4Glv0VMy+qOXQcvBjAwGoM7H6R7eQNKr1X2vlPOUlBDTGAgc7A0c43zux/Wd1Jt9pJp/E0HgYwcLzzHSvaIPhN4iVeDGAAA+sx0L166t0NrdgfKvh6BVdLtcQABrpXTxWvP3QOEqLAAAbWZaB7dVfi/VbR1y26eqonBqZn4NtdifcHkEwPiReEvCCEgRUZaIn3h12JV8FXLLhDzCGGAQx0BoiXWB2uGMBAmAHiDRdc4pF4MIAB4iVeaQcDGAgzQLzhgks70g4GMEC8xCvtYAADYQaIN1xwaUfawQAGiJd4pR0MYCDMAPGGCy7tSDsYwADxEq+0gwEMhBkg3nDBpR1pBwMYIF7ilXYwgIEwA8QbLri0I+1gAAPES7zSDgYwEGaAeMMFl3akHQxggHiJV9rBAAbCDBBvuODSjrSDAQwQL/FKOxjAQJgB4g0XXNqRdjCAAeIlXmkHAxgIM0C84YJLO9IOBjBAvMQr7WAAA2EGiDdccGlH2sEABoiXeKUdDGAgzADxhgsu7Ug7GMAA8RKvtIMBDIQZIN5wwaUdaQcDGCBe4pV2MICBMAPEGy64tCPtYAADxEu80g4GMBBmgHjDBZd2pB0MYIB4iVfawQAGwgwQb7jg0o60gwEMEC/xSjsYwECYAeINF1zakXYwgAHiJV5pBwMYCDNAvOGCSzvSDgYwQLzEK+1gAANhBog3XHBpR9rBAAaIl3ilHQxgIMwA8YYLLu1IOxjAAPESr7SDAQyEGSDecMGlHWkHAxggXuKVdjCAgTADxBsuuLQj7WAAA8RLvNIOBjAQZoB4wwWXdqQdDGCAeIlX2sEABsIMEG+44NKOtIMBDBAv8Uo7GMBAmAHiDRdc2pF2MIAB4iVeaQcDGAgzQLzhgks70g4GMEC8xCvtYAADYQaIN1xwaUfawQAGiJd4pR0MYCDMAPGGCy7tSDsYwADxEq+0gwEMhBkg3nDBK6ad999///jrr78+/umnn45HfPR1+/r9OkbVRw2k0CR7xDu5eD/55JMRrv3NNfv1JBugr6UGpJtmjngnFu9bb71VSroPLqZfV6oR1IB0U6w9vA7xTizee/fulRRvv65UM6gB8aZYI96JZfvwk390dFRSvP26Us2gBsSbYo14ifd/Yqv8kWoGNSDeFGvES7zEe8IA8RIv8RJi7Edsiff/wqn8MUII1swcRF5cm1j2pEO8RJsR7S/rTLzEW9K/KSGU3PzJRaVqYJ28fImXeEu6JyWDkpsn3ujILcWaF9cmlu3DTz7pGDWMkI41rx1LvBNLmHiJlwTzY4Zec+Il3pL+TQmh5OaNGowaUg1gnfzJSzoSr77L953EO3HadQ+r+3hJd4x0iZd4y4belBTKFqBdWKoG1skL2Ix3YvmSjlED6ealK/FOLF2jBqMG0h0jXeIl3rKhNyWFsgUwatj0qMWoYWL5ko5RQ+qAs86j6Zp4ibekf1ONWnLz7uPddNo1aphYuma8Zrypw806j8+SJd6J5SvtGTWQ4pgX2IiXeEv6NyWEkps3ajBqSDWAdfInL+lIvPou33dmvBOnXTNeM17SHSNd4iXesqE3JYWyBXAf76bHDWa8E8uXdIwaUgecddzHu+mTdB/AiZd49+HFY9cbTUi8Em9J/6aavOTm3dWw+XBEvMRb0j3E689CphgYsQ7xEi/xlqwA8Y4QYmpN4iXektpJNUDJzRs1GDWkGsA66w3ul9aSdLy4tpQVj1u3PyVeibekf1ONXnLzEq/Em2oA66x7oi6pJ+lIvEs48Zj1e1PilXhL+jfV7CU3L/FKvKkGsM76p+qumpKOxLuLEZ8/TF9KvBJvSf+mGr7k5iVeiTfVANY5zMl6Wl1JR+LVd/m+6zWXeCXekv5NCaHk5iVeiTfVANbJn7ykI/Hqu3zfSbwTp93+5Ff+SAlBDcaIJ/X8Vl3HqGFi+ZKOw6eqmLZ+XcRLvCX9m2q8kps34zXjTTWAdfI/8pGOxKvv8n1nxjtx2jXj9WaXpDtGusRLvGVDb0oKZQvQLixVA+vkBWzGO7F8SceogXTz0pV4J5auUYNRA+mOkS7xEm/Z0JuSQtkCGDVsetRi1DCxfEnHqCF1wFnn0XRNvMRb0r+pRi25effxbjrtGjVMLF0zXjPe1OFmncdnyRLvxPKV9owaSHHMC2zES7wl/ZsSQsnNGzUYNaQawDr5k5d0JF59l+87M96J064Zrxkv6Y6RLvESb9nQm5JC2QK4j3fT4wYz3onlSzpGDakDzjru4930SboP4MRLvPvw4rHrjSYkXom3pH9TTV5y8+5q2Hw4Il7iLeke4vVnIVMMjFiHeImXeEtWgHhHCDG1JvESb0ntpBqg5OaNGowaUg1gnfUG90trSTpeXFvKiset258Sr8Rb0r+pRi+5eYlX4k01gHXWPVGX1JN0JN4lnHjM+r0p8Uq8Jf2bavaSm5d4Jd5UA1hn/VN1V01JR+LdxYjPH6YvJV6Jt6R/Uw1fcvMSr8SbagDrHOZkPa2upCPx6rt83/WaS7wSb0n/poRQcvMSr8SbagDr5E9e0pF49V2+7yTeidNuf/Irf6SEoAZjxJN6fquuY9QwsXxJx+FTVUxbvy7iJd6S/k01XsnNm/Ga8aYawDr5H/lIR+LVd/m+M+OdOO2a8XqzS9IdI13iJd6yoTclhbIFaBeWqoF18gI2451YvqRj1EC6eelKvBNL16jBqIF0x0iXeIm3bOhNSaFsAYwaNj1qMWqYWL6kY9SQOuCs82i6Jl7iLenfVKOW3Lz7eDeddo0aJpauGa8Zb+pws87js2SJd2L5SntGDaQ45gU24iXekv5NCaHk5o0ajBpSDWCd/MlLOhKvvsv3nRnvxGnXjNeMl3THSJd4ibds6E1JoWwB3Me76XGDGe/E8iUdo4bUAWcd9/Fu+iTdB3DiJd59ePHY9UYTEq/EW9K/qSYvuXl3NWw+HBEv8ZZ0D/H6s5ApBkasQ7zES7wlK0C8I4SYWpN4ibekdlINUHLzRg1GDakGsM56g/ultSQdL64tZcXj1u1PiVfiLenfVKOX3LzEK/GmGsA6656oS+pJOhLvEk48Zv3elHgl3pL+TTV7yc1LvBJvqgGss/6puqumpCPx7mLE5w/TlxKvxFvSv6mGL7l5iVfiTTWAdQ5zsp5WV9KRePVdvu96zSVeibekf1NCKLl5iVfiTTWAdfInL+lIvPou33cS78Rptz/5lT9SQlCDMeJJPb9V1zFqmFi+pOPwqSqmrV8X8RJvSf+mGq/k5s14zXhTDWCd/I98pCPx6rt835nxTpx2zXi92SXpjpEu8RJv2dCbkkLZArQLS9XAOnkBm/FOLF/SMWog3bx0Jd6JpWvUYNRAumOkS7zEWzb0pqRQtgBGDZsetRg1TCxf0jFqSB1w1nk0XRMv8Zb0b6pRS27efbybTrtGDRNL14zXjDd1uFnn8VmyxDuxfKU9owZSHPMCG/ESb0n/poRQcvNGDUYNqQawTv7kJR2JV9/l+86Md+K0a8Zrxku6Y6RLvMRbNvSmpFC2AO7j3fS4wYx3YvmSjlFD6oCzjvt4N32S7gM48RLvPrx47HqjCYlX4i3p31STl9y8uxo2H46Il3hLuod4/VnIFAMj1iFe4iXekhUg3hFCTK1JvMRbUjupBii5eaMGo4ZUA1hnvcH90lqSjhfXlrLicev2p8Qr8Zb0b6rRS25e4pV4Uw1gnXVP1CX1JB2JdwknHrN+b0q8Em9J/6aaveTmJV6JN9UA1ln/VN1VU9KReHcx4vOH6UuJV+It6d9Uw5fcvMQr8aYawDqHOVlPqyvpSLz6Lt93veYSr8Rb0r8pIZTcvMQr8aYawDr5k5d0JF59l+87iXfitNuf/MofKSGowRjxpJ7fqusYNUwsX9Jx+FQV09avi3iJt6R/U41XcvNmvGa8qQawTv5HPtKRePVdvu/MeCdOu2a83uySdMdIl3iJt2zoTUmhbAHahaVqYJ28gM14J5Yv6Rg1kG5euhLvxNI1ajBqIN0x0iVe4i0belNSKFsAo4ZNj1qMGiaWL+kYNaQOOOs8mq6Jl3hL+jfVqCU37z7eTaddo4aJpWvGa8abOtys8/gsWeKdWL7SnlEDKY55gY14ibekf1NCKLl5owajhlQDWCd/8pKOxKvv8n1nxjtx2jXjNeMl3THSJV7iLRt6U1IoWwD38W563GDGO7F8SceoIXXAWcd9vJs+SfcBnHiJdx9ePHa90YTEK/GW9G+qyUtu3l0Nmw9HxEu8Jd1DvP4sZIqBEesQL/ESb8kKEO8IIabWJF7iLamdVAOU3LxRg1FDqgGss97gfmktSceLa0tZ8bh1+1PilXhL+jfV6CU3L/FKvKkGsM66J+qSeh4dHZX0Tr+uJde/xmPUIM/dGs/bRf8eEu/EiffevXslxduvK9VYakC8KdYeXod4Jxbv7du3S4q3X1eqGdSAeFOsEe/Esv0lZJ9++mkp+fbrSTeCGpBvmjmJl4SP33nnneNvvvnm+Oeffx4m4b5+v450AzxYTw3IN8ke8RLvMNklQbcWsVZigHiJl3gxgIEwA8QbLnilU9e1SIEYGMMA8RKvtIMBDIQZIN5wwSWMMQlD3dW9EgPES7zSDgYwEGaAeMMFr3TquhYpEANjGCBe4pV2MICBMAPEGy64hDEmYai7uldigHiJV9rBAAbCDBBvuOCVTl3XIgViYAwDxEu80g4GMBBmgHjDBZcwxiQMdVf3SgwQL/FKOxjAQJgB4g0XvNKp61qkQAyMYYB4iVfawQAGwgwQb7jgEsaYhKHu6l6JAeIlXmkHAxgIM0C84YJXOnVdixSIgTEMEC/xSjsYwECYAeINF1zCGJMw1F3dKzFAvMQr7WAAA2EGiDdc8EqnrmuRAjEwhgHiJV5pBwMYCDNAvOGCSxhjEoa6q3slBoiXeKUdDGAgzADxhgte6dR1LVIgBsYwQLzEK+1gAANhBog3XHAJY0zCUHd1r8QA8RKvtIMBDIQZIN5wwSuduq5FCsTAGAaIl3ilHQxgIMwA8YYLLmGMSRjqru6VGCBe4pV2MICBMAPEGy54pVPXtUiBGBjDAPESr7SDAQyEGSDecMEljDEJQ93VvRIDxEu80g4GMBBmgHjDBa906roWKRADYxggXuKVdjCAgTADxBsuuIQxJmGou7pXYoB4iVfawQAGwgwQb7jglU5d1yIFYmAMA8RLvNIOBjAQZoB4wwWXMMYkDHVX90oMEC/xSjsYwECYAeINF7zSqetapEAMjGGAeIlX2sEABsIMEG+44BLGmISh7upeiQHiJV5pBwMYCDNAvOGCVzp1XYsUiIExDBAv8Uo7GMBAmAHiDRdcwhiTMNRd3SsxQLzEK+1gAANhBog3XPBKp65rkQIxMIYB4iVeaQcDGAgzQLzhgksYYxKGuqt7JQaIl3ilHQxgIMvA0anivXr16g+VTgnXIrVgAAMXnYHm1f/sSrzfXvRNun6NigEMVGKgifffuxLv55Uu2LVoIAxg4KIz0MT7+a7E++FF36Tr16gYwEAxBj7clXjfLHbBXgTIvgig3uqNgZUZaIn3r6eK9/r16y8Sr7SAAQxgYD0GuldPFe+lS5eeagX/UdHXK7paqiUGpmbgqHv1VPH2TzZI7gJlalD8qLnyj5r6aep+urtTuifivQWUqUEhXuLFwHoM3Fok3jYIfraJ9z75ki8GMICBczFwv/t0kXj7g9qD/6ng5yq4xLBeYlBLtbyQDDSPfrxYuv2Br7766p+Jl3gxgAEMnJ2BJt4X9hKvF9nOXmygqh0GMNBvUthbuifjhucBBCAMYAAD+zPQ0u7zZxLviXw/UPT9i65maoaBeRlo0v3gzNLtX3jlypXn2jf5HkTzQuS599xjYDkD3Zfdm+cS78kLbS8r/PLCq5VaYWBeBtqNCS+fW7oPvkGz+Ntgmhcmz73nHgO7GeieXE26/Rtdvnz5yVb4O4q/u/hqpEYYmJKBO92Tq4q3f7ObN28+3YD6F6imhOpC3sCOVayGGPiy+3F16T40cui/TvxlaDOa3W8sYQAD1Rn4cq9fCz6rnV977bXfNfF+Rr7SBAYwMDkDn3UfntWle3/dycz33cmLXv0kdn3SIgYOx8C7B5npLrFxi9iXvCW81OMAxsAsDHTfde8t8eNBH9Pe1uKZk9vNjmYpvn0SDQamY+Coe6777qBC3febtwv6Q/9VOUBOB6QfZw/346zaFqht91r3275OjD7+xo0bf+p/h5KACRgDGLjIDHSPdZ9FBXrexU7eyeL1kzsgvKNFgZP7IjeBayfxAAPdU/2Ordcjt4idV7K7vr6/y2Z/i+O2mTfapv7W/vtF++9XgUL6UY3wMYCBX2PgqxMPdR+90f206N2Ad8nO51VABVRABVRABVRABVRABVRABVRABVRABVRABVRABTZfgf8CGR0eAYmNuzMAAAAASUVORK5CYII=");}
.#<uispace> .js-loading{background-image:url("data:image/png;base64,R0lGODlhGgAaAOZTAPz8/PLy8u3t7fDw8PX19fn5+fr6+v39/ff399ra2vj4+LS0tPv7+4+Pj2lpaf7+/vT09O/v7+7u7sHBweDg4OXl5erq6pWVlfPz85CQkOTk5Lm5ucrKytzc3KOjo7GxsXJycq2trdbW1t3d3cnJyejo6Obm5tTU1KysrJaWltDQ0MfHx4WFhbCwsGpqauPj49/f39fX1+vr65KSkqqqqmtra7+/v/b29tLS0np6eqKiooSEhJGRkcDAwJubm7W1tdXV1a6urs/Pz7y8vOLi4pSUlKurq9vb23FxccTExMjIyIODg6WlpYeHh8PDw9HR0eHh4fHx8ezs7P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpENjdBNEJEODc5RDNFMDExQUU0NkQ5MkQ0QkJCOTZDQSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyMkZEQjVEQ0U4RDMxMUUwQjI1NUZDMjA5MkZGQ0VFRiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyMkZEQjVEQkU4RDMxMUUwQjI1NUZDMjA5MkZGQ0VFRiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5NzY0Rjk1OUNDRThFMDExQkQyOThDMjVCRjJEQTlBMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpENjdBNEJEODc5RDNFMDExQUU0NkQ5MkQ0QkJCOTZDQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAUKAFMALAAAAAAaABoAAAf/gFOCgwcwg1MXGYcGh42HHx4Cgy4OgwADAY6OEw1BDIKUg1FSBJqNUYlHgiCVUwVSAgemjSoNHghTrFMPA1K4piWLHg0qiIoIUgONBQWDC0qZgkQ+SYcEEoyCDKPKghsLC0CfUxSO2VMEUrAKgwwn4BMK7KYHEeoQmgEcJBgYswBRAgCYNSUawYEEExKs0KFDggQVFAoKIECAugAvHj58IXHKKHVSonQcOYgZSUfbkhE0aSrdOoK9oowjZE8KPkHnBjFSYJHUIYACLWE6FGAAQgjqIsgShFCUzwAi04lkCrXpMliy1E05YLGZJVO8fAnSOgXZgAcKzQ6yOKjXL4LXDc6xxSmhlMKcUBdpCgQAIfkECQoAUwAsAAAAABQADgAAB4aAU4KDDxaDUy0ohycAh4IcExiDGQ2DJjspjlMiCySNU5SCBkUOIZo3Gz8lgheVU0I1IAKaUzALEwVTrVMQLA49gxCHABMLFIiKEw4sCoMJGs2CMkMxhx851YMdCQkWB4KGjiKOBxbcFAwMtOsKFdDR67Tw8fT1AQICUlIB9YNR+vqi9BMUCAAh+QQJCgBTACwAAAAAGgAaAAAHtIBTgoNTBIQcK4QwB4SNgxUUBYMLC4MCHh+OjhYJGg+ClIIMQQ0Tmo0MHQkYghuVU0cZF1GnjQMJFABTrlMIHg0qtZKDDxQJA1OIUyoNHgaEOE+DUlEMgwQjMoRJPkSDGjwOTZZSUoaC54QUggpGDg5IJIQQ5REHjKcDS+80Co4AAaIA0HXKxIwUFWpNIagwocKHCgMIEFAuAMRTUcqVo3Wxo8ePIEOKHEmypMmTKFOqXDkoEAAh+QQJCgBTACwAAAAAGgAaAAAH/4BTgoNTBoQVL4QWD4SNgwEDAIMJCYMYExyOjgRSUZOVUwAkCyKajQcCUgWCHaAlPxs3po0IUgOMrVMFEwsws6uEA1IIU4hTFAsTkoMjI4OdDIMGEgSEMUMygxYhDUyDqVLVgoaNFoK7DQ0XpYMQUlIRBwezGDrpNsCEAAFRAMuaUkJ8kDIrVEFBBA8qNBVAALgAC6dcAAHChYsLUd6987Qwg4OPDjJEHDmoQD6SgxhkHFDQ5CxOUgQoKCgsSjRCByK8gyDNkSEF4MQJAhAlwD8AAyA+iiTIHbx5QxtlrMZvCieOofj9a1Qg5rx3U1Cp0mfqgTBiU8BOqXVLIdtvCRSnnFVIQAK5KamkUVt4d0rVno4CAQAh+QQJCgBTACwAAAAAGgAaAAAH/4BTgoNTBoQBUYQEhIyHAwCDUlKDBRQVjY0EUomCkoIPGgkWmIwHAlIFgqeCGAkdDKSMCFIDD1OrABQJA7GphANSCFOIUwMJFLaDJSWRUbCCBhKLgzIj08NKC06Dp1LXhozTDEALCxsahBCSEQcHsQoT5SfPhACIAJCkGCQcAbFT+f75+0dQoIBuAwu2uHAhQ4YWUSRJ4lQQRYOLDVAU3IipgC+OjRhE5BXrCY5YmqQIUPCviQMe6AgdiCAJwiBwhAyRQOLAgRGWggBECRAQwICEwx5NUUCj5xKSABlFXERME8UKKWaYIFVApTtPplARuoTpATBhUzxNmVWrIFtukxMEnS1IQALOVdCkbcQ5jGIhTIEAACH5BAkKAFMALAAAAAAaABoAAAf/gFOCg1MGhAFRhIaEjIMBAwCDUlKDAAMBjY0EUomCk4NRUgSZjAcCUgWCp4IFUgIHpIwIUgMPU6sPA1IIsamEuryIU7MDjBAYklEMgwYSo4MEEotTChoJUIOnosyNiwcWCQkdnYIQkxEHsKQMFOEW6oQAiACRpNUVCrFT9fr5+v/6AgjQhgngFA4bNixYwCHUJE4Gp6xYuHBFxIuDCvjCSIhBqGKxRoyItcmVP1JMGoSwUCrCJAjc4p2YIuJCgwYTNgKIEoCfpYKCUuwwMaWAjZs6kAniJyjUKGEhHBRZJOVDCEqZWr2a8kkAiBpCCGFtlGuXJ6w9HLCA+Y9YNqwKFlg4mAAw2rRVgmLk+GBw2hRhg0RkCgQAIfkEBQoAUwAsAAAAABoAGgAAB/+AU4KDUwaEAVGEhoSMgwEDAINSUoMAAwGNjQRSiYKTg1FSBJmMBwJSBYKnggVSAgekjAhSAw9Tqw8DUgixqYS6vIhTswOMBb5TnAyDBhKjgwQSi1MMocWqk8+FjdObrgqEEJMRB7CkBxGTEJkAiACRpABRAfDxsZX3+fkBAqdSmPqmVOjQIUGCCqEmcQo45YVBgy8YShx0bGKjarTulSgRy5sAcLGcLFACcBA6dcxKwZiiYcOCBUCWCZJHr9IlQh88CKB24uUEkFPqCQo16kKGKRMaBJEZgAMJDKRavZriwsGUKEaPHCKVa5egqoJUNPDAKx+xQSCsFvLQQIW+aNMP0g4i4iNJwGlTjBKikCkQACH5BAkKAFMALAYADAAUAA4AAAeHgFOCg4SEAQICUlIBhY2DUYqKUY6UlZaXjhgQmI1QCRoKjicAhA8WU1EdCQkWB4QmOymEHBMYUwcWqxQMggZFDiFTLShTIgskpFMKFaCCQjUgAlMZDVM3Gz8lhKFTECwOPYLUgjALEwWNEw4s3BfVUwATCxSNHzkxg+6DMkP4jSKEhhE61SgQACH5BAkKAFMALAAAAAAaABoAAAezgFOCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmHAQICUlIBlFGfn1GahjhPlho8Dk2KBQWICkYODkgkigNSUQyFA0u2NAqCMAeFBFMKnlLJgyYzKRWDAh4fhBUUslMQnxHHgtODDEENE1McK1MWCRoPggABUQCIRxkXpgsLUwwdCRiE6B1C4KGBCkH6BA1IQEGgIhUNPBgQtGHflAcUEgxglMQHkUEVBxEYIaMRBULpCDkrFAgAIfkECQoAUwAsAAAAABoAGgAAB/+AU4KDUwaEAVGEhoSMgwEDAINSUoMAAwGNjQRSiYKTg1FSBJmMBwJSBYKnggVSAgekjAhSAw9Tqw8DUgixqYS6vIhTswOMBb5TnAyDBhKjgwQSi1MMocWqk8+FjdObrgqEEJMRB7CkBxGTEJkAiACRpABRAfDxsZX3+fkXICAuLhf0CQog4JSUABkcKHSQQeCUUJM4OZw4aMQIio0shGjA5N4xUgUmNGhwQcQ9XVGWEcKgY6QNXxZsKZqiwKC2ZCE+UBKEYQKHQ5AEiZNCThIhACQWmKzwYsqmTlPaRanHqMSPDTemJEgwxRSqoyAnLIAhaKsgYjLvUVgwAV4HroITgOmLMUTGoLfMnAm0QIjpzEaBAAAh+QQJCgBTACwAAAAAGgAaAAAH/4BTgoNTBoQBUYSGhIyDAQMAg1JSgwADAY2NBFKJgpODUVIEmYwHAlIFgqeCBVICB6SMCFIDD1OrDwNSCLE4jLq8iFOzA4wFqYIOPBqDBhKjgwQSi1MMocWCSA4ORgqC1M3RkwLeggo020sD2JkHEZMQmRUpMyYmsQBRAZGxFbGV/wIGbHHhQoYMLQQKCiDglJQAKBpIbIBC4ZRQkzhZ3DioRAmOjQIoWeDk3zFSDIAsWLCBWSxdURgwUjBh5QmZU6ApmqLAoc4pGEhwwMSKgj9HkARBmBQB1kJCDzQksDBF2KZOUwAg4tcIQ4IOMj+ZQkWIKyMAFBJg+zSMlq2AAxYSUHi7ShAwgTJG6Kxb6JnCn8LCNQoEACH5BAUKAFMALAAAAAAaABoAAAf/gFOCgwAng1MBUYcGh42HKTsmg1JShAMBjo4hDkWMU5SDUVIEmY0CIDVCggKVUwVSAgeljT0OLBBTrFMPA1IIsyOHCiwOE4iKCFIDjQUFgw0hFoMxOR+HBBKeUwyiy4IXDQ0TzlMijtoElAIKgwU24ToYGLMHEZS4jlIfIaClAFEBAMz6NFCQwIIIS3HYsGHBAg4JEQlgJSXACocOV0QURUmKooggBUGYF7KRAg0JoAxsVuqAhQQJOnws1SsKg0YMKMC0IGuKtkGMFFAkNehkBXYGLx0KMOAgBEoRek5BGmrUsSnpZgJIdNDRq1ifKh1gRc5gKV6+BPVLNuABQraDFHQJ6vWrIDZtcn1KIFrwZ6JFmQIBADs=")}
<div>
<marquee class="z-ttl"></marquee>
<div class="z-act js-play">&nbsp;</div>
</div>
/*
* ------------------------------------------
* 音频播放器实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/audio/audio */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/event',
'ui/base',
'util/media/audio',
'util/template/tpl',
'text!./audio.css',
'text!./audio.html'
],function(NEJ,_k,_e,_v,_u,_t0,_t1,_css,_html,_p,_o,_f,_r){
// variable declaration
var _pro,
_seed_css = _e._$pushCSSText(_css),
_seed_html= _t1._$addNodeTemplate(_html);
/**
* 音频播放器
*
* @class module:ui/audio/audio._$$AudioPlayer
* @uses module:util/audio/audio._$$MediaAudio
* @extends module:ui/base._$$Abstract
* @param {Object} config - 可选配置参数
* @property {String} url - 音乐地址
* @property {String} title - 音乐标题
* @property {Boolean} autostart - 自动开始播放
*/
/**
* 状态变化事件
*
* @event module:ui/audio/audio._$$AudioPlayer#onstatechange
* @param {Object} arg0 - 事件对象
*/
_p._$$AudioPlayer = _k._$klass();
_pro = _p._$$AudioPlayer._$extend(_u._$$Abstract);
/**
* 初始化外观信息
*
* @protected
* @method module:ui/audio/audio._$$AudioPlayer#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
this.__seed_html= _seed_html;
};
/**
* 初始化节点
*
* @protected
* @method ui/audio/audio._$$AudioPlayer#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
var _child = _e._$getChildren(this.__body);
this.__nttl = _child[0];
this.__nact = _child[1];
_v._$addEvent(this.__nact,'tap',
this.__onAction._$bind(this));
};
/**
* 控件重置
*
* @protected
* @method ui/audio/audio._$$AudioPlayer#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__nttl.innerHTML = _options.title||'音乐标题';
this.__audio = this.__getAudio(_options.url);
};
/**
* 控件销毁
*
* @protected
* @method ui/audio/audio._$$AudioPlayer#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
if (!!this.__audio)
this.__audio = this.__audio.constructor
._$recycle(this.__audio);
};
/**
* 操作事件
*
* @protected
* @method ui/audio/audio._$$AudioPlayer#__onAction
* @return {Void}
*/
_pro.__onAction = function(){
_e._$hasClassName(this.__nact,'js-play')?this._$play():this._$pause();
};
/**
* 返回音频对象
*
* @protected
* @method ui/audio/audio._$$AudioPlayer#__getAudio
* @param {String} arg0 - 音频URI
* @return {Object} 音频对象
*/
_pro.__getAudio = function(_source){
return _t0._$$MediaAudio._$allocate({url:_source,
onstatechange:this.__onStateChange._$bind(this)});
};
/**
* 音频控件状态变化回调事件
*
* @protected
* @method ui/audio/audio._$$AudioPlayer#__onStateChange
* @param {Event} arg0 - 事件对象
* @return {Void}
*/
_pro.__onStateChange = (function(){
var _state_list = ['js-play','js-loading','js-pause'],
_state_str = _state_list.join(' ');
return function(_event){
this.__state = _event.state;
_e._$replaceClassName(this.__nact,_state_str,
_state_list[_event.state]||_state_list[0]);
this._$dispatchEvent('onstatechange',_event);
};
})();
/**
* 播放音乐
* @method ui/audio/audio._$$AudioPlayer#_$play
* @return {Void}
*/
_pro._$play = function(){
if (!!this.__audio)
this.__audio._$play();
};
/**
* 暂停播放
*
* @method ui/audio/audio._$$AudioPlayer#_$pause
* @return {Void}
*/
_pro._$pause = function(){
if (!!this.__audio)
this.__audio._$pause();
};
/**
* 停止播放
*
* @method ui/audio/audio._$$AudioPlayer#_$stop
* @return {Void}
*/
_pro._$stop = function(){
if (!!this.__audio)
this.__audio._$stop();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
.#<uispace> .m-pre, .#<uispace> .m-play, .#<uispace> .m-next, .#<uispace> .m-cur, .#<uispace> .m-pause, .#<uispace> .m-volmin,
.#<uispace> .m-volminc, .#<uispace> .m-shuffled, .#<uispace> .m-repeatd-1, .#<uispace> .m-shufflec, .#<uispace> .m-repeatd, .#<uispace> .m-repeatc,
.#<uispace> .m-volmax, .#<uispace> .m-volmaxc{background:url(#<root>audio_sprite.png) no-repeat 9999px 9999px;}
.#<uispace> .m-player{height:40px;min-width:530px;background:#606060;cursor:default}
.#<uispace> .m-player .ctl{width:300px; float:left;}
.#<uispace> .m-pre{height:10px;width:16px;background-position:0 0;float:left;margin-top:14px;margin-left: 10px;}
.#<uispace> .m-pre:active, .#<uispace> .m-preatv{background-position:-104px -1px;}
.#<uispace> .m-play{height:11px;width:10px;background-position:2px -28px;float:left;margin:14px 20px 0;}
.#<uispace> .m-play:active{background-position:-202px -36px;}
.#<uispace> .m-pause{height:11px;width:10px;background-position:0 -96px;float:left;margin:14px 20px 0;}
.#<uispace> .m-pause:active{background-position:-155px -36px;}
.#<uispace> .m-next{height:10px;width:16px;background-position:0 -61px;float:left;margin-top:14px;}
.#<uispace> .m-next:active, .#<uispace> .m-nextatv{background-position:-103px -81px;}
.#<uispace> .m-player .loop{width:120px;float:right}
.#<uispace> .m-curtime{float: right;margin-right: 10px;color:#fff;line-height: 40px;}
.#<uispace> .m-time{float: left;margin-left: 10px;color:#fff;line-height: 40px;}
.#<uispace> .m-player .timeline{height:25px;position:absolute;left:315px;right:120px;bottom:0;top:0;width:135px;padding-top:15px;}
.#<uispace> .m-vol{height:27px;width:90px;padding:13px 0 0 20px;float:left;}
.#<uispace> .m-volicn{width:20px;height:20px;margin:10px 0 0 10px;float:left}
.#<uispace> .m-vzero .m-volminc{background-position:0 -354px;width:100%;height:100%;float:left;}
.#<uispace> .m-vmin .m-volminc{background-position:0 -124px;width:100%;height:100%;float:left;}
.#<uispace> .m-vmax .m-volminc{background-position:0 -155px;width:100%;height:100%;float:left;}
.#<uispace> .m-timeline{position:absolute;width:100%;height:8px;border-radius:4px;background:#3b3b3b;border-top:1px solid #212121;border-bottom:1px solid #636363}
.#<uispace> .m-timelinei{width:0%;}
.#<uispace> .m-timeline-1{margin-top:0px;width:90px;position:absolute;}
.#<uispace> .m-progress{background:green;margin-top:-1px;}
.#<uispace> .m-cur{position:absolute;right:-5px;margin-left:-5px;background-position:0 -302px;height:10px;width:10px;}
.#<uispace> .m-cur2{position:absolute;right:-5px;margin-left:-5px;background:url(#<root>audio_sprite.png) no-repeat 9999px 9999px;width:10px;background-position:0 -302px;}
.#<uispace> .m-cur:active, .#<uispace> .m-cur2:active{background-position:0 -328px;}
.#<uispace> .m-shuffled{background-position:0 -262px;}
.#<uispace> .m-shufflec{background-position:-56px -115px;}
.#<uispace> .m-repeatb, .m-repeatb-1, .m-shuffleb{height:22px;width:32px;float:right;margin:10px 10px 0 0 }
.#<uispace> .m-repeatd{background-position:0 -187px;}
.#<uispace> .m-repeatd-1{background-position:0 -225px;}
.#<uispace> .m-repeatc{background-position:-56px -149px;}
.m-cnt{width:600px;position: relative;}
<div class="m-cnt">
<div class="cse">
<div class="m-player">
<div class="ctl">
<span class="f-ib m-pre" data-name="pre">&nbsp;</span>
<span class="f-ib m-play ztag" data-name="play">&nbsp;</span>
<span class="f-ib m-next" data-name="next" value="next">&nbsp;</span>
<div class="m-vol">
<div class="f-ib m-timeline m-timeline-1 vtag">
<div class="f-ib m-timeline m-progress m-timeline-1 vtag">
<span class="f-ib m-cur2 vtag">&nbsp;</span>
</div>
</div>
</div>
<span class="m-volicn ztag m-vmax f-ib">
<span class="f-ib m-volminc">&nbsp;</span>
</span>
<span class="m-curtime ztag">00:00</span>
</div>
<div class="timeline">
<div class="m-timeline ttag">
<div class="m-timeline m-progress ttag m-timelinei">
<span class="m-cur ttag">&nbsp;</span>
</div>
</div>
</div>
<div class="loop">
<span class="m-time ztag">00:00</span>
<span class="m-repeatb m-repeatd ztag" data-name="mode">&nbsp;</span>
</div>
</div>
</div>
</div>
/*
* ------------------------------------------
* 音频播放器实现文件
* @version 1.0
* @author cheng-lin([email protected])
* ------------------------------------------
*/
/** @module ui/audio/mp3 */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/event',
'ui/base',
'base/config',
'util/slider/slider.simple',
'util/media/playlist',
'util/audio/audio',
'util/template/tpl',
'text!./mp3.css',
'text!./mp3.html'
],function(NEJ,_k,_e,_v,_u,_c,_t0,_t1,_t2,_t3,_css,_html,_p,_o,_f,_r) {
var _pro,
_seed_css = _e._$pushCSSText(_css,{root:_c._$get('root')}),
_seed_html= _t3._$addNodeTemplate(_html);
/**
* 音频播放器
*
* @class module:ui/audio/mp3._$$MP3Player
* @uses module:util/slider/simple._$$SimpleSlider
* @uses module:util/media/playlist._$$PlayList
* @extends module:ui/base._$$Abstract
* @param {Object} config - 可选配置参数
* @property {String|Node} parent - 父节点
* @property {String} mode - 播放模式,0:列表(默认),1:单曲,2:随机
* @property {Array} list - 歌曲列表
* @property {Boolean} autostart - 是否自动开始,0:不自动,1:自动(默认)
*/
_p._$$MP3Player = _k._$klass();
_pro = _p._$$MP3Player._$extend(_u._$$Abstract);
/**
* 重置控件
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__reset
* @param {Objec} _options - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__vslide.value = _options.volnumber||100;
this.__autostart = _options.autostart === 0 ? !1 : !0;
this.__doInitDomEvent([
[this.__body,'click',this.__onAction._$bind(this)]
]);
if (!this.__volSlider){
this.__volSlider = _t0._$$SimpleSlider._$allocate(this.__vslide);
}
this._$refreshList(_options);
};
/**
* 销毁控件
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__doClearComponent();
this.__super();
};
/**
* 初始化播放器结构
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
/**
* 初始化结构
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
// 0 - 播放按钮
// 1 - 小音量
// 2 - 当前播放时间
// 3 - 歌曲总时长
// 4 - 歌曲播放模式
var _list = _e._$getByClassName(this.__body,'ztag'),
_vlist = _e._$getByClassName(this.__body,'vtag'),
_tlist = _e._$getByClassName(this.__body,'ttag');
this.__nplay = _list[0];
this.__nvol = _list[1];
this.__nctime = _list[2];
this.__nstime = _list[3];
this.__nmode = _list[4];
this.__vslide = {
track:_vlist[0],
thumb:_vlist[2],
progress:_vlist[1],
onslidestop:this.__onVolSlideStop._$bind(this)
};
this.__tslide = {
track:_tlist[0],
thumb:_tlist[2],
progress:_tlist[1],
value:0,
onslidestop:this.__onTimeSlideStop._$bind(this)
};
};
/**
* 播放器点击事件
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onAction
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__onAction = function(_event){
var _action;
var _node = _v._$getElement(_event,function(_node){
_action = _e._$dataset(_node,'name');
return !!_action;
});
if (!_node) return;
if (_action == 'mode'){
this.__doModeChange();
}
if (!this.__audio) return;
this.__autostart = !0;
if (_action == 'pre'){
this.__onPre();
}else if (_action == 'play'){
this.__onPlay();
}else if (_action == 'next'){
this.__onNext();
}
};
/**
* 更新音量大小图标
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onVolumeChange
* @return {Void}
*/
_pro.__onVolumeChange = (function(){
var _map = ['m-vmax','m-vmin','m-vzero'],
_old = _map.join(' ');
return function(_event){
this.__volSlider._$setPosition(_event.volume/this.__vslide.value);
var _value = _event.volume;
if (_value == 0){
_value = 2;
}else if (_value < 50){
_value = 1;
}else{
_value = 0;
}
_e._$replaceClassName(this.__nvol,_old,_map[_value]);
};
})();
/**
* 播放模式切换
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__doModeChange
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__doModeChange = function(_event){
var _mode = this.__playlist._$getPlayMode();
this.__playlist._$setPlayMode((_mode+1)%3);
};
/**
* 切换前一首
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onPre
* @return {Void}
*/
_pro.__onPre = function(){
this.__playlist._$prev();
};
/**
* 播放或暂停
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onPlay
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__onPlay = function(_event){
if (!!this.__audio){
var _pause = _e._$hasClassName(this.__nplay,'m-play');
if (_pause){
this.__audio._$play();
}else{
this.__audio._$pause();
}
}else{
this.__playlist._$play();
}
};
/**
* 切换下一首
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onNext
* @return {Void}
*/
_pro.__onNext = function(){
this.__playlist._$next();
};
/**
* 播放状态更新
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onStateChange
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__onStateChange = function(_event){
var _state = _event.state;
if (_state == 2){
_e._$replaceClassName(this.__nplay,'m-play','m-pause');
}else{
_e._$replaceClassName(this.__nplay,'m-pause','m-play');
}
if (_state == 0 || _state == 4){
this.__onTimeUpdate({current:0,duration:0});
}
if (_state == 4){
this.__playlist._$autoNext();
}
};
/**
* 更新时间轴
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onTimeUpdate
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__onTimeUpdate = function(_event){
if (!this.__timeSlider)
this.__timeSlider = _t0._$$SimpleSlider._$allocate(this.__tslide);
// 播放第二首的current有问题
var _current = _event.current,
_duration = _event.duration;
if (parseInt(_current) === 0){
this.__nctime.innerHTML = '00:00';
this.__nstime.innerHTML = this.__doFormatSecond(_duration);
}
this.__nctime.innerHTML = this.__doFormatSecond(_current);
var _played = _current / (_duration ? _duration : 1);
this.__timeSlider._$setPosition(_played);
};
/**
* 格式化秒为小时或分钟
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__doFormatSecond
* @param {Number} _second - 秒数
* @return {String} 格式化好的时间
*/
_pro.__doFormatSecond = function(_second){
var _hour = parseInt(_second/3600),
_min = parseInt((_second%3600)/60),
_sec = parseInt(_second%60);
_min = _min > 9 ? _min : '0' + _min;
_sec = _sec > 9 ? _sec : '0' + _sec;
return (_hour > 0 ? _hour + ':' : '') + _min + ':' + _sec;
};
/**
* 设置播放时间
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onTimeSlideStop
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__onTimeSlideStop = function(_event){
if (!this.__audio._$duration()) return;
var _value = _event.ratio;
this.__audio._$seek(_value * this.__audio._$duration());
};
/**
* 设置音量
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onVolSlideStop
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__onVolSlideStop = function(_event){
var _value = _event.ratio;
_value = _value * this.__vslide.value
if (!!this.__audio){
this.__audio._$volume(_value);
}else{
this.__onVolumeChange({volume:_value});
}
};
/**
* 更新播放模式
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onModeChange
* @param {Event} _event - 事件对象
* @return {Void}
*/
_pro.__onModeChange = (function(){
var _map = ['m-repeatb m-repeatd','m-repeatb-1 m-repeatd-1','m-shuffleb m-shuffled'],
_old = _map.join(' ');
return function(_event){
_e._$replaceClassName(this.__nmode,_old,_map[_event.mode]);
};
})();
/**
* 多媒体状态改变
*
* @protected
* @method ui/audio/mp3._$$MP3Player#__onMediaChange
* @param {Object} _options - 配置信息
* @param {Event} arg0 - 事件对象
* @return {Void}
*/
_pro.__onMediaChange = function(_options,_event){
if (_event.index < 0){
if (!!this.__audio){
this.__audio = this.__audio._$recycle();
}
this.__onTimeUpdate({current:0,duration:0});
this.__onStateChange({state:0});
if (!!this.__timeSlider){
this.__timeSlider = this.__timeSlider._$recycle();
}
return;
}
var _url = _event.list[_event.index];
if (!this.__audio){
var _volume = this.__volSlider._$getPosition() * this.__vslide.value;
this.__audio = _t2._$audio({
preload:_options.preload||false,
volume:_volume,
onstatechange:this.__onStateChange._$bind(this),
ontimeupdate:this.__onTimeUpdate._$bind(this),
onvolumechange:this.__onVolumeChange._$bind(this)
});
}
this.__audio._$source(_url);
if (this.__autostart){
setTimeout(function(){
this.__audio._$play();
}._$bind(this),0);
}
};
/**
* 指定播放歌曲
*
* @method ui/audio/mp3._$$MP3Player#_$playByIndex
* @param {Number} arg0 - 歌曲列表的下标,默认为0
* @return {Void}
*/
_pro._$playByIndex = function(_index){
_index = _index || 0;
this.__autostart = !0;
this.__playlist._$setPlayIndex(_index);
};
/**
* 开始播放
*
* @method ui/audio/mp3._$$MP3Player#_$play
* @return {Void}
*/
_pro._$play = function(){
this.__autostart = !0;
this.__playlist._$play();
};
/**
* 刷新播放列表
*
* @method ui/audio/mp3._$$MP3Player#_$refreshList
* @param {Object} arg0 - 配置信息
* @property {Array} mode - 歌曲播放模式
* @property {Array} list - 歌曲列表
* @return {Void}
*/
_pro._$refreshList = function(_options){
var _mode = _options.mode||0,
_list = _options.list||[];
if (!this.__playlist){
this.__playlist = _t1._$$PlayList._$allocate({
mode:_mode,
list:_list,
onmodechange:this.__onModeChange._$bind(this),
onmediachange:this.__onMediaChange._$bind(this,_options)
});
}else{
this.__autostart = !0;
this.__playlist._$setPlayMode(_mode);
this.__playlist._$setPlayList(_list);
}
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>audio测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
div{-webkit-user-select:none;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit audio test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="id-box"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./audio.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("audio");
//开始单元测试
test('audio',function(){
expect(0);
var _audio = nej.ui._$$AudioPlayer._$allocate({
parent:document.getElementById('id-box'),
title:'Track01',
url:'http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',
onstatechange:function(_event){
}
});
setTimeout(function(){
_audio._$play();
},500);
// _audio._$pause();
// _audio._$stop();
// _audio._$play();
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}audio.test.js',['ui/audio/audio'],f);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>mp3测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit mask test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="box" class="box"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./mp3.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("ui-mp3");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui');
//开始单元测试
test('mp3',function(){
expect(0);
// var _mp3 = _p._$$MP3Player._$allocate({
// parent:'box',
// list:[]
// });
// _mp3 = _p._$$MP3Player._$recycle(_mp3);
var _mp3 = _p._$$MP3Player._$allocate({
parent:'box',
mode:1,
list:['http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',
'http://www.zhlongyin.com/UploadFiles/xrxz/2012/2/201202201555569985.mp3']
});
// setTimeout(function(){
// _mp3._$refreshList({
// list:[]
// });
// }._$bind(this),5000);
// 2秒后开始播放
// setTimeout(function(){
// _mp3._$play();
// }._$bind(this),2000);
// 5秒后切换歌曲列表
// setTimeout(function(){
// _mp3._$refreshList({
// list:['../../../qunit/res/海阔天空 - 豆瓣FM.mp3',
// '../../../qunit/res/开始懂了 - 豆瓣FM.mp3']
// });
// }._$bind(this),3000);
// setTimeout(function(){
// _mp3._$play();
// },5000)
// setTimeout(function(){
// _p._$$MP3Player._$recycle(_mp3);
// }._$bind(this),10000);
// setTimeout(function(){
// var _mp3 = _p._$$MP3Player._$allocate({
// parent:'box',
// mode:0,
// list:['../../../qunit/res/开始懂了 - 豆瓣FM.mp3']
// });
// }._$bind(this),15000);
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}mp3.test.js',['ui/audio/mp3'],f);
});
/*
* ------------------------------------------
* UI控件基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/base */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/util',
'util/event',
'util/template/tpl'
],function(NEJ,_k,_e,_u,_t,_t0,_p,_o,_f,_r){
var _pro;
/**
* UI控件基类,框架及项目中所有涉及UI的控件均继承此类
*
* 脚本举例
* ```javascript
* // 分配控件实例
* NEJ.define([
* 'ui/base'
* ],function(_i,_p,_o,_f,_r){
* var ctrl = _i._$allocate({
* clazz:'xxx',
* parent:document.body
* });
* ctrl._$appendTo(document.body);
* // 如果在分配时传入了parent则这步可省略
* ctrl._$appendTo(function(_body){
* // 如果需要自定义body插入的位置可以输入函数,返回父容器节点
* _parent.insertAdjacentElement('afterBegin',_body);
* return _parent;
* });
* });
* ```
*
* @class module:ui/base._$$Abstract
* @extends module:util/event._$$EventTarget
* @param {Object} arg0 - 可选配置参数
* @property {String} clazz - 控件样式
* @property {String|Node|Function} parent - 控件所在容器节点或者追加控件节点执行函数
*/
_p._$$Abstract = _k._$klass();
_pro = _p._$$Abstract._$extend(_t._$$EventTarget);
/**
* 初始化
*
* @protected
* @method module:ui/base._$$Abstract#__init
* @return {Void}
*/
_pro.__init = function(){
this.__super();
_e._$dumpCSSText();
this.__initXGui();
this.__initNode();
};
/**
* 控件重置
*
* @protected
* @method module:ui/base._$$Abstract#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__doInitClass(_options.clazz);
this._$appendTo(_options.parent);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/base._$$Abstract#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
// clear parent
this.__doDelParentClass();
delete this.__parent;
// clear body
_e._$removeByEC(this.__body);
_e._$delClassName(
this.__body,
this.__class
);
delete this.__class;
};
/**
* 初始化外观信息,子类实现具体逻辑
*
* @abstract
* @method module:ui/base._$$Abstract#__initXGui
* @return {Void}
*/
_pro.__initXGui = _f;
/**
* 初始化节点,子类重写具体逻辑
*
* @protected
* @method module:ui/base._$$Abstract#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
if (!this.__seed_html){
this.__initNodeTemplate();
}
this.__body = _t0._$getNodeTemplate(this.__seed_html);
if (!this.__body){
this.__body = _e._$create('div',this.__seed_css);
}
_e._$addClassName(this.__body,this.__seed_css);
};
/**
* 动态构建控件节点模板,子类实现具体逻辑
*
* @abstract
* @method module:ui/base._$$Abstract#__initNodeTemplate
* @return {Void}
*/
_pro.__initNodeTemplate = _f;
/**
* 添加节点样式
*
* @protected
* @method module:ui/base._$$Abstract#__doInitClass
* @param {String} arg0 - 样式名称
* @return {Void}
*/
_pro.__doInitClass = function(_clazz){
this.__class = _clazz||'';
_e._$addClassName(this.__body,this.__class);
};
/**
* 父节点增加辅助样式
*
* @protected
* @method module:ui/base._$$Abstract#__doAddParentClass
* @return {Void}
*/
_pro.__doAddParentClass = function(){
if (!!this.__seed_css){
var _arr = this.__seed_css.split(/\s+/);
_e._$addClassName(
this.__parent,
_arr.pop()+'-parent'
);
}
};
/**
* 父节点删除辅助样式
*
* @protected
* @method module:ui/base._$$Abstract#__doDelParentClass
* @return {Void}
*/
_pro.__doDelParentClass = function(){
if (!!this.__seed_css){
var _arr = this.__seed_css.split(/\s+/);
_e._$delClassName(
this.__parent,
_arr.pop()+'-parent'
);
}
};
/**
* 取当前控件节点
*
* 脚本举例
* ```javascript
* // _mask是一个继承了此基类的实例化对象
* // 获取当前控件的节点
* _mask._$getBody();
* ```
*
* @method module:ui/base._$$Abstract#_$getBody
* @return {Node} 控件节点
*/
_pro._$getBody = function(){
return this.__body;
};
/**
* 控件节点追加至容器
*
* 脚本举例
* ```javascript
* // _mask是一个继承了此基类的实例化对象
* _mask._$appendTo(document.body);
* // 还可以传方法
* _mask._$appendTo(function(_body){
* // 根据情况插入节点
* var _parent = document.body;
* _parent.insertAdjacentElement('afterBegin',_body);
* return _parent;
* });
* ```
*
* @method module:ui/base._$$Abstract#_$appendTo
* @param {String|Node|Function} arg0 - 控件所在容器节点
* @return {Void}
*/
_pro._$appendTo = function(_parent){
if (!this.__body) return;
this.__doDelParentClass();
if (_u._$isFunction(_parent)){
this.__parent = _parent(this.__body);
}else{
this.__parent = _e._$get(_parent);
if (!!this.__parent){
this.__parent.appendChild(this.__body);
}
}
this.__doAddParentClass();
};
/**
* 显示控件
*
* 脚本举例
* ```javascript
* // _mask是一个继承了此基类的实例化对象
* _mask._$show();
* ```
*
* @method module:ui/base._$$Abstract#_$show
* @return {Void}
*/
_pro._$show = function(){
if (!this.__parent||!this.__body||
this.__body.parentNode==this.__parent){
return;
}
this.__parent.appendChild(this.__body);
};
/**
* 隐藏控件
*
* 脚本举例
* ```javascript
* // _mask是一个继承了此基类的实例化对象
* _mask._$hide();
* ```
*
* @method module:ui/base._$$Abstract#_$hide
* @return {Void}
*/
_pro._$hide = function(){
_e._$removeByEC(this.__body);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
.#<uispace>{width:160px;margin:0 auto;overflow:hidden;$<user-select>:none;}
.#<uispace> .zbg{background:url(#<root>nej_color_btn.png) no-repeat -50px -50px;}
.#<uispace> .zwrp{position:relative;padding:3px;zoom:1;cursor:default;font-size:1px;}
.#<uispace> .zwrp .zdot{position:absolute;top:0;left:0;height:9px;overflow:hidden;}
.#<uispace> .zwrp .zshw{height:104px;border:1px solid #bdbabd;}
.#<uispace> .zpnl{float:left;}
.#<uispace> .zpnl .zdot{width:9px;background-position:0 0;}
.#<uispace> .zpnl .zshw{width:104px;background:url(#<root>nej_color.png) no-repeat;}
.#<uispace> .zhlt{float:right;padding:3px 7px;}
.#<uispace> .zhlt .zdot{width:44px;background-position:0 -30px;}
.#<uispace> .zhlt .zshw{width:26px;background:url(#<root>nej_color_mask.png) repeat-x;}
<div>
<div class="zwrp zpnl js-ztag">
<span class="zdot zbg js-ztag">&nbsp;</span>
<div class="zshw">&nbsp;</div>
</div>
<div class="zwrp zhlt js-ztag">
<span class="zdot zbg js-ztag">&nbsp;</span>
<div class="zshw js-ztag">&nbsp;</div>
</div>
</div>
/*
* ------------------------------------------
* 颜色面板控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/colorpick/colorpanel */
NEJ.define([
'base/global',
'base/klass',
'base/config',
'base/element',
'base/event',
'util/template/tpl',
'util/slider/slider.y',
'util/slider/slider.xy',
'util/color/color',
'ui/base',
'text!./colorpanel.css',
'text!./colorpanel.html'
],function(NEJ,_k,_c,_e,_v,_t0,_t1,_t2,_i0,_i,_css,_html,_p,_o,_f,_r){
var _pro;
/**
* 颜色选择面板控件
*
* 结构举例
* ```html
* <div id='colorpanel-box'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/colorpick/colorpanel'
* ],function(_i0,_p,_o,_f,_r){
* var _cp = _i0._$$ColorPanel._$allocate({
* parent:'colorpanel-box',
* onchange:function(_color){
* // 选择颜色或者亮度的时候触发
* }
* });
* });
* ```
*
* @class module:ui/colorpick/colorpanel._$$ColorPanel
* @uses module:util/slider/xy._$$SliderXY
* @uses module:util/slider/y._$$SliderY
* @extends module:ui/event._$$Abstract
*
* @param {Object} arg0 - 可选配置参数
* @property {String} color - RGB颜色值
* @property {String} defaultColor - 默认颜色,默认为#fff
*/
/**
* 颜色变化触发事件
*
* @event module:ui/colorpick/colorpanel._$$ColorPanel#onchange
* @param {String} arg0 - RGB颜色串
*/
_p._$$ColorPanel = _k._$klass();
_pro = _p._$$ColorPanel._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/colorpick/colorpanel._$$ColorPanel#__init
* @return {Void}
*/
_pro.__init = function(){
this.__hsl = {};
this.__sopt = {
onchange:this.__onLightChange._$bind(this)
};
this.__dopt = {
onchange:this.__onHueSatChange._$bind(this)
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/colorpick/colorpanel._$$ColorPanel#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__default = _options.defaultColor||'#fff';
this.__lslide = _t2._$$SliderXY._$allocate(this.__dopt);
this.__rslide = _t1._$$SliderY._$allocate(this.__sopt);
this._$setColor(_options.color);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/colorpick/colorpanel._$$ColorPanel#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__hsl = {};
this.__lslide._$recycle();
delete this.__lslide;
this.__rslide._$recycle();
delete this.__rslide;
this.__super();
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/colorpick/colorpanel._$$ColorPanel#__initXGui
* @return {Void}
*/
_pro.__initXGui = (function(){
var _seed_css = _e._$pushCSSText(_css,{
root:_c._$get('root')
}),
_seed_html= _t0._$addNodeTemplate(_html);
return function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
})();
/**
* 初始化节点
*
* @protected
* @method module:ui/colorpick/colorpanel._$$ColorPanel#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
var _list = _e._$getByClassName(
this.__body,'js-ztag'
);
this.__dopt.track = _list[0];
this.__dopt.thumb = _list[1];
this.__sopt.track = _list[2];
this.__sopt.thumb = _list[3];
this.__nlprv = _list[4];
};
/**
* 亮度变化触发事件
*
* @protected
* @method module:ui/colorpick/colorpanel._$$ColorPanel#__onLightChange
* @param {Object} arg0 - 位置信息
* @return {Void}
*/
_pro.__onLightChange = function(_event){
var _light = 1-_event.y.rate;
if (_light==this.__hsl.l){
return;
}
this.__hsl.l = _light;
this._$dispatchEvent(
'onchange',
_i0._$hsl2color(this.__hsl)
);
};
/**
* 色度饱和度变化触发事件
*
* @protected
* @method module:ui/colorpick/colorpanel._$$ColorPanel#__onHueSatChange
* @param {Object} arg0 - 位置信息
* @return {Void}
*/
_pro.__onHueSatChange = function(_event){
var _hue = _event.x.rate,
_sat = 1-_event.y.rate;
if (_hue==this.__hsl.h&&
_sat==this.__hsl.s){
return;
}
this.__hsl.h = _hue;
this.__hsl.s = _sat;
_e._$setStyle(
this.__nlprv,'backgroundColor',
_i0._$hsl2color({
h:this.__hsl.h,
s:this.__hsl.s,
l:0.5
})
);
this._$dispatchEvent(
'onchange',
_i0._$hsl2color(this.__hsl)
);
};
/**
* 设置颜色
*
* 脚本举例
* ```javascript
* // 先把颜色转成rgb,然后转成hsl,在一个面板设置sh,在另外一个面板设置l
* _cp._$setColor('#000');
* ```
*
* @method module:ui/colorpick/colorpanel._$$ColorPanel#_$setColor
* @param {String} arg0 - 颜色值
* @return {Void}
*/
_pro._$setColor = function(_color){
if (!_i0._$isColor(_color)){
_color = this.__default;
}
this.__hsl = _i0._$color2hsl(_color);
this.__lslide._$setPosition({
x:this.__hsl.h,
y:1-this.__hsl.s
});
this.__rslide._$setPosition({
y:1-this.__hsl.l
});
this._$dispatchEvent(
'onchange',_color
);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/colorpick/complex for compatible
// use ui/colorpick/complex for new project
NEJ.define(['./complex.js'],function(_t){return _t;});
.#<uispace> .zbx{background:url(<#root>nej_color_btn.png) no-repeat -50px -50px;}
.#<uispace> .zinf{width:160px;margin:0 auto;padding-bottom:2px;overflow:hidden;font-size:12px;}
.#<uispace> .zinf .zfl{float:left;}
.#<uispace> .zinf .zes{width:19px;height:19px;margin:0 2px 0 3px;background-position:-22px 0;cursor:pointer;}
.#<uispace> .zinf .zpv{width:17px;height:17px;border:1px solid #bdbabd;}
.#<uispace> .zinf .ztxt{width:56px;height:13px;line-height:13px;}
.#<uispace> .zinf .zbtn{width:49px;height:20px;line-height:20px;padding:0;cursor:pointer;}
<div>
<div class="zinf">
<span class="zfl zes zbx js-ztag" title="清除颜色">&nbsp;</span>
<span class="zfl zpv js-ztag">&nbsp;</span>
<label class="zfl">#<input class="ztxt js-ztag" type="text" maxlength="6"/></label>
<input class="zfl zbtn js-ztag" type="button" value="确定"/>
</div>
</div>
/*
* ------------------------------------------
* 颜色选择控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/colorpick/colorpick */
NEJ.define([
'base/global',
'base/klass',
'base/config',
'base/element',
'base/event',
'util/template/tpl',
'util/color/color',
'ui/base',
'ui/colorpick/colorpanel',
'text!./colorpick.css',
'text!./colorpick.html'
],function(NEJ,_k,_c,_e,_v,_t0,_t1,_i,_i0,_css,_html,_p,_o,_f,_r){
var _pro;
/**
* 颜色选择控件
*
* 页面结构举例
* ```html
* <div id='colorpanel-box'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/colorpick/colorpick'
* ],function(_i0,_p,_o,_f,_r){
* var _cp = _i0._$$ColorPick._$allocate({
* parent:'colorpanel-box',
* color:'默认rgb颜色',
* defaultColor:'默认rgb颜色',
* onchange:function(_event){
* // 选择颜色或者亮度的时候触发
* console.log(_event.color)
* },
* onselect:function(_color){
* // 最后保存颜色的时候触发
* console.log(_event.color)
* }
* });
* });
* ```
*
* @class module:ui/colorpick/colorpick._$$ColorPick
* @uses module:ui/colorpick/colorpanel._$$ColorPanel
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {String} color - 颜色值
* @property {String} defaultColor - 默认颜色值
*/
/**
* 颜色变化触发事件
*
* @event module:ui/colorpick/colorpick._$$ColorPick#onchange
* @param {Object} arg0 - 颜色信息
* @property {String} color - 颜色值
*/
/**
* 确定选择颜色触发事件
*
* @event module:ui/colorpick/colorpick._$$ColorPick#onselect
* @param {Object} arg0 - 颜色信息
* @property {String} color - 颜色值
*
*/
_p._$$ColorPick = _k._$klass();
_pro = _p._$$ColorPick._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__init
* @return {Void}
*/
_pro.__init = function(){
this.__popt = {
onchange:this.__onColorChange._$bind(this)
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__default = _options.defaultColor||'#fff';
this.__popt.color = _options.color;
this.__popt.defaultColor = this.__default;
this.__panel = _i0._$$ColorPanel._$allocate(this.__popt);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__panel._$recycle();
delete this.__panel;
this.__super();
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__initXGui
* @return {Void}
*/
_pro.__initXGui = (function(){
var _seed_css = _e._$pushCSSText(_css,{
root:_c._$get('root')
}),
_seed_html= _t0._$addNodeTemplate(_html);
return function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
})();
/**
* 初始化节点
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
var _list = _e._$getByClassName(this.__body,'js-ztag');
this.__ninput = _list[2];
this.__npreview = _list[1];
this.__popt.parent = this.__body;
_v._$addEvent(
_list[0],'click',
this.__onColorClear._$bind(this)
);
_v._$addEvent(
_list[2],'enter',
this.__onColorSelect._$bind(this)
);
_v._$addEvent(
_list[3],'click',
this.__onColorSelect._$bind(this)
);
};
/**
* 清除颜色
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__onColorClear
* @return {Void}
*/
_pro.__onColorClear = function(){
this.__panel._$setColor(this.__default);
};
/**
* 颜色变化触发事件
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__onColorChange
* @param {String} arg0 - 颜色值
* @return {Void}
*/
_pro.__onColorChange = function(_color){
this.__ninput.value = _color.substr(1);
_e._$setStyle(this.__npreview,'backgroundColor',_color);
this._$dispatchEvent('onchange',{color:_color});
};
/**
* 确定选择颜色
*
* @protected
* @method module:ui/colorpick/colorpick._$$ColorPick#__onColorSelect
* @return {Void}
*/
_pro.__onColorSelect = function(){
var _color = '#'+this.__ninput.value.trim();
if (!_t1._$isColor(_color)){
return;
}
this.__panel._$setColor(_color);
_color = '#'+this.__ninput.value.trim();
this._$dispatchEvent('onselect',{color:_color});
};
/**
* 设置颜色
*
* 脚本举例
* ```javascript
* // 先把颜色转成rgb,然后转成hsl,在一个面板设置sh,在另外一个面板设置l
* _cp._$setColor('#ccc');
* ```
*
* @method module:ui/colorpick/colorpick._$$ColorPick#_$setColor
* @param {String} arg0 - 颜色值
* @return {Void}
*/
_pro._$setColor = function(_color){
this.__panel._$setColor(_color);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/colorpick/simple for compatible
// use ui/colorpick/simple for new project
NEJ.define(['./simple.js'],function(_t){return _t;});
{list xlist as x}
<a class="zitm zitm2" style="background-color:#${x}" data-value="#${x}" href="#">&nbsp;</a>
{/list}
/*
* ------------------------------------------
* 颜色选择控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/colorpick/complex */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'ui/colorpick/colorpick.simple',
'util/template/jst',
'text!./complex.html'
],function(NEJ,_k,_u,_i0,_t0,_html,_p,_o,_f,_r){
var _pro,
_seed_color = _t0._$add(_html);
/**
* 颜色选择控件
*
* 页面结构举例
* ```html
* <div id='colorpanel-box'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/colorpick/complex'
* ],function(_i0,_p,_o,_f,r){
* var _cp = _i0._$$ComplexColorPick._$allocate({
* parent:'colorpanel-box',
* defaultColor:'默认rgb颜色',
* onselect:function(_event){
* console.log(_event.color)
* }
* });
* });
* ```
*
* @class module:ui/colorpick/complex._$$ComplexColorPick
* @extends module:ui/colorpick/simple._$$SimpleColorPick
* @param {Object} arg0 - 可选配置参数
* @property {String} defaultColor - 默认颜色值
*/
/**
* 确定选择颜色触发事件
*
* @event module:ui/colorpick/complex._$$ComplexColorPick#onselect
* @param {Object} arg0 - 颜色信息
* @property {String} color - 颜色值
*
*/
_p._$$ComplexColorPick = _k._$klass();
_pro = _p._$$ComplexColorPick._$extend(_i0._$$SimpleColorPick);
/**
* 初始化节点
*
* @protected
* @method module:ui/carousel/complex._$$ComplexColorPick#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
_e._$addClassName(this.__nbox,'zbox2');
};
/**
* 绘制可选颜色列表
*
* @protected
* @method module:ui/carousel/complex._$$ComplexColorPick#__doRenderColorList
* @return {Void}
*/
_pro.__doRenderColorList = (function(){
var _xlist = ['00','33','66','99','cc','ff'],
_ylist = ['ff0000','00ff00','0000ff','ffff00','00ffff','ff00ff'];
return function(){
var _arr = [],
_test = ['','','',''];
// top panel
_u._$forEach(
_xlist,function(_value,_index){
_arr.push(_test.join(_value));
_arr.push('000000');
for(var i=0;i<3;i++){
for(var j=0;j<6;j++){
_arr.push(_xlist[i]+_xlist[j]+_xlist[_index]);
}
}
}
);
// bottom panel
_u._$forEach(
_xlist,function(_value,_index){
_arr.push(_ylist[_index]);
_arr.push('000000');
for(var i=3;i<6;i++){
for(var j=0;j<6;j++){
_arr.push(_xlist[i]+_xlist[j]+_xlist[_index]);
}
}
}
);
_e._$render(
this.__nbox,_seed_color,{
xlist:_arr
}
);
};
})();
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>demo for colorpick</title>
<meta charset="utf-8" />
<style>
body{padding-top:500px;}
</style>
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script>
window.NEJ_CONF = {
root:'../../../../res/'
};
</script>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../colorpanel.js'
],function(_i){
var _colorpick = _i._$$ColorPanel._$allocate({
parent:document.body,
defaultColor:'#fdc',
onchange:function(_color){
log('change color -> '+_color);
}
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>demo for colorpick</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script>
window.NEJ_CONF = {
root:'../../../../res/'
};
</script>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../colorpick.js'
],function(_i){
var _colorpick = _i._$$ColorPick._$allocate({
parent:document.body,
color:'#f00',
defaultColor:'#fdc',
onchange:function(_event){
log('change color -> '+_event.color);
},
onselect:function(_event){
log('select color -> '+_event.color);
}
});
});
</script>
</body>
</html>
.#<uispace>{text-align:left;}
.#<uispace> .zdft{display:block;padding:3px 1px 3px 5px;margin:3px;cursor:pointer;}
.#<uispace> .zdft:hover{padding:2px 0 2px 4px;background:#ffeec2;border:1px solid #000080;text-decoration:none;}
.#<uispace> .zprv{display:block;width:28px;height:11px;overflow:hidden;border:1px solid #aca899;}
.#<uispace> .zbox{width:152px;margin:0 5px;overflow:hidden;}
.#<uispace> .zbox .zitm{display:block;float:left;width:11px;height:11px;overflow:hidden;margin:3px;border:1px solid #aca899;cursor:pointer;}
.#<uispace> .zbox2{width:220px;margin-left:9px;border-width:1px 0 0 1px;border-color:#000;border-style:solid;}
.#<uispace> .zbox2 .zitm2{width:10px;height:10px;margin:-1px 0 0 -1px;border-color:#000;}
<textarea name='ntp' id='#<seedHtml>'>
<div class="'+_seed_css+'">
<a class="zdft" title="去除颜色" href="#">
<span class="zprv j-flag">&nbsp;</span>
</a>
<div class="zbox j-flag"></div>
</div>
</textarea>
<textarea name='jst' id='#<seedColor>'>
{list xlist as x}
<a class="zitm" title="${x.t}" style="background-color:${x.v}" data-value="${x.v}" href="#">&nbsp;</a>
{/list}'
</textarea>
/*
* ------------------------------------------
* 颜色选择控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/colorpick/simple */
NEJ.define([
'base/global',
'base/klass',
'base/config',
'base/element',
'base/event',
'ui/base',
'util/template/tpl',
'util/template/jst',
'text!./simple.css',
'text!./simple.html'
],function(NEJ,_k,_c,_e,_v,_i,_t0,_t1,_css,_html,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css,{root:_c._$get('root')}),
_seed_ui = _t0._$parseUITemplate(_html),
_seed_html = _seed_ui['seedHtml'],
_seed_color = _seed_ui['seedColor'];
/**
* 颜色选择控件
*
* 页面结构举例
* ```html
* <div id='colorpanel-box'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/colorpick/simple'
* ],function(_i0,_p,_o,_f,_r){
* var _cp = _i0._$$SimpleColorPick._$allocate({
* parent:'colorpanel-box',
* defaultColor:'默认rgb颜色',
* onselect:function(_color){
* // 最后保存颜色的时候触发
* }
* });
* });
* ```
*
* @class module:ui/colorpick/simple._$$SimpleColorPick
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {String} arg0 - defaultColor 默认颜色值
*/
/**
* 确定选择颜色触发事件
*
* @event module:ui/colorpick/simple._$$SimpleColorPick#onselect
* @param {Object} arg0 - 颜色信息
* @property {String} color - 颜色值
*
*/
_p._$$SimpleColorPick = _k._$klass();
_pro = _p._$$SimpleColorPick._$extend(_i._$$Abstract);
/**
* 控件重置
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__default = _options.defaultColor||'#ffffff';
this.__doInitDomEvent([[
this.__nprv.parentNode,'click',
this.__onClearColor._$bind(this)
],[
this.__nbox,'click',
this.__onSelectColor._$bind(this)
],[
this.__nbox,'mouseover',
this.__onPreviewColor._$bind(this)
]]);
this.__doPreviewColor(this.__default);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__default;
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
// 0 - color preview
// 1 - color list box
var _list = _e._$getByClassName(this.__body,'j-flag');
this.__nprv = _list[0];
this.__nbox = _list[1];
this.__doRenderColorList();
};
/**
* 绘制可选颜色列表
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__doRenderColorList
* @return {Void}
*/
_pro.__doRenderColorList = (function(){
var _xlist = [
{t:'黑色',v:'#000000'},{t:'褐色',v:'#993300'},{t:'橄榄色',v:'#333300'},{t:'深绿',v:'#003300'},{t:'深青',v:'#003366'},{t:'深蓝',v:'#000080'},{t:'靛蓝',v:'#333399'},{t:'灰色-80%',v:'#333333'},
{t:'深红',v:'#800000'},{t:'橙色',v:'#ff6600'},{t:'深黄',v:'#808000'},{t:'绿色',v:'#008000'},{t:'青色',v:'#008080'},{t:'蓝色',v:'#0000ff'},{t:'蓝-灰',v:'#666699'},{t:'灰色-50%',v:'#808080'},
{t:'红色',v:'#ff0000'},{t:'浅橙色',v:'#ff9900'},{t:'酸橙色',v:'#99cc00'},{t:'海绿',v:'#339966'},{t:'水绿色',v:'#33cccc'},{t:'浅蓝',v:'#3366ff'},{t:'紫罗兰',v:'#800080'},{t:'灰色-40%',v:'#999999'},
{t:'粉红',v:'#ff00ff'},{t:'金色',v:'#ffcc00'},{t:'黄色',v:'#ffff00'},{t:'鲜绿',v:'#00ff00'},{t:'青绿',v:'#00ffff'},{t:'天蓝',v:'#00ccff'},{t:'梅红',v:'#993366'},{t:'灰色-25%',v:'#c0c0c0'},
{t:'玫瑰红',v:'#ff99cc'},{t:'茶色',v:'#ffcc99'},{t:'浅黄',v:'#ffff99'},{t:'浅绿',v:'#ccffcc'},{t:'浅青绿',v:'#ccffff'},{t:'淡蓝',v:'#99ccff'},{t:'淡紫',v:'#cc99ff'},{t:'白色',v:'#ffffff'}
];
return function(){
_t1._$render(
this.__nbox,_seed_color,{
xlist:_xlist
}
);
};
})();
/**
* 清除颜色
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__onClearColor
* @param {Event} arg0 - 事件信息
* @return {Void}
*/
_pro.__onClearColor = function(_event){
_v._$stop(_event);
this.__doChangeColor(this.__default);
};
/**
* 颜色选择事件
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__onSelectColor
* @param {Event} arg0 - 事件信息
* @return {Void}
*/
_pro.__onSelectColor = function(_event){
var _element = _v._$getElement(_event,'d:value');
if (!_element) return;
_v._$stop(_event);
this.__doChangeColor(
_e._$dataset(_element,'value')
);
};
/**
* 预览颜色
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__onPreviewColor
* @param {Event} arg0 - 事件信息
* @return {Void}
*/
_pro.__onPreviewColor = function(_event){
var _element = _v._$getElement(_event,'d:value');
if (!_element) return;
this.__doPreviewColor(
_e._$dataset(_element,'value')
);
};
/**
* 预览颜色
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__doPreviewColor
* @param {String} arg0 - 颜色值
* @return {Void}
*/
_pro.__doPreviewColor = function(_color){
_e._$setStyle(this.__nprv,'backgroundColor',_color);
};
/**
* 修改颜色
*
* @protected
* @method module:ui/colorpick/simple._$$SimpleColorPick#__doChangeColor
* @param {String} arg0 - 颜色值
* @return {Void}
*/
_pro.__doChangeColor = function(_color){
this._$dispatchEvent('onselect',{
color:_color
});
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>colorpanel测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit colorpanel test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="colorpanel-box"></div>
<div id="colorpanel-box2"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./colorpanel.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("colorpanel");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui');
//开始单元测试
// test('colorpanel',function(){
// stop();
// var _cp = _p._$$ColorPanel._$allocate({
// parent:'colorpanel-box',
// onchange:function(_color){
// ok(true,'设置的颜色为:' + _color);
// start();
// }
// });
// });
test('colorpick',function(){
stop();
expect(0);
var _cp = _p._$$ColorPick._$allocate({
parent:'colorpanel-box2',
onchange:function(_color){
// ok(true,'设置的颜色为:' + _color);
},
onselect:function(_color){
// ok(true,'最后设置的颜色为:' + _color);
start();
}
});
_cp._$setColor('#00ff00');
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}colorpanel.test.js',['ui/colorpick/colorpick'],f);
});
.#<uispace>{width:210px;border:1px solid #aaa;font-size:14px;text-align:center;}
.#<uispace> .zact{line-height:30px;overflow:hidden;zoom:1;}
.#<uispace> .zact .zfl{float:left;}
.#<uispace> .zact .zfr{float:right;}
.#<uispace> .zact .zbtn{padding:0 5px;cursor:pointer;}
.#<uispace> .zact .ztxt{margin-left:10px;}
.#<uispace> .zday{table-layout:fixed;border-collapse:collapse;width:100%;}
.#<uispace> .zday th{font-weight:normal;}
.#<uispace> .zday a{display:block;height:22px;line-height:22px;color:#333;text-decoration:none;}
.#<uispace> .zday a:hover{background:#eee;}
.#<uispace> .zday a.js-extended{color:#aaa;}
.#<uispace> .zday a.js-selected,
.#<uispace> .zday a.js-selected:hover{background:#DAE4E7;}
.#<uispace> .zday a.js-disabled,
.#<uispace> .zday a.js-disabled:hover{background:#fff;color:#eee;cursor:default;}
<textarea name='jst' id='#<seedDate>'>
<table class="zday">
<tr>{list ["日","一","二","三","四","五","六"] as x}<th>${x}</th>{/list}</tr>
{list 1..6 as x}
<tr>{list 1..7 as y}<td><a href="javascript:void(0);" class="js-ztag"></a></td>{/list}</tr>
{/list}
</table>
</textarea>
<textarea name='txt' id='#<seedAction>'>
<div class="zact">
<span class="zbtn zfl" title="上一年">&lt;&lt;</span>
<span class="zbtn zfl" title="上一月">&lt;</span>
<span class="zbtn zfr" title="下一年">&gt;&gt;</span>
<span class="zbtn zfr" title="下一月">&gt;</span>
<span class="ztxt"></span>年
<span class="ztxt"></span>月
</div>
</textarea>
/*
* ------------------------------------------
* 日期选择控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/datepick/datepick */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/util',
'ui/layer/card.wrapper',
'util/calendar/calendar',
'util/template/tpl',
'util/template/jst',
'text!./datepick.css',
'text!./datepick.html'
],function(NEJ,_k,_e,_u,_i0,_t0,_t1,_t2,_css,_html,_p,_o,_f,_r){
var _pro,
_seed_html,
_seed_css = _e._$pushCSSText(_css),
_seed_ui = _t1._$parseUITemplate(_html),
_seed_date = _seed_ui['seedDate'],
_seed_action = _seed_ui['seedAction'];
/**
* 日期选择控件
*
* 页面结构举例
* ```html
* <style>
* // 注意,样式的优先级
* // 扩展 < 当前 < 禁止
* #datepick-box .js-extended{background:green;}
* #datepick-box .js-selected{background:yellow;}
* #datepick-box .js-disabled{background:red;}
* </style>
* <div id="datepick-box"></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element',
* 'ui/datepick/datepick'
* ],function(_e,_i0,_p,_o,_f,_r){
* var pDate = new Date(1997,7,9)
* var nDate = new Date(2013,7,9);
* var _dp = _i0._$$DatePick._$allocate({
* parent:_e._$get('datepick-box'),
* // 默认选中日期
* date:'2012-10-10',
* // 设置日期的可选范围
* range:[pDate,nDate],
* onchange:function(_date){
* // 选择了一个日期,返回此日期
* }
* });
* });
* ```
*
* @class module:ui/datepick/datepick._$$DatePick
* @uses module:util/calendar/calendar._$$Calendar
* @extends module:ui/layer/card._$$CardWrapper
* @param {Object} arg0 - 可选配置参数
* @property {Date} date - 设置日期
* @property {Array} range - 可选范围
*/
/**
* 日期变化触发事件
*
* @event module:ui/datepick/datepick._$DatePick#onchange
* @param {Date} arg0 - 日期
*
*/
_p._$$DatePick = _k._$klass();
_pro = _p._$$DatePick._$extend(_i0._$$CardWrapper);
/**
* 控件初始化
*
* @protected
* @method module:ui/datepick/datepick._$$DatePick#__init
* @return {Void}
*/
_pro.__init = function(){
this.__copt = {
onselect:this.__onDateChange._$bind(this)
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/datepick/datepick._$$DatePick#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__copt.range = _options.range;
this.__calendar = _t0._$$Calendar
._$allocate(this.__copt);
this._$setDate(_options.date||(new Date()));
};
/**
* 控件销毁
*
* @protected
* @method module:ui/datepick/datepick._$$DatePick#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__copt.range;
var _calendar = this.__calendar;
if (!!_calendar){
delete this.__calendar;
_calendar._$recycle();
}
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/datepick/datepick._$$DatePick#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/datepick/datepick._$$DatePick#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
var _list = _e._$getChildren(this.__body);
this.__copt.list = _e._$getByClassName(_list[1],'js-ztag');
_list = _e._$getChildren(_list[0]);
this.__copt.yprv = _list[0];
this.__copt.mprv = _list[1];
this.__copt.ynxt = _list[2];
this.__copt.mnxt = _list[3];
this.__copt.year = _list[4];
this.__copt.month= _list[5];
};
/**
* 动态构建控件节点模板
*
* @protected
* @method module:ui/datepick/datepick._$$DatePick#__initNodeTemplate
* @return {Void}
*/
_pro.__initNodeTemplate = function(){
_seed_html = _t1._$addNodeTemplate(
'<div class="'+_seed_css+' zcard">'+
_t1._$getTextTemplate(_seed_action)+
_t2._$get(_seed_date)+
'</div>'
);
this.__seed_html = _seed_html;
};
/**
* 日期变化回调函数
*
* @protected
* @method module:ui/datepick/datepick._$$DatePick#__onDateChange
* @param {Date} arg0 - 日期
* @return {Void}
*/
_pro.__onDateChange = function(_date){
try{
this._$dispatchEvent('onchange',_date);
}catch(e){
// ignore
}
this._$hide();
};
/**
* 设置日期
*
* 脚本举例
* ```javascript
* _dp._$setDate('2012-12-21');
* ```
*
* @method module:ui/datepick/datepick._$$DatePick#_$setDate
* @param {Date} arg0 - 日期
* @return {Void}
*/
_pro._$setDate = function(_date){
_date = _u._$var2date(_date);
this.__calendar._$setDate(_date);
};
/**
* 取当前时间
*
* 脚本举例
* ```javascript
* // 返回一个Date对象
* var _date = _dp._$getDate();
* ```
*
* @method module:ui/datepick/datepick._$$DatePick#_$getDate
* @return {Date} 日期
*/
_pro._$getDate = function(){
return this.__calendar._$getDate();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>demo for colorpick</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../datepick.js'
],function(_i){
_i._$$DatePick._$allocate({
parent:document.body,
onchange:function(_date){
log('select date -> '+_date);
}
});
});
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>datepick测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
#datepick-box .js-extended{background:green;}
#datepick-box .js-selected{background:yellow;}
#datepick-box .js-disabled{background:red;}
#datepick-box2 .js-extended{background:green;}
#datepick-box2 .js-selected{background:yellow;}
#datepick-box2 .js-disabled{background:red;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit datepick test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="datepick-box"></div>
<div id="datepick-box2">
<div id="days"></div>
<div id="year"></div>
<div id="month"></div>
<div id="yprv">前一年</div>
<div id="mprv">前一月</div>
<div id="ynxt">后一年</div>
<div id="mnxt">后一月</div>
</div>
<div id="datepick">jjjjjjjjjjjjj</div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./datepick.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("datepick");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui'),
_ut= _('nej.ut');
//开始单元测试
test('datepick-ui',function(){
stop();
var _dp = _p._$$DatePick._$allocate({
parent:_e._$get('datepick-box'),
onchange:function(_date){
ok(true,'选择了一个日期,返回此日期'+_date);
start();
}
});
_dp._$setDate('2012-12-21');
_dp._$getDate();
});
test('datepick-util',function(){
expect(0);
var pDate = new Date(1997,7,9)
var nDate = new Date(2013,7,9);
var _days = _e._$get('days');
_html = _e._$add('{list 1..2 as x}<div>{list 1..6 as y}<p class="z-day"></p>{/list}</div>{/list}');
_days.innerHTML = _e._$get(_html);
var _dp = _ut._$$Calendar._$allocate({
parent:_e._$get('datepick-box2'),
offset:1,
list:_e._$getByClassName(_days,"z-day"),
year:_e._$get('year'),
month:_e._$get('month'),
yprv:_e._$get('yprv'),
mprv:_e._$get('mprv'),
ynxt:_e._$get('ynxt'),
mnxt:_e._$get('mnxt'),
onchange:function(_date){
// ok(true,'日期变化'+_date);
// start();
},
onselect:function(_date){
_dp._$setDate(_date)
// ok(true,'直接用calendar选择了一个日期,返回此日期'+_date);
// start();
},
range:[pDate,nDate]
});
_dp._$setDate('1998-09-03');
_dp._$getDate();
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}datepick.test.js',['ui/datepick/datepick'],f);
});
// link to ui/editor/command/complex for compatible
// use ui/editor/command/complex for new project
NEJ.define(['./complex.js'],function(_t){return _t;});
.#<uispace>{width:160px;padding:10px 5px 5px;border:1px solid #9FAC87;}
/*
* ------------------------------------------
* 颜色选择卡片实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/command/color */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/layer/card.wrapper',
'ui/colorpick/colorpick',
'text!./color.css'
],function(NEJ,_k,_e,_i0,_i1,_css,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 颜色选择卡片
*
* @class module:ui/editor/command/color._$$ColorCard
* @extends module:ui/layer/wrapper/card._$$CardWrapper
* @param {Object} arg0 - 可选配置参数
* @property {String} color - 颜色值
*/
/**
* 颜色选中回调函数
*
* @event module:ui/editor/command/color._$$ColorCard#onchange
* @param {String} color - 颜色值
*
*/
_p._$$ColorCard = _k._$klass();
_pro = _p._$$ColorCard._$extend(_i0._$$CardWrapper);
/**
* 控件初始化
*
* @protected
* @method module:ui/editor/command/color._$$ColorCard#__init
* @return {Void}
*/
_pro.__init = function(){
this.__copt = {
onselect:this.__onColorSelect._$bind(this)
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/editor/command/color._$$ColorCard#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__copt.color = _options.color;
this.__copt.parent = this.__layer._$getBody();
this.__copt.defaultColor = _options.defaultColor;
this.__colorpick = this.__getColorPicker();
};
/**
* 控件回收
*
* @protected
* @method module:ui/editor/command/color._$$ColorCard#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
if (!!this.__colorpick){
this.__colorpick._$recycle();
delete this.__colorpick;
}
delete this.__copt.parent;
this.__super();
};
/**
* 取取色器实例
*
* @protected
* @method module:ui/editor/command/color._$$ColorCard#__getColorPicker
* @return {Void}
*/
_pro.__getColorPicker = function(){
this.__copt.clazz = _seed_css;
return _i1._$$ColorPick._$allocate(this.__copt);
};
/**
* 颜色选择回调
*
* @protected
* @method module:ui/editor/command/color._$$ColorCard#__onColorSelect
* @param {Object} arg0 - 颜色配置
* @property {String} color - 颜色值
* @return {Void}
*/
_pro.__onColorSelect = function(_event){
this._$dispatchEvent('onchange',_event.color);
this._$hide();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui.cmd'),_p);
}
return _p;
});
// link to ui/editor/command/simple for compatible
// use ui/editor/command/simple for new project
NEJ.define(['./simple.js'],function(_t){return _t;});
.#<uispace>{width:238px;padding:5px 0 8px;border:1px solid #9FAC87;}
/*
* ------------------------------------------
* 颜色选择卡片实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/command/complex */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/editor/command/color',
'ui/colorpick/colorpick.complex',
'text!./complex.css'
],function(NEJ,_k,_e,_i0,_i1,_css,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 颜色选择卡片
*
* @class module:ui/editor/command/complex._$$ComplexColorCard
* @extends module:ui/editor/command/color._$$ColorCard
* @param {Object} arg0 - 可选配置参数
* @property {String} color - 颜色值
*/
/**
* 颜色选中回调函数
*
* @event module:ui/editor/command/complex._$$ComplexColorCard#onchange
* @param {String} color - 颜色值
*
*/
_p._$$ComplexColorCard = _k._$klass();
_pro = _p._$$ComplexColorCard._$extend(_i0._$$ColorCard);
/**
* 取取色器实例
*
* @protected
* @method module:ui/editor/command/complex._$$ComplexColorCard#__getColorPicker
* @return {Void}
*/
_pro.__getColorPicker = function(){
this.__copt.clazz = _seed_css;
return _i1._$$ComplexColorPick._$allocate(this.__copt);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui.cmd'),_p);
}
return _p;
});
.#<uispace>{border:1px solid #9FAC87;font-size:12px;text-align:left;}
.#<uispace> .zitm{display:block;position:relative;margin:1px;outline:none;padding:2px 0 2px 8px;border:1px solid #ddd;color:#000;background-color:#fff;text-decoration:none;}
.#<uispace> .zitm:hover{background-color:#e5e5e1;text-decoration:none;}
.#<uispace> .zitm .ztip{position:absolute;top:2px;right:5px;font-size:10px;}
{list xlist as x}
<a class="zitm" hidefocus="true" style="${style}:${x.style|default:x.name};" data-index="${x_index}">
${x.name}
{if !!x.tip}<span class="ztip">${x.tip}</span>{/if}
</a>
{/list}
/*
* ------------------------------------------
* 字体字号选择卡片基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/command/font */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/event',
'base/util',
'ui/layer/card.wrapper',
'util/template/jst',
'text!./font.css',
'text!./font.html'
],function(NEJ,_k,_e,_v,_u,_i,_t0,_css,_html,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css),
_seed_fnt = _t0._$add(_html);
/**
* 字体字号选择卡片基类
*
* @class module:ui/editor/command/font._$$FontCard
* @extends module:ui/layer/wrapper/card._$$CardWrapper
* @param {Object} arg0 - 可选配置参数
*/
/**
* 字号/字体选中回调函数
*
* @event module:ui/editor/command/font._$$FontCard#onchange
* @param {String} font - 字号/字体
*
*/
_p._$$FontCard = _k._$klass();
_pro = _p._$$FontCard._$extend(_i._$$CardWrapper);
/**
* 控件重置
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
if (_options.width!=null){
_e._$setStyle(
this.__body,'width',
_options.width+'px'
);
}
};
/**
* 控件销毁
*
* @protected
* @method module:ui/editor/command/font._$$FontCard#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__flist;
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/editor/command/font._$$FontCard#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/editor/command/font._$$FontCard#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
_v._$addEvent(
this.__body,'click',
this.__onFontSelect._$bind(this)
);
};
/**
* 构建字体大小选择列表
*
* @protected
* @method module:ui/editor/command/font._$$FontCard#__doGenFontListXhtml
* @param {Object} arg0 - 字体大小列表信息
* @return {Void}
*/
_pro.__doGenFontListXhtml = function(_data){
return _t0._$get(_seed_fnt,_data);
};
/**
* 字体大小选择事件
*
* @protected
* @method module:ui/editor/command/font._$$FontCard#__onFontSelect
* @param {Event} arg0 - 事件对象
* @return {Void}
*/
_pro.__onFontSelect = (function(){
var _doFilter = function(_node){
return !isNaN(parseInt(_e._$dataset(_node,'index')));
};
return function(_event){
var _element = _v._$getElement(_event,_doFilter);
if (!_element) return;
var _index = parseInt(_e.
_$dataset(_element,'index'));
this._$dispatchEvent('onchange',
this.constructor.list[_index]);
this._$hide();
};
})();
/**
* 取字体字号提示文字
*
* @method module:ui/editor/command/font._$$FontCard._$getText
* @param {String} value - 字体/字号
* @return {String} 字体/字号
*/
_p._$$FontCard._$getText = function(_value){
var _index = _u._$indexOf(this.list,
function(_data){
return (_data.value||_data.name)==_value;
});
return (this.list[_index]||_o).name;
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui.cmd'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 字体选择控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/command/fontname */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/editor/command/font',
'util/template/tpl'
],function(NEJ,_k,_e,_i0,_t0,_p,_o,_f,_r){
var _pro,
_seed_html;
/**
* 字体选择控件
*
* @class module:ui/editor/command/fontname._$$FontNameCard
* @extends module:ui/editor/command/font._$$FontCard
* @param {Object} arg0 - 可选配置参数
*/
/**
* 字体选中回调函数
*
* @event module:ui/editor/command/fontname._$$FontNameCard#onselect
* @param {String} arg0 - 字体
*
*/
_p._$$FontNameCard = _k._$klass();
_pro = _p._$$FontNameCard._$extend(_i0._$$FontCard);
/**
* 字体选项列表
*
* @const {Array} module:ui/editor/command/fontname._$$FontNameCard.list
*/
_p._$$FontNameCard.list =
[{name:'宋体'}
,{name:'微软雅黑'}
,{name:'黑体'}
,{name:'楷体'}
,{name:'隶书'}
,{name:'幼圆'}
,{name:'Arial'}
,{name:'Arial Narrow'}
,{name:'Arial Black'}
,{name:'Comic Sans MS'}
,{name:'Courier'}
,{name:'System'}
,{name:'Verdana'}
,{name:'Times New Roman'}];
/**
* 初始化外观信息
*
* @protected
* @method module:ui/editor/command/fontname._$$FontNameCard#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__super();
this.__seed_html = _seed_html;
};
/**
* 动态构建控件节点模板
*
* @protected
* @method module:ui/editor/command/fontname._$$FontNameCard#__initNodeTemplate
* @return {Void}
*/
_pro.__initNodeTemplate = function(){
_seed_html = _t0._$addNodeTemplate(
'<div class="'+this.__seed_css+'">'
+this.__doGenFontListXhtml({
style:'font-family'
,xlist:this.constructor.list
})+
'</div>');
this.__seed_html = _seed_html;
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui.cmd'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 富媒体编辑器字号选择控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/command/fontsize */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'util/template/tpl',
'ui/editor/command/font'
],function(NEJ,_k,_e,_t0,_u,_p,_o,_f,_r){
var _pro,
_seed_html;
/**
* 字号选择控件
*
* @class module:ui/editor/command/fontsize._$$FontSizeCard
* @extends module:ui/editor/command/font._$$FontCard
* @param {Object} arg0 - 可选配置参数
*/
/**
* 字号选中回调函数
*
* @event module:ui/editor/command/fontsize._$$FontSizeCard#onselect
* @param {String} arg0 - 字号
*
*/
_p._$$FontSizeCard = _k._$klass();
_pro = _p._$$FontSizeCard._$extend(_u._$$FontCard);
/**
* 字号选项列表
* @member {Array}
*/
_p._$$FontSizeCard.list =
[{name:'小',style:'x-small',value:1}
,{name:'标准',style:'small',value:2}
,{name:'大',style:'medium',value:3}
,{name:'特大',style:'large',value:4}
,{name:'极大',style:'x-large',value:5}];
/**
* 初始化外观信息
*
* @protected
* @method module:ui/editor/command/fontsize._$$FontSizeCard#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__super();
this.__seed_html = _seed_html;
};
/**
* 动态构建控件节点模板
*
* @protected
* @method module:ui/editor/command/fontsize._$$FontSizeCard#__initNodeTemplate
* @return {Void}
*/
_pro.__initNodeTemplate = function(){
_seed_html = _t0._$addNodeTemplate(
'<div class="'+this.__seed_css+'">'
+this.__doGenFontListXhtml({
style:'font-size'
,xlist:this.constructor.list
})+
'</div>');
this.__seed_html = _seed_html;
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui.cmd'),_p);
}
return _p;
});
.#<uispace>{width:160px;padding:5px 0;border:1px solid #9FAC87;}
/*
* ------------------------------------------
* 颜色选择卡片实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/command/simple */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/editor/command/color',
'ui/colorpick/colorpick.simple',
'text!./simple.css'
],function(NEJ,_k,_e,_i0,_i1,_css,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 颜色选择卡片
*
* @class module:ui/editor/command/simple._$$SimpleColorCard
* @extends module:ui/editor/command/color._$$ColorCard
* @param {Object} arg0 - 可选配置参数
* @property {String} color - 颜色值
*/
/**
* 颜色选中回调函数
*
* @event module:ui/colorpick/colorpanel._$$ColorPanel#onchange
* @param {String} arg0 - 颜色值
*
*/
_p._$$SimpleColorCard = _k._$klass();
_pro = _p._$$SimpleColorCard._$extend(_i0._$$ColorCard);
/**
* 取取色器实例
*
* @protected
* @method module:ui/editor/command/simple._$$SimpleColorCard#__initXGui
* @return {Void}
*/
_pro.__getColorPicker = function(){
this.__copt.clazz = _seed_css;
return _i1._$$SimpleColorPick._$allocate(this.__copt);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui.cmd'),_p);
}
return _p;
});
.#<uispace>{width:336px;}
.#<uispace> .m-iframe{position:absolute;height:0px;width:0px;left:-9000px;}
.#<uispace> .u-upload-file{height:0px;width:0px;font-size:0px;}
.#<uispace> .u-error{color:red;padding-top:10px;}
.#<uispace> .choose_file{position:relative;margin-bottom:10px;}
.#<uispace> .choose_file object{position:absolute;left:0;top:0;}
.#<uispace> .web_img{margin-bottom:8px;}
.#<uispace> .web_img .u-edit{margin-bottom:10px;}
.#<uispace> .u-desc{color:#ccc;}
.#<uispace> .middle{color:#528CE0;}
.#<uispace> .u-btn{cursor:pointer;color:#528CE0;}
.#<uispace> .u-image{width:0px;height:0px;visibility:hidden;}
<div>
<div>
<a class="u-btn f-ib upload j-tab f-fl" name="upload"><span class="img-upload">上传图片</span></a>
<a class="u-btn f-ib extern j-tab" name="extern"><span class="img-extern">引用站外图片</span></a>
<img class="j-ztag u-image" />
</div>
<div class="j-cnt">
<div class="choose_file" name="select_image">
<div class="btn2">
<a class="main middle"><span>选择图片</span></a>
</div>
</div>
<p class="u-desc j-desc"></p>
</div>
<div class="j-cnt">
<div class="f-cb web_img">
<div class="f-fl u-edit"><input class="ipt j-ztag" type="text" /></div>
<div class="btn2 f-fl j-ztag">
<a class="main small"><span>确定</span></a>
</div>
</div>
<p class="u-desc j-desc"></p>
</div>
<div class="u-error j-ztag"></div>
</div>
/*
* ------------------------------------------
* 富媒体编辑器图片上传控件实现文件
* @version 1.0
* @author cheng-lin([email protected])
* ------------------------------------------
*/
/** @module ui/editor/command/uploadimage */
NEJ.define([
'base/global',
'base/klass',
'base/config',
'base/element',
'base/event',
'base/util',
'ui/layer/window.wrapper',
'util/tab/tab',
'util/flash/flash',
'util/template/tpl',
'text!./uploadimage.css',
'text!./uploadimage.html'
],function(NEJ,_k,_c,_e,_v,_u,_i0,_t0,_t1,_t2,_css,_html,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css),
_seed_html = _t2._$addNodeTemplate(_html);
/**
* 图片上传控件
*
* @class module:ui/editor/command/uploadimage._$$UploadImageCard
* @uses module:util/tab/tab._$$Tab
* @extends module:ui/layer/wrapper/window._$$WindowWrapper
* @param {Object} arg0 - 可选配置参数
* @property {String|Node} parent - 父容器
* @property {Boolean} draggable - 是否可拖拽
* @property {Boolean} destroyable - 关闭是否销毁
* @property {String} title - 卡片标题
* @property {String} fDesc - 自定义错误提示1
* @property {String} oDesc - 自定义错误提示2
* @property {String} swfUrl - Flash文件路径
* @property {String} baseUrl - Flash文件路径的前缀
* @property {Number} flashWidth - Flash宽度
* @property {Number} flashHeight - Flash高度
* @property {String} userdefinesize - 图片尺寸,默认750x750x0x90;350x350x0x85
* @property {String} saveorigin - 是否保存源文件,默认false
* @property {String} responsetype - 响应格式,默认xml
* @property {String} rotatedegree - 旋转角度,默认0
* @property {String} stamptype - 水印类型,默认无
* @property {String} stampstring - 水印内容,默认无
* @property {String} sitefrom - 产品名称
*/
/**
* Flash开始初始化
*
* @event module:ui/editor/command/uploadimage._$$UploadImageCard#oninitflash
*/
/**
* Flash初始化完成
*
* @event module:ui/editor/command/uploadimage._$$UploadImageCard#onflashinited
*/
/**
* 图片上传完成
*
* @event module:ui/editor/command/uploadimage._$$UploadImageCard#onchange
* @param {String} arg0 - 命令名称
* @param {Object} arg1 - Flash返回的图片对象
*
*/
_p._$$UploadImageCard = _k._$klass();
_pro = _p._$$UploadImageCard._$extend(_i0._$$WindowWrapper);
/**
* 重置卡片
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__reset
* @param {Object} arg0 - 可配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
_options = _options || {};
_options.parent = _options.parent || document.body; //默认以document为parent
_options.draggable = _options.draggable || false;
_options.destroyable = _options.destroyable || false;
_options.title = _options.title || '选择图片';
_options.mask = true;
this.__super(_options);
this.__onShowErrorTips('');
};
/**
* 初始化卡片
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__init
* @param {Object} arg0 - 可配置参数
* @return {Void}
*/
_pro.__init = function(_options){
_options = _options||{};
this.__super(_options);
this.__desc[0].innerText = _options.fDesc || '支持JPG、JPEG、GIF、BMP格式的图片,文件需小于10M';
this.__desc[1].innerText = _options.oDesc || '网络图片不能超过2M';
this._$setEvent('oninitflash',_options.oninitflash || _f);
this._$setEvent('onflashinited',_options.onflashinited || _f);
this._$dispatchEvent('oninitflash');
this.__doRegiestFlashEvent(_options.namespace || 'nej.ui.cmd');
var _url = encodeURIComponent(_options.baseUrl || "http://upload.photo.163.com/anony/web/upload/userdefinesize?"+
+ "userdefinesize=" + _options.userdefinesize || '750x750x0x90;350x350x0x85'
+ "&saveorigin=" + _options.saveorigin || 'false'
+ "&responsetype=" + _options.responsetype || 'xml'
+ "&rotatedegree=" + _options.rotatedegree || '0'
+ "&stamptype=" + _options.stamptype || ''
+ "&stampstring=" + encodeURIComponent(_options.stampstring || '')
+ "&sitefrom=" + _options.sitefrom || 'study');
this.__hopt = {
src: _options.swfUrl || _c._$get('upload.image.swf'),
hidden: false,
parent: _e._$getByClassName(this.__body,'choose_file')[0],
width: _options.flashWidth || 100,
height: _options.flashHeight || 20,
params: {
flashvars: 'cbNameSpace=' + this.__namespace + '&uploadExif=true&uploadUrl=' + _url,
allowscriptaccess: 'always',
wmode: 'transparent'
},
onready: this.__onFlashReady._$bind(this)
};
_t1._$flash(this.__hopt);
};
/**
* 初始化节点
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
this.__desc = _e._$getByClassName(this.__body,'j-desc');
// 0 : 图片上传模式1
// 1 :图片上传模式2
this.__cnts = _e._$getByClassName(this.__body,'j-cnt');
var _nlist = _e._$getByClassName(this.__body,'j-ztag');
// 0 : 检查网络图片的容器
// 1 : 图片url
// 2 : 确认按钮
// 3 : 错误提示节点
this.__nimgUrl = _nlist[1];
this.__nerrorMsg = _nlist[3];
this.__nimgBox = _nlist[0];
this.__topt = {
list:_e._$getByClassName(this.__body,'j-tab'),
selected:'j-selected',
onchange:this.__onTabChange._$bind(this)
};
this.__tabMg = _t0._$$Tab._$allocate(this.__topt);
_v._$addEvent(_nlist[2],'click',this.__onSubmitImgUrl._$bind(this));
_v._$addEvent(this.__nimgBox,'error',this.__onImgUrlError._$bind(this));
_v._$addEvent(this.__nimgBox,'load',this.__onImgLoad._$bind(this));
_v._$addEvent(this.__nimgUrl,'focus',this.__onShowErrorTips._$bind(this,''));
};
/**
* 动态构建控件节点模板
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__initNodeTemplate
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
/**
* 注册flash回调方法
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__doRegiestFlashEvent
* @param {String} arg0 - Flash回调方法的命名空间
* @return {Void}
*/
_pro.__doRegiestFlashEvent = function(_space){
this.__namespace = _space + _u._$randNumberString(2);
var _namespace = NEJ.P(this.__namespace);
_namespace.uploadStart = this.__onUploadStart._$bind(this);
_namespace.uploadComplete = this.__onUploadComplete._$bind(this);
_namespace.uploadError = this.__uploadError._$bind(this);
_namespace.showProgress = this.__showProgress._$bind(this);
};
/**
* 图片上传完成的回调
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onUploadComplete
* @param {Number} id - flash的操作id
* @param {String} code - 图片上传状态码
* @param {Object} photoObj - 相册返回的图片对象
* @return {Void}
*/
_pro.__onUploadComplete = function(_id,_code,_photoObj){
if(_code != 999){
this.__onShowErrorTips('图片上传失败');
}else{
this.__onShowErrorTips('');
this._$dispatchEvent('onchange','inserthtml',_photoObj);
this.__onafterupload();
this._$hide();
}
};
/**
* 上传图片出错信息设置
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onShowErrorTips
* @param {String} arg0 - 错误信息
* @return {Void}
*/
_pro.__onShowErrorTips = function(_message){
this.__nerrorMsg.innerText = _message;
};
/**
* 开始图片上传
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onUploadStart
* @return {Void}
*/
_pro.__onUploadStart = function(){
this.__onbeforeupload();
};
/**
* flash加载完成回调
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onFlashReady
* @param {Object} arg0 - Flash对象
* @return {Void}
*/
_pro.__onFlashReady = function(_flash){
this.__flashObj = _flash;
this._$dispatchEvent('onflashinited');
};
/**
* 提交网络图片
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onSubmitImgUrl
* @return {Void}
*/
_pro.__onSubmitImgUrl = function(){
this.__nimgBox.src = this.__nimgUrl.value.trim();
};
/**
* 图片链接错误
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onImgUrlError
* @return {Void}
*/
_pro.__onImgUrlError = function(){
if (this.__nimgBox.src.indexOf('htpp://false')>0){
this.__nerrorMsg.innerText = '无法获取链接中的图片,请检查链接或稍后重试';
}
};
/**
* 图片链接正确
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onImgLoad
* @return {Void}
*/
_pro.__onImgLoad = function(){
var _photoObj = {
resultcode:999,
userDef2Url:this.__nimgUrl.value
};
this.__nimgBox.src = 'htpp://false';
this.__onUploadComplete('webimg',_photoObj.resultcode,_photoObj);
};
/**
* 图片上传前操作,子类实现
*
* @abstract
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onbeforeupload
* @return {Void}
*/
_pro.__onbeforeupload = _f;
/**
* 图片上传后操作,子类实现
*
* @abstract
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onafterupload
* @return {Void}
*/
_pro.__onafterupload = _f;
/**
* 图片上传错误,子类实现
*
* @abstract
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__uploadError
* @return {Void}
*/
_pro.__uploadError = _f;
/**
* 图片上传进程回调,子类实现
*
* @abstract
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__showProgress
* @return {Void}
*/
_pro.__showProgress = _f;
/**
* 切换tab
*
* @protected
* @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onTabChange
* @param {Object} arg0 - 当前Tab对象
* @return {Void}
*/
_pro.__onTabChange = function(_event){
this.__onShowErrorTips('');
var _index = _event.index;
this.__nimgUrl.value = '';
_e._$setStyle(this.__cnts[_index],'display','');
_e._$setStyle(this.__cnts[(_index+1)%2],'display','none');
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui.cmd'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 自定义富媒体编辑器封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/custom */
NEJ.define([
'base/global',
'base/klass',
'ui/editor/editor',
'util/template/tpl',
'util/editor/command/fontsize',
'util/editor/command/fontname',
'util/editor/command/bold',
'util/editor/command/italic',
'util/editor/command/insertorderedlist',
'util/editor/command/insertunorderedlist',
'util/editor/command/underline',
'util/editor/command/strikethrough',
'util/editor/command/forecolor',
'util/editor/command/backcolor',
'util/editor/command/justifyleft',
'util/editor/command/justifycenter',
'util/editor/command/justifyright',
'util/editor/command/link',
'util/editor/command/format',
'util/editor/command/uploadimage',
'util/editor/command/blockquote'
],function(NEJ,_k,_i0,_t0,_t1,_t2,_t3,_t4,_t5,_t6,_t7,_t8,_t9,_t10,_t11,_t12,_t13,_t14,_t15,_t16,_t17,_p,_o,_f,_r){
var _pro,
_seed_html;
/**
* 富媒体编辑器封装
*
* @class module:ui/editor/custom._$$CustomEditor
* @extends module:ui/editor/editor._$$Editor
* @param {Object} arg0 - 可选配置参数
*/
_p._$$CustomEditor = _k._$klass();
_pro = _p._$$CustomEditor._$extend(_i0._$$Editor);
/**
* 初始化外观信息
*
* @protected
* @method module:ui/editor/custom._$$CustomEditor#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__super();
this.__seed_html = _seed_html;
};
/**
* 动态构建控件节点模板
*
* @protected
* @method module:ui/editor/custom._$$CustomEditor#__initNodeTemplate
* @return {Void}
*/
_pro.__initNodeTemplate = (function(){
var _flist = [{cmd:'bold',txt:'加粗',icn:'z-i-30'}
,{cmd:'italic',txt:'斜体',icn:'z-i-31'}
,{cmd:'underline',txt:'下划线',icn:'z-i-32'}
,{cmd:'strikethrough',txt:'删除线',icn:'z-i-40'}
,{cmd:'insertorderedlist',txt:'有序列表',icn:'z-i-61'}
,{cmd:'insertunorderedlist',txt:'无序列表',icn:'z-i-62'}
,{cmd:'foreColor',txt:'字体颜色',icn:'z-i-41'}
,{cmd:'hiliteColor',txt:'背景颜色',icn:'z-i-122'}],
_tlist = [{cmd:'justifyLeft',txt:'左对齐',icn:'z-i-50'}
,{cmd:'justifyCenter',txt:'居中对齐',icn:'z-i-51'}
,{cmd:'justifyRight',txt:'右对齐',icn:'z-i-52'}
,{cmd:'link',txt:'超链接',icn:'z-i-42'}
,{cmd:'format',txt:'清除格式',icn:'z-i-72'}
,{cmd:'uploadImage',txt:'照片上传',icn:'z-i-82'}];
return function(){
_seed_html = _t0._$addNodeTemplate(
this.__doGenEditorXhtml({
toolbar:this.__doGenFontSizeXhtml()
+this.__doGenFontNameXhtml()
+this.__doGenCmdXhtml({xlist:_flist,hr:!0})
+this.__doGenCmdXhtml({xlist:_tlist})
}));
this.__seed_html = _seed_html;
};
})();
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>test editor</title>
<meta charset="utf-8"/>
</head>
<body>
<script>window.NEJ_CONF={root:'../../../../res/'};</script>
<script src="../../../../src/define.js"></script>
<script>
define([
'../custom.js'
],function(_i){
_i._$$CustomEditor._$allocate({
parent:document.body
});
});
</script>
</body>
</html>
.#<uispace>{width:500px;border:1px solid #ddd;text-align:center;}
.#<uispace> .zbg{background:url(#<root>nej_editor.png?20131028) no-repeat 100px 100px;}
.#<uispace> .ztbar{height:30px;background-color:#eee;zoom:1;}
.#<uispace> .ztbar:after{display:block;clear:both;visibility:hidden;height:0;content:".";}
.#<uispace> .zitm{float:left;width:24px;height:24px;margin:3px 0;course:pointer;}
.#<uispace> .zitm:hover{background-position:0 0;}
.#<uispace> .zitm.js-selected{background-position:-30px 0;}
.#<uispace> .zitm .zicn{width:16px;height:16px;margin:4px auto 0;overflow:hidden;text-indent:100px;}
.#<uispace> .zitm .ztxt{display:none;}
.#<uispace> .zisp{float:left;width:10px;height:24px;margin:3px 0;background-position:-60px 0;overflow:hidden;}
.#<uispace> .zsel{float:left;position:relative;height:20px;overflow:hidden;line-height:20px;padding:0 5px;margin:4px;border:1px solid #C5C5C5;background:#fff;font-size:12px;text-align:left;cursor:pointer;}
.#<uispace> .zsel .zarw{position:absolute;top:0;right:0;width:18px;height:18px;background-position:0px -244px;}
.#<uispace> .zsel.zfs{width:60px;}
.#<uispace> .zsel.zfm{width:140px;}
.#<uispace> .zarea{height:200px;}
.#<uispace> .zarea iframe{width:100%;height:100%;overflow:hidden;}
<textarea name='jst' id='#<seedIcmd>'>
{list xlist as x}
<div class="zitm zbg ${'js-'|seed}" data-command="${x.cmd}" title="${x.txt}">
<div class="zicn zbg ${x.icn}">&nbsp;</div>
<div class="ztxt">${x.txt}</div>
</div>
{/list}
{if defined("hr")&&!!hr}
<div class="zbg zisp">&nbsp;</div>
{/if}
</textarea>
<textarea name='jst' id='#<seedIfnt>'>
<div class="zsel ${icn} ${'js-'|seed}" data-command="${cmd}">
<span class="${'js-t-'|seed}">${txt}</span>
<span class="zarw zbg">&nbsp;</span>
</div>
</textarea>
<textarea name='jst' id='#<seedIedt>'>
<div>
<div class="ztbar">${toolbar}</div>
<div class="zarea"></div>
</div>
</textarea>
/*
* ------------------------------------------
* 富媒体编辑器基类封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/editor/editor */
NEJ.define([
'base/global',
'base/klass',
'base/config',
'base/element',
'base/event',
'base/util',
'ui/base',
'util/editor/editor',
'util/template/jst',
'util/editor/area',
'util/editor/toolbar',
'util/template/tpl',
'text!./editor.css',
'text!./editor.html'
],function(NEJ,_k,_c,_e,_v,_u,_i,_t0,_t1,_t2,_t3,_t4,_css,_html,_p,_o,_f,_r){
var _seed_css,
_seed_ui = _t4._$parseUITemplate(_html),
_seed_icmd = _seed_ui['seedIcmd'],
_seed_ifnt = _seed_ui['seedIfnt'],
_seed_iedt = _seed_ui['seedIedt'],
_pro;
/**
* 富媒体编辑器基类封装
*
* @class module:ui/editor/editor._$$Editor
* @uses module:util/editor/area._$$EditorArea
* @uses module:util/editor/toolbar._$$EditorToolbar
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {Boolean} focus - 是否自动聚焦
* @property {String} content - 文本内容
*
*/
_p._$$Editor = _k._$klass();
_pro = _p._$$Editor._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/editor/editor._$$Editor#__init
* @return {Void}
*/
_pro.__init = function(){
this.__aopt = {};
this.__topt = {};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/editor/editor._$$Editor#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
_u._$merge(this.__aopt,_options,function(_value,_key){
if(_key.search(/^on/)<0){
return !0;
}
});
this.__aopt.style = _options.style;
this.__aopt.content = _options.content;
this.__aopt.focus = _options.focus!==!1;
this.__editor = _t0._$$Editor._$allocate({
area:_t2._$$EditorArea._$allocate(this.__aopt)
,toolbar:_t3._$$EditorToolbar._$allocate(this.__topt)
});
};
/**
* 控件销毁
*
* @protected
* @method module:ui/editor/editor._$$Editor#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
// recycle editor first
this.__editor._$recycle();
this.__super();
delete this.__editor;
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/editor/editor._$$Editor#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/editor/editor._$$Editor#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
var _list = _e._$getChildren(this.__body);
this.__aopt.parent = _list[1];
this.__topt.list = _e._$getByClassName(_list[0],
'js-'+_t1._$seed());
};
/**
* 获取按钮html代码
*
* @protected
* @method module:ui/editor/editor._$$Editor#__doGenCmdXhtml
* @param {Object} arg0 - 命令数据
* @return {String} html代码
*/
_pro.__doGenCmdXhtml = function(_data){
return _t1._$get(_seed_icmd,_data);
};
/**
* 获取字号选择html代码
*
* @protected
* @method module:ui/editor/editor._$$Editor#__doGenFontSizeXhtml
* @return {String} html代码
*/
_pro.__doGenFontSizeXhtml = function(){
return _t1._$get(_seed_ifnt,
{cmd:'fontSize',txt:'标准',icn:'zfs'});
};
/**
* 获取字体选择html代码
*
* @protected
* @method module:ui/editor/editor._$$Editor#__doGenFontNameXhtml
* @return {String} html代码
*/
_pro.__doGenFontNameXhtml = function(){
return _t1._$get(_seed_ifnt,
{cmd:'fontName',txt:'Arial',icn:'zfm'});
};
/**
* 获取编辑器html代码
*
* @protected
* @method module:ui/editor/editor._$$Editor#__doGenEditorXhtml
* @param {Object} arg0 - 命令数据
* @return {Void}
*/
_pro.__doGenEditorXhtml = function(_data){
return _t1._$get(_seed_iedt,_data);
};
/**
* 取编辑内容
*
* @method module:ui/editor/editor._$$Editor#_$getContent
* @return {String} 内容
*/
_pro._$getContent = function(){
return this.__editor._$getContent();
};
/**
* 取编辑内容里的图片id和url列表
*
* @method module:ui/editor/editor._$$Editor#_$getContent
* @return {Array} 编辑内中的图片ID+@+图片地址的列表,根据ID是否为0判断是否需要放入列表
*/
_pro._$getPhotoIdsAndUrls = (function(){
var _filter = function(_item){
if(_item.id!=0)
this.__idsAndUrls.push(_item.id+'@'+_item.src);
}
return function(){
this.__idsAndUrls = [];
var _photoIdsAndUrls = [],
_content = this.__editor._$getContent(),
_div = document.createElement('div');
_div.innerHTML = _content;
var _document = _e._$get(_div),
_list = _document.getElementsByTagName('img');
_u._$forEach(_list,_filter,this);
var _idsAndUrlsLength = this.__idsAndUrls.length;
for(var i = 0; i < _idsAndUrlsLength; i++)
_photoIdsAndUrls.push(this.__idsAndUrls[i]);
return _photoIdsAndUrls;
}
})();
/**
* 取纯文本编辑内容
* @method module:ui/editor/editor._$$Editor#_$getTextContent
* @return {String} 内容
*/
_pro._$getTextContent = function(){
return this.__editor._$getTextContent();
};
/**
* 设置编辑内容
* @method module:ui/editor/editor._$$Editor#_$setContent
* @param {String} arg0 - 内容
* @return {Void}
*/
_pro._$setContent = function(_content){
this.__editor._$setContent(_content);
};
/**
* 注册命令实现
* @method module:ui/editor/editor._$$Editor#_$registCommand
* @param {Array|nej.ut._$$EditorCommand} arg0 - 命令实现类构造
* @return {Void}
*/
_pro._$registCommand = function(_class){
this.__editor._$registCommand(_class);
};
/**
* 显示编辑器
* @method module:ui/editor/editor._$$Editor#_$show
* @return {Void}
*/
_pro._$show = function(){
this.__body.style.display = '';
};
/**
* 隐藏编辑器
* @method module:ui/editor/editor._$$Editor#_$hide
* @return {Void}
*/
_pro._$hide = function(){
this.__body.style.display = 'none';
};
/*
* 获取图标样式代码
* @return {String} 图标样式
*/
var __doGenIconStyle = function(){
var _arr=[],_row=20,_col=3;
for(var i=0;i<_row;i++)
for(var j=0;j<_col;j++)
_arr.push('.#<uispace> .z-i-'+i+j+'{background-position:-'+(16*j)+'px -'+(40+i*16)+'px;}');
return _arr.join('');
};
// ui css text
_seed_css = _e._$pushCSSText(_css + __doGenIconStyle(),{root:_c._$get('root')});
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>custom测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
#editor-parent .mycustom{width:600px;}
</style>
</head>
<body>
<h1 id="qunit-header">nej custom.js test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id='editor-parent'></div>
<div id='getcnt'>getcnt</div>
<input id="files-upload" type="file" multiple accept="image/gif,image/png" name="file">
<script>
window.NEJ_CONF = {
root : '/res/'
}
</script>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./custom.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("custom",{
setup:function(){
this._e = nej.e;
this._ui = nej.ui;
this._v = nej.v;
}
});
//开始单元测试
test('生成一个富文本编辑器',function(){
expect(0);
var _getcnt = this._e._$get('getcnt');
var _parent = this._e._$get('editor-parent');
var _custom = this._ui._$$CustomEditor._$allocate({
parent:_parent,
clazz:'mycustom'
});
this._v._$addEvent(_getcnt,'click',function(){
alert(_custom.__editor.__copt.area._$getSelectText());
}._$bind(this));
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}custom.test.js',[
'../custom.js',
'base/element'
],f);
});
// test('define',function(){expect(0);
// define('{pro}src/ui/customTest.js',[
// 'base/platform',
// '../mywidget/{platform}hack.js',
// '../../..////../src/ui/editor/custom.js',
// 'base/element',
// '{pro}log.js'
// ],f);
// });
/*
* ------------------------------------------
* 列表项控件基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/item/item */
NEJ.define([
'base/global',
'base/klass',
'ui/base'
],function(NEJ,_k,_i,_p,_o,_f,_r){
var _pro;
/**
* 列表项控件基类
*
* 页面结构举例
*
* ```html
* <div id='item-box'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'ui/item/item'
* ],function(_k,_i0,_p,_o,_f,_r){
* var _ = NEJ.P,
* _p = _('nej.ut'),
* _e = _('nej.e');
* // 第一步:新建一个类,继承自此基类
* var _html_key = _e._$addNodeTemplate('<div>123</div>');
*
* _p._$$MyItem = _k._$klass();
* _proMyItem = _p._$$MyItem._$extend(_i0._$$Item);
* _proMyItem.__reset = function(_options){
* this.__data = _options.data;
* this.__super(_options);
* }
*
* _proMyItem.__doRefresh = function(){
* // 刷新一项,设置数据{name:'sean'}
* this.__body.innerText = this.__data.name;
* };
*
* _proMyItem.__initXGui = function(){
* this.__seed_html = _html_key;
* };
* });
* // 第二步:生成item列表
* // 可以自己循环list,生成item
* NEJ.define([
* 'base/event',
* 'path/to/custom/myitem.js'
* ],function(_e,_i0,_p,_o,_f,_r){
* var _item = _i0._$$MyItem._$allocate({
* parent:'item-box',
* data:list[i]
* });
* // 可以利用_e._$getItemTemplate接口,返回item列表
* _e._$getItemTemplate(
* [{name:'jack'},{name:'sean'}],
* _i0._$$MyItem,
* {parent:'item-box'}
* );
* });
* ```
*
* @class module:ui/item/item._$$Item
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {Object} data - 当前项绑定的数据
* @property {Number} index - 当前项的索引
* @property {Number} total - 总列表长度
* @property {Array} range - 当前项所在的列表片段方位(begin,end)
*/
_p._$$Item = _k._$klass();
_pro = _p._$$Item._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/item/item._$$Item#__init
* @return {Void}
*/
_pro.__init = function(){
this.__id = this.__genId();
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/item/item._$$Item#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__index = _options.index;
this.__total = _options.total;
this.__range = _options.range;
this._$refresh(_options.data);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/item/item._$$Item#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__data;
delete this.__index;
delete this.__total;
delete this.__range;
};
/**
* 刷新项,子类实现具体逻辑
*
* @abstract
* @method module:ui/item/item._$$Item#__doRefresh
* @return {Void}
*/
_pro.__doRefresh = _f;
/**
* 生成ID
*
* @protected
* @method module:ui/item/item._$$Item#__genId
* @return {String} ID
*/
_pro.__genId = (function(){
var _seed = +new Date;
return function(){
return 'itm-'+(++_seed);
};
})();
/**
* 取项标识
*
* 脚本举例
* ```javascript
* // 获取当前item的id标识
* _item._$getId();
* ```
*
* @method module:ui/item/item._$$Item#_$getId
* @return {String} 项标识
*/
_pro._$getId = function(){
return this.__id;
};
/**
* 取项绑定数据
*
* 脚本举例:
* ```javascript
* // 获取当前item的数据信息
* _item._$getData();
* ```
*
* @method module:ui/item/item._$$Item#_$getData
* @return {Object} 数据信息
*/
_pro._$getData = function(){
return this.__data;
};
/**
* 刷新项绑定的数据
*
* 脚本举例:
* ```javascript
* // 获取当前item的数据信息
* _item._$refresh({
* a:'aaaaa',
* b:'bbbbb'
* });
* ```
*
* @method module:ui/item/item._$$Item#_$refresh
* @param {Object} arg0 - 项绑定的数据
* @return {Void}
*/
_pro._$refresh = function(_data){
this.__data = _data||{};
this.__doRefresh(this.__data);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 列表项基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/item/list */
NEJ.define([
'base/global',
'base/klass',
'ui/item/item'
],function(NEJ,_k,_i0,_p,_o,_f,_r){
var _pro;
/**
* 列表项基类对象
*
* @class module:ui/item/list._$$ListItem
* @extends module:ui/item/item._$$Item
* @param {Object} arg0 - 配置参数
* @property {String} pkey - 主键字段名称,默认为id
*/
/**
* 删除列表项触发事件
*
* @event module:ui/item/list._$$ListItem#ondelete
* @param {Object} arg0 - 事件信息
* @property {String} id - 项标识
* @property {Object} data - 项绑定的数据
*
*/
_p._$$ListItem = _k._$klass();
_pro = _p._$$ListItem._$extend(_i0._$$Item);
/**
* 控件重置
*
* @protected
* @method module:ui/item/list._$$ListItem#__reset
* @param {Object} arg0 - 配置信息
* @return {Void}
*/
_pro.__reset = function(_options){
this.__pkey = _options.pkey||'id';
this.__prefix = _options.prefix||'';
this.__super(_options);
};
/**
* 删除列表项触发事件
*
* @protected
* @method module:ui/item/list._$$ListItem#__onDelete
* @return {Void}
*/
_pro.__onDelete = function(_data){
this._$dispatchEvent('ondelete',{
ext:_data,
id:this._$getId(),
data:this._$getData(),
body:this._$getBody()
});
};
/**
* 删除列表项触发事件
*
* @protected
* @method module:ui/item/list._$$ListItem#__onUpdate
* @return {Void}
*/
_pro.__onUpdate = function(_data){
this._$dispatchEvent('onupdate',{
ext:_data,
id:this._$getId(),
data:this._$getData(),
body:this._$getBody()
});
};
/**
* 刷新项绑定的数据<br/>
*
* 脚本举例:
* ```javascript
* // 获取当前item的数据信息
* _item._$refresh({
* a:'aaaaa',
* b:'bbbbb'
* });
* ```
*
* @method module:ui/item/list._$$ListItem#_$refresh
* @param {Object} arg0 - 项绑定的数据
* @return {Void}
*/
_pro._$refresh = function(_data){
this.__super(_data);
var _id = this.__data[this.__pkey];
this.__id = (this.__prefix+_id)||this.__genId();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
.#<uispace>{position:absolute;background:#fff;}
/*
* ------------------------------------------
* 卡片控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/layer/card */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/event',
'ui/layer/layer',
'text!./card.css'
],function(NEJ,_k,_e,_v,_i0,_css,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 卡片控件
*
* 页面结构举例
* ```html
* <div id="card-box" class="box"></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event',
* 'ui/layer/card'
* ],function(_e,_i0,_p,_o,_f,_r){
* // 生成卡片的实例
* var _card = _i0._$$Card._$allocate({
* parent:'card-box',
* top:10,
* left:10,
* destroyable:true,
* content:'<div>您要显示的内容HTML或节点</div>',
* oncontentready:function(_html){
* // 卡片里塞入内容的回调
* },
* onbeforerecycle:function(){
* // 回收前触发的回调
* }
* });
* // 默认就是显示的,此方法对应_$hide();
* _card._$show();
* });
* ```
*
* @class module:ui/layer/card._$$Card 卡片控件
* @extends module:ui/layer/layer._$$Layer
* @param {Object} arg0 - 可选配置参数
* @property {String} top - 卡片垂直位置
* @property {String} left - 卡片水平位置
* @property {Boolean} nostop - 是否禁用事件阻止
*/
_p._$$Card = _k._$klass();
_pro = _p._$$Card._$extend(_i0._$$Layer);
/**
* 控件重置
*
* @protected
* @method module:ui/layer/card._$$Card#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__doInitDomEvent([[
document,'click',
this.__onDocClick._$bind(this)
]]);
this.__nostop = !!_options.nostop;
this.__position = {
top:_options.top,
left:_options.left
};
};
/**
* 控件销毁
*
* @protected
* @method module:ui/layer/card._$$Card#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
delete this.__pbox;
delete this.__fbox;
delete this.__align;
delete this.__fitable;
delete this.__byPoint;
delete this.__position;
this.__super();
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/layer/card._$$Card#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/layer/card._$$Card#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
this.__ncnt = this.__body;
_v._$addEvent(
this.__body,'click',
this.__doCheckStop._$bind(this)
);
};
/**
* 文档点击事件
*
* @protected
* @method module:ui/layer/card._$$Card#__onDocClick
* @return {Void}
*/
_pro.__onDocClick = function(_event){
// fix firefox fire click when right button click
if (_event.button!=2) this._$hide();
};
/**
* 检查点击节点默认事件
*
* @protected
* @method module:ui/layer/card._$$Card#__doCheckStop
* @return {Void}
*/
_pro.__doCheckStop = function(_event){
if (this.__nostop) return;
_v._$stopBubble(_event);
var _element = _v._$getElement(_event);
if (_element.tagName=='A')
_v._$stopDefault(_event);
};
/**
* 设置对齐方式
*
* @protected
* @method module:ui/layer/card._$$Card#__setAlign
* @param {String} arg0 - 对齐方式
* @return {Void}
*/
_pro.__setAlign = (function(){
var _reg = /\s+/i;
return function(_align){
_align = (_align||'').trim()
.toLowerCase().split(_reg);
_align[0] = _align[0]||'bottom';
_align[1] = _align[1]||'left';
this.__align = _align;
};
})();
/**
* 根据适应方式取位置信息
*
* @protected
* @method module:ui/layer/card._$$Card#__doCalPosition
* @param {String} arg0 - 适应位置
* @return {Object} 位置信息
*/
_pro.__doCalPosition = function(_align){
var _result = {},
_fbox = this.__fbox,
_pbox = _e._$getPageBox(),
_width = this.__body.offsetWidth,
_height = this.__body.offsetHeight;
switch(_align[0]){
case 'top':
_result.top = _fbox.top-_height;
_result.left = _align[1]=='right'
? _fbox.left+_fbox.width-_width
: _fbox.left;
break;
case 'left':
_result.left = _fbox.left-_width;
_result.top = _align[1]=='bottom'
? _fbox.top+_fbox.height-_height
: _fbox.top;
break;
case 'right':
_result.left = _fbox.left+_fbox.width;
_result.top = _align[1]=='bottom'
? _fbox.top+_fbox.height-_height
: _fbox.top;
break;
default:
_result.top = _fbox.top+_fbox.height;
_result.left = _align[1]=='right'
? _fbox.left+_fbox.width-_width
: _fbox.left;
break;
}
return _result;
};
/**
* 调整显示位置
*
* @protected
* @method module:ui/layer/card._$$Card#__doPositionAlign
* @return {Void}
*/
_pro.__doPositionAlign = function(){
if (!this.__fitable){
this._$setPosition(this.__position);
return;
}
if(!!this.__byPoint){
this._$setPosition(this.__pbox);
return;
}
if (!!this.__fbox)
this._$setPosition(
this.__doCalPosition(this.__align));
};
/**
* 根据卡片规则计算左上角的坐标
*
* @protected
* @method module:ui/layer/card._$$Card#__doFindPosition
* @return {Object} 卡片左上角坐标{top:20,left:10}
*/
_pro.__doFindPosition = function(_element,_delta,_event){
_delta = _delta||_o;
var _pageBox = _e._$getPageBox(),
_x = _v._$pageX(_event) + (_delta.left||0),
_y = _v._$pageY(_event) + (_delta.top||0),
_width = _element.offsetWidth + (_delta.right||0),
_height= _element.offsetHeight + (_delta.bottom||0),
_pageWidth = _pageBox.scrollWidth,
_pageHeight= _pageBox.scrollHeight,
_temp0 = _x + _width,
_temp1 = _y + _height;
switch(this.__align[0]){
case 'top':
_y = (_temp1 > _pageHeight) ? (_y - _height): _y;
if(this.__align[1] == 'right'){
_x = (_x - _width) < 0 ? 0 : (_x - _width);
}else{
_x = (_temp0 > _pageWidth) ? (_pageWidth - _width): _x;
}
break;
case 'left':
_x = (_temp0 > _pageWidth) ? (_pageWidth - _width): _x;
if(this.__align[1] == 'top'){
_y = (_temp1 > _pageHeight) ? (_y - _height): _y;
}else{
_y = (_y - _height) < 0 ? _y : (_y - _height);
}
break;
case 'right':
_x = (_x - _width) < 0 ? 0 : (_x - _width);
if(this.__align[1] == 'top'){
_y =(_temp1 > _pageHeight) ? (_y - _height) : _y;
}else{
_y = (_y - _height) < 0 ? _y : (_y - _height);
}
break;
default:
_y = (_y - _height) < 0 ? _y : (_y - _height);
if(this.__align[1] == 'left'){
_x = (_temp0 > _pageWidth) ? (_pageWidth - _width): _x;
}else{
_x = (_x - _width) < 0 ? 0 : (_x - _width);
}
break;
}
return {top:_y,left:_x};
};
/**
* 偏移量信息对象
*
* @typedef {Object} module:ui/layer/card._$$Card~Delta
* @property {Number} top - 上偏移量
* @property {Number} right - 右偏移量
* @property {Number} bottom - 下偏移量
* @property {Number} left - 左偏移量
*/
/**
* 对齐方式信息对象
*
* @typedef {Object} module:ui/layer/card._$$Card~Align
* @property {Number} top - 上对齐
* @property {Number} right - 右对齐
* @property {Number} bottom - 下对齐
* @property {Number} left - 左对齐
*/
/**
* 通过参照节点显示卡片位置
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event',
* 'ui/layer/card'
* ],function(_e,_i0,_p,_o,_f,_r){
* // 生成卡片的实例
* var _card = _i0._$$Card._$allocate({
* parent:'card-box',
* top:10,
* left:10,
* destroyable:true,
* content:'<div>您要显示的内容HTML或节点</div>',
* oncontentready:function(_html){
* // 卡片里塞入内容的回调
* },
* onbeforerecycle:function(){
* // 回收前触发的回调
* }
* });
* // 卡片显示的时候,根据target节点来定位,卡片位置固定
* // align代表卡片的对齐方式
* // delta代表偏移量
* _card._$showByReference({
* align:'top right',
* target:document.body,
* delta:{top:10,right:20}
* });
* // 另外一种情况,根据鼠标点击来定位卡片位置
* // 需要传入鼠标事件的event信息
* // 鼠标传入的点的坐标为基准
* // align表示,此点代表卡片的哪个位置
* // delta代表偏移量
* // 如果卡片超出可视区域范围,会参照windows桌面右键卡片布局
* _card._$showByReference({
* event:_event,
* align:'top right',
* target:document.body,
* delta:{top:10,right:20}
* });
* });
* ```
*
* @method module:ui/layer/card._$$Card#_$showByReference
* @param {Object} arg0 - 可选配置参数
* @property {module:ui/layer/card._$$Card~Delta} delta - 位置偏移
* @property {module:ui/layer/card._$$Card~Align} align - 卡片对齐位置,默认为'top left'
* | 整体位置 | 对齐方式 |
* | :--- | :--- |
* | top/right/bottom/left| top/bottom/left/right |
* @property {Boolean} fitable - 是否需要调整卡片位置使其适应页面
* @return {Void}
*/
_pro._$showByReference = (function(){
var _doCalTargetBox = function(_element,_delta){
_element = _e._$get(_element);
if (!_element) return;
_delta = _delta||_o;
var _offset = _e._$offset(_element);
return {top:_offset.y-(_delta.top||0),
left:_offset.x-(_delta.left||0),
width:_element.offsetWidth+(_delta.right||0),
height:_element.offsetHeight+(_delta.bottom||0)};
};
return function(_options){
_options = _options||_o;
this.__byPoint = _options.event;
this.__setAlign(_options.align);
if(!!this.__byPoint)
this.__pbox = this.__doFindPosition(_options.target,_options.delta,this.__byPoint);
this.__fbox = _doCalTargetBox(
_options.target,_options.delta);
this.__fitable = !!_options.fitable;
this._$show();
};
})();
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/layer/wrapper/card for compatible
// use ui/layer/wrapper/card for new project
NEJ.define(['./wrapper/card.js'],function(_t){return _t;});
<!DOCTYPE html>
<html>
<head>
<title>test window</title>
<meta charset="utf-8" />
<style>
body,html{width:100%;height:100%;}
</style>
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<select><option>1</option><option>2</option></select>
<textarea name="ntp" id="tpl-win">
<form>
<input type="text" name="time" data-type="date" data-required="true" data-message="必须设置日期"/>
<input type="button" name="btn" value="ok"/>
</form>
</textarea>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'base/klass',
'base/event',
'util/template/tpl',
'util/form/form',
'../wrapper/window.js'
],function(_k,_v,_e,_t,_i,_p,_o,_f,_r,_pro){
_e._$parseTemplate('tpl-win');
_p._$$Window = _k._$klass();
_pro = _p._$$Window._$extend(_i._$$WindowWrapper);
_pro.__initXGui = function(){
this.__seed_html = 'tpl-win';
};
_pro.__initNode = function(){
this.__super();
_v._$addEvent(
this.__body.btn,'click',
this.__onSubmit._$bind(this)
);
this.__form = _t._$$WebForm._$allocate({
form:this.__body
});
};
_pro.__onSubmit = function(){
if (this.__form._$checkValidity()){
this._$hide();
log('submit form to server');
}
};
// init
_p._$$Window._$allocate({
parent:document.body,
draggable:true,
align:'left top'
})._$show();
});
</script>
</body>
</html>
/*
* ------------------------------------------
* 弹出层控件基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/layer/layer */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/util',
'ui/base'
],function(NEJ,_k,_e,_u,_i,_p,_o,_f,_r){
var _pro;
/**
* 弹出层控件基类
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'base/element',
* 'ui/layer/layer'
* ],function(_k,_e,_i0,_p,_o,_f,_r){
* // 第一步:继承此基类生成新类
* var _seed_css = _e._$pushCSSText('.#<uispace>{position:absolute;background:#fff;}');
* _p._$$MyLayer = _k._$klass();
* _proMyLayer = _p._$$MyLayer._$extend(_i0._$$Layer);
*
* _proMyLayer.__initXGui = function(){
* this.__seed_css = _seed_css;
* };
*
* _proMyLayer.__initNode = function(){
* this.__super();
* // this.__ncnt作为放置卡片内容的容器
* this.__ncnt = this.__body;
* };
*
*
* // 最后项目中实例化wrapper的实例
* var _ly = _p._$$MyLayerCard._$allocate({
* parent:document.body,
* // 隐藏浮层时,是否销毁
* destroyable:false,
* oncontentready:function(_html){
* // 设置浮层内容的回调
* }
* });
* });
* // 第二步:实例化一个弹出层
* // 一般在layerwrapper控件中使用
* // 因为lopt的有默认配置在layerwrapper中
* NEJ.define([
* 'base/klass',
* 'ui/layer/wrapper/layer',
* '/path/custom/to/mylayer.js'
* ],function(_k,_i0,_i1,_p,_o,_f,_r){
* // 下面是对layerwrapper的描述
*
* // 首先:继承layerwrapper基类生成的一个新类
* _p._$$MyCardWrapper = _k._$klass();
* _proMyCardWrapper = _p._$$MyCardWrapper._$extend
* (_i0._$$LayerWrapper);
*
* // 这里返回内容层的实例
* _proMyCardWrapper.__getLayerInstance = function(){
* return _i1._$$MyLayer._$allocate(this.__lopt);
* };
*
* // 这里配置lopt参数,生成内容层用
* _proMyCardWrapper.__doInitLayerOptions = function(){
* this.__super();
* this.__lopt.top = null;
* this.__lopt.left = null;
* };
* });
* ```
*
* @class module:ui/layer/layer._$$Layer
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {String|Node} content - 内容HTML代码或者节点对象
* @property {Boolean} destroyable -调用隐藏时是否自动回收,默认不自动回收
* @property {Boolean} nohack - 针对IE6不做hack处理
*/
/**
* 显示内容准备就绪触发事件
*
* @event module:ui/layer/layer._$$Layer#oncontentready
* @param {Node} arg0 - 显示内容的节点
*/
/**
* 控件回收前触发事件
*
* @event module:ui/layer/layer._$$Layer#onbeforerecycle
*/
_p._$$Layer = _k._$klass();
_pro = _p._$$Layer._$extend(_i._$$Abstract);
/**
* 控件重置
*
* @protected
* @method module:ui/layer/layer._$$Layer#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this._$setEvent('oncontentready',
_options.oncontentready||
this.__doInitContent._$bind(this));
this.__nohack = !!_options.nohack;
this.__destroyable = !!_options.destroyable;
this._$setContent(_options.content);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/layer/layer._$$Layer#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this._$dispatchEvent('onbeforerecycle');
this.__super();
this.__doHide();
this._$setContent('');
_e._$style(this.__body,{top:'',left:''});
};
/**
* 初始化内容区域,子类实现具体逻辑
*
* @abstract
* @method module:ui/layer/layer._$$Layer#__doInitContent
* @param {Node} arg0 - 内容区容器节点
* @return {Void}
*/
_pro.__doInitContent = _f;
/**
* 调整显示位置,子类实现具体业务逻辑
*
* @abstract
* @method module:ui/layer/layer._$$Layer#__doPositionAlign
* @return {Void}
*/
_pro.__doPositionAlign = _f;
/**
* 控件隐藏
*
* @protected
* @method module:ui/layer/layer._$$Layer#__doHide
* @return {Void}
*/
_pro.__doHide = function(){
_e._$removeByEC(this.__body);
if (!!this.__mask){
_e._$unmask(this.__body);
delete this.__mask;
}
};
/**
* 设置层显示内容
*
* 脚本举例
* ```javascript
* // 设置层里面展示的内容
* _ly._$setContent('节点或者字符串');
* ```
*
* @method module:ui/layer/layer._$$Layer#_$setContent
* @param {String|Node} arg0 - 内容HTML代码或者节点
* @return {Void}
*/
_pro._$setContent = function(_content){
if (!this.__body||
!this.__ncnt||
_content==null) return;
_content = _content||'';
_u._$isString(_content)
? this.__ncnt.innerHTML = _content
: this.__ncnt.appendChild(_content);
this._$dispatchEvent('oncontentready',this.__ncnt);
};
/**
* 设置位置
*
* 脚本举例
* ```javascript
* // 设置浮层位置
* _ly._$setPosition({top:100,left:200});
* ```
*
* @method module:ui/layer/layer._$$Layer#_$setPosition
* @param {Object} arg0 - 位置信息,如{top:100,left:200}
* @return {Void}
*/
_pro._$setPosition = function(_offset){
var _value = _offset.top;
if (_value!=null){
_value += 'px';
_e._$setStyle(this.__body,'top',_value);
_e._$setStyle(this.__mask,'top',_value);
}
var _value = _offset.left;
if (_value!=null){
_value += 'px';
_e._$setStyle(this.__body,'left',_value);
_e._$setStyle(this.__mask,'left',_value);
}
};
/**
* 显示控件
*
* 脚本举例
* ```javascript
* // 显示浮层
* _ly._$show();
* ```
*
* @method module:ui/layer/layer._$$Layer#_$show
* @return {Void}
*/
_pro._$show = function(){
_e._$setStyle(this.__body,'visibility','hidden');
this.__super();
this.__doPositionAlign();
_e._$setStyle(this.__body,'visibility','');
if (!this.__nohack){
this.__mask = _e._$mask(this.__body);
}
};
/**
* 隐藏控件
*
* 脚本举例
* ```javascript
* // 隐藏浮层
* _ly._$hide();
* ```
*
* @method module:ui/layer/layer._$$Layer#_$hide
* @return {Void}
*/
_pro._$hide = function(){
this.__destroyable ? this._$recycle()
: this.__doHide();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/layer/wrapper/layer for compatible
// use ui/layer/wrapper/layer for new project
NEJ.define(['./wrapper/layer.js'],function(_t){return _t;});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>card测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
.box{position:relative;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit card test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="card-box" class="box"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./card.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("ui-card");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui');
//开始单元测试
test('card',function(){
stop();
var _card = _p._$$Card._$allocate({
parent:'card-box',
top:10,
left:10,
destroyable:true,
content:'<div>请点击一下页面,完成卡片的回收</div>',
oncontentready:function(_html){
ok(true,'设置卡片内容成功');
},
onbeforerecycle:function(){
ok(true,'destroyable属性决定回收前是否触发');
start();
}
});
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}card.test.js',['ui/layer/card'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>layer测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit layer test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./layer.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("layer");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui');
//开始单元测试
test('layer',function(){
stop();
var _ly = _p._$$MyLayerCard._$allocate({
parent:document.body,
destroyable:false,
oncontentready:function(_html){
ok(true,'设置卡片内容成功');
start();
}
});
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}layer.test.js',['{pro}mylayercard.js'],f);
});
/*
* ------------------------------------------
* 卡片控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
var f = function(){
var _ = NEJ.P,
_o = NEJ.O,
_v = _('nej.v'),
_e = _('nej.e'),
_p = _('nej.ui'),
_proMyLayer;
if (!!_p._$$MyLayer) return;
// ui css text
var _seed_css = _e._$pushCSSText('.#<uispace>{position:absolute;background:#fff;}');
/**
* 卡片控件
* @param {Object} 可选配置参数
* @property {String} top 卡片垂直位置
* @property {String} left 卡片水平位置
*/
_p._$$MyLayer = NEJ.C();
_proMyLayer = _p._$$MyLayer._$extend(_p._$$Layer);
/**
* 控件重置
*
* @protected
* @method {__reset}
* @param {Object} 可选配置参数
* @return {Void}
*/
_proMyLayer.__reset = function(_options){
this.__super(_options);
};
/**
* 控件销毁
*
* @protected
* @method {__destroy}
* @return {Void}
*/
_proMyLayer.__destroy = function(){
this.__super();
};
/**
* 初始化外观信息
*
* @protected
* @method {__initXGui}
* @return {Void}
*/
_proMyLayer.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 初始化节点
*
* @protected
* @method {__initNode}
* @return {Void}
*/
_proMyLayer.__initNode = function(){
this.__super();
this.__ncnt = this.__body;
};
};
define('{pro}mylayer.js',
['ui/layer/layer'],f);
var f = function(){
var _ = NEJ.P,
_f = NEJ.F,
_u = _('nej.u'),
_e = _('nej.e'),
_p = _('nej.ui'),
_proMyLayerCard;
var _seed_html = _e._$addNodeTemplate('<div>您要展示的内容部分</div>');
/**
* 弹出层封装基类对象,主要实现层里面内容部分的业务逻辑
* @class 弹出层封装基类对象
* @extends {nej.ui._$$CardWrapper}
* @param {Object} _options 可选配置参数
*
*/
_p._$$MyLayerCard = NEJ.C();
_proMyLayerCard = _p._$$MyLayerCard._$extend(_p._$$MyCardWrapper);
_proMyLayerCard.__initXGui = function(){
this.__seed_html = _seed_html;
};
};
define('{pro}mylayercard.js',
['{pro}mylayerwrapper.js'],f);
/*
* ------------------------------------------
* 弹出卡片封装基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
var f = function(){
var _ = NEJ.P,
_o = NEJ.O,
_e = _('nej.e'),
_v = _('nej.v'),
_u = _('nej.u'),
_p = _('nej.ui'),
_proMyCardWrapper;
if (!!_p._$$MyCardWrapper) return;
/**
*
* @class module:nej.ui._$$MyCardWrapper 弹出卡片封装基类对象
* @extends {nej.ui._$$LayerWrapper}
* @param {Object} 可选配置参数
*
*/
_p._$$MyCardWrapper = NEJ.C();
_proMyCardWrapper = _p._$$MyCardWrapper._$extend(_p._$$LayerWrapper);
/**
* 构建弹层控件实例,子类实现具体业务逻辑
*
* @protected
* @method {__getLayerInstance}
* @return {nej.ui._$$Layer} 弹层控件实例
*/
_proMyCardWrapper.__getLayerInstance = function(){
return _p._$$MyLayer._$allocate(this.__lopt);
};
/**
* 初始化弹层控件可选配置参数
*
* @protected
* @method {__doInitLayerOptions}
* @return {Void}
*/
_proMyCardWrapper.__doInitLayerOptions = function(){
_p._$$MyCardWrapper._$supro
.__doInitLayerOptions.apply(this,arguments);
this.__lopt.top = null;
this.__lopt.left = null;
};
};
define('{pro}mylayerwrapper.js',
['ui/layer/layer.wrapper'
,'{pro}mylayer.js'],f);
var f = function(){
var _ = NEJ.P,
_f = NEJ.F,
_u = _('nej.u'),
_e = _('nej.e'),
_p = _('nej.ui'),
_proMyWindow;
var _seed_html = _e._$addNodeTemplate('<div>您要展示的内容部分</div>');
/**
* 弹出层封装基类对象,主要实现层里面内容部分的业务逻辑
* @class 弹出层封装基类对象
* @extends {nej.ui._$$CardWrapper}
* @param {Object} _options 可选配置参数
*
*/
_p._$$MyWindow = NEJ.C();
_proMyWindow = _p._$$MyWindow._$extend(_p._$$WindowWrapper);
_proMyWindow.__initXGui = function(){
this.__seed_html = _seed_html;
};
_proMyWindow.__reset = function(_options){
_options = _options || {};
_options.draggable = !!_options.draggable ? true : false;
_options.destroyable = !!_options.destroyable ? true : false;
this.__super(_options);
};
};
define('{pro}mywindow.js',
['ui/layer/window.wrapper'],f);
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>window测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
body, html{width:100%;height:100%;border:0;padding:0;margin:0;}
.box{position:relative;width:500px;height:200px;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit window test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="window-box" class="box"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./window.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("ui-window");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui');
//开始单元测试
test('window',function(){
stop();
var _window = _p._$$Window._$allocate({
parent:document.body,
title:'弹出框标题',
align:'left middle',
draggable:true,
onclose:function(){
ok(true,'成功关闭窗口');
start();
}
});
_window._$show();
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}window.test.js',['ui/layer/window'],f);
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>windowWarpper测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
.box{position:relative;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit windowWarpper test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./window.wrapper.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("ui-windowWarpper");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui'),
_v = _('nej.v');
//开始单元测试
test('windowWarpper',function(){
stop();
var _myCard = _p._$$MyWindow._$allocate({
parent:document.body,
title:'窗口标题',
draggable:false,
mask:true,
onclose:function(){
ok(true,'成功关闭浮层');
start();
}
});
});
// test('windowWarpper-2',function(){
// stop();
// var _myCard = _p._$$MyWindow._$allocate({
// parent:document.body,
// title:'窗口标题2',
// draggable:true,
// mask:true,
// onclose:function(){
// ok(true,'成功关闭浮层');
// start();
// }
// });
// });
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}window.wrapper.test.js',['{pro}mywindow.js'],f);
});
.#<uispace>{position:absolute;z-index:1000;border:1px solid #aaa;background:#fff;}
.#<uispace> .zbar{line-height:30px;background:#8098E7;border-bottom:1px solid #aaa;}
.#<uispace> .zcnt{padding:10px 5px;}
.#<uispace> .zttl{margin-right:20px;text-align:left;}
.#<uispace> .zcls{position:absolute;top:5px;right:0;width:20px;height:20px;line-height:20px;cursor:pointer;}
<div>
<div class="zbar"><div class="zttl">标题</div></div>
<div class="zcnt"></div>
<span class="zcls" title="关闭窗体">×</span>
</div>
/*
* ------------------------------------------
* 窗体控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/layer/window */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/event',
'base/util',
'ui/layer/layer',
'ui/mask/mask',
'util/dragger/dragger',
'util/template/tpl',
'text!./window.css',
'text!./window.html'
],function(NEJ,_k,_e,_v,_u,_i0,_i1,_t0,_t1,_css,_html,_p,_o,_f,_r){
var _seed_css = _e._$pushCSSText(_css),
_seed_html = _t1._$addNodeTemplate(_html),
_pro;
/**
* 窗体控件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/layer/window'
* ],function(_i0,_p,_o,_f,_r){
* var _window = _i0._$$Window._$allocate({
* parent:document.body,
* title:'弹出框标题',
* align:'left middle',
* draggable:true,
* onclose:function(){
* // 窗口关闭前的回调方法
* }
* });
* // 显示窗口,默认实例化后会显示,如果_$hide()后需要手动调用
* _window._$show();
* });
* ```
*
* @class module:ui/layer/window._$$Window 窗体控件
* @extends module:ui/layer/layer._$$Layer
* @param {Object} arg0 - 可选配置参数
* @property {String} title - 窗口标题
* @property {String} align - 相对于视窗位置定义,横向+空格+纵向,默认为center middle
* | 横向 | 纵向 |
* | :--- | :--- |
* | left/center/right/auto | top/middle/bottom/auto |
* @property {Boolean} draggable - 是否可拖拽
* @property {nej.ui._$$Mask|Boolean|String} mask - 盖层信息
* | mask参数 | 含义 |
* | :--- | :--- |
* | 如果是nej.ui._$$Mask的子类 | 则为盖层构造 |
* | 如果是布尔值 | 则使用默认盖层 |
* | 如果是字符串 | 则为盖层样式 |
*/
/**
* 关闭窗体触发事件
*
* @event module:ui/layer/window._$$Window#onclose
*
*/
_p._$$Window = _k._$klass();
_pro = _p._$$Window._$extend(_i0._$$Layer);
/**
* 控件初始化
*
* @protected
* @method module:ui/layer/window._$$Window#__init
* @return {Void}
*/
_pro.__init = function(){
this.__mopt = {};
this.__dopt = {onchange:this.__onDragging._$bind(this)};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/layer/window._$$Window#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__setMask(_options.mask);
this._$setAlign(_options.align);
this._$setTitle(_options.title);
if (!_options.draggable) return;
this.__dragger = _t0._$$Dragger.
_$allocate(this.__dopt);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/layer/window._$$Window#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__align;
delete this.__mclz;
if (!!this.__imask){
this.__imask._$recycle();
delete this.__imask;
}
if (!!this.__dragger){
this.__dragger._$recycle();
delete this.__dragger;
}
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/layer/window._$$Window#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
this.__seed_html= _seed_html;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/layer/window._$$Window#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
// 0 - move bar
// 1 - content box
// 2 - close btn
var _list = _e._$getChildren(this.__body);
this.__ncnt = _list[1];
this.__dopt.mbar = _list[0];
this.__dopt.body = this.__body;
_v._$addEvent(_list[2],'mousedown',
this.__onClose._$bind(this));
_v._$addEvent(this.__dopt.mbar,'mousedown',
this.__onDragStart._$bind(this));
this.__nttl = _e._$getChildren(this.__dopt.mbar)[0];
};
/**
* 关闭窗口
*
* @protected
* @method module:ui/layer/window._$$Window#__onClose
* @param {Event} arg0 - 事件对象
* @return {Void}
*/
_pro.__onClose = function(_event){
_v._$stop(_event);
this._$dispatchEvent('onclose');
this._$hide();
};
/**
* 窗口开始拖动过程
*
* @protected
* @method module:ui/layer/window._$$Window#__onDragStart
* @param {Event} arg0 - 事件信息
* @return {Void}
*/
_pro.__onDragStart = function(_event){
_v._$dispatchEvent(document,'click');
};
/**
* 窗口拖动过程
*
* @protected
* @method module:ui/layer/window._$$Window#__onDragging
* @param {Object} arg0 - 窗口位置信息
* @return {Void}
*/
_pro.__onDragging = function(_event){
if (!this.__mask) return;
_e._$style(this.__mask,{
top:_event.top+'px',
left:_event.left+'px'
});
};
/**
* 窗口位置调整
*
* @protected
* @method module:ui/layer/window._$$Window#__doPositionAlign
* @return {Void}
*/
_pro.__doPositionAlign = (function(){
var _func = [function(){return 0;},
function(_scroll,_delta,_key){
return Math.max(0,_scroll[_key]+_delta[_key]/2);
},
function(_scroll,_delta,_key){
return _scroll[_key]+_delta[_key];
}],
_keys = ['left','top'];
return function(){
var _value = {},
_style = this.__body.style,
_view = _e._$getPageBox(),
_scroll= {left:_view.scrollLeft,top:_view.scrollTop},
_delta = {left:_view.clientWidth-this.__body.offsetWidth
,top:_view.clientHeight-this.__body.offsetHeight};
_u._$forEach(_keys,
function(_key,_index){
var _handler = _func[this.__align[_index]];
if (!_handler) return;
_value[_key] = _handler(_scroll,_delta,_key);
},this);
this._$setPosition(_value);
};
})();
/**
* 显示盖层
*
* @protected
* @method module:ui/layer/window._$$Window#__doShowMask
* @return {Void}
*/
_pro.__doShowMask = function(){
if (!this.__imask){
if (!this.__mclz) return;
this.__mopt.parent = this.__parent;
this.__imask = this.__mclz
._$allocate(this.__mopt);
}
this.__imask._$show();
};
/**
* 隐藏窗体
*
* @protected
* @method module:ui/layer/window._$$Window#__doHide
* @return {Void}
*/
_pro.__doHide = function(){
if (!!this.__imask)
this.__imask._$hide();
this.__super();
};
/**
* 设置盖层构造
*
* @protected
* @method module:ui/layer/window._$$Window#__setMask
* @param {nej.ui._$$Mask|Boolean} arg0 - 盖层构造
* @return {Void}
*/
_pro.__setMask = function(_mask){
if (!!_mask){
if (_mask instanceof _i1._$$Mask){
this.__imask = _mask;
return;
}
if (_u._$isFunction(_mask)){
this.__mclz = _mask;
return;
}
this.__mclz = _i1._$$Mask;
if (_u._$isString(_mask))
this.__mopt.clazz = _mask;
return;
}
this.__mclz = null;
};
/**
* 设置标题
*
* 脚本举例
* ```javascript
* _window._$setTitle('设置浮层标题');
* ```
*
* @method module:ui/layer/window._$$Window#_$setTitle
* @param {String} arg0 - 标题
* @return {nej.ui._$$Window}
*/
_pro._$setTitle = function(_title,_html){
if (!!this.__nttl){
var _method = !_html?'innerText':'innerHTML';
this.__nttl[_method] = _title||'标题';
}
return this;
};
/**
* 设置窗体对齐方式
*
* 脚本举例
* ```javascript
* // 设置对齐方式,默认是center,middle
* _window._$setAlign();
* ```
*
* @method module:ui/layer/window._$$Window#_$setAlign
* @param {String} arg0 - 对齐方式
* @return {nej.ui._$$Window}
*/
_pro._$setAlign = (function(){
var _reg = /\s+/,
_halign = {left:0,center:1,right:2,auto:3},
_valign = {top:0,middle:1,bottom:2,auto:3};
return function(_align){
this.__align = (_align||'').split(_reg);
var _tmp = _halign[this.__align[0]];
if (_tmp==null) _tmp = 1;
this.__align[0] = _tmp;
var _tmp = _valign[this.__align[1]];
if (_tmp==null) _tmp = 1;
this.__align[1] = _tmp;
return this;
};
})();
/**
* 显示窗体
*
* 脚本举例
* ```javascript
* _window._$show();
* ```
*
* @method module:ui/layer/window._$$Window#_$show
* @return {nej.ui._$$Window}
*/
_pro._$show = function(){
this.__super();
this.__doShowMask();
return this;
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/layer/wrapper/window for compatible
// use ui/layer/wrapper/window for new project
NEJ.define(['./wrapper/window.js'],function(_t){return _t;});
/*
* ------------------------------------------
* 弹出卡片封装基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/layer/wrapper/card */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/event',
'base/util',
'ui/layer/layer.wrapper',
'ui/layer/card'
],function(NEJ,_k,_e,_v,_u,_i0,_i1,_p,_o,_f,_r){
var _pro;
/**
* 弹出卡片封装基类对象,主要实现层里面内容部分的业务逻辑
*
* 页面结构举例
* ```html
* <div id='cardWarpper-box'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'ui/layer/wrapper/card'
* ],function(_k,_i0,_p,_o,_f,_r){
* // 第一步:继承此基类生成一个新类
* _p._$$MyCard = _k._$klass();
* _proMyCard = _p._$$MyCard._$extend(_i0._$$CardWrapper);
* // 生成card的内容
* _proMyCard.__initXGui = function(){
* this.__seed_html = _seed_html;
* };
* });
* // 第二步:实例化一个card对象
* NEJ.define([
* '/path/custom/to/mycard.js'
* ],function(_i0,_p,_o,_f,_r){
* var _myCard = _i0._$$MyCard._$allocate({
* parent:'cardWarpper-box'
* });
* });
* ```
*
* @class module:ui/layer/wrapper/card._$$CardWrapper
* @extends module:ui/layer/wrapper/layer._$$LayerWrapper
* @param {Object} arg0 - 可选配置参数
*
*/
_p._$$CardWrapper = _k._$klass();
_pro = _p._$$CardWrapper._$extend(_i0._$$LayerWrapper);
/**
* 卡片绑定到执行节点上
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'ui/layer/wrapper/card'
* ],function(_k,_i0,_p,_o,_f,_r){
* // 第一步:继承此基类生成一个新类
* _p._$$MyCard = _k._$klass();
* _proMyCard = _p._$$MyCard._$extend(_i0._$$CardWrapper);
* // 生成card的内容
* _proMyCard.__initXGui = function(){
* this.__seed_html = _seed_html;
* };
* });
* NEJ.define([
* '/path/custom/to/mycard.js'
* ],function(_i0,_p,_o,_f,_r){
* var _node = 'cardWarpper-box';
* var _options = {
* // 卡片偏移量
* delta: {
* bottm: 10,
* right: 10
* },
* // 卡片对齐方式
* align: 'bottom right',
* // 是否需要调整卡片位置使其适应页面
* fitable: true,
* parent:document.body,
* onbeforeclick:function(_options){
* // 修改构造参数
* _options.date = new Date;
* // 阻止打开卡片,同时隐藏已打开的卡片
* // _options.showed 判断卡片是否已经显示
* _options.stopped = !0;
* // TODO something
* }
* };
* // 生成卡片实例
* _i0._$$MyCard._$attach(_node,_options);
* });
* ```
* @method module:ui/layer/wrapper/card._$$CardWrapper._$attach
* @param {String|Node} arg0 - 执行节点
*
* @param {Object} arg1 - 构建卡片配置参数
* @property {String} event - 触发显示卡片事件名称,默认为click事件
* @property {Boolean} fixed - 是否固定位置,如果已固定位置则卡片显示位置不会自动计算
* @property {Object} delta 四周偏移,默认全为0,{top:0,right:0,bottom:0,left:0}
* @property {String} align - 卡片位置,默认为'bottom left'
* @property {Boolean} fitable - 是否需要调整卡片位置使其适应页面
* @property {Boolean} noclear - 显示卡片之前是否不做卡片清理
* @property {Boolean} toggled - 是否采用切换形式打开卡片,如果卡片已经显示则
* @property {Function} onbeforeclick - 点击之前触发事件,用以调整参数,输入卡片构造配置对象,{noclear:true,toggled:true}
* @return {Void}
*/
_p._$$CardWrapper._$attach = (function(){
var _doShowCard = function(_event,_id,_class,_copt,_sopt){
var _instance,
_key = _id+'-i',
_cache = _class.__cdpol,
_noclear = !!_copt.noclear,
_toggled = !!_copt.toggled;
// check click
if (_u._$isFunction(_copt.onbeforeclick)){
var _oldc = _copt.noclear,
_oldt = _copt.toggled;
try{_copt.onbeforeclick(_copt);}catch(e){}
_noclear = !!_copt.noclear;
_toggled = !!_copt.toggled;
_copt.toggled = _oldt;
_copt.noclear = _oldc;
}
// toggle card
var _inst = _cache[_key];
if (_toggled&&!!_inst){
_inst._$hide();
return;
}
// show card
_v._$stop(_event);
if (!_noclear){
_v._$dispatchEvent(document,'click');
_instance = _class._$allocate(_copt);
}else{
_instance = _class._$getInstanceWithReset(_copt,!0);
}
// cache wrapper instance
_cache[_key] = _instance;
_instance._$setEvent(
'onbeforerecycle',
function(){
delete _cache[_key];
});
_instance._$showByReference(_sopt);
};
return function(_node,_options){
_node = _e._$get(_node);
if (!_node) return;
if (!this.__cdpol)
this.__cdpol = {};
var _id = _e._$id(_node);
if (!!this.__cdpol[_id]) return;
_options = _u._$merge({},_options);
var _sopt = _u._$fetch({
align:'',delta:null,fitable:!1
},_options);
_sopt.target = _id;
_options.destroyable = !0;
if (!_options.fixed){
_sopt.fitable = !0;
_options.parent = document.body;
}
this.__cdpol[_id] = [
_id,_options.event||'click',
_doShowCard._$bind2(null,_id,this,_options,_sopt)
];
_v._$addEvent.apply(_v,this.__cdpol[_id]);
};
})();
/**
* 取消节点绑定的卡片
*
* @method module:ui/layer/wrapper/card._$$CardWrapper._$detach
* @param {String|Node} arg0 - 执行节点
* @return {Void}
*/
_p._$$CardWrapper._$detach = function(_node){
if (!this.__cdpol) return;
var _id = _e._$id(_node),
_event = this.__cdpol[_id];
if (!_event) return;
delete this.__cdpol[_id];
_v._$delEvent.apply(_v,_event);
var _instance = this.__cdpol[_id+'-i'];
if (!!_instance) _instance._$hide();
};
/**
* 构建弹层控件实例,子类实现具体业务逻辑
*
* @protected
* @method module:ui/layer/wrapper/card._$$CardWrapper#__getLayerInstance
* @return {module:ui/layer/card._$$Card} 弹层控件实例
*/
_pro.__getLayerInstance = function(){
return _i1._$$Card._$allocate(this.__lopt);
};
/**
* 初始化弹层控件可选配置参数
*
* @protected
* @method module:ui/layer/wrapper/card._$$CardWrapper#__doInitLayerOptions
* @return {Void}
*/
_pro.__doInitLayerOptions = function(){
this.__super();
this.__lopt.top = null;
this.__lopt.left = null;
this.__lopt.nostop = !1;
};
/**
* 通过参照节点显示卡片位置
*
* @method module:ui/layer/wrapper/card._$$CardWrapper#_$showByReference
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro._$showByReference = function(_options){
if (!!this.__layer)
this.__layer._$showByReference(_options);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 弹出层封装基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/layer/wrapper/layer */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/util',
'ui/base',
'ui/layer/layer'
],function(NEJ,_k,_e,_u,_i,_i0,_p,_o,_f,_r){
var _pro;
/**
* 弹出层封装基类对象,主要实现层里面内容部分的业务逻辑
*
* 脚本举例
* ```javascript
* // 第一步:继承此基类生成新类
* NEJ.define([
* 'base/element',
* 'ui/layer/wrapper/layer'
* ],function(_e,_i0,_p,_o,_f,_r){
* var _seed_css = _e._$pushCSSText('.#<uispace>
* {position:absolute;background:#fff;}');
* _p._$$MyLayer = _k._$klass();
* _proMyLayer = _p._$$MyLayer._$extend(_i0._$$Layer);
*
* _proMyLayer.__initXGui = function(){
* this.__seed_css = _seed_css;
* };
*
* _proMyLayer.__initNode = function(){
* this.__super();
* // this.__ncnt作为放置卡片内容的容器
* this.__ncnt = this.__body;
* };
* });
* // 下面是对layerwrapper的描述
* NEJ.define([
* 'base/klass',
* 'ui/layer/wrapper/layer',
* '/path/custom/to/layer.js'
* ],function(_k,_i0,_i1,_p,_o,_f,_r){
* // 首先:继承layerwrapper基类生成的一个新类
* _p._$$MyCardWrapper = _k._$klass();
* _proMyCardWrapper = _p._$$MyCardWrapper._$extend(_i0.
* _$$LayerWrapper);
*
* // 这里返回内容层的实例
* _proMyCardWrapper.__getLayerInstance = function(){
* return _i1._$$MyLayer._$allocate(this.__lopt);
* };
*
* // 这里配置lopt参数,生成内容层用
* _proMyCardWrapper.__doInitLayerOptions = function(){
* this.__super();
* this.__lopt.top = null;
* this.__lopt.left = null;
* };
*
* // 最后项目中实例化wrapper的实例
* var _ly = _p._$$MyLayerCard._$allocate({
* parent:document.body,
* // 隐藏浮层时,是否销毁
* destroyable:false,
* oncontentready:function(_html){
* // 设置浮层内容的回调
* }
* });
* });
* ```
*
* @class module:ui/layer/wrapper/layer._$$LayerWrapper
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
*
*/
_p._$$LayerWrapper = _k._$klass();
_pro = _p._$$LayerWrapper._$extend(_i._$$Abstract);
/**
* 控件重置
*
* @protected
* @method module:ui/layer/wrapper/layer._$$LayerWrapper#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__doInitLayerOptions();
this.__super(this
.__doFilterOptions(_options));
this.__lopt.onbeforerecycle =
this._$recycle._$bind(this);
this.__layer = this.__getLayerInstance();
};
/**
* 控件销毁
*
* @protected
* @method module:ui/layer/wrapper/layer._$$LayerWrapper#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this._$dispatchEvent('onbeforerecycle');
this.__super();
delete this.__lopt;
_e._$removeByEC(this.__body);
var _layer = this.__layer;
if (!!_layer){
delete this.__layer;
_layer._$recycle();
}
};
/**
* 构建弹层控件实例,子类实现具体业务逻辑
*
* @abstract
* @method module:ui/layer/wrapper/layer._$$LayerWrapper#__getLayerInstance
* @return {nej.ui._$$Layer} 弹层控件实例
*/
_pro.__getLayerInstance = _f;
/**
* 将配置参数拆分为两部分,一部分用于弹层控件,一部分用于本控件
*
* @protected
* @method module:ui/layer/wrapper/layer._$$LayerWrapper#__doFilterOptions
* @param {Object} arg0 - 可选配置参数
* @return {Object} 过滤后的配置参数
*/
_pro.__doFilterOptions = function(_options){
var _result = {};
_u._$loop(_options,
function(_item,_key){
this.__lopt.hasOwnProperty(_key)
? this.__lopt[_key] = _item
: _result[_key] = _item;
},this);
return _result;
};
/**
* 初始化弹层控件可选配置参数
*
* @protected
* @method module:ui/layer/wrapper/layer._$$LayerWrapper#__doInitLayerOptions
* @return {Void}
*/
_pro.__doInitLayerOptions = function(){
this.__lopt = {
clazz:''
,parent:null
,content:this.__body
,destroyable:!1
,oncontentready:null
,nohack:!1
};
};
/**
* 显示弹层
*
* 脚本举例
* ```javascript
* // 显示浮层
* _ly._$show();
* ```
*
* @method module:ui/layer/wrapper/layer._$$LayerWrapper#_$show
* @return {Void}
*/
_pro._$show = function(){
if (!!this.__layer)
this.__layer._$show();
this._$dispatchEvent('onaftershow');
};
/**
* 隐藏弹层
*
* 脚本举例
* ```javascript
* // 隐藏弹层
* _ly._$hide();
* ```
*
* @method module:ui/layer/wrapper/layer._$$LayerWrapper#_$hide
* @return {Void}
*/
_pro._$hide = function(){
if (!!this.__layer)
this.__layer._$hide();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 弹出窗体封装基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/layer/wrapper/window */
NEJ.define([
'base/global',
'base/klass',
'ui/layer/layer.wrapper',
'ui/layer/window'
],function(NEJ,_k,_i0,_i1,_p,_o,_f,_r){
var _pro;
/**
* 弹出窗体封装基类对象,主要实现层里面内容部分的业务逻辑
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'base/element',
* 'ui/layer/wrapper/window'
* ],function(_i0,_p,_o,_f,_r){
* // 第一步:继承此类,生成一个新类
* _p = NEJ.P('nej.ui');
* _p._$$MyWindow = _k._$klass();
* var _seed_html = _e._$addNodeTemplate('<div>您要展示的内容部分</div>');
* _proMyWindow = _p._$$MyWindow._$extend(_i0._$$WindowWrapper);
* // 生成窗体的展示内容
* _proMyWindow.__initXGui = function(){
* this.__seed_html = _seed_html;
* };
* });
*
* NEJ.define([
* '/path/custom/to/mywindow.js'
* ],function(_i0,_p,_o,_f,_r){
* // 第二步:实例化一个窗体控件
* var _myCard = _i0._$$MyWindow._$allocate({
* parent:document.body,
* title:'窗口标题',
* draggable:false,
* // 是否有盖层
* mask:true,
* onclose:function(){
* // 关闭窗口的回调
* }
* });
* });
* ```
*
* @class module:ui/layer/wrapper/window._$$WindowWrapper
* @extends module:ui/layer/wrapper/layer._$$LayerWrapper
* @param {Object} arg0 - 可选配置参数
*
*/
_p._$$WindowWrapper = _k._$klass();
_pro = _p._$$WindowWrapper._$extend(_i0._$$LayerWrapper);
/**
* 构建弹层控件实例,子类实现具体业务逻辑
*
* @protected
* @method module:ui/layer/wrapper/window._$$WindowWrapper#__getLayerInstance
* @return {module:ui/layer/layer._$$Layer} 弹层控件实例
*/
_pro.__getLayerInstance = function(){
return _i1._$$Window._$allocate(this.__lopt);
};
/**
* 初始化弹层控件可选配置参数
*
* @protected
* @method module:ui/layer/wrapper/window._$$WindowWrapper#__doInitLayerOptions
* @return {Void}
*/
_pro.__doInitLayerOptions = function(){
this.__super();
this.__lopt.mask = null;
this.__lopt.title = '标题';
this.__lopt.align = '';
this.__lopt.draggable = !1;
this.__lopt.onclose = null;
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>NEJ实例 - LightBox</title>
<meta charset="utf-8" />
<style>
*{margin:0;padding:0;border:0;}
html,body{width:100%;height:100%;}
</style>
</head>
<body>
<script>window.NEJ_CONF={root:'../../../../res/'};</script>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../lightbox.js'
],function(_i){
_i._$$LightBox._$allocate({
parent:document.body,
list:[
{title:'汽车1',src:'http://www0.autoimg.cn/newspic/2014/11/5/620x0_0_2014110510432141064.jpg'},
{title:'汽车2',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071745705345010.jpg'},
{title:'汽车3',src:'http://car1.autoimg.cn/carnews/2014/11/5/d_20141105071823084345010.jpg'},
{title:'汽车4',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071820932345010.jpg'},
{title:'汽车5',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071756548345010.jpg'},
{title:'汽车6',src:'http://car1.autoimg.cn/carnews/2014/11/5/d_20141105092940897345011.jpg'},
{title:'汽车7',src:'http://car1.autoimg.cn/carnews/2014/11/5/d_20141105071754832345010.jpg'},
{title:'汽车8',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071818090345011.jpg'}
]
});
});
</script>
</body>
</html>
.#<uispace>-mask{position:fixed;_position:absolute;z-index:5000;top:0;bottom:0;left:0;right:0;width:100%;height:100%;background:#aaa;}
.#<uispace>{position:fixed;_position:absolute;z-index:5001;background:#fff;text-align:center;$<vendor>transition-duration:300ms;}
.#<uispace> .zbtn{position:absolute;cursor:pointer;width:24px;height:24px;line-height:24px;border:2px solid #fff;background:#333;color:#fff;$<vendor>border-radius:50%;font-weight:bold;}
.#<uispace> .zcls{top:-12px;right:-12px;}
.#<uispace> .zbtn{opacity:0;*filter:alpha(opacity=0);$<vendor>transition-duration:300ms;$<vendor>transition-property:opacity;}
.#<uispace> .zprv{left:5px;}
.#<uispace> .znxt{right:5px;}
.#<uispace> .ztrp{position:absolute;left:0;right:0;bottom:0;width:100%;}
.#<uispace> .zshw{display:block;width:100%;height:100%;}
.#<uispace>:hover .zbtn{opacity:1;*filter:alpha(opacity=100);}
.#<uispace> .js-disabled,.#<uispace>.js-loading .zbpt{visibility:hidden;}
<div>
<span class="zbtn zcls" data-action="close" title="关闭">×</span>
<span class="zbtn zbpt zprv j-zflag" data-action="prev" title="上一张">&lt;</span>
<span class="zbtn zbpt znxt j-zflag" data-action="next" title="下一张">&gt;</span>
<img class="zshw j-zflag"/>
<div class="ztrp">
<div class="zttl j-zflag"></div>
</div>
</div>
/*
* ------------------------------------------
* 图片幻灯片控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/lightbox/lightbox */
NEJ.define([
'base/global',
'base/klass',
'base/constant',
'base/element',
'base/event',
'util/template/tpl',
'ui/base',
'text!./lightbox.css',
'text!./lightbox.html'
],function(NEJ,_k,_g,_e,_v,_t,_i,_css,_html,_p,_o,_f,_r){
var _pro;
/**
* 图片幻灯片控件
*
* ```javascript
* NEJ.define([
* 'ui/lightbox/lightbox'
* ],function(_i){
* _i._$$LightBox._$allocate({
* parent:document.body,
* list:[
* {title:'汽车1',src:'./1.jpg'},
* {title:'汽车2',src:'./2.jpg'},
* {title:'汽车3',src:'./3.jpg'},
* {title:'汽车4',src:'./4.jpg'},
* {title:'汽车5',src:'./5.jpg'},
* {title:'汽车6',src:'./6.jpg'},
* {title:'汽车7',src:'./7.jpg'},
* {title:'汽车8',src:'./8.jpg'}
* ]
* });
* });
* ```
*
* @class module:ui/lightbox/lightbox._$$LightBox
* @extends module:ui/base._$$Abstract
*
* @param {Object} config - 配置参数
* @property {String} mask - 遮罩样式名称
* @property {String} loading - 图片加载中样式名称,默认为js-loading
* @property {String} disabled - 按钮禁用样式名称,默认为js-disabled
* @property {Array} list - 图片数据列表,[{src:'xxx',title:'xxx'},...]
* @property {Number} index - 当前显示图片索引
*/
_p._$$LightBox = _k._$klass();
_pro = _p._$$LightBox._$extend(_i._$$Abstract);
/**
* 控件重置
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__ilist = _options.list||_r;
this.__discs = _options.disabled||'js-disabled';
this.__loading = _options.loading||'js-loading';
_e._$addClassName(this.__mask,_options.mask);
// init event
this.__doInitDomEvent([[
this.__body,'click',
this.__onAction._$bind(this)
],[
document,'click',
this.__doClose._$bind(this)
],[
this.__test,'load',
this.__onImageLoad._$bind(this,!0)
],[
this.__test,'error',
this.__onImageLoad._$bind(this,!1)
]]);
this.__body.insertAdjacentElement(
'beforeBegin',this.__mask
);
this.__doUpdateIndex(_options.index);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
delete this.__ilist;
_e._$removeByEC(this.__mask);
this.__mask.className = this.__seed_css+'-mask';
var _blank = _g._$BLANK_IMAGE;
this.__image.src = _blank;
this.__test.src = _blank;
this.__super();
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__initXGui
* @return {Void}
*/
_pro.__initXGui = (function(){
var _seed_css = _e._$pushCSSText(_css),
_seed_html= _t._$addNodeTemplate(_html);
return function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
})();
/**
* 初始化节点
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
this.__test = _e._$create('img');
this.__mask = _e._$create(
'div',this.__seed_css+'-mask'
);
_e._$setStyle(this.__mask,'opacity',0.7);
// 0 - previous button
// 1 - next button
// 2 - image show
// 3 - image title
var _list = _e._$getByClassName(
this.__body,'j-zflag'
);
this.__nprev = _list[0];
this.__nnext = _list[1];
this.__image = _list[2];
this.__title = _list[3];
};
/**
* 关闭幻灯片
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__doClose
* @return {Void}
*/
_pro.__doClose = function(){
this._$recycle();
};
/**
* 更新索引值
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__doUpdateIndex
* @param {Number} arg0 - 索引值
* @return {Void}
*/
_pro.__doUpdateIndex = function(_index){
this.__index = parseInt(_index)||0;
this.__doSyncBtnState();
this.__doSyncImageData(
this.__ilist[this.__index]
);
};
/**
* 同步按钮状态
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__doSyncBtnState
* @return {Void}
*/
_pro.__doSyncBtnState = function(){
// previous button
this.__index<=0
? _e._$addClassName(this.__nprev,this.__discs)
: _e._$delClassName(this.__nprev,this.__discs);
// next button
this.__index>=this.__ilist.length-1
? _e._$addClassName(this.__nnext,this.__discs)
: _e._$delClassName(this.__nnext,this.__discs);
};
/**
* 同步图片数据
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__doSyncImageData
* @param {Object} arg0 - 图片数据,如{src:'xxxxx',title:'xxxxxxxx'}
* @return {Void}
*/
_pro.__doSyncImageData = function(_data){
_data = _data||_o;
this.__title.innerText = _data.title;
//_e._$setStyle(this.__image,'opacity',0);
_e._$addClassName(this.__body,this.__loading);
this.__test.src = _data.src||_g._$BLANK_IMAGE;
};
/**
* 图片载入回调
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__onImageLoad
* @return {Void}
*/
_pro.__onImageLoad = function(_isok){
_e._$delClassName(this.__body,this.__loading);
// load blank
if (this.__test.src.indexOf(_g._$BLANK_IMAGE)>=0){
return;
}
// dump image info
var _url = this.__test.src,
_pbox = _e._$getPageBox(),
_sbox = _e._$getMaxBox({
width:this.__test.naturalWidth||this.__test.width,
height:this.__test.naturalHeight||this.__test.height
},{
width:_pbox.clientWidth*0.85,
height:_pbox.clientHeight*0.85
}),
_mbox = _e._$align({
width:_pbox.clientWidth,
height:_pbox.clientHeight
},_sbox);
this.__test.src = _g._$BLANK_IMAGE;
// update button position
_e._$setStyle(
this.__nprev,'top',
(_sbox.height-this.__nprev.offsetHeight)/2+'px'
);
_e._$setStyle(
this.__nnext,'top',
(_sbox.height-this.__nnext.offsetHeight)/2+'px'
);
// update image show
_e._$style(
this.__body,{
top:_mbox.top+'px',
left:_mbox.left+'px',
width:_sbox.width+'px',
height:_sbox.height+'px'
}
);
//_e._$setStyle(this.__image,'opacity',1);
this.__image.src = _url;
};
/**
* 操作行为
*
* @protected
* @method module:ui/lightbox/lightbox._$$LightBox#__onAction
* @param {Event} arg0 - 事件对象
* @return {Void}
*/
_pro.__onAction = function(_event){
_v._$stop(_event);
// check action
var _action = _e._$dataset(
_v._$getElement(
_event,'d:action'
),'action'
);
if (!_action) return;
// do action
switch(_action){
case 'close':
this.__doClose();
break;
case 'prev':
if (!_e._$hasClassName(this.__nprev,this.__discs)){
this.__doUpdateIndex(this.__index-1);
}
break;
case 'next':
if (!_e._$hasClassName(this.__nnext,this.__discs)){
this.__doUpdateIndex(this.__index+1);
}
break;
}
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
.#<uispace>{position:fixed;_position:absolute;z-index:100;top:0;bottom:0;left:0;right:0;width:100%;height:100%;background-image:url(#<blankimage>);}
/*
* ------------------------------------------
* 盖层控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/maks/mask */
NEJ.define([
'base/global',
'base/klass',
'base/constant',
'base/element',
'base/util',
'ui/base',
'text!./mask.css'
],function(NEJ,_k,_g,_e,_u,_i,_css,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css,{blankimage:_g._$BLANK_IMAGE});
/**
* 盖层控件
*
* 页面结构举例
* ```html
* <style type="text/css">
* .box{position:relative;}
* </style>
* <div id="mask-box" class="box"></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/maks/mask'
* ],function(_i0,_p,_o,_f,_r){
* var _mask = _i0._$$Mask._$allocate({
* parent:document.body,
* content:'<div style="width:100px;height:100px;margin:0 auto;margin-top:150px;">搞一点盖层的内容</div>'
* });
* });
* ```
*
* @class module:ui/maks/mask._$$Mask
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {String|Node} content - 内容节点或者HTML代码
*/
_p._$$Mask = _k._$klass();
_pro = _p._$$Mask._$extend(_i._$$Abstract);
/**
* 控件重置
*
* @protected
* @method module:ui/maks/mask._$$Mask#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
var _content = _options.content||'&nbsp;';
_u._$isString(_content)
? this.__body.innerHTML = _content
: this.__body.appendChild(_content);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/maks/mask._$$Mask#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
this.__body.innerHTML = '&nbsp;';
};
/**
* 初始化外观
*
* @protected
* @method module:ui/maks/mask._$$Mask#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 显示盖层
*
* ```javascript
* // 先隐藏盖层
* _mask._$hide();
* // 显示盖层
* _mask._$show();
* ```
*
* @method module:ui/maks/mask._$$Mask#_$show
* @return {Void}
*/
_pro._$show = function(){
_e._$fullScreen(this.__body);
this.__super();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>mask测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
.box{position:relative;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit mask test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="mask-box" class="box"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./mask.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("ui-mask");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui');
//开始单元测试
test('mask',function(){
expect(0);
var _mask = _p._$$Mask._$allocate({
parent:document.body,
content:'<div style="width:100px;height:100px;margin:0 auto;margin-top:150px;">搞一点盖层的内容</div>'
});
_mask._$hide();
_mask._$show();
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}mask.test.js',['ui/mask/mask'],f);
});
.#<uispace>{font-size:12px;line-height:160%;}
.#<uispace> a{margin:0 2px;padding:2px 8px;color:#333;border:1px solid #aaa;text-decoration:none;}
.#<uispace> .js-disabled{cursor:default;}
.#<uispace> .js-selected{cursor:default;background-color:#bbb;}
/*
* ------------------------------------------
* 分页器控件基类封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/pager/base */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/util',
'ui/base',
'util/template/jst',
'text!./base.css'
],function(NEJ,_k,_e,_u,_i,_t0,_css,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 分页器控件基类封装
*
* 页面结构举例
* ```html
* <div id="pagerCnt">page</div>
* <div id="pagerCnt2">page</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'ui/pager/pager.base',
* 'util/page/page'
* ],function(_k,_u,_t,_p,_o,_f,_r){
* // 第一步:继承此类,新建一个子类
* _p._$$Pager = _k._$klass();
* _pro = _p._$$Pager._$extend(_u._$$AbstractPager);
*
* // 调用父类reset方法后,
* 实例化一个_t._$page对象,首尾页用数字表示
* // 表现为,上一页 1 2 3.. 10 下一页
* // 或者实例化一个page.simple对象,首尾页需要辅助,数字可能不会出现
* // 表现为,首页 上一页 5 6 7 8 9 10 下一页 末页
* _pro.__reset = function(_options){
* this.__super(_options);
* this.__page = _t._$$PageFragment._$allocate(this.__popt);
* };
*
* // reset之前生成需要的页码结构
* _pro.__initNode = function(){
*
* };
*
* // reset之前生成需要的页码结构
* _pro.__initNodeTemplate = function(){
* // _seed_html根据需求定制
* this.__seed_html = _seed_html;
* };
* return _p;
* })
*
* NEJ.define([
* '/path/to/custom/pager.js'
* ],function(_u,_p,_o,_f,_r){
* // 第二步:生成一个pager实例
* // 总页数10,默认第一页
* var _pager = _u._$$Pager._$allocate({
* parent:'pagerCnt',
* onchange: function(_event){},
* total: 10,
* index:1
* });
* })
* ```
*
* @class module:ui/pager/base._$$AbstractPager
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {Number} index - 当前页码
* @property {Number} total - 总页码数
* @property {Number} number - 显示页数
* @property {Number} limit - 总页数限制
* @property {Object} label - 按钮文案,{prev:'&lt;',next:'&gt;'}
*/
/**
* 页码切换事件,输入{last:3,index:1,total:12}
*
* @event module:ui/pager/base._$$AbstractPager#onchange
* @param {Object} arg0 - 页码状态对象
* @property {Number} last - 上一次的页码
* @property {Number} index - 当前要切换的页面
* @property {Number} total - 总页面数
*
*/
_p._$$AbstractPager = _k._$klass();
_pro = _p._$$AbstractPager._$extend(_i._$$Abstract);
/**
* 控件重置
*
* @protected
* @method module:ui/pager/base._$$AbstractPager#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__bopt = _u._$merge({},_options);
this.__popt = _u._$merge({},_options);
delete this.__bopt.onchange;
this.__popt.onchange =
this.__onChange._$bind(this);
this.__super(_options);
this.__doResetNumber({
number:_options.number,
label:_options.label||_o
});
};
/**
* 控件销毁
*
* @protected
* @method module:ui/pager/base._$$AbstractPager#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
if (!!this.__page){
this.__page._$recycle();
delete this.__page;
}
this.__super();
delete this.__bopt;
delete this.__popt;
this._$unbind();
this.__body.innerHTML = '&nbsp;';
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/pager/base._$$AbstractPager#__initXGui
* @return {Void}
*/
_pro.__initXGui = (function(){
var _seed_css = _e._$pushCSSText(_css);
return function(){
this.__seed_css = _seed_css;
};
})();
/**
* 重置页码数
*
* @protected
* @method module:ui/pager/base._$$AbstractPager#__doResetNumber
* @return {Void}
*/
_pro.__doResetNumber = function(_data){
var _label = _data.label;
// previous button
if (!_data.noprv){
this.__popt.pbtn = _e._$create(
'a','zbtn zprv',this.__body
);
this.__popt.pbtn.innerHTML = _label.prev||'上一页';
}
// page show
var _arr = [];
for(var i=1,l=_data.number;i<l;i++){
_arr.push(_e._$create(
'a','zpgi zpg'+i,this.__body
));
}
this.__popt.list = _arr;
// next button
if (!_data.nonxt){
this.__popt.nbtn = _e._$create(
'a','zbtn znxt',this.__body
);
this.__popt.nbtn.innerHTML = _label.next||'下一页';
}
};
/**
* 页面变化触发事件
*
* @protected
* @method module:ui/pager/base._$$AbstractPager#__onChange
* @param {Object} arg0 - 事件对象
* @return {Void}
*/
_pro.__onChange = function(_event){
if (this.__flag) return;
var _index = _event.index,
_total = _event.total;
// sync pagers
this.__flag = !0;
this._$updatePage(_index,_total);
_u._$forEach(this.__binders,
function(_pager){
_pager._$updatePage(_index,_total);
});
this.__flag = !1;
this._$dispatchEvent('onchange',_event);
};
/**
* 绑定联动分页器
*
* 脚本举例
* ```javascript
* // 绑定一个联动翻页器
* _pager._$bind('pagerCnt2')
* ```
*
* @method module:ui/pager/base._$$AbstractPager#_$bind
* @param {String|Node} arg0 - 联动分页器父容器
* @return {Void}
*/
_pro._$bind = function(_parent){
_parent = _e._$get(_parent);
if (!_parent) return;
var _opt = _u._$merge(
{},this.__bopt
);
_opt.parent = _parent;
_opt.index = this._$getIndex();
_opt.total = this._$getTotal();
var _pager = this.constructor._$allocate(_opt);
_pager._$setEvent('onchange',this.__popt.onchange);
if (!this.__binders) this.__binders = [];
this.__binders.push(_pager);
};
/**
* 解除联动分页器
*
* 脚本举例
* ```javascript
* // 解绑所以联动翻页器
* _pager._$unbind()
* ```
*
* @method module:ui/pager/base._$$AbstractPager#_$unbind
* @return {nej.ui._$$AbstractPager}
*/
_pro._$unbind = (function(){
var _doRemove = function(_pager,_index,_list){
_pager._$recycle();
_list.splice(_index,1);
};
return function(){
_u._$reverseEach(this.__binders,_doRemove);
};
})();
/**
* 跳转至指定页码
*
* 脚本举例
* ```javascript
* // 设置页码到第二页
* _pager._$setIndex(2)
* ```
*
* @method module:ui/pager/base._$$AbstractPager#_$setIndex
* @param {Number} arg0 - 页码
* @return {nej.ui._$$AbstractPager}
*/
_pro._$setIndex = function(_index){
if (!this.__page) return;
this.__page._$setIndex(_index);
};
/**
* 取当前页码
*
* 脚本举例
* ```javascript
* // 取当前页码
* _pager._$getIndex()
* ```
*
* @method module:ui/pager/base._$$AbstractPager#_$getIndex
* @return {Number} 当前页码
*/
_pro._$getIndex = function(){
if (!this.__page) return 1;
return this.__page._$getIndex();
};
/**
* 取总页数
*
* 脚本举例
* ```javascript
* // 取总页数
* _pager._$getTotal()
* ```
*
* @method module:ui/pager/base._$$AbstractPager#_$getTotal
* @return {Number} 总页数
*/
_pro._$getTotal = function(){
if (!this.__page) return 1;
return this.__page._$getTotal();
};
/**
* 更新页码信息
*
* 脚本举例
* ```javascript
* // 重新设置默认页和总页数
* _pager._$updatePage(2,10);
* ```
*
* @method module:ui/pager/base._$$AbstractPager#_$updatePage
* @param {Number} arg0 - 当前页码
* @param {Number} arg1 - 总页码数
* @return {nej.ui._$$AbstractPager}
*/
_pro._$updatePage = function(_index,_total){
if (!this.__page) return;
this.__page._$updatePage(_index,_total);
};
/**
* 更新总页数
*
* @method module:ui/pager/base._$$AbstractPager#_$updateTotal
* @param {Number} arg0 - 总页数
* @return {Void}
*/
_pro._$updateTotal = function(_total){
if (!this.__page) return;
this.__page._$updateTotal(_total);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>demo for pager</title>
<meta charset="utf-8" />
<style>
body{padding:50px;}
</style>
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../pager.js'
],function(_i){
var _pager = _i._$$Pager._$allocate({
index:3,
total:100,
parent:document.body,
onchange:function(_event){
log('change page from '+_event.last+' to '+_event.index);
}
});
});
</script>
</body>
</html>
// link to ui/pager/base for compatible
// use ui/pager/base for new project
NEJ.define(['./base.js'],function(_t){return _t;});
/*
* ------------------------------------------
* 分页器控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/pager/pager */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/pager/base',
'util/page/page'
],function(NEJ,_k,_e,_i0,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 分页器控件封装
*
* 页面结构举例
* ```html
* <div id="pagerCnt">page</div>
* <div id="pagerCnt2">page</div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/pager/pager'
* ],function(_u,_p,_o,_f,_r){
* // 默认第一页
* var _setIndex = 1;
* // 页面更改的回调方法
* var _onchangeHandle = function(_obj){
* var _index = _obj.index;
* };
* // 实例化一个pager对象,总共10页
* var _pager = _u._$$Pager._$allocate({
* parent:'pagerCnt',
* onchange: _onchangeHandle,
* total: 10,
* index:_setIndex
* });
* // 从第2页翻到第10页
* for(var i = 2 ; i < 11 ; i++){
* _setIndex = i;
* _pager._$setIndex(_setIndex);
* }
* // 绑定一个翻页器,视觉上翻页器会联动,
* 但最后触发一次翻页器的回调,避免重复触发
* _pager._$bind('pagerCnt2');
* })
* ```
*
* @class module:ui/pager/pager._$$Pager
* @uses module:util/page/page._$$PageFragment
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {Number} index - 当前页码
* @property {Number} total - 总页码数
* @property {Boolean} noend - 无尾页显示
*/
/**
* 页码切换事件,输入{last:3,index:1,total:12}
*
* @event module:ui/pager/pager._$$Pager#onchange
* @param {Object} arg0 - 页码状态对象
* @property {Number} last - 上一次的页码
* @property {Number} index - 当前要切换的页面
* @property {Number} total - 总页面数
*
*/
_p._$$Pager = _k._$klass();
_pro = _p._$$Pager._$extend(_i0._$$AbstractPager);
/**
* 控件重置
*
* @protected
* @method module:ui/pager/pager._$$Pager#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
_options.number =
parseInt(_options.number)||9;
this.__super(_options);
this.__page = _t0._$$PageFragment._$allocate(this.__popt);
};
/**
* 页面变化触发事件
*
* @protected
* @method module:ui/pager/pager._$$Pager#__onChange
* @param {Object} arg0 - 事件对象
* @return {Void}
*/
_pro.__onChange = function(_event){
if (!!this.__bopt.noend){
var _dext = _event.ext||_o,
_list = _dext.list||_r;
if (_dext.last){
_e._$setStyle(
_list[_list.length-1],
'display','none'
);
}
}
this.__super(_event);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/pager/simple for compatible
// use ui/pager/simple for new project
NEJ.define(['./simple.js'],function(_t){return _t;});
/*
* ------------------------------------------
* 分页器控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/pager/simple */
NEJ.define([
'base/global',
'base/klass',
'ui/pager/base',
'util/page/simple'
],function(NEJ,_k,_i0,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 分页器控件封装<br />
* 页面结构举例
* ```html
* <div id="pagerCnt">page</div>
* <div id="pagerCnt2">page</div>
* ```
* 脚本举例
* ```javascript
* NEJ.define([
* 'ui/pager/pager.simple'
* ],function(_u,_p,_o,_f,_r){
* // 默认第一页
* var _setIndex = 1;
* // 页面更改的回调方法
* var _onchangeHandle = function(_obj){
* var _index = _obj.index;
* };
* // 实例化一个pager对象,总共10页
* var _pager = _u._$$Pager._$allocate({
* parent:'pagerCnt',
* onchange: _onchangeHandle,
* total: 10,
* index:_setIndex
* });
* // 从第2页翻到第10页
* for(var i = 2 ; i < 11 ; i++){
* _setIndex = i;
* _pager._$setIndex(_setIndex);
* }
* // 绑定一个翻页器,视觉上翻页器会联动,
* 但最后触发一次翻页器的回调,避免重复触发
* _pager._$bind('pagerCnt2');
* })
* ```
*
* @class module:ui/pager/simple._$$Pager
* @uses module:util/page/page._$$PageFragment
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {Number} index - 当前页码
* @property {Number} total - 总页码数
*/
/**
* 页码切换事件,输入{last:3,index:1,total:12}
*
* @event module:ui/pager/simple._$$SimplePager#onchange
* @param {Object} arg0 - 页码状态对象
* @property {Number} last - 上一次的页码
* @property {Number} index - 当前要切换的页面
* @property {Number} total - 总页面数
*
*/
_p._$$SimplePager = _k._$klass();
_pro = _p._$$SimplePager._$extend(_i0._$$AbstractPager);
/**
* 控件重置
*
* @protected
* @method module:ui/pager/simple._$$SimplePager#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
_options.number =
parseInt(_options.number)||1;
if (_options.total==null)
_options.total = 10000;
this.__super(_options);
this.__page = _t0._$$PageSimple._$allocate(this.__popt);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>pager测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
.js-selected{color:pink;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit pager test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="pagerCnt">page</div>
<div id="pagerCnt2">page</div>
<div id="pagerCnt3">page</div>
<div id="page">
<a href="#" class="zbtn sbtn">首页</a>
<a href="#" class="zbtn zprv">上一页</a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zbtn znxt">下一页</a>
<a href="#" class="zbtn ebtn">末页</a>
</div>
<div id="pagebox">
<a href="#" class="zbtn zprv">上一页</a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zpgi"></a>
<a href="#" class="zbtn znxt">下一页</a>
</div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./pager.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("pager");
var p = NEJ.P('nej.ui'),
v = NEJ.P('nej.v'),
t = NEJ.P('nej.ut'),
e = NEJ.P('nej.e');
//开始单元测试
test('实例化一个翻页器,并测试放回的页码是否一致', function() {
var _parent = document.getElementById('pagerCnt');
var _setIndex = 1;
var _onchangeHandle = function(_obj){
var _index = _obj.index;
equal(_index,_setIndex,'设置的页码数一致');
};
stop();
var _pager = p._$$Pager._$allocate({
parent:_parent,
onchange: _onchangeHandle,
total: 10,
index:1
});
for(var i = 2 ; i < 11 ; i++){
_setIndex = i;
_pager._$setIndex(_setIndex);
}
start();
});
test('关联一个翻页器',function(){
stop();
var _parent = document.getElementById('pagerCnt2');
var _setIndex = 1,_setIndex2 = 1;
var _onchangeHandle = function(_obj){
var _index = _obj.index;
if(_index == 1)//初始化页不用测试
return;
var _pnt1 = document.getElementById('pagerCnt2');
var _pnt2 = document.getElementById('pagerCnt3');
if(_index == 10){
equal(_pnt2.children.length,0,'解绑后翻页器从页面回收');
return;
}
var _children1 = _pnt1.children[0].children;
var _children2 = _pnt2.children[0].children;
var i = _index;
if(_children1[i].className.match('js-selected') == null)
return;
if(i == _children1.length - 2)
notEqual(_children1[i].className,_children2[i].className,'解绑后联动翻页器的表现形式不一致')
else
equal(_children1[i].className,_children2[i].className,'联动翻页器的表现形式一致,但最后触发一次翻页器的回调');
};
var _pager = p._$$Pager._$allocate({
parent:_parent,
onchange: _onchangeHandle,
total: 10,
index:1
});
var _parent2 = document.getElementById('pagerCnt3');
var _onchangeHandle2 = function(_index2){
_setIndex2 = _index2;
};
_pager._$bind(_parent2);
for(var i = 2 ; i < 11 ; i++){
_setIndex = i;
//最后一个解绑
if(i == 10)
_pager._$unbind();
_pager._$setIndex(_setIndex);
}
start();
});
test('util page.simple',function(){
var _page = e._$get('page');
var _ps = t._$$PageSimple._$allocate({
list:e._$getByClassName(_page,'zpgi'),
event:'click',
pbtn:e._$getByClassName(_page,'zprv')[0],
nbtn:e._$getByClassName(_page,'znxt')[0],
sbtn:e._$getByClassName(_page,'sbtn')[0],
ebtn:e._$getByClassName(_page,'ebtn')[0],
index:90,
total:100,
onchange:function(_obj){
ok(true,'last page is :' + _obj.last + ' index page is:' + _obj.index + 'total:' + _obj.total)
}
});
});
test('util page',function(){
stop();
var _box = e._$get('pagebox');
var _pg = e._$page(_box,{
event:'click',
index:9,
total:10,
onchange:function(_obj){
ok(true,'last page is :' + _obj.last + ' index page is:' + _obj.index + 'total:' + _obj.total)
start();
}
});
_pg._$setIndex(10);
_pg._$setTotal(20);
_pg._$updatePage(5,10);
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}pager.test.js',
['ui/pager/pager',
'util/page/page.simple',
'util/page/page'],f);
});
.#<uispace>{width:410px;border:1px;font-size:12px;text-align:center;}
.#<uispace>,.#<uispace> .zbrd{border-style:solid;border-color:#aaa;}
.#<uispace> a{text-decoration:none;}
.#<uispace> .zbgp{background:url(#<portrait>btn.png) no-repeat;}
.#<uispace> .zsdb{float:right;width:80px;text-align:left;}
.#<uispace> .zsdb .zpgr{text-align:center;}
.#<uispace> .zsdb .zpgr span{display:block;height:24px;margin:0 10px;border-color:#eee;cursor:pointer;}
.#<uispace> .zsdb .zpup span{border-width:0 0 1px;background-position:center 2px;}
.#<uispace> .zsdb .zpdn span{border-width:1px 0 0;background-position:center -18px;}
.#<uispace> .zsdb .zwin{position:relative;height:180px;overflow:hidden;}
.#<uispace> .zsdb .zlst{position:absolute;top:0;left:0;width:100%;}
.#<uispace> .zsdb .zlst .zitm{height:22px;line-height:22px;padding-left:5px;border-width:0;}
.#<uispace> .zsdb .zlst .zitm.js-selected{border-width:1px 0;margin-left:0;}
.#<uispace> .zsdb .zbtn{display:block;margin-left:1px;color:#777;}
.#<uispace> .zsdb .zbtn:hover,
.#<uispace> .zsdb .zlst .zitm.js-selected{background-color:#e5e5e1;color:#000;text-decoration:none;}
.#<uispace> .zsdb .js-disabled{cursor:default;}
.#<uispace> .zsdb .js-disabled span{opacity:0.6;filter:alpha(opacity=60);cursor:default;}
.#<uispace> .zsdb .js-disabled:hover{background-color:transparent;}
.#<uispace> .zcnt{margin-right:79px;padding:5px 5px 0;border-width:0 1px 0 0;background:#e5e5e1;}
.#<uispace> .zcnt .zptrt{border:none;}
<textarea name='ntp' id='#<mid>'>
<div class="zbrd">
<div class="zsdb">
<a class="zbtn zpgr zpup j-flag" href="#" hidefocus="true" title="上一页"><span class="zbrd zbgp">&nbsp;</span></a>
<div class="zwin"><div class="zlst j-flag"></div></div>
<a class="zbtn zpgr zpdn j-flag" href="#" hidefocus="true" title="下一页"><span class="zbrd zbgp">&nbsp;</span></a>
</div>
<div class="zcnt zbrd j-flag"></div>
</div>
</textarea>
<textarea name='jst' id='#<lid>'>
{list xlist as x}
<a href="#" hidefoucus="true" class="zbtn zitm zbrd" data-value="${x.id}">${x.name}</a>
{/list}
</textarea>
/*
* ------------------------------------------
* 复杂表情控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/portrait/complex */
NEJ.define([
'base/global',
'base/klass',
'base/config',
'base/element',
'base/util',
'ui/base',
'ui/portrait/portrait',
'util/template/tpl',
'util/tab/tab',
'util/page/simple',
'util/data/portrait/portrait',
'util/template/jst',
'text!./complex.css',
'text!./complex.html'
],function(NEJ,_k,_c,_e,_u,_i,_i0,_t0,_t2,_t3,_t4,_t5,_css,_html,_p,_o,_f,_r){
// variable declaration
var _pro,
_seed_css = _e._$pushCSSText(
_css,{portrait:_c._$get('portrait')}
);
/**
* 复杂表情控件
*
* @class module:ui/portrait/complex._$$ComplexPortrait
* @extends module:util/event._$$EventTarget
* @uses module:ui/portrait/portait._$$Portrait
* @param {Object} arg0 - 可选配置参数
*/
/**
* 表情选中事件
*
* @event module:ui/portrait/complex._$$ComplexPortrait#onselect
* @param {Object} arg0 - 表情数据对象
* @property {String} text - 表情描述
* @property {String} url - 表情文件地址
*/
_p._$$ComplexPortrait = _k._$klass();
_pro = _p._$$ComplexPortrait._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__init
* @return {Void}
*/
_pro.__init = function(){
this.__popt = {
clazz:'zptrt',
cache:{
data:{},
klass:_t4._$$CachePortrait
}
};
this.__topt = {
offset:0,
limit:1000,
data:{type:'type'},
key:'portrait-type'
};
this.__bopt = {
onchange:this.__onTypeChange._$bind(this)
};
this.__copt = {
onlistload:this.__cbTypeListLoad._$bind(this)
};
this.__gopt = {
limit:8,
onchange:this.__onPageChange._$bind(this)
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__popt.onselect = _options.onselect;
delete _options.onselect;
this.__super(_options);
this.__cache = _t4._$$CachePortrait
._$allocate(this.__copt);
this.__cache._$getList(this.__topt);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__doClearComponent();
this.__super();
};
/**
* 初始化外观
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__initXGui
* @return {Void}
*/
_pro.__initXGui = (function(){
var _seed = _t0._$parseUITemplate(_html);
return function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed.mid;
this.__seed_list = _seed.lid;
};
})();
/**
* 初始化控件节点
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
// 0 - previous type
// 1 - type list
// 2 - next type
// 3 - portrait list
var _list = _e._$getByClassName(this.__body,'j-flag');
this.__tbox = _list[1];
this.__gopt.pbtn = _list[0];
this.__gopt.nbtn = _list[2];
this.__popt.parent = _list[3];
};
/**
* 分类列表载入回调
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__cbTypeListLoad
* @return {Void}
*/
_pro.__cbTypeListLoad = (function(){
var _inited = !1,
_limit = {
30:60,
60:15
};
var _doInit = function(_list){
if (_inited)
return;
_inited = !0;
var _arr = [];
_u._$forEach(
_list,function(_item){
var _id = _item.id,
_prefix = _c._$get('portrait')+_id+'/'+_id+'-',
_total = Math.ceil(_item.total/_limit[_item.size]);
for(var i=0;i<_total;i++){
_arr.push('.'+_seed_css+' .js-'+_id+'-'+(i+1)+' .zitm{background-image:url('+_prefix+i+'.png);}');
}
}
);
_e._$addStyle(_arr.join(''));
};
return function(_options){
var _list = this.__cache.
_$getListInCache(_options.key);
_doInit(_list);
_t5._$render(
this.__tbox,this.__seed_list,{
xlist:_list
}
);
this.__gopt.total = Math.ceil(_list.length/this.__gopt.limit);
this.__pager = _t3._$$PageSimple._$allocate(this.__gopt);
this.__bopt.list = _e._$getChildren(this.__tbox);
this.__taber = _t2._$$Tab._$allocate(this.__bopt);
};
})();
/**
* 分类变化事件
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__onTypeChange
* @param {Object} arg0 - 分类信息
* @return {Void}
*/
_pro.__onTypeChange = function(_event){
if (!!this.__portrait){
this.__portrait._$recycle();
}
var _cache = this.__popt.cache,
_item = this.__cache._$getItemInCache(_event.data);
this.__popt.size = _item.size;
this.__popt.page = 'js-'+_item.id+'-';
_cache.lkey = 'portrait-'+_item.id;
_cache.data.type = _item.id;
this.__portrait = _i0._$$Portrait._$allocate(this.__popt);
};
/**
* 分类页码变化事件
*
* @protected
* @method module:ui/portrait/complex._$$ComplexPortrait#__onPageChange
* @param {Object} arg0 - 页码信息
* @return {Void}
*/
_pro.__onPageChange = function(_event){
var _offset = 0;
if (!!this.__taber){
var _list = this.__taber._$getList(),
_index = (_event.index-1)*this.__gopt.limit,
_offset = Math.max(0,_list[_index].offsetTop-2);
this.__taber._$go(_index);
}
_e._$setStyle(this.__tbox,'top',0-_offset+'px');
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>test complex portrait</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script>
window.NEJ_CONF = {
portrait:'http://nej.netease.com/images/portrait/'
};
</script>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../complex.js'
],function(_i){
_i._$$ComplexPortrait._$allocate({
parent:document.body
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>test simple portrait</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script>
window.NEJ_CONF = {
portrait:'http://nej.netease.com/images/portrait/'
};
</script>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../simple.js'
],function(_i){
_i._$$SimplePortrait._$allocate({
parent:document.body
});
});
</script>
</body>
</html>
// link to ui/portrait/complex for compatible
// use ui/portrait/complex for new project
NEJ.define(['./complex.js'],function(_t){return _t;});
.#<uispace>{width:310px;padding:5px;background:#e5e5e1;border:1px solid #888;}
.#<uispace> .zlst{position:relative;height:190px;}
.#<uispace> .zlst .zitm{display:block;float:left;margin:-1px 0 0 -1px;text-indent:200px;overflow:hidden;border:1px solid #e5e5e1;cursor:pointer;background:no-repeat;}
.#<uispace> .zlst .zitm:hover{position:relative;border-color:#000;zoom:1;}
.#<uispace> .zlst .z30{width:30px;height:30px;line-height:30px;}
.#<uispace> .zlst .z60{width:61px;height:60px;line-height:60px;}
#<arrbg>
.#<uispace> .zpbx{padding:5px 0 1px;text-align:right;}
.#<uispace> .zpager .zbtn,.#<uispace> .zpager .zpgi{border:0;margin:0;}
.#<uispace> .zpager .zpgi{display:none;}
.#<uispace> .zpager .js-disabled{color:#777;}
.#<uispace> .js-prev{position:absolute;top:0;left:0;background:#fff no-repeat center center;border:1px solid #888;}
.#<uispace> .js-prev-30{width:60px;height:60px;}
.#<uispace> .js-prev-30 img{display:none;}
<textarea name='ntp' id='#<mid>'>
<div>
<div class="zlst j-flag"></div>
<div class="zpbx j-flag"></div>
</div>
</textarea>
<textarea name='jst' id='#<lid>'>
{list beg..end as y}
{var x=xlist[y]}
<a href="#" hidefocus="true" class="zitm z${size} z${size}-${y%(row*col)}" title="${x.text}" data-id="${x.id}" data-align="{if y%col<col/2}right{else}left{/if} top">${x.text}</a>
{/list}
</textarea>
/*
* ------------------------------------------
* 表情控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/portrait/portrait */
NEJ.define([
'base/global',
'base/klass',
'base/constant',
'base/element',
'base/event',
'base/util',
'ui/base',
'ui/pager/pager.simple',
'util/list/module.pager',
'util/template/tpl',
'text!./portrait.css',
'text!./portrait.html'
],function(NEJ,_k,_g,_e,_v,_u,_i,_i0,_t0,_t1,_css,_html,_p,_o,_f,_r){
// variable declaration
var _pro,
_seed_css = 'auto-'+_u._$uniqueID();
/**
* 表情控件
*
* @class module:ui/portrait/portrait._$$Portrait
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {Number} size - 表情大小,30或60,默认为30, 目前支持30*30和60*60
* @property {String} page - 分页标识前缀,默认为js-page-
* @property {Object} cache - 数据缓存配置
*/
/**
* 表情选中事件
*
* @event module:ui/portrait/portrait._$$Portrait#onselect
* @param {Object} arg0 - 表情数据对象
* @property {String} text - 表情描述
* @property {String} url - 表情文件地址
*
*/
_p._$$Portrait = _k._$klass();
_pro = _p._$$Portrait._$extend(_i._$$Abstract);
/**
* 控件初始化
* @return {Void}
*/
_pro.__init = function(){
this.__mopt = {
item:{},
pager:{
fixed:!0,
clazz:'zpager',
klass:_i0._$$SimplePager
},
onpagechange:this.__onChangePage._$bind(this)
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = (function(){
var _iconf = {
60:{row:3,col:5,size:60},
30:{row:6,col:10,size:30}
};
return function(_options){
this.__super(_options);
this.__mopt.cache = _options.cache;
var _conf = _iconf[_options.size]||_iconf['30'];
this.__prefix = _options.page||'js-page-';
this.__mopt.limit = _conf.row*_conf.col;
NEJ.X(this.__mopt.item,_conf);
_e._$addClassName(
this.__nprv.parentNode,
'js-prev-'+_conf.size
);
this.__mdl = _t0._$$ListModulePG._$allocate(this.__mopt);
};
})();
/**
* 控件销毁
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
if (!!this.__mdl){
this.__mdl._$recycle();
delete this.__mdl;
}
_e._$delClassName(
this.__mopt.parent,
this.__pgcls
);
_e._$delClassName(
this.__nprv.parentNode,
'js-prev-'+this.__mopt.item.size
);
delete this.__pgcls;
delete this.__mopt.cache;
};
/**
* 初始化外观
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__initXGui
* @return {Void}
*/
_pro.__initXGui = (function(){
var _seed = _t1._$parseUITemplate(_html);
return function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed.mid;
this.__mopt.item.klass = _seed.lid;
};
})();
/**
* 初始化控件节点
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
// build preview
this.__nprv = new Image();
var _node = _e._$create('div','js-prev');
_node.appendChild(this.__nprv);
// 0 - item list box
// 1 - pager box
var _list = _e._$getByClassName(this.__body,'j-flag');
this.__mopt.parent = _list[0];
this.__mopt.pager.parent = _list[1];
_v._$addEvent(
this.__mopt.parent,'click',
this.__onSelectPortrait._$bind(this)
);
_v._$addEvent(
this.__mopt.parent,'mouseover',
this.__onPreviewPortrait._$bind(this,!0)
);
_v._$addEvent(
this.__mopt.parent,'mouseout',
this.__onPreviewPortrait._$bind(this,!1)
);
};
/**
* 通过事件取表情数据
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__getPortraitByEvent
* @param {Event} arg0 - 事件对象
* @return {Object} 表情数据
*/
_pro.__getPortraitByEvent = function(_event){
var _node = _v._$getElement(_event,'d:id');
if (!_node) return;
var _id = _e._$dataset(_node,'id'),
_data = this.__mdl._$cache()
._$getItemInCache(_id);
if (!_data) return;
return {
node:_node,data:_data,
align:_e._$dataset(_node,'align')
};
};
/**
* 解析预览图片对齐方式
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__doParseAlign
* @param {String} arg0 - 对齐方式,'left top'
* @return {Object} 对齐信息
*/
_pro.__doParseAlign = function(_align){
var _result = {
top:'auto',
left:'auto',
right:'auto',
bottom:'auto'
};
var _arr = (_align||'').split(/\s+/);
_result[_arr[0]||'left'] = 0;
_result[_arr[1]||'top'] = 0;
return _result;
};
/**
* 预览表情事件
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__onPreviewPortrait
* @param {Boolean} arg0 - 是否预览
* @param {Event} arg0 - 事件对象
* @return {Void}
*/
_pro.__onPreviewPortrait = function(_in,_event){
var _parent = this.__nprv.parentNode;
if (!_in){
if (this.__mopt.item.size==30){
_e._$setStyle(_parent,'backgroundImage','none');
}else{
this.__nprv.src = _g._$BLANK_IMAGE;
}
_e._$removeByEC(_parent);
return;
}
// do preview
var _data = this.__getPortraitByEvent(_event);
if (!_data) return;
_e._$style(_parent,this.__doParseAlign(_data.align));
this.__mopt.parent.appendChild(_parent);
var _url = _data.data.url;
if (this.__mopt.item.size==30){
_e._$setStyle(_parent,'backgroundImage','url('+_url+')');
}else{
this.__nprv.src = _url;
}
};
/**
* 选中表情触发事件
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__onSelectPortrait
* @param {Event} arg0 - 事件对象
* @return {Void}
*/
_pro.__onSelectPortrait = function(_event){
var _data = this.__getPortraitByEvent(_event);
if (!!_data){
_v._$stop(_event);
this._$dispatchEvent('onselect',_data.data);
}
};
/**
* 页码变化触发事件
*
* @protected
* @method module:ui/portrait/portrait._$$Portrait#__onChangePage
* @param {Object} arg0 - 页码信息
* @return {Void}
*/
_pro.__onChangePage = function(_event){
this.__pgcls = this.__prefix+(_event.index||'');
var _last = this.__prefix+(_event.last||'');
_e._$replaceClassName(
this.__mopt.parent,
_last,this.__pgcls
);
};
// init style and html
var _arr = [];
for(var i=0;i<6;i++){
for(var j=0;j<10;j++){
_arr.push('.'+_seed_css+' .zlst .z30-'+(i*10+j)+'{background-position:-'+(j*30)+'px -'+(i*30)+'px;}');
}
}
for(var i=0;i<3;i++){
for(var j=0;j<5;j++){
_arr.push('.'+_seed_css+' .zlst .z60-'+(i*5+j)+'{background-position:-'+(j*60)+'px -'+(i*60)+'px;}');
}
}
// ui style
_e._$pushCSSText(_css,{
uispace:_seed_css,
arrbg:_arr.join(' ')
});
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/portrait/simple for compatible
// use ui/portrait/simple for new project
NEJ.define(['./simple.js'],function(_t){return _t;});
/*
* ------------------------------------------
* 简易表情控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/portrait/simple */
NEJ.define([
'base/global',
'base/klass',
'base/config',
'base/element',
'base/util',
'ui/base',
'ui/portrait/portrait'
],function(NEJ,_k,_c,_e,_u,_i,_i0,_p,_o,_f,_r){
// variable declaration
var _pro,
_seed_css;
/**
* 简易表情控件
*
* @class module:ui/portrait/simple._$$SimplePortrait
* @extends module:ui/base._$$Abstract
* @uses module:ui/portrait/portrait._$$Portrait
* @param {Object} 可选配置参数
*/
/**
* 表情选中事件
*
* @event module:ui/portrait/simple._$$SimplePortrait#onselect
* @param {Object} 表情数据对象
* @property {String} text 表情描述
* @property {String} url 表情文件地址
*/
_p._$$SimplePortrait = _k._$klass();
_pro = _p._$$SimplePortrait._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/portrait/simple._$$SimplePortrait#__init
* @return {Void}
*/
_pro.__init = (function(){
var _ilist = [
'微笑','开怀笑','哭泣','失望','困了','好好笑','啵','电到了','汗','流口水了',
'真困啊','我吐','眨眼','???','嘘','砸死你','不说','坏','色迷迷','教训',
'可爱','YEAH','崩溃','惊讶','鄙视','开心','仰慕你','晕','挖鼻孔','撒娇',
'鼓掌','害羞','老大','欠揍','吐舌笑脸','飞吻','工作忙','大哭','偷偷笑','送花给你',
'来,亲一个','拍桌子','拜拜','得意的笑','生气','怕怕','尴尬','难过','叹气','我是女生',
'玫瑰','好爱你','心碎了','亲亲','NO','YES','握个手','到点了','音乐','我是男生',
'带血的刀','炸弹','有了','好晚了','吸血蝙蝠','便便','干一杯','抽烟','打电话','家',
'车子','礼物','金钱','太阳','下雨','猪猪','小猫','小狗','骨头','喝水',
'汉堡','包子','西瓜','约会','CALL我'
];
var _doInit = function(){
if (!!_ilist[0].id) return;
// push css text
var _arr = [],
_prefix = _c._$get('portrait')+'face/face-';
for(var i=0;i<2;i++){
_arr.push('.#<uispace> .js-page-'+(i+1)+' .zitm{background-image:url('+_prefix+i+'.png);}');
}
_seed_css = _e._$pushCSSText(_arr.join(' '));
// format data
var _root = _c._$get('portrait')+'face/preview/';
_u._$forEach(
_ilist,function(_text,_index,_list){
_list[_index] = {
text:_text,
id:'sp-'+_index,
url:_root+'face'+_index+'.gif'
};
}
);
};
return function(){
_doInit();
this.__popt = {
cache:{
list:_ilist,
lkey:'portrait',
id:'nej-simple-portrait'
}
};
this.__super();
};
})();
/**
* 控件重置
*
* @protected
* @method module:ui/portrait/simple._$$SimplePortrait#__reset
* @param {Object} 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
_options.cache = _u._$merge({},this.__popt.cache);
_options.clazz = _seed_css+' '+(_options.clazz||'');
this.__portrait = _i0._$$Portrait._$allocate(_options);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/portrait/simple._$$SimplePortrait#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
if (!!this.__portrait){
this.__portrait._$recycle();
delete this.__portrait;
}
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
.#<uispace>{position:absolute;top:0;left:0;width:0;height:0;overflow:hidden;border:1px solid #0C32F6;background:#B8D4F0;_filter:alpha(opacity=70);opacity:0.7;}
/*
* ------------------------------------------
* 范围选择控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/range/range */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/base',
'util/range/range',
'text!./range.css'
],function(NEJ,_k,_e,_i,_t0,_css,_p,_o,_f,_r){
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 范围选择控件封装
*
* @class module:ui/range/range._$$Range
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
*/
/**
* 页码切换事件
*
* @event module:ui/range/range._$$Range#onchange
* @param {Object} arg0 - 区域信息
*/
/**
* 区域变化之后触发事件
*
* @event module:ui/range/range._$$Range#onafterchange
*/
/**
* 区域变化之前触发事件
*
* @event module:ui/range/range._$$Range#onbeforechange
* @param {Object} arg0 - 区域信息
*/
_p._$$Range = _k._$klass();
_pro = _p._$$Range._$extend(_i._$$Abstract);
/**
* 初始化控件
*
* @protected
* @method module:ui/range/range._$$Range#__init
* @return {Void}
*/
_pro.__init = function(){
this.__ropt = {
onchange:this.__onRangeChange._$bind(this)
,onafterchange:this.__onAfterRangeChange._$bind(this)
,onbeforechange:this.__onBeforeRangeChange._$bind(this)
};
this.__super();
};
/**
* 重置控件
*
* @protected
* @method module:ui/range/range._$$Range#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__ropt.parent = this.__parent;
this.__range = _t0._$$Range._$allocate(this.__ropt);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/range/range._$$Range#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
this.__range._$recycle();
delete this.__range;
delete this.__ropt.parent;
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/range/range._$$Range#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 初始化结构
*
* @protected
* @method module:ui/range/range._$$Range#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
this.__body.innerHTML = '&nbsp;';
this.__ropt.body = this.__body;
};
/**
* 区域变化触发事件
*
* @protected
* @method module:ui/range/range._$$Range#__onRangeChange
* @param {Object} arg0 - 区域信息
* @return {Void}
*/
_pro.__onRangeChange = function(_event){
this._$dispatchEvent('onchange',_event);
};
/**
* 区域变化触发事件
*
* @protected
* @method module:ui/range/range._$$Range#__onBeforeRangeChange
* @param {Object} arg0 - 区域信息
* @return {Void}
*/
_pro.__onBeforeRangeChange = function(_event){
this._$dispatchEvent('onbeforchange',_event);
};
/**
* 区域变化触发事件
*
* @protected
* @method module:ui/range/range._$$Range#__onAfterRangeChange
* @param {Object} arg0 - 区域信息
* @return {Void}
*/
_pro.__onAfterRangeChange = function(){
this._$dispatchEvent('onafterchange');
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>resizer demo</title>
<meta charset="utf-8" />
<script>
function log(m){
var p = document.createElement('p');
p.innerHTML = m;
document.body.appendChild(p);
}
</script>
</head>
<body>
<script src="../../../define.js"></script>
<script>
NEJ.define([
'../resizer.js'
],function(_i){
_i._$$Resizer._$allocate({
parent:document.body
});
});
</script>
</body>
</html>
.#<uispace>-parent{position:relative;}
.#<uispace>{position:absolute;top:0;left:0;border:1px solid #aaa;cursor:move;$<user-select>:none;z-index:1000;}
.#<uispace> .zln{width:48px;height:48px;border:1px solid #fff;background:url(#<blankimage>);}
.#<uispace> .zpc{border:1px solid #aaa;}
.#<uispace> .zpt{position:absolute;width:5px;height:5px;font-size:1px;overflow:hidden;}
.#<uispace> .znt{top:-1px;left:-1px;width:100%;cursor:n-resize;}
.#<uispace> .znr{top:-1px;right:-1px;height:100%;cursor:e-resize;}
.#<uispace> .znb{bottom:-1px;left:-1px;width:100%;cursor:s-resize;}
.#<uispace> .znl{top:-1px;left:-1px;height:100%;cursor:w-resize;}
.#<uispace> .zntl{top:-1px;left:-1px;cursor:nw-resize;}
.#<uispace> .zntr{top:-1px;right:-1px;cursor:ne-resize;}
.#<uispace> .znbr{bottom:-1px;right:-1px;cursor:se-resize;}
.#<uispace> .znbl{bottom:-1px;left:-1px;cursor:sw-resize;}
<div>
<div class="zln">
{list clazz as x}
<div class="zpt ${x} js-rs-${x_index+1}">&nbsp;</div>
{/list}
</div>
</div>
/*
* ------------------------------------------
* 范围裁剪控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/resizer/resizer */
NEJ.define([
'base/global',
'base/klass',
'base/constant',
'base/element',
'base/util',
'ui/base',
'util/resize/resize',
'util/template/tpl',
'util/template/jst',
'text!./resizer.css',
'text!./resizer.html'
],function(NEJ,_k,_g,_e,_u,_i,_t0,_t1,_t2,_css,_html,_p,_o,_f,_r){
var _pro,
_seed_html,
_seed_point = _t2._$add(_html);
/**
* 初始大小
* @typedef {Object} module:ui/resizer/resizer._$$Resizer~Size
* @property {Number} width - 宽
* @property {Number} height - 高
* @property {Number} ratio - 比例
*/
/**
* 最大宽高限制
* @typedef {Object} module:ui/resizer/resizer._$$Resizer~Max
* @property {Number} width - 宽
* @property {Number} height - 高
*/
/**
* 范围裁剪控件封装
*
* @class module:ui/resizer/resizer._$$Resizer
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数,其他参数见module:util/resize/resize._$$ResizerResize控件所示
* @property {module:ui/resizer/resizer._$$Resizer~Size} size - 初始大小,输入任意两个值,其中ratio为width/height
* @property {module:ui/resizer/resizer._$$Resizer~Max} max - 最大宽高限制
*/
_p._$$Resizer = _k._$klass();
_pro = _p._$$Resizer._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/resizer/resizer._$$Resizer#__init
* @return {Void}
*/
_pro.__init = function(){
this.__ropt = {
onbeforeresize:this.__onBeforeResize._$bind(this),
onresizestart:this._$dispatchEvent._$bind(this,'onresizestart'),
onresizeend:this._$dispatchEvent._$bind(this,'onresizeend'),
onresize:this._$dispatchEvent._$bind(this,'onresize'),
onmove:this._$dispatchEvent._$bind(this,'onmove')
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/resizer/resizer._$$Resizer#__reset
* @param {Object} arg0 - 配置参数
* @return {Void}
*/
_pro.__reset = (function(){
var _doParseSize = function(_size,_max){
if (!_size) return;
var _result,
_width = _size.width,
_height = _size.height,
_ratio = _size.ratio;
if (!!_width&&!!_height){
_result = {
width:_width-2,
height:_height-2
};
}else if(!!_ratio){
if (!!_width){
_result = {
width:_width-2,
height:Math.floor(_width/_ratio)-2
};
}else if(!!_height){
_result = {
height:_height-2,
width:Math.floor(_height*_ratio)-2
};
}
}
// fix max limit
if (!!_max){
var _maxw = _max.width-2,
_maxh = _max.height-2,
_orgw = _result.width,
_orgh = _result.height,
_delta = _maxw/_maxh-_orgw/_orgh;
if (_delta>0&&_orgh>_maxh){
_result.height = _maxh;
_result.width = Math.floor(_orgw*_maxh/_orgh);
}else if(_delta<0&&_orgw>_maxw){
_result.width = _maxw;
_result.height = Math.floor(_maxw*_orgh/_orgw);
}
}
_result.width += 'px';
_result.height += 'px';
return _result;
};
return function(_options){
this.__super(_options);
var _opt = _u._$merge(_u._$fetch({
lock:!1,
min:null
},_options),this.__ropt);
_opt.view = this.__parent;
_opt.body = this.__body;
_e._$style(
this.__nsize,
_doParseSize(_options.size,_options.max)
);
this.__resize = _t0._$$Resize._$allocate(_opt);
};
})();
/**
* 控件销毁
*
* @protected
* @method module:ui/resizer/resizer._$$Resizer#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
if (!!this.__resize){
this.__resize._$recycle();
delete this.__resize;
}
this.__super();
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/resizer/resizer._$$Resizer#__initXGui
* @return {Void}
*/
_pro.__initXGui = (function(){
var _seed_css = _e._$pushCSSText(
_css,{blankimage:_g._$BLANK_IMAGE}
);
return function(){
this.__seed_css = _seed_css;
this.__seed_html = _seed_html;
};
})();
/**
* 动态构建控件节点模板
*
* @protected
* @method module:ui/resizer/resizer._$$Resizer#__initNodeTemplate
* @return {Void}
*/
_pro.__initNodeTemplate = (function(){
var _clazz = [
'znt','znr','znb','znl',
'zpc zntl','zpc zntr','zpc znbr','zpc znbl'
];
return function(){
_seed_html = _t1._$addNodeTemplate(
_t2._$get(_seed_point,{clazz:_clazz})
);
this.__seed_html = _seed_html;
};
})();
/**
* 初始化节点
*
* @protected
* @method module:ui/resizer/resizer._$$Resizer#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
this.__nsize = _e._$getChildren(this.__body)[0];
};
/**
* 大小变化之前触发事件
*
* @protected
* @method module:ui/resizer/resizer._$$Resizer#__onBeforeResize
* @return {Void}
*/
_pro.__onBeforeResize = function(_event){
_event.stopped = !0;
_e._$style(
this.__nsize,{
width:_event.width-2+'px',
height:_event.height-2+'px'
}
);
_e._$style(
this.__body,{
top:_event.top+'px',
left:_event.left+'px'
}
);
this._$dispatchEvent('onresize',_event);
};
/**
* 裁剪信息
*
* @typedef {Object} module:ui/resizer/resizer._$$Resizer~ResizeBox
* @property {Number} top - 距离上
* @property {Number} left - 距离左
* @property {Number} width - 宽
* @property {Number} height - 高
*/
/**
* 取裁剪信息
*
* @method module:ui/resizer/resizer._$$Resizer#_$getResizeBox
* @return {module:ui/resizer/resizer._$$Resizer~ResizeBox} 信息
*/
_pro._$getResizeBox = function(){
return this.__resize._$getResizeBox();
};
/**
* 更新裁剪信息
*
* @method module:ui/resizer/resizer._$$Resizer#_$update
* @param {module:ui/resizer/resizer._$$Resizer~ResizeBox} arg0 - 裁剪信息
* @return {Void}
*/
_pro._$update = function(_box){
this.__resize._$update(_box);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/scroller/list for compatible
// use ui/scroller/list for new project
NEJ.define(['ui/scroller/list'],function(_t){return _t;});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>scrollList测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
.box{position:relative;}
#scrollList-box{height:200px;overflow:hidden;background:pink;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit scrollList test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div>
<div id="scrollList-box" class="box"></div>
</div>
<div style="height:1000px;"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./scroller.list.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("ui-scrollList");
var _ = NEJ.P,
_e = _('nej.e'),
_p = _('nej.ui'),
_t = _('nej.ut');
//开始单元测试
// test('scrollList',function(){
// stop();
// var _scrollList = _p._$$ListScroller._$allocate({
// parent:'scrollList-box',
// onscroll:function(_offset){
// ok(true,'onscroll');
// },
// onbounce:function(_event){
// ok(true,'onbounce');
// },
// onbouncestart:function(){
// ok(true,'onbouncestart');
// },
// onlistupdate:function(_node){
// ok(true,'onlistupdate');
// start();
// },
// onbeforeclear:function(_box){
// ok(true,'onbeforeclear');
// }
// });
// _scrollList._$bindPuller(_p._$$PullRefresh._$allocate({
// onrefresh:function(){
// var _list = '';
// for(var _i = 20; _i > 0; _i--){
// _list += '<div>' + _i + '</div>'
// }
// _scrollList._$addLast(_list);
// }
// }));
// });
test('profile',function(){
stop();
var _sp = _t._$$ScrollPerf._$allocate({
level:1,
offset:10,
viewport:'scrollList-box'
});
var _scrollList = _p._$$ListScroller._$allocate({
parent:'scrollList-box',
onscroll:function(_offset){
ok(true,'onscroll');
_sp._$performance(_scrollList._$getScrollTop());
},
onbounce:function(_event){
ok(true,'onbounce');
},
onbouncestart:function(){
ok(true,'onbouncestart');
},
onlistupdate:function(_node){
ok(true,'onlistupdate');
start();
},
onbeforeclear:function(_box){
ok(true,'onbeforeclear');
}
});
_scrollList._$bindPuller(_p._$$PullRefresh._$allocate({
onrefresh:function(){
var _list = '';
for(var _i = 40; _i > 0; _i--){
_list += '<p class="js-perf">' + _i + '</p>'
}
_scrollList._$addLast(_list);
}
}));
});
// test('profile image',function(){
// stop();
// var _sp = _t._$$ScrollPerf._$allocate({
// level:1,
// offset:10,
// viewport:'scrollList-box'
// });
// var _scrollList = _p._$$ListScroller._$allocate({
// parent:'scrollList-box',
// onscroll:function(_offset){
// ok(true,'onscroll');
// _sp._$performance(_scrollList._$getScrollTop());
// },
// onbounce:function(_event){
// ok(true,'onbounce');
// },
// onbouncestart:function(){
// ok(true,'onbouncestart');
// },
// onlistupdate:function(_node){
// ok(true,'onlistupdate');
// start();
// },
// onbeforeclear:function(_box){
// ok(true,'onbeforeclear');
// }
// });
// _scrollList._$bindPuller(_p._$$PullRefresh._$allocate({
// onrefresh:function(){
// var _list = '';
// for(var _i = 40; _i > 0; _i--){
// _list += '<p class="js-perf">' + _i + '</p>'
// }
// _scrollList._$addLast(_list);
// }
// }));
// });
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}scroller.list.test.js',
['util/profile/profile',
'ui/scroller.list/scroller.list',
'ui/pullrefresh/pullrefresh'],f);
});
<!DOCTYPE html>
<html>
<head>
<title>test scroll y</title>
<meta charset="utf-8"/>
<style>
.abc{position:relative;}
.abc p{margin:50px 0;}
</style>
</head>
<body>
<div class="abc" id="abc">
<p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>
<p>bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb</p>
<p>cccccccccccccccccccccccccccccccccc</p>
<p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>
<p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>
<p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>
<p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>
</div>
<script src="../../../../src/define.js"></script>
<script>
define([
'../y.js'
],function(_i){
_i._$$ScrollerY._$allocate({
container:'abc'
});
});
</script>
</body>
</html>
.#<uispace>{position:relative;}
/*
* ------------------------------------------
* 列表滚动控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/scroller/list */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/util',
'ui/base',
'ui/scroller/scroller.y',
'ui/pullrefresh/puller',
'text!./list.css'
],function(NEJ,_k,_e,_u,_i,_i0,_i1,_css,_p,_o,_f,_r){
// variable declaration
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 列表滚动控件
*
* @class module:ui/scroller/list._$$ListScroller
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {module:ui/scroller/y._$$ScrollerY.Config} config - 滚动参数配置信息
*/
/**
* 列表滚动触发事件
*
* @event module:ui/scroller/list._$$ListScroller#onscroll 列表滚动触发事件
* @param {Number} offset - 当前位置
*/
/**
* 弹性触发事件
*
* @event module:ui/scroller/list._$$ListScroller#onbounce
* @param {Object} arg0 - 弹性信息
* @property {Number} movement - 偏移量
* @property {Number} direction - 方向
* | 数值 | 含义 |
* | :--- | :--- |
* | <0 | 正向滚动(远离顶部的滚动) |
* | >0 | 反向滚动(接近顶部的滚动) |
*/
/**
* 弹性开始时触发事件
*
* @event module:ui/scroller/list._$$ListScroller#onbouncestart
*/
/**
* 列表更新触发事件
*
* @event module:ui/scroller/list._$$ListScroller#onlistupdate
* @param {Node} arg0 - 更新后的节点
*/
/**
* 列表清除之前触发事件
*
* @event module:ui/scroller/list._$$ListScroller#onbeforeclear
* @param {Node} arg0 - 缓存的节点
*/
_p._$$ListScroller = _k._$klass();
_pro = _p._$$ListScroller._$extend(_i._$$Abstract);
/**
* 初始化外观信息
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
this.__cache = {};
this.__nlist = e._$create('div','z-list');
this.__sopt = {container:this.__body,style:'z-bar',
onscroll:this.__onScrolling._$bind(this),
onbounce:this.__onScrollBounce._$bind(this),
onrelease:this.__onScrollRelease._$bind(this),
onbouncestart:this._$dispatchEvent._$bind(this,'onbouncestart')};
};
/**
* 控件重置
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__reset
* @param {Object} arg0 - 可选配置参数
* @property {module:ui/scroller/y._$$ScrollerY.Config} config - 滚动参数配置信息
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__body.appendChild(this.__nlist);
this.__sopt.parent = this.__parent;
this.__sopt.config = _options.config;
this.__scroller = p._$$ScrollerY._$allocate(this.__sopt);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this._$setList();
e._$removeByEC(this.__nlist);
this.__super();
if (!!this.__puller)
this.__puller = this.__puller.constructor
._$recycle(this.__puller);
this.__scroller = p._$$ScrollerY._$recycle(this.__scroller);
};
/**
* 内容封装
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__doParseWrapBox
* @param {String} arg0 - 内容
* @return {Node} 封装后的内容节点
*/
_pro.__doParseWrapBox = function(_html){
if (!_html) return null;
var _node = e._$create('div','z-box');
_node.id = 'box-' + _u._$uniqueID();
_node.innerHTML = _html;
return _node;
};
/**
* 列表清理
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__doPerformListClear
* @return {Void}
*/
_pro.__doPerformListClear = function(){
var _list = e._$getChildren(this.__nlist);
if (!_list||!_list.length) return;
for(var i=0,l=_list.length,_id,_box;i<l;i++){
_box = _list[i]; _id = _box.id;
_box = this.__cache[_id]||_box;
delete this.__cache[_id];
this._$dispatchEvent('onbeforeclear',_box);
}
};
/**
* 图片延时载入优化
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__doPerformImage
* @param {Node} arg0 - 容器节点
* @return {Boolean} 是否存在未处理的图片
*/
_pro.__doPerformImage = function(_node){
if (!!_node.finished) return;
var _ndpf = !1,
_images = _node.getElementsByTagName('img');
if (!!_images&&!!_images.length)
for(var i=0,l=_images.length,_image,_src;i<l;i++){
_image = _images[i];
_src = e._$dataset(_image,'src');
if (!_src) continue;
if (!this.__scroller._$isInViewPoint(_image)){
_ndpf = !0; continue;
}
_image.src = _src;
e._$dataset(_image,'src','');
}
if (!_ndpf) _node.finished = !0;
};
/**
* 优化节点的显示
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__doPerformNode
* @param {Node} arg0 - 节点
* @return {Void}
*/
_pro.__doPerformNode = function(_node){
this.__scroller._$isInViewPoint(_node)
? this.__doPerformAppend(_node.id)
: this.__doPerformRecycle(_node.id);
};
/**
* 执行节点追加
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__doPerformAppend
* @param {String} arg0 - 节点ID
* @return {Void}
*/
_pro.__doPerformAppend = function(_id){
var _parent = e._$get(_id),
_children = this.__cache[_id];
if (!!_parent&&!!_children){
_parent.appendChild(_children);
_parent.style.height = 'auto';
}
delete this.__cache[_id];
this.__doPerformImage(_parent);
};
/**
* 执行节点回收
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__doPerformRecycle
* @param {String} arg0 - 节点ID
* @return {Void}
*/
_pro.__doPerformRecycle = function(_id){
var _parent = e._$get(_id);
if (!_parent||!!this.__cache[_id]) return;
var _fragment = document.createDocumentFragment();
this.__cache[_id] = _fragment;
_parent.style.height = _parent.scrollHeight+'px';
var _children = e._$getChildren(_parent);
if (!_children||!_children.length) return;
var _element = _children.shift();
while(!!_element){
_fragment.appendChild(_element);
_element = _children.shift();
}
};
/**
* 优化滚动
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__doPerformWithTimer
* @return {Void}
*/
_pro.__doPerformWithTimer = function(){
var _list = e._$getChildren(this.__nlist);
if (!_list||!_list.length) return;
this.__doPerformImage(_list[0]);
for(var i=1,l=_list.length,_id,_tmp0;i<l;i++){
_id = _list[i].id;
_tmp0 = this.__scroller._$isInViewPoint(_list[i]);
_tmp0 ? this.__doPerformAppend(_id)
: this.__doPerformRecycle(_id);
}
};
/**
* 滚动事件
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__onScrolling
* @param {Number} arg0 - 当前位置
* @return {Void}
*/
_pro.__onScrolling = (function(){
var _timer = null;
return function(_offset){
if (!_timer)
_timer = window.setTimeout(function(){
_timer = window.clearTimeout(_timer);
this.__performed ? this.__doPerformWithTimer()
: this.__doPerformImage(this.__nlist);
}._$bind(this),150);
this._$dispatchEvent('onscroll',_offset);
};
})();
/**
* 滚动结束
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__onScrollRelease
* @return {Void}
*/
_pro.__onScrollRelease = function(_event){
if (!this.__puller||
this.__puller._$getState()!=1) return;
// auto revert bounce to state bar
_event.offset = this.__puller._$getRange();
this.__puller._$setState(2);
window.setTimeout(function(){
this.__puller._$dispatchEvent('onrefresh');
}._$bind(this),250);
};
/**
* 滚动弹性
*
* @protected
* @method module:ui/scroller/list._$$ListScroller#__onScrollBounce
* @param {Object} arg0 - 弹性信息
* @return {Void}
*/
_pro.__onScrollBounce = function(_event){
var _distance = _event.movement||0;
if (!!this.__puller&&_distance>0&&
this.__puller._$getState()!=2)
this.__puller._$setState(this.__puller
._$isOutThreshold(_distance)?1:0);
this._$dispatchEvent('onbounce',_event);
};
/**
* 执行性能优化
*
* @method module:ui/scroller/list._$$ListScroller#_$performance
* @return {Void}
*/
_pro._$performance = function(){
this.__performed = !0;
};
/**
* 绑定下拉更新控件
*
* @method module:ui/scroller/list._$$ListScroller#_$bindPuller
* @param {nej.ui._$$Puller} arg0 - 下拉更新控件
* @return {Void}
*/
_pro._$bindPuller = function(_puller){
if (!(_puller instanceof p._$$Puller)) return;
if (!!this.__puller){
_puller._$setState(this.__puller._$getState());
this.__puller.constructor._$recycle(this.__puller);
}
this.__puller = _puller;
this.__body.insertAdjacentElement(
'afterBegin',this.__puller._$getBody());
};
/**
* 追加更多列表
*
* @method module:ui/scroller/list._$$ListScroller#_$addMore
* @param {String} arg0 - 列表html代码
* @return {Void}
*/
_pro._$addMore = function(_html){
var _node = this.__doParseWrapBox(_html);
if (!!_node){
this.__nlist.appendChild(_node);
this.__doPerformImage(_node);
this._$dispatchEvent('onlistupdate',_node);
}
};
/**
* 追加最新列表
* @method module:ui/scroller/list._$$ListScroller#_$addLast
* @param {String} arg0 - 列表html代码
* @return {Void}
*/
_pro._$addLast = function(_html){
this.__scroller._$revertBounce();
window.setTimeout(function(){
this.__puller._$setState(3);
var _node = this.__doParseWrapBox(_html);
if (!!_node){
this.__nlist.insertAdjacentElement('afterBegin',_node);
this.__doPerformImage(_node);
this._$dispatchEvent('onlistupdate',_node);
}
}._$bind(this),250);
};
/**
* 设置列表
*
* @method module:ui/scroller/list._$$ListScroller#_$setList
* @param {String} arg0 - 列表html代码
* @return {Void}
*/
_pro._$setList = function(_html){
this.__doPerformListClear();
this.__nlist.innerHTML = '';
this._$addMore(_html);
this._$scrollTop();
};
/**
* 判断偏移是否在可视范围内
*
* @method module:ui/scroller/list._$$ListScroller#_$isInViewPoint
* @param {String|Node} arg0 - 检测节点
* @return {Boolean} 是否在可视范围内
*/
_pro._$isInViewPoint = function(_element){
return this.__scroller._$isInViewPoint.apply(this.__scroller,arguments);
};
/**
* 取当前滚动高度
*
* @method module:ui/scroller/list._$$ListScroller#_$getScrollTop
* @return {Number} 滚动高度
*/
_pro._$getScrollTop = function(){
return this.__scroller._$getScrollTop.apply(this.__scroller,arguments);
};
/**
* 滚动至偏移位置
*
* @method module:ui/scroller/list._$$ListScroller#_$scrollBy
* @param {Number} delta - 偏移量
* @param {Boolean} refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollBy = function(_delta,_refresh){
this.__scroller._$scrollBy.apply(this.__scroller,arguments);
};
/**
* 滚动至指定位置
*
* @method module:ui/scroller/list._$$ListScroller#_$scrollTo
* @param {Number} delta - 偏移量
* @param {Boolean} refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollTo = function(_offset,_refresh){
this.__scroller._$scrollTo.apply(this.__scroller,arguments);
};
/**
* 滚动至顶部
*
* @method module:ui/scroller/list._$$ListScroller#_$scrollTop
* @param {Boolean} arg0 - 是否需要刷新
* @return {Void}
*/
_pro._$scrollTop = function(_refresh){
this.__scroller._$scrollTop.apply(this.__scroller,arguments);
};
/**
* 滚动至中部
*
* @method module:ui/scroller/list._$$ListScroller#_$scrollMiddle
* @param {Boolean} arg0 - 是否需要刷新
* @return {Void}
*/
_pro._$scrollMiddle = function(_refresh){
this.__scroller._$scrollMiddle.apply(this.__scroller,arguments);
};
/**
* 滚动至底部
*
* @method module:ui/scroller/list._$$ListScroller#_$scrollBottom
* @param {Boolean} arg0 - 是否需要刷新
* @return {Void}
*/
_pro._$scrollBottom = function(_refresh){
this.__scroller._$scrollBottom.apply(this.__scroller,arguments);
};
/**
* 滚动到指定元素
*
* @method module:ui/scroller/list._$$ListScroller#_$scrollToElement
* @param {String|Node} element - 目标元素
* @param {Boolean} refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollToElement = function(_element,_refresh){
this.__scroller._$scrollToElement.apply(this.__scroller,arguments);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
/**
* ------------------------------------------
* 滚动控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/scroller/scroller */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/event',
'base/util',
'ui/base',
'util/gesture/tap',
'util/gesture/drag',
'util/animation/bounce',
'util/animation/easeout',
'util/animation/decelerate'
],function(NEJ,_k,_e,_v,_u,_i,_t0,_t1,_t2,_t3,_t4,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 滚动配置信息
* @typedef {Object} module:ui/scroller/scroller._$$Scroller~Config
* @property {Float} bcfactor - 弹性移动距离与触点移动距离比例,默认0.5 表示触点移动2px弹性增加1px
* @property {Float} minbar - 滚动条保留的最小高度与窗体可视高度比例,默认1/3
* @property {Number} reset - 滚动加速检测时间间隔【单位ms】,默认350,连续滚动操作350ms后重新开始计算加速初始速度
* @property {Number} acceleration - 减速度,值越大加速越慢,默认30
* @property {Number} minvelocity - 加速最小初始速度,默认为1
* @property {String|Node} container - 内容容器节点ID或者对象
*/
/**
* 滚动控件
* @class module:ui/scroller/scroller._$$Scroller
* @extends module:ui/base._$$Abstract
* @param {Object} options - 可选配置参数
* @property {module:ui/scroller/scroller._$$Scroller~Config} config - 滚动配置信息
*/
/**
* 滚动过程触发事件
*
* @event module:ui/scroller/scroller._$$Scroller#onscroll
*/
/**
* 滚动动画结束触发事件(不包括弹性)
*
* @event module:ui/scroller/scroller._$$Scroller#onscrollend
*/
/**
* 弹性效果过程触发事件
*
* @event module:ui/scroller/scroller._$$Scroller#onbounce
*/
/**
* 弹性结束触发事件
*
* @event module:ui/scroller/scroller._$$Scroller#onbouncend
*/
/**
* 弹性开始触发事件
*
* @event module:ui/scroller/scroller._$$Scroller#onbouncestart
*/
/**
* 释放滚动触发事件
*
* @event module:ui/scroller/scroller._$$Scroller#onrelease
*/
_p._$$Scroller = _k._$klass();
_pro = _p._$$Scroller._$extend(_i._$$Abstract);
/**
* 初始化控件
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__init
* @return {Void}
*/
_pro.__init = function(){
this.__super();
this.__momentum = {};
this.__config = this.__getConfig();
this.__alopt = {from:{},to:{},
onstop:this.__doStopBounceRevert._$bind(this),
onupdate:this.__doUpdateBounceRevert._$bind(this)};
this.__adopt = {from:{},
onstop:this.__doStopDecelerate._$bind(this),
onupdate:this.__doUpdateDecelerate._$bind(this)};
this.__abopt = {from:{},
onstop:this.__doStopBounce._$bind(this),
onupdate:this.__doUpdateBounce._$bind(this)};
this.__evopt = {ontapstart:this.__onTouchStart._$bind(this),
ondragstart:this.__onDragStart._$bind(this),
ondrag:this.__onDragging._$bind(this),
ondragend:this.__onDragEnd._$bind(this),
ontransitionend:this.__onTransitionEnd._$bind(this)};
};
/**
* 取滚动配置信息,子类实现具体逻辑
*
* @abstract
* @return {Object} 滚动配置信息
*/
_pro.__getConfig = _f;
/**
* 控件重置
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__reset
* @param {Object} _options - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__doInitDomEvent([
[this.__parent.parentNode,'touchstart',v._$stopDefault],
[this.__parent.parentNode,'touchmove',v._$stopDefault]
]);
// init param
this.__bpoint = [0,0];
this.__animate = {minvelocity:1,
bcfactor:0.5,minbar:1/5,
reset:300,acceleration:30};
_u._$fetch(this.__animate,_options.config);
this.__cbox = _e._$get(_options.container)||
_e._$getChildren(this.__parent)[0];
_e._$addClassName(this.__cbox,this.__seed+'-view');
};
/**
* 控件销毁
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
_e._$delClassName(this.__cbox,this.__seed+'-view');
delete this.__offset;
_e._$setStyle(this.__cbox,'transform','');
};
/**
* 刷新滚动控件参数
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__refresh
* @return {Void}
*/
_pro.__refresh = (function(){
var _offset = function(_element,_attr){
if (!_element) return 0;
var _value = _element[_attr];
while(!!_element&&!_value){
_element = _element.parentNode;
if (!!_element)
_value = _element[_attr];
}
return _value;
};
return function(){
var _sbox = this.__cbox[this.__config.sb],
_obox = _offset(this.__parent,this.__config.ob);
this.__scrollable = _sbox>_obox;
this.__boxsize = _obox;
this.__barsize = Math.max(_obox*_obox/_sbox,
_obox*this.__animate.minbar);
this.__scratio = (_obox-this.__barsize)/(_sbox-_obox);
this.__body.style[this.__config.g] = this.__barsize+'px';
this.__bpoint = [Math.min(0,_obox-_sbox),0];
this.__offset = this.__getOffset();
};
})();
/**
* 清理定时器
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__clearScrollBarTimer
* @return {Void}
*/
_pro.__clearScrollBarTimer = function(){
if (!this.__timer) return;
this.__timer = window.clearTimeout(this.__timer);
};
/**
* 显示滚动条
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__showScrollBar
* @return {Void}
*/
_pro.__showScrollBar = function(){
if (!this.__barable||
!this.__scrollable) return;
this.__clearScrollBarTimer();
this.__body.style.opacity = 1;
};
/**
* 隐藏滚动条
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__hideScrollBar
* @return {Void}
*/
_pro.__hideScrollBar = function(){
if (!this.__barable||
!this.__scrollable) return;
this.__clearScrollBarTimer();
// delay 0.5s hide scrollbar
this.__timer = window.setTimeout(function(){
this.__body.style.opacity = 0;
}._$bind(this),300);
};
/**
* 取偏移量
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__getOffset
* @return {Number} 偏移量
*/
_pro.__getOffset = function(){
var _transform = _e._$matrix(e.
_$getStyle(this.__cbox,'transform'));
return parseInt(_transform[this.__config.dx])||0;
};
/**
* 取弹性距离
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__getOutofBounce
* @param {Number} _offset - 偏移量
* @return {Number} 弹性距离
* | 数值 | 含义 |
* | :--- | :--- |
* | <0 | 下超出 |
* | =0 | 非弹性超出 |
* | >0 | 上超出 |
*/
_pro.__getOutofBounce = function(_offset){
var _out = _offset==null?this.__offset:_offset;
if (this.__bpoint[0]<=_out&&
this.__bpoint[1]>=_out)
return 0;
var _delta = _out-this.__bpoint[0];
if (_delta<0) return _delta;
_delta = _out-this.__bpoint[1];
if (_delta>0) return _delta;
};
/**
* 刷新布局信息
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doRefresh
* @param {Boolean} _force - 强制刷新
* @return {Void}
*/
_pro.__doRefresh = function(_force){
_force = !!_force||this.__offset===undefined;
if (!!_force) this.__refresh();
};
/**
* 恢复弹性
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doRevertBounce
* @param {Number} _offset - 弹性距离
* @param {Number} _duration - 持续时间
* @return {Void}
*/
_pro.__doRevertBounce = function(_offset,_duration){
var _distance = this.__getOutofBounce();
if (_distance!=0&&!this.__linear){
var _end = _offset!=null ? _offset
: this.__bpoint[_distance<0?0:1];
this.__alopt.duration = _duration||200;
this.__alopt.from.offset = this.__offset;
this.__alopt.to.offset = _end;
this.__linear = _t3._$$AnimEaseOut._$allocate(this.__alopt);
this.__linear._$play();
return !0;
}
};
/**
* 弹性恢复动画回收
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doStopBounceRevert
* @return {Void}
*/
_pro.__doStopBounceRevert = function(){
if (!!this.__linear)
this.__linear = this.__linear._$recycle();
this.__skip = !1;
};
/**
* 更新弹性恢复
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doUpdateBounceRevert
* @param {Object} _event - 偏移量对象
* @property {Number} offset - 偏移量
* @return {Void}
*/
_pro.__doUpdateBounceRevert = function(_event){
this.__doScrollTo(_event.offset);
};
/**
* 减速动画回收
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doStopDecelerate
* @param {Boolean} _nohide - 是否回收
* @return {Void}
*/
_pro.__doStopDecelerate = function(_nohide){
if (!!this.__decelerator)
this.__decelerator = this.__decelerator._$recycle();
if (!_nohide){
this.__hideScrollBar();
this._$dispatchEvent('onscrollend',this.__getOffset());
}
};
/**
* 减速动画
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doUpdateDecelerate
* @param {Object} _event - 配置参数
* @property {Number} offset - 偏移量
* @property {Number} velocity - 当前速度
* @return {Void}
*/
_pro.__doUpdateDecelerate = function(_event){
var _offset = _event.offset,
_velocity = _event.velocity,
_distance = this.__getOutofBounce(_offset);
if (_distance==0){
this.__doScrollTo(_offset);
return;
}
this.__doStopDecelerate(!0);
this.__abopt.from.velocity = _velocity;
this.__abopt.from.offset = this.__bpoint[_distance<0?0:1];//this.__offset;
this.__bouncer = _t2._$$AnimBounce._$allocate(this.__abopt);
this.__bouncer._$play();
};
/**
* 弹性动画回收
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doStopBounce
* @return {Void}
*/
_pro.__doStopBounce = function(){
if (!!this.__bouncer)
this.__bouncer = this.__bouncer._$recycle();
this.__hideScrollBar();
};
/**
* 弹性动画
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doUpdateBounce
* @param {Object} _event - 偏移量对象
* @property {Number} offset - 偏移量
* @return {Void}
*/
_pro.__doUpdateBounce = function(_event){
this.__doScrollTo(_event.offset);
};
/**
* 滚动至指定位置
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doScrollBy
* @param {Number} _delta - 偏移量
* @return {Void}
*/
_pro.__doScrollBy = function(_delta){
this.__doScrollTo(this.__offset+_delta);
};
/**
* 滚动至指定位置
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__doScrollTo
* @param {Number} _offset - 偏移量
* @return {Void}
*/
_pro.__doScrollTo = function(_offset){
// 正向滚动(远离顶部的滚动):<0
// 反向滚动(接近顶部的滚动):>0
var _delta = _offset-this.__offset;
if (!_delta) return;
this.__offset = _offset;
var _distance = this.__getOutofBounce(),
_index = _distance<0?0:1,
_bounce = _distance!=0;
if (_bounce)
this.__offset = Math.ceil(this.__offset-_delta+
this.__animate.bcfactor*_delta);
var _map = {};
_map[this.__config.of] = _u._$fixed(this.__offset,2)+'px';
_e._$css3d(this.__cbox,'translate',_map);
// synchronize scrollbar
if (this.__barable){
var _offset = Math.floor(Math.max(0,-this.__scratio*this.__offset));
if (_bounce){
var _size = Math.max(8,this.__barsize-Math.abs(_distance)*2);
this.__body.style[this.__config.g] = _size+'px';
if (_distance<0)
_offset = this.__boxsize-_size;
}else{
this.__body.style[this.__config.g] = this.__barsize+'px';
_offset = Math.min(_offset,this.__boxsize-this.__barsize);
}
var _map = {};
_map[this.__config.of] = _u._$fixed(_offset,2)+'px';
_e._$css3d(this.__body,'translate',_map);
}
// event trigger
if (!_bounce){
var _name = this.__bouncing?'onbouncend':'onscroll';
this.__bouncing = !1;
this._$dispatchEvent(_name,this.__offset);
return;
}
if (!!this.__skip) return;
var _event = {movement:_distance,
direction:_delta>0?-1:1};
if (!!this.__bouncing){
this._$dispatchEvent('onbounce',_event);
return;
}
this.__bouncing = !0;
this._$dispatchEvent('onbouncestart',_event);
};
/**
* 开始触摸触发事件
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__onTouchStart
* @return {Void}
*/
_pro.__onTouchStart = function(){
// stop all animation
if (!!this.__linear)
this.__linear._$stop();
if (!!this.__bouncer)
this.__bouncer._$stop();
if (!!this.__decelerator)
this.__decelerator._$stop();
if (!!this.__timer2){
this.__timer2 = window.clearInterval(this.__timer2);
this.__onTransitionEnd();
}
};
/**
* 开始事件
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__onDragStart
* @param {Touch} _touch - 触点对象
* @return {Void}
*/
_pro.__onDragStart = function(){
//v._$stopBubble(_event);
this.__refresh();
this.__scrolling = !0;
this.__showScrollBar();
this.__momentum.offset = this.__offset;
this.__momentum.time = new Date().getTime();
};
/**
* 过程事件
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__onDragging
* @param {Touch} _touch - 触点对象
* @return {Void}
*/
_pro.__onDragging = function(_touch){
if (!this.__scrolling) return;
var _delta = _touch.detalY;
this.__doScrollBy(_delta);
var _time = new Date().getTime();
if (_time-this.__momentum.time>this.__animate.reset){
this.__momentum.time = _time;
this.__momentum.offset = this.__offset;
}
};
/**
* 结束事件
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__onDragEnd
* @param {Touch} _touch - 触点对象
* @return {Void}
*/
_pro.__onDragEnd = function(_touch){
if (!this.__scrolling) return;
this.__scrolling = !1;
var _event = {};
this._$dispatchEvent('onrelease',_event);
var _bounce = this.__doRevertBounce(_event.offset);
if (!!_bounce){
this.__hideScrollBar();
return;
}
var _duration = new Date().getTime()-this.__momentum.time,
_distance = this.__offset-this.__momentum.offset,
_velocity = _distance/_duration*this.__animate.acceleration;
if (Math.abs(_velocity)<this.__animate.minvelocity){
this.__hideScrollBar();
this._$dispatchEvent('onscrollend',this.__getOffset());
return;
}
this.__adopt.from.offset = this.__offset;
this.__adopt.from.velocity = _velocity;
this.__decelerator = _t4._$$AnimDecelerate._$allocate(this.__adopt);
this.__decelerator._$play();
};
/**
* 动画结束触发事件
*
* @protected
* @method module:ui/scroller/scroller._$$Scroller#__onTransitionEnd
* @return {Void}
*/
_pro.__onTransitionEnd = function(){
this.__cbox.style.webkitTransitionDuration = '0ms';
};
/**
* 控件节点追加至容器
* @method module:ui/scroller/scroller._$$Scroller#_$appendTo
* @param {String|Node} arg0 - 控件所在容器节点
* @return {Void}
*/
_pro._$appendTo = function(_parent){
this.__super();
this.__barable = _e._$getStyle(
this.__body,'display')!='none';
if (!this.__parent) return;
this.__doInitDomEvent([
[document,'dragging',this.__evopt.ondrag],
[document,'dragcomplete',this.__evopt.ondragend],
[this.__parent,'tapdown',this.__evopt.ontapstart],
[this.__parent,'dragbegin',this.__evopt.ondragstart]
]);
};
/**
* 恢复弹性
* @method module:ui/scroller/scroller._$$Scroller#_$revertBounce
* @return {Void}
*/
_pro._$revertBounce = function(){
if (!!this.__linear)
this.__linear._$stop();
// skip bounce event
this.__skip = !0;
this.__doRevertBounce(null,200);
};
/**
* 判断偏移是否在可视范围内
* @method module:ui/scroller/scroller._$$Scroller#_$isInViewPoint
* @param {String|Node} _element - 检测节点
* @return {Boolean} 是否在可视范围内
*/
_pro._$isInViewPoint = function(_element){
_element = _e._$get(_element);
if (!_element) return !1;
var _range0 = _e._$offset(_element,
this.__cbox)[this.__config.of],
_range1 = _range0+_element.offsetHeight;
this.__doRefresh();
var _beg = Math.abs(Math.min(0,this.__offset)),
_end = _beg+this.__boxsize;
return !(_range1<_beg||_range0>_end);
};
/**
* 取当前滚动高度
* @method module:ui/scroller/scroller._$$Scroller#_$getScrollTop
* @return {Number} 滚动高度
*/
_pro._$getScrollTop = function(){
this.__doRefresh();
return Math.abs(Math.max(this.__bpoint[0],
Math.min(this.__bpoint[1],this.__offset)));
};
/**
* 滚动至偏移位置
* @method module:ui/scroller/scroller._$$Scroller#_$scrollBy
* @param {Number} _delta - 偏移量
* @param {Boolean} _refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollBy = function(_delta,_refresh){
this.__doRefresh(_refresh);
this._$scrollTo(Math.abs(this.__offset)+
(parseInt(_delta)||0));
};
/**
* 滚动至指定位置
* @method module:ui/scroller/scroller._$$Scroller#_$scrollTo
* @param {Number} _offset - 偏移量
* @param {Boolean} _refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollTo = function(_offset,_refresh){
this.__onTouchStart();
this.__doRefresh(_refresh);
_offset = Math.max(this.__bpoint[0],
Math.min(this.__bpoint[1],0-_offset));
_e._$setStyle(this.__cbox,'transitionDuration','150ms');
this.__doScrollTo(_offset);
if (!!this.__timer2)
this.__timer2 = window.clearTimeout(this.__timer2);
this.__timer2 = window.setTimeout(this.__evopt.ontransitionend,150);
};
/**
* 滚动至顶部
* @method module:ui/scroller/scroller._$$Scroller#_$scrollTop
* @param {Boolean} _refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollTop = function(_refresh){
this.__doRefresh(_refresh);
this._$scrollTo(Math.abs(this.__bpoint[1]));
};
/**
* 滚动至中部
* @method module:ui/scroller/scroller._$$Scroller#_$scrollMiddle
* @param {Boolean} _refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollMiddle = function(_refresh){
this.__doRefresh(_refresh);
this._$scrollTo((this.__bpoint[1]-this.__bpoint[0])/2);
};
/**
* 滚动至底部
* @method module:ui/scroller/scroller._$$Scroller#_$scrollBottom
* @param {Boolean} _refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollBottom = function(_refresh){
this.__doRefresh(_refresh);
this._$scrollTo(Math.abs(this.__bpoint[0]));
};
/**
* 滚动到指定元素
* @method module:ui/scroller/scroller._$$Scroller#_$scrollToElement
* @param {String|Node} _element - 目标元素
* @param {Boolean} _refresh - 是否需要刷新
* @return {Void}
*/
_pro._$scrollToElement = function(_element,_refresh){
var _offset = _e._$offset(_element,this.__cbox);
if (!_offset) return;
this._$scrollTo(_offset[this.__config.of],_refresh);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
// link to ui/scroller/x for compatible
// use ui/scroller/x for new project
NEJ.define(['./x.js'],function(_t){return _t;});
// link to ui/scroller/y for compatible
// use ui/scroller/y for new project
NEJ.define(['./y.js'],function(_t){return _t;});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>scrolly测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<style type="text/css">
#scroll-y-container{height:200px;position:relative;overflow:hidden;}
</style>
</head>
<body>
<h1 id="qunit-header">Qunit scrolly test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="scroll-y-container">
<div>
123
</div>
</div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./scroller.y.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("scrolly");
var _ = NEJ.P,
_p = _('nej.ui');
//开始单元测试
test('scrolly',function(){
expect(0);
var _sly = _p._$$ScrollerY._$allocate({
parent:'scroll-y-container',
onscroll:function(){
},
onscrollend:function(){
},
onbounce:function(_event){
},
onbouncend:function(_event){
},
onbouncestart:function(_event){
},
onrelease:function(){
}
});
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}scroller.y.test.js',['ui/scroller/scroller.y'],f);
});
.#<uispace>{position:absolute;z-index:10;$<transform>-origin:0 0;$<transition>-property:opacity;$<transition>-duration:250ms;background-color:rgba(0,0,0,0.6);$<border-radius>:4px;border:1px solid rgba(255,255,255,0.2);opacity:0;overflow:hidden;}
.#<uispace>-view{position:relative;z-index:5;$<transform>:$<translate>;}
.#<uispace>{bottom:1px;left:0;height:4px;}
/*
* ------------------------------------------
* 水平滚动控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/scroller/x */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/scroller/scroller',
'text!./x.css'
],function(NEJ,_k,_e,_i0,_css,_p,_o,_f,_r){
// variable declaration
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 滚动配置信息
* @typedef {Object} module:ui/scroller/x._$$ScrollerX~Config
* @property {Number} f - h
* @property {Number} a - 方向
* @property {Number} g - 宽度
* @property {Number} t - pageX
* @property {Number} of - x
* @property {Number} ob - offsetWidth
* @property {Number} sb - scrollWidth
* @property {Number} dx - m41
*/
/**
* 水平滚动控件
*
* @class module:ui/scroller/x._$$ScrollerX
* @extends module:ui/scroller/scroller._$$Scroller
* @param {Object} arg0 - 可选配置参数
*/
_p._$$ScrollerX = _k._$klass();
_pro = _p._$$ScrollerX._$extend(_i0._$$Scroller);
/**
* 初始化外观信息
*
* @protected
* @method module:ui/scroller/x._$$ScrollerX#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 取滚动配置信息
*
* @protected
* @method module:ui/scroller/x._$$ScrollerX#__getConfig
* @return {module:ui/scroller/x._$$ScrollerX~Config} 滚动配置信息
*/
_pro.__getConfig = function(){
return {f:'h',a:'left',g:'width',t:'pageX',of:'x',
ob:'offsetWidth',sb:'scrollWidth',dx:'m41'};
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
.#<uispace>{position:absolute;z-index:10;$<transform>-origin:0 0;$<transition>-property:opacity;$<transition>-duration:250ms;background-color:rgba(0,0,0,0.6);$<border-radius>:4px;border:1px solid rgba(255,255,255,0.2);opacity:0;overflow:hidden;}
.#<uispace>-view{position:relative;z-index:5;$<transform>:$<translate>;}
.#<uispace>{top:0;right:1px;width:6px;}
/*
* ------------------------------------------
* 垂直滚动控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/scroller/y */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'ui/scroller/scroller',
'text!./y.css'
],function(NEJ,_k,_e,_i0,_css,_p,_o,_f,_r){
// variable declaration
var _pro,
_seed_css = _e._$pushCSSText(_css);
/**
* 滚动配置信息
* @typedef {Object} module:ui/scroller/y._$$ScrollerY.Config
* @property {Number} f - v
* @property {Number} a - 方向
* @property {Number} g - 高度
* @property {Number} t - pageY
* @property {Number} of - y
* @property {Number} ob - offsetHeight
* @property {Number} sb - scrollHeight
* @property {Number} dx - m42
*/
/**
* 垂直滚动控件
*
* @class module:ui/scroller/y._$$ScrollerY 垂直滚动控件
* @extends module:ui/scroller/scroller._$$Scroller
* @param {Object} arg0 - 可选配置参数
*/
_p._$$ScrollerY = _k._$klass();
_pro = _p._$$ScrollerY._$extend(_i0._$$Scroller);
/**
* 初始化外观信息
*
* @protected
* @method module:ui/scroller/y._$$ScrollerY#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 取滚动配置信息
*
* @protected
* @method module:ui/scroller/y._$$ScrollerY#__getConfig
* @return {Object} 滚动配置信息
*/
_pro.__getConfig = function(){
return {f:'v',a:'top',g:'height',t:'pageY',of:'y',
ob:'offsetHeight',sb:'scrollHeight',dx:'m42'};
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE html>
<html>
<head>
<title>test suggest</title>
<meta charset="utf-8"/>
<style>
p{margin:200px 0;}
.abc{width:170px;}
</style>
</head>
<body>
<input type="text" id="abc"/>
<script src="../../../../src/define.js"></script>
<script>
define([
'../suggest.js'
],function(_i){
_i._$$Suggest._$allocate({
input:'abc',
clazz:'abc',
autofill:!1,
onchange:function(_event){
console.log(_event);
this._$setList(['1','2','3','4']);
},
onselect:function(v){
console.log(v);
}
});
});
</script>
</body>
</html>
.#<uispace>-parent{position:relative;}
.#<uispace>{position:absolute;border:1px solid #aaa;background:#fff;text-align:left;visibility:hidden;}
.#<uispace> .zitm{height:20px;line-height:20px;cursor:default;}
.#<uispace> .js-selected{background:#1257F9;}
{if defined("xlist")&&!!xlist.length}
{list xlist as x}<div class="zitm" data-value="${x}">${x}</div>{/list}
{/if}
/*
* ------------------------------------------
* 建议提示控件封装实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module ui/suggest/suggest */
NEJ.define([
'base/global',
'base/klass',
'base/element',
'base/util',
'ui/base',
'util/suggest/suggest',
'util/template/jst',
'text!./suggest.css',
'text!./suggest.html'
],function(NEJ,_k,_e,_u,_i,_t0,_t1,_css,_html,_p,_o,_f,_r){
var _seed_css = _e._$pushCSSText(_css),
_seed_item = _t1._$add(_html),
_pro;
/**
* 提示建议控件
*
* 页面结构举例
* ```html
* <input type='text' id='suggest-input' />
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/element',
* 'ui/suggest/suggest',
* ],function(_e,_i0,_p,_o,_f,_r){
* var _input = _e._$get('suggest-input');
* // 输入框内容变化回调
* var _onchage = function(_value){
* // 根据输入框的值,获取需要展示的列表,返回给控件展示
* _suggest._$setList(['1','2','3','4']);
* };
* // 选择某一项的回调
* var _onselect = function(_value){
* // 返回选中的值
* };
* // 生成下拉列表实例
* var _suggest = _i0._$$Suggest._$allocate({
* input:_input,
* onchange:_onchage._$bind(this),
* onselect:_onselect._$bind(this)
* });
* });
* ```
*
* @class module:ui/suggest/suggest._$$Suggest
* @uses module:util/suggest/suggest._$$Suggest
* @extends module:ui/base._$$Abstract
* @param {Object} arg0 - 可选配置参数
* @property {Node|String} input - 输入框节点或者ID
* @property {Boolean} autofill - 是否自动填充,默认自动填充
*/
/**
* 选中触发事件
*
* @event module:ui/suggest/suggest._$$Suggest#onselect
* @param {String} arg0 - 选中值
*/
/**
* 输入内容变化触发事件
*
* @event module:ui/suggest/suggest._$$Suggest#onchange
* @param {String} arg0 - 输入内容
*
*/
_p._$$Suggest = _k._$klass();
_pro = _p._$$Suggest._$extend(_i._$$Abstract);
/**
* 控件初始化
*
* @protected
* @method module:ui/suggest/suggest._$$Suggest#__init
* @return {Void}
*/
_pro.__init = function(){
this.__sopt = {
onchange:this.__onChange._$bind(this),
onselect:this.__onSelect._$bind(this)
};
this.__super();
};
/**
* 控件重置
*
* @protected
* @method module:ui/suggest/suggest._$$Suggest#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__sopt.autofill = _options.autofill!=!1;
this.__sopt.input = _e._$get(_options.input);
this.__sopt.input.insertAdjacentElement('afterEnd',this.__body);
this.__suggest = _t0._$$Suggest._$allocate(this.__sopt);
};
/**
* 控件销毁
*
* @protected
* @method module:ui/suggest/suggest._$$Suggest#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
if (!!this.__suggest){
this.__suggest._$recycle();
delete this.__suggest;
}
this.__super();
delete this.__sopt.input;
};
/**
* 初始化外观信息
*
* @protected
* @method module:ui/suggest/suggest._$$Suggest#__initXGui
* @return {Void}
*/
_pro.__initXGui = function(){
this.__seed_css = _seed_css;
};
/**
* 初始化节点
*
* @protected
* @method module:ui/suggest/suggest._$$Suggest#__initNode
* @return {Void}
*/
_pro.__initNode = function(){
this.__super();
this.__sopt.body = this.__body;
};
/**
* 输入内容变化触发事件
*
* @protected
* @method module:ui/suggest/suggest._$$Suggest#__onChange
* @param {String} arg0 - 输入内容
* @return {Void}
*/
_pro.__onChange = function(_value){
this._$dispatchEvent('onchange',_value);
};
/**
* 选中建议项触发事件
*
* @protected
* @method module:ui/suggest/suggest._$$Suggest#__onSelect
* @param {String} arg0 - 选中值
* @return {Void}
*/
_pro.__onSelect = function(_value,_options){
this._$dispatchEvent('onselect',_value,_options);
};
/**
* 设置建议列表
*
* 脚本举例
* ```javascript
* // 设置下拉列表的值
* _suggest._$setList(['1','2','3','4']);
* ```
*
* @method module:ui/suggest/suggest._$$Suggest#_$setList
* @param {String|Array} _html - 列表html代码或者数据列表
* @param {String} _clazz - 列表项标识样式
* @return {Void}
*/
_pro._$setList = function(_html,_clazz){
if (_u._$isArray(_html))
_html = _t1._$get(
_seed_item,{xlist:_html});
this.__body.innerHTML = _html||'';
this.__suggest._$setList(!_clazz
? _e._$getChildren(this.__body)
: _e._$getByClassName(this.__body,_clazz));
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ui'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>suggest测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">nej suggest.js test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<input type='text' id='suggest-input' />
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./suggest.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("suggest",{
setup:function(){
this._e = nej.e;
this._ui = nej.ui;
}
});
//开始单元测试
test('生成一个suggest', function() {
expect(0);
var _input = this._e._$get('suggest-input');
var _onchage = function(_value){
_suggest._$setList(['0','1','2','3','4','5','6','7','8','9']);
};
var _onselect = function(_value,_options){
console.log(_options.type);
};
var _suggest = this._ui._$$Suggest._$allocate({
input:_input,
onchange:_onchage._$bind(this),
onselect:_onselect._$bind(this)
});
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}suggest.test.js',
['ui/suggest/suggest','base/element'],f);
});
<div>
<p>aaaaaaaaaaa</p>
</div>
<!DOCTYPE html>
<html>
<head>
<title>test tag</title>
<meta charset="utf-8"/>
</head>
<body>
<script src="../../../../src/define.js"></script>
<script>
define([
'../tag.js'
],function(_j){
_j._$loadHtml('./a.html',{
onload:function(result){
console.log(result);
}
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>test file upload</title>
<meta charset="utf-8"/>
</head>
<body>
<script src="../../../../src/define.js"></script>
<script>
define([
'../tag.js'
],function(_j){
_j._$loadHtml('./a.html',{
onload:function(result){
console.log(result);
}
});
});
</script>
</body>
</html>
/*
* ------------------------------------------
* DWR框架前端引擎实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/dwr */
NEJ.define([
'base/global',
'base/constant',
'base/util',
'util/ajax/xdr',
'util/ajax/tag',
'util/cache/cookie'
],function(NEJ,_g,_u,_j0,_j1,_j2,_p,_o,_f,_r){
var _batchid, // 请求ID标识
_doFilter = _f, // 全局异常过滤器
_xcache = {}, // 请求缓存
_cname = 'JSESSIONID',
_xbatch = null; // 请求临时构造对象,范例
// {h:{0:{c:function(){}, // callback
// e:function(){}}}, // exception
// p:1, // param number
// u:'http://xxxx/x.x.dwr',// url
// r:{script:!1,sync:!1,method:'POST',timeout:null}
// // request options
// m:{}} // send data
/**
* 设置全局异常过滤器
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/dwr'
* ],function(_j){
* // 所有请求对错误码是401的情况不做处理
* _j._$setFilter(function(_event){
* // _event.code
* // _event.message
*
* return _event.code == 401;
* });
* });
* ```
*
* @method module:util/ajax/dwr._$setFilter
* @param {Function} arg0 - 过滤器,过滤器返回值
*
* * true - 不继续执行后续错误处理接口
* * false - 继续执行后续错误处理接口
*
* @return {Void}
*/
_p._$setFilter = function(_filter){
_doFilter = _u._$isFunction(_filter)?_filter:_f;
};
/**
* 设置CSRF使用的cookie名,请求时会将此cookie对应的值带在参数上发送到服务器
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/dwr'
* ],function(_j){
* _j._$setCookieName('CSRF-CKN');
*
* // 假设cookie里有CSRF-CKN的值为asldjsdi23234asdfasdf
* // 则以下请求参数中带有httpSessionId=asldjsdi23234asdfasdf
* // 服务器端取请求参数中的httpSessionId值与cookie中的CSRF-CKN值比较,判断是否是伪造请求
* _j._$request(
* 'DownloadBean.getDownloadUrlByBrandAndModel1',{
* path:'/dwr/call/plaincall/',
* script:false,
* param:["nokia","n97"],
* onload:function(data){
* // TODO
* },onerror:function(error){
* // TODO
* }
* }
* );
* });
* ```
*
* @method module:util/ajax/dwr._$setCookieName
* @param {String} arg0 - cookie名称
* @return {Void}
*/
_p._$setCookieName = function(_name){
_cname = _name||_cname;
};
/**
* 设置请求标识
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/dwr'
* ],function(_j){
* // 手动设置请求标识
* _j._$setBatchId('batchId-12345');
* });
* ```
*
* @method module:util/ajax/dwr._$setBatchId
* @param {String} arg0 - 请求标识
* @return {Void}
*/
_p._$setBatchId = function(_id){
_batchid = _id||'';
};
/**
* 开始批处理请求<br/>
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/dwr'
* ],function(_j){
* _j._$begin();
* _j._$request(
* 'DownloadBean.getDownloadUrlByBrandAndModel1',{
* path:'/dwr/call/plaincall/',
* script:false,
* param:["nokia","n97"],
* onload:function(data){
* // TODO
* },onerror:function(error){
* // TODO
* }
* }
* );
* _j._$request(
* 'DownloadBean.getDownloadUrlByBrandAndModel2',{
* path:'/dwr/call/plaincall/',
* script:false,
* param:["nokia","n98"],
* onload:function(data){
* // TODO
* },onerror:function(error){
* // TODO
* }
* }
* );
* // 最后做一次请求发送
* _j._$end();
* });
* ```
*
* @method module:util/ajax/dwr._$begin
* @see module:util/ajax/dwr._$end
* @return {Void}
*/
_p._$begin = function(){
if (!!_xbatch) return;
_xbatch = {
h:{},p:0,
m:{
callCount:0,
scriptSessionId:'${scriptSessionId}190',
httpSessionId:_j2._$cookie(_cname)
},
r:{
script:!1,
sync:!1,
method:'POST',
timeout:null,
proxy:!0,
cookie:!1,
onbeforerequest:null
}
};
};
/**
* 使用DWR方式载入数据
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/dwr'
* ],function(_j){
* _j._$request(
* 'LogBean.log',{
* path:'/dwr/call/plaincall/',
* script:true,param:{},
* onload:function(data){
* // 正常回调方法
* },
* onerror:function(error){
* // 异常回调
* },
* onbeforerequest:function(data){
* // 请求发送前对请求数据进行处理
* }
* }
* );
* });
* ```
*
* @method module:util/ajax/dwr._$request
* @param {String} arg0 - 请求地址,格式为class.method
* @param {Object} arg1 - 可选配置参数
* @property {String} path - 请求路径,默认为/dwr/call/plaincall/
* @property {String} query - 请求地址附带的查询参数,格式a=aaa&b=bbb
* @property {Array} param - 参数列表,不传或空数组均作为无参数处理
* @property {String} proxy - 代理标识,使用该代理时忽略script/sync/method/timeout属性
* @property {Boolean} script - 使用脚本方式载入
* @property {Boolean} sync - 是否同步请求,使用脚本载入方式忽略此属性
* @property {String} method - 请求方式,GET/POST,使用脚本载入方式忽略此属性
* @property {Number} timeout - 请求超时时间
* @property {Object} headers - 头信息,批处理请求合并所有头信息,同名的头信息后面请求覆盖前面请求
* @property {String} session - CSRF验证的COOKIE名称
*
* @property {module:util/ajax/xdr.onload} onload - 数据载入回调
* @property {module:util/ajax/xdr.onerror} onerror - 请求异常回调
* @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 请求之前回调
*
* @return {Void}
*/
_p._$request = function(_url,_options){
var _info = (_url||'').split('.');
if (!_info||_info.length!=2) return;
var _single = !1;
_options = _options||_o;
if (!_xbatch){
_single = !0;
_p._$begin();
if (!!_options.session){
_xbatch.m.httpSessionId = _j2._$cookie(_options.session);
}
}
_xbatch.u = (_options.path||'/dwr/call/plaincall/')+
(_options.query&&('?'+_options.query)||'');
_u._$fetch(_xbatch.r,_options);
var _headers = _u._$merge(
_xbatch.r.headers,_options.headers
);
_headers[_g._$HEAD_CT] = _g._$HEAD_CT_PLAN;
_xbatch.r.headers = _headers;
var _prefix = 'c'+_xbatch.m.callCount;
_xbatch.m[_prefix+'-scriptName'] = _info[0];
_xbatch.m[_prefix+'-methodName'] = _info[1];
_xbatch.m[_prefix+'-id'] = _xbatch.m.callCount;
_xbatch.h[_xbatch.m.callCount] = {
c:_options.onload||_f,
e:_options.onerror||_f
};
_u._$forEach(
_options.param,function(v,i){
var _value = __doSerialize(v,_prefix);
if (!!_value){
_xbatch.m[_prefix+'-param'+i] = _value;
}
}
);
_xbatch.m.callCount++;
if (_single){
_p._$end();
}
};
/**
* 结束请求批处理,正式发送请求
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/dwr'
* ],function(_j){
* _j._$begin();
* _j._$request(
* 'DownloadBean.getDownloadUrlByBrandAndModel1',{
* path:'/dwr/call/plaincall/',
* script:false,
* param:["nokia","n97"],
* onload:function(data){
* // TODO
* },onerror:function(error){
* // TODO
* }
* }
* );
* _j._$request(
* 'DownloadBean.getDownloadUrlByBrandAndModel2',{
* path:'/dwr/call/plaincall/',
* script:false,
* param:["nokia","n98"],
* onload:function(data){
* // TODO
* },onerror:function(error){
* // TODO
* }
* }
* );
* // 最后做一次请求发送
* _j._$end();
* });
* ```
*
* @method module:util/ajax/dwr._$end
* @see module:util/ajax/dwr._$begin
* @return {Void}
*/
_p._$end = function(){
if (!_xbatch||!_xbatch.u){
_xbatch = null;
return;
}
var _bid = _batchid||_u._$uniqueID();
_batchid = 0;
_xbatch.m.batchId = _bid;
_xcache[_bid] = _xbatch;
_xbatch = null;
__doRequest(_bid);
};
/*
* 销毁请求对象
* @param {String} 请求对象标识
* @return {Void}
*/
var __doDestroyBatch = function(_bid){
var _batch = _xcache[_bid];
if (!_batch) return;
delete _batch.h;
delete _batch.m;
delete _xcache[_bid];
};
/*
* 序列化数据
* @param {Variable} 数据
* @param {String} 前缀
* @return {String} 序列化后的字串
*/
var __doSerialize = function(_data,_prefix){
if (_data==null){
return 'null:null';
}
if (_u._$isBoolean(_data)){
return 'boolean:'+!!_data;
}
if (_u._$isNumber(_data)){
return 'number:'+_data;
}
if (_u._$isString(_data)){
return 'string:'+encodeURIComponent(_data);
}
if (_u._$isDate(_data)){
return 'Date:'+_data.getTime();
}
if (_u._$isArray(_data)){
return __doSerializeArray(_data,_prefix);
}
if (_u._$isObject(_data)){
return __doSerializeObject(_data,_prefix);
}
if (_u._$isFunction(_data,'function')){
return '';
}
return 'default:'+_data;
};
/*
* 序列化数组
* @param {Array} _data 数组
* @param {String} _prefix 前缀
* @return {String} 序列化后的字串
*/
var __doSerializeArray = function(_list,_prefix){
var _arr = [];
_u._$forEach(
_list,function(v,i){
_xbatch.p++;
var _ref = _prefix+'-e'+_xbatch.p,
_value = __doSerialize(v,_prefix);
if (!_value) return;
_xbatch.m[_ref] = _value;
_arr.push('reference:'+_ref);
}
);
return 'Array:['+_arr.join(',')+']';
};
/*
* 序列化对像
* @param {Array} _data 对像
* @param {String} _prefix 前缀
* @return {String} 序列化后的字串
*/
var __doSerializeObject = function(_object,_prefix){
var _arr = [];
_u._$forIn(
_object,function(v,k){
_xbatch.p++;
var _ref = _prefix+'-e'+_xbatch.p,
_value = __doSerialize(v,_prefix);
if (!_value) return;
_xbatch.m[_ref] = _value;
_arr.push(encodeURIComponent(k)+':reference:'+_ref);
}
);
return 'Object_Object:{'+_arr.join(',')+'}';
};
/*
* 序列化要发送的数据
* @param {Object} _data 数据对象
* @param {String} _sep 数据分隔符
* @return {String} 数据字符串
*/
var __doSerializeSendData = function(_data,_sep){
if (!_data) return null;
var _arr = [],
_and = _sep=='&';
_u._$forIn(
_data,function(v,k){
_arr.push(
!_and ? (k+'='+v) :
(encodeURIComponent(k)+'='+encodeURIComponent(v))
);
}
);
return _arr.join(_sep||'\n');
};
/*
* 发送请求
* @param {String} _bid 请求标识
* @return {Void}
*/
var __doRequest = function(_bid){
var _batch = _xcache[_bid];
if (!_batch) return;
_batch.u = _batch.u.replace(/(\?|$)/,(
_batch.m.callCount>1
?'Multiple.'+_batch.m.callCount
:_batch.m['c0-scriptName']+'.'+
_batch.m['c0-methodName'])+'.dwr$1');
var _option = _batch.r,
_script = !!_option.script,
_ispost = _option.method=='POST';
delete _batch.r;
delete _option.script;
_option.method = _option.method.toUpperCase();
_option.onerror = __onErrorWithReq._$bind(null,_bid);
if (_script||!_ispost){
_batch.u += (_batch.u.indexOf('?')>=0?'&':'?')
+__doSerializeSendData(_batch.m,'&');
}
if (_script){
_j1._$loadScript(_batch.u,_option);
}else{
_option.onload = __onLoadWithXDR._$bind(null,_bid);
_option.data = _ispost?__doSerializeSendData(_batch.m):null;
_j0._$request(_batch.u,_option);
}
};
/*
* 单个接口出错处理
* @param {String} _bid 请求标识
* @param {String} _cid 接口标识
* @param {Object} _error 错误信息
* @return {Void}
*/
var __onError = function(_bid,_cid,_error){
var _batch = _xcache[_bid];
if (!_batch||_doFilter(_error)) return;
var _handler = _batch.h[_cid];
if (!_handler) return;
try{
(_handler.e||f)(_error);
}catch(ex){
// ignore
if (DEBUG) throw ex;
console.error(ex.message);
console.error(ex);
}
};
/*
* 整个请求出错处理
* @param {String} _bid 请求标识
* @param {Object} _error 错误信息
* @return {Void}
*/
var __onErrorAll = function(_bid,_error){
var _batch = _xcache[_bid];
if (!_batch) return;
_u._$forIn(
_batch.h,function(v,k){
__onError(_bid,k,_error);
}
);
};
/*
* 数据加载成功回调函数
* @param {String} _bid 请求ID
* @param {String} _cid 回调ID
* @param {Variable} _data 数据内容
* @return {Void}
*/
var __onLoadFromDWR = function(_bid,_cid,_data){
var _batch = _xcache[_bid];
if (!_batch) return;
try{
(_batch.h[_cid].c||f)(_data);
}catch(ex){
__onError(
_bid,_cid,{
code:_g._$CODE_ERRCABK,
message:'DWR回调执行异常:'+ex.message||ex
}
);
}
};
/*
* 数据载入回调
* @param {String} _bid 请求标识
* @param {String} _text 返回数据内容
* @return {Void}
*/
var __onLoadWithXDR = function(_bid,_text){
try{
!!_text&&_text.search('//#DWR')>=0
? (new Function(_text))()
: __onErrorAll(_bid,{
code:_g._$CODE_ERRSERV,
message:'DWR请求返回数据不合法!'
});
}catch(ex){
__onErrorAll(_bid,{
code:_g._$CODE_ERREVAL,
message:'DWR返回脚本执行异常:'+(ex.message||ex)
});
}finally{
__doDestroyBatch(_bid);
}
};
/*
* 数据载入异常
* @param {String} _bid 请求标识
* @param {Object} _error 错误信息
* @return {Void}
*/
var __onErrorWithReq = function(_bid,_error){
__onErrorAll(_bid,_error);
__doDestroyBatch(_bid);
};
// DWR2 Adapter
this.dwr = this.dwr||{};
var w = dwr.engine = dwr.engine||{};
w['_remoteHandleCallback'] = __onLoadFromDWR;
w['_remoteHandleException'] = __onError;
w['_remoteHandleBatchException'] = __onErrorAll;
// DWR3 Adapter
dwr['_'] = [{
handleCallback:w['_remoteHandleCallback'],
handleException:w['_remoteHandleException'],
handleBatchException:w['_remoteHandleBatchException']
}];
if (CMPT){
var _j = NEJ.P('nej.j');
_j._$endBatch = _p._$end;
_j._$requestByDWR = _p._$request;
_j._$beginBatch = _p._$begin;
_j._$setFilter = _p._$setFilter;
_j._$setBatchId = _p._$setBatchId;
_j._$setCookieName = _p._$setCookieName;
}
return _p;
});
/*
* ------------------------------------------
* HTML资源加载器实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/loader/html */
NEJ.define([
'./loader.js',
'base/klass',
'base/element',
'{platform}html.js'
],function(_t,_k,_e,_h,_p,_o,_f,_r){
var _pro;
/**
* HTML资源加载器
*
* @class module:util/ajax/loader/html._$$LoaderHtml
* @extends module:util/ajax/loader/loader._$$LoaderAbstract
*
* @param {Object} config - 可选配置参数
*/
_p._$$LoaderHtml = _k._$klass();
_pro = _p._$$LoaderHtml._$extend(_t._$$LoaderAbstract);
/**
* 取资源载入控件
*
* @protected
* @method module:util/ajax/loader/html._$$LoaderHtml#__getRequest
* @return {Node} IFrame节点
*/
_pro.__getRequest = function(){
var _iframe = _e._$create('iframe');
_iframe.width = 0;
_iframe.height = 0;
_iframe.style.display = 'none';
return _iframe;
};
/**
* 资源载入
*
* @protected
* @method module:util/ajax/loader/html._$$LoaderHtml#__doRequest
* @param {Node} arg0 - 控件节点
* @return {Void}
*/
_pro.__doRequest = function(_request){
try{
// append first for history bug
document.body.appendChild(_request);
_request.src = this.__url;
}catch(ex){
console.log(_request);
console.error(ex);
}
};
/**
* 资源载入异常事件
*
* @protected
* @method module:util/ajax/loader/html._$$LoaderHtml#__onError
* @param {Object} arg0 - 错误信息
* @return {Void}
*/
_pro.__onError = function(_error){
var _iframe = (
this.__getLoadData(this.__url)||_o
).request;
this.__doCallback('onerror',_error);
_h.__removeIFrameKeepHistory(_iframe);
};
/**
* 资源载入成功事件
*
* @protected
* @method module:util/ajax/loader/html._$$LoaderHtml#__onLoaded
* @return {Void}
*/
_pro.__onLoaded = function(){
var _body = null,
_iframe = (this.__getLoadData(this.__url)||_o).request;
try{
if (_iframe.src!=this.__url) return;
_body = _iframe.contentWindow.document.body;
}catch(ex){
// ignore
}
this.__doCallback('onload',_body);
_h.__removeIFrameKeepHistory(_iframe);
};
return _p;
});
/*
* ------------------------------------------
* 资源加载器实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/loader/loader */
NEJ.define([
'base/global',
'base/klass',
'base/constant',
'base/event',
'base/util',
'util/event'
],function(NEJ,_k,_g,_v,_u,_t,_p,_o,_f,_r){
var _pro,
_timeout = 60000;
/**
* 资源加载器
*
* @class module:util/ajax/loader/loader._$$LoaderAbstract
* @extends module:util/event._$$EventTarget
*
* @param {Object} config - 可选配置参数
* @property {String} version - 版本信息
* @property {Number} timeout - 超时时间,0表示禁止超时监测
*/
/**
* 资源载入失败回调
*
* @event module:util/ajax/loader/loader._$$LoaderAbstract#onerror
* @param {Object} event - 错误信息
* @property {Number} code - 错误码
* @property {String} message - 错误信息
*/
/**
* 资源载入成功回调
*
* @event module:util/ajax/loader/loader._$$LoaderAbstract#onload
* @param {Variable} event - 请求返回数据
*/
/**
* 资源加载中回调
*
* @event module:util/ajax/loader/loader._$$LoaderAbstract#onloading
*/
_p._$$LoaderAbstract = _k._$klass();
_pro = _p._$$LoaderAbstract._$extend(_t._$$EventTarget);
/**
* 控件初始化
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__init
* @return {Void}
*/
_pro.__init = function(){
this.__super();
this.__qopt = {
onerror:this.__onQueueError._$bind(this),
onload:this.__onQueueLoaded._$bind(this)
};
if (!this.constructor.__cache){
// url : {request:script,timer:2,bind:[instance1,instance2 ... ]}
// key : {error:0,loaded:0,total:0,bind:[instance1,instance2 ... ]}
this.constructor.__cache = {loaded:{}};
}
};
/**
* 控件重置
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__version = _options.version;
this.__timeout = _options.timeout;
this.__qopt.version = this.__version;
this.__qopt.timeout = this.__timeout;
};
/**
* 删除加载信息
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__delLoadData
* @param {String} arg0 - 标识
* @return {Object} 加载信息
*/
_pro.__delLoadData = function(_key){
delete this.constructor.__cache[_key];
};
/**
* 取加载信息
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__getLoadData
* @param {String} arg0 - 标识
* @return {Object} 加载信息
*/
_pro.__getLoadData = function(_key){
return this.constructor.__cache[_key];
};
/**
* 设置加载信息
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__setLoadData
* @param {String} arg0 - 标识
* @param {Object} arg1 - 加载信息
* @return {Void}
*/
_pro.__setLoadData = function(_key,_data){
this.constructor.__cache[_key] = _data;
};
/**
* 取资源载入控件,子类实现具体逻辑
*
* @abstract
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__getRequest
* @return {Script|Link} 控件
*/
_pro.__getRequest = _f;
/**
* 清理控件
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__doClearRequest
* @param {Script|Link} arg0 - 控件
* @return {Void}
*/
_pro.__doClearRequest = function(_request){
_v._$clearEvent(_request);
};
/**
* 资源载入
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__doRequest
* @param {Script|Link} arg0 - 控件
* @return {Void}
*/
_pro.__doRequest = function(_request){
_request.src = this.__url;
document.head.appendChild(_request);
};
/**
* 执行清理任务
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__doClear
* @return {Void}
*/
_pro.__doClear = function(){
var _cache = this.__getLoadData(this.__url);
if (!_cache) return;
window.clearTimeout(_cache.timer);
this.__doClearRequest(_cache.request);
delete _cache.bind;
delete _cache.timer;
delete _cache.request;
this.__delLoadData(this.__url);
this.__getLoadData('loaded')[this.__url] = !0;
};
/**
* 执行回调
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__doCallback
* @param {String} arg0 - 回调名称
* @return {Void}
*/
_pro.__doCallback = function(_name){
var _cache = this.__getLoadData(this.__url);
if (!_cache) return;
var _list = _cache.bind;
this.__doClear();
if (!!_list&&_list.length>0){
var _instance;
while(_list.length){
_instance = _list.shift();
try{
_instance._$dispatchEvent(_name,arguments[1]);
}catch(ex){
// ignore
if (DEBUG) throw ex;
console.error(ex.message);
console.error(ex.stack);
}
_instance._$recycle();
}
}
};
/**
* 资源载入异常事件
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__onError
* @param {Object} arg0 - 错误信息
* @return {Void}
*/
_pro.__onError = function(_error){
this.__doCallback('onerror',_error);
};
/**
* 资源载入成功事件
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__onLoaded
* @return {Void}
*/
_pro.__onLoaded = function(){
this.__doCallback('onload');
};
/**
* 载入队列资源
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__doLoadQueue
* @param {String} arg0 - 资源地址
* @return {Void}
*/
_pro.__doLoadQueue = function(_url){
this.constructor._$allocate(this.__qopt)._$load(_url);
};
/**
* 检查队列状况
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__onQueueCheck
* @return {Void}
*/
_pro.__onQueueCheck = function(_error){
var _cache = this.__getLoadData(this.__key);
if (!_cache) return;
if (!!_error)
_cache.error++;
_cache.loaded ++;
if (_cache.loaded<_cache.total) return;
this.__delLoadData(this.__key);
this._$dispatchEvent(_cache.error>0?'onerror':'onload');
};
/**
* 队列载入资源异常事件
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__onQueueError
* @param {Object} arg0 - 错误信息
* @return {Void}
*/
_pro.__onQueueError = function(_error){
this.__onQueueCheck(!0);
};
/**
* 队列载入资源成功事件
*
* @protected
* @method module:util/ajax/loader/loader._$$LoaderAbstract#__onQueueLoaded
* @return {Void}
*/
_pro.__onQueueLoaded = function(){
this.__onQueueCheck();
};
/**
* 载入资源
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/loader/html',
* 'util/ajax/loader/style',
* 'util/ajax/loader/script'
* ],function(_t0,_t1,_t2){
* // 载入指定html,10秒超时
* var _loader = _t0._$$LoaderHtml._$allocate({
* timeout:10000,
* onload:function(){
* // 载入资源成功的回调
* }
* });
* // 绝对路径或者当前页面的相对路径
* _loader._$load('../../../html/util/formTest.html');
*
* // 载入指定script,20秒超时
* var _loader = _t2._$$LoaderScript._$allocate({
* timeout:20000,
* onload:function(){
* // 载入资源成功的回调
* }
* });
* // 绝对路径或者当前页面的相对路径
* _loader._$load('../../../javascript/log.js');
*
* // 载入指定style,30秒超时
* var _loader = _t1._$$LoaderStyle._$allocate({
* timeout:30000,
* onload:function(){
* // 载入资源成功的回调
* }
* });
* // 绝对路径或者当前页面的相对路径
* _loader._$load('../../../base/qunit.css');
* });
* ```
*
* @method module:util/ajax/loader/loader._$$LoaderAbstract#_$load
* @param {String} arg0 - 资源地址
* @return {Void}
*/
_pro._$load = function(_url){
_url = _u._$absolute(_url);
if (!_url){
this._$dispatchEvent('onerror',{
code:_g._$CODE_NOTASGN,
message:'请指定要载入的资源地址!'
});
return;
};
this.__url = _url;
if (!!this.__version){
this.__url += (this.__url.indexOf('?')<0?'?':'&')+this.__version;
}
if (this.__getLoadData('loaded')[this.__url]){
try{
this._$dispatchEvent('onload');
}catch(ex){
// ignore
if (DEBUG) throw ex;
console.error(ex.message);
console.error(ex.stack);
}
this._$recycle();
return;
}
var _cache = this.__getLoadData(this.__url),_request;
if (!!_cache){
_cache.bind.unshift(this);
_cache.timer = window.clearTimeout(_cache.timer);
}else{
_request = this.__getRequest();
_cache = {request:_request,bind:[this]};
this.__setLoadData(this.__url,_cache);
_v._$addEvent(
_request,'load',
this.__onLoaded._$bind(this)
);
_v._$addEvent(
_request,'error',
this.__onError._$bind(this,{
code:_g._$CODE_ERRSERV,
message:'无法加载指定资源文件['+this.__url+']!'
})
);
}
if (this.__timeout!=0){
_cache.timer = window.setTimeout(
this.__onError._$bind(this,{
code:_g._$CODE_TIMEOUT,
message:'指定资源文件['+this.__url+']载入超时!'
}),
this.__timeout||_timeout
);
}
if (!!_request){
this.__doRequest(_request);
}
this._$dispatchEvent('onloading');
};
/**
* 队列载入资源
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/loader/html.js'
* ],function(_t){
* var _loader = _t._$$LoaderHtml._$allocate({
* onload:function(){
* // 载入队列资源成功的回调
* }
* });
* // 路径列表,可以是绝对路径也可以是当前页面的相对路径
* var _list = [
* '../../../html/util/formTest.html',
* '../../../html/util/cacheTest.html'
* ];
* _loader._$queue(_list);
* });
* ```
*
* @method module:util/ajax/loader/loader._$$LoaderAbstract#_$queue
* @param {Array} arg0 - 资源地址队列
* @return {Void}
*/
_pro._$queue = function(_list){
if (!_list||!_list.length){
this._$dispatchEvent('onerror',{
code:_g._$CODE_NOTASGN,
message:'请指定要载入的资源队列!'
});
return;
}
this.__key = _u._$uniqueID();
var _cache = {error:0,loaded:0,total:_list.length};
this.__setLoadData(this.__key,_cache);
_u._$forEach(
_list,function(v,i){
if (!v){
_cache.total--;
return;
}
this.__doLoadQueue(v);
},this
);
this._$dispatchEvent('onloading');
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'base/element'
],function(_e,_p,_o,_f,_r){
/**
* 删除IFrame节点,保留历史
* @param {Node} iframe节点
* @return {Void}
*/
_p.__removeIFrameKeepHistory = function(_iframe){
_e._$remove(_iframe);
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./html.js',
'base/element',
'base/platform'
],function(_h,_e,_m,_p,_o,_f,_r){
// for ie6-
NEJ.patch('TR<=2.0',function(){
/**
* 删除IFrame节点,保留历史
* @param {Node} iframe节点
* @return {Void}
*/
_h.__removeIFrameKeepHistory = function(_iframe){
_e._$setStyle(_iframe,'display','none');
try{_iframe.contentWindow.document.body.innerHTML = '&nbsp;';}catch(ex){}
};
});
return _h;
});
/*
* ------------------------------------------
* 脚本加载器实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/loader/script */
NEJ.define([
'./loader.js',
'base/klass',
'base/element'
],function(_t,_k,_e,_p,_o,_f,_r){
var _pro;
/**
* 脚本加载器
*
* @class module:util/ajax/loader/script._$$LoaderScript
* @extends module:util/ajax/loader/loader._$$LoaderAbstract
*
* @param {Object} config - 可选配置参数
* @property {Boolean} async - 异步载入并立刻执行,默认为!0
* @property {String} charset - 脚本编码
*/
_p._$$LoaderScript = _k._$klass();
_pro = _p._$$LoaderScript._$extend(_t._$$LoaderAbstract);
/**
* 控件重置
*
* @protected
* @method module:util/ajax/loader/script._$$LoaderScript#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__async = _options.async;
this.__charset = _options.charset;
this.__qopt.async = !1;
this.__qopt.charset = this.__charset;
};
/**
* 取资源载入控件
*
* @protected
* @method module:util/ajax/loader/script._$$LoaderScript#__getRequest
* @return {Script} 控件
*/
_pro.__getRequest = function(){
var _request = _e._$create('script');
if (this.__async!=null){
_request.async = !!this.__async;
}
if (this.__charset!=null){
_request.charset = this.__charset;
}
return _request;
};
/**
* 删除控件
*
* @protected
* @method module:util/ajax/loader/script._$$LoaderScript#__doClearRequest
* @param {Node} arg0 - 控件节点
* @return {Void}
*/
_pro.__doClearRequest = function(_request){
_e._$remove(_request);
};
return _p;
});
/*
* ------------------------------------------
* 样式加载器实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/loader/style */
NEJ.define([
'./loader.js',
'base/klass',
'base/element'
],function(_t,_k,_e,_p,_o,_f,_r){
var _pro;
/**
* 样式加载器
*
* @class module:util/ajax/loader/style._$$LoaderStyle
* @extends module:util/ajax/loader/loader._$$LoaderAbstract
*
* @param {Object} config - 可选配置参数
*/
_p._$$LoaderStyle = _k._$klass();
_pro = _p._$$LoaderStyle._$extend(_t._$$LoaderAbstract);
/**
* 取资源载入控件
*
* @protected
* @method module:util/ajax/loader/style._$$LoaderStyle#__getRequest
* @return {Node} 控件节点
*/
_pro.__getRequest = function(){
return _e._$create('link');
};
/**
* 资源载入
*
* @protected
* @method module:util/ajax/loader/style._$$LoaderStyle#__doRequest
* @param {Node} 控件节点
* @return {Void}
*/
_pro.__doRequest = function(_request){
_request.href = this.__url;
document.head.appendChild(_request);
};
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>load测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit load test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../../../define.js?pro=./"></script>
<script type="text/javascript" src="./loader.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("Load");
var _ = NEJ.P,
_p = _('nej.ut.j'),
_j = _('nej.j');
test('load HTML资源',function(){
stop();
var _htmlLoad = _p._$$LoaderHtml._$allocate({timeout:30000,
onloaded:function(){
ok(true,'载入HTML资源成功');
start();
}});
_htmlLoad._$load('../../../html/util/formTest.html');
});
test('load HTML资源,通过api',function(){
stop();
_j._$loadHtml('../../../html/util/formTest.html',{
onloaded:function(){
ok(true,'载入HTML资源成功');
start();
}});
});
test('load script资源',function(){
stop();
var _scriptLoad = _p._$$LoaderScript._$allocate({
onloaded:function(){
ok(true,'载入script资源成功');
start();
}});
_scriptLoad._$load('../../../javascript/log.js');
});
test('load script资源,通过api',function(){
stop();
_j._$loadScript('../../../javascript/log.js',{
onloaded:function(){
ok(true,'载入script资源成功');
start();
}});
});
test('load style资源',function(){
stop();
var _styleLoad = _p._$$LoaderStyle._$allocate({
onloaded:function(){
ok(true,'载入style资源成功');
start();
}});
_styleLoad._$load('../../../base/qunit.css');
});
test('load style资源,通过api',function(){
stop();
_j._$loadStyle('../../../base/qunit.css',{
onloaded:function(){
ok(true,'载入style资源成功');
start();
}});
});
test('载入队列资源',function(){
stop();
var _list = ['../../../html/util/formTest.html','../../../html/util/cacheTest.html']
var _styleLoad = _p._$$LoaderHtml._$allocate({
onloaded:function(){
ok(true,'载入html资源队列成功');
start();
}});
_styleLoad._$queue(_list);
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}loader.test.js',
['{lib}util/ajax/tag.js',
'{lib}util/ajax/loader/html.js',
'{lib}util/ajax/loader/script.js',
'{lib}util/ajax/loader/style.js'],f);
});
/*
* ------------------------------------------
* 文本资源加载器实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/loader/text */
NEJ.define([
'./loader.js',
'base/klass',
'base/element',
'util/ajax/xdr'
],function(_t,_k,_e,_j,_p,_o,_f,_r){
var _pro;
/**
* 文本资源加载器
*
* @class module:util/ajax/loader/text._$$LoaderText
* @extends module:util/ajax/loader/loader._$$LoaderAbstract
*
* @param {Object} config - 可选配置参数
*/
_p._$$LoaderText = _k._$klass();
_pro = _p._$$LoaderText._$extend(_t._$$LoaderAbstract);
/**
* 取资源载入控件
*
* @protected
* @method module:util/ajax/loader/style._$$LoaderText#__getRequest
* @return {Node} 控件节点
*/
_pro.__getRequest = function(){
return null;
};
/**
* 资源载入
*
* @protected
* @method module:util/ajax/loader/style._$$LoaderText#__doRequest
* @param {Node} 控件节点
* @return {Void}
*/
_pro.__doRequest = function(){
_j._$request(this.__url,{
method:'GET',
type:'text',
onload:this.__onLoaded._$bind(this),
onerror:this.__onError._$bind(this)
});
};
/**
* 资源载入成功事件
*
* @protected
* @method module:util/ajax/loader/style._$$LoaderText#__onLoaded
* @return {Void}
*/
_pro.__onLoaded = function(_text){
this.__doCallback('onload',{
url:this.__url,
content:_text
});
};
return _p;
});
/*
* ------------------------------------------
* 跨文档消息交互API实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/message */
NEJ.define([
'base/global',
'base/util',
'base/element',
'{platform}message.js'
],function(NEJ,_u,_e,_h,_p,_o,_f,_r){
/**
* 发送跨文档的消息
*
* 结构举例
* ```html
* <!-- 注意需要通过source进行双向交互的frame节点必须设置id属性作为标识 -->
* <iframe id="targetFrame" src="http://a.b.com/a.html"></iframe>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event'
* 'util/ajax/message'
* ],function(_v,_j){
* // top页面代码
* // 发送消息至 http://c.d.com 的页面
* _j._$postMessage('targetFrame',{
* data:'hello c.d.com',
* origin:'http://c.d.com'
* });
*
* // http://a.b.com/a.html页面代码
* // 添加消息监测事件
* _v._$addEvent(
* window,'message',function(_event){
* // 因为top页面发送消息到 http://c.d.com
* // 所以在http://a.b.com页面不会收到任何消息
* }
* );
*
* // top页面代码
* // 发送消息至 http://a.b.com 的页面
* _j._$postMessage('targetFrame',{
* data:'hello a.b.com'
* });
*
* // http://a.b.com/a.html页面代码
* // 添加消息监测事件
* _v._$addEvent(
* window,'message',function(_event){
* // 必须先验证消息来源_event.origin是否你允许的域
* if (!_isAllow(_event.origin))
* return;
*
* // 处理_event.data中的消息内容
* // TODO something
*
* // 回复消息,使用_event.source
* _j._$postMessage(_event.source,{
* data:'hello!',
* origin:_event.origin
* });
* }
* );
* });
* ```
*
* @method module:util/ajax/message._$postMessage
* @param {String|Window} arg0 - window对象或者Frame的name,或者字符串如_top、_parent、_self
* @param {Object} arg1 - 消息配置
* @property {Variable} data - 消息内容
* @property {String} origin - 目标Origin,只有指定的页面可以收到消息,如http://a.b.com
* @property {String} source - 当前窗体标识,除非你非常确定当前窗体的标识是什么,否则请采用自动识别
* @return {Void}
*/
_p._$postMessage = (function(){
var _self = window.name||'_parent',
_wmap = {
'_top' : window.top,
'_self' : window,
'_parent': window.parent
};
return function(_target,_options){
if (_u._$isString(_target)){
_target = _wmap[_target]||
window.frames[_target]||
(_e._$get(_target)||_o).contentWindow;
if (!_target) return;
}
// check data
var _data = _u._$fetch({
origin:'*',
source:_self
},_options);
// send message
_h.__postMessage(_target,_data);
};
})();
if (CMPT){
NEJ.copy(NEJ.P('nej.j'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 跨文档消息交互API实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define(function(_p,_o,_f,_r){
/**
* 格式化源信息
* @param {String} 源
* @return {String} 格式化后源
*/
_p.__formatOrigin = (function(){
var _reg = /^([\w]+?:\/\/.*?(?=\/|$))/i;
return function(_origin){
_origin = _origin||'';
if (_reg.test(_origin)){
return RegExp.$1;
}
return '*';
};
})();
/**
* 解析消息传递数据
* @param {Variable} 数据
* @return {Variable} 数据
*/
_p.__formatPassData = function(_data){
return _data;
};
/**
* 跨文档发送数据
* @param {Window} 窗体对象
* @param {Object} 发送配置
* @return {Void}
*/
_p.__postMessage = function(_window,_options){
if (!_window.postMessage){
return;
}
_options = _options||_o;
_window.postMessage(
_p.__formatPassData(_options.data),
_p.__formatOrigin(_options.origin)
);
};
return _p;
});
/*
* ------------------------------------------
* 跨文档消息交互API实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./message.js',
'base/util',
'base/event'
],function(_h,_u,_v,_p,_o,_f,_r){
// for ie8-9
NEJ.patch('4.0<=TR<=5.0',function(){
/**
* 解析消息传递数据
* @param {Variable} 数据
* @return {Variable} 数据
*/
_h.__formatPassData = function(_data){
// ie8-9 only support string data
return JSON.stringify(_data);
};
});
// for ie7-
NEJ.patch('TR<=3.0',[
'util/event/event',
'util/encode/json'
],function(_t){
var _key = 'MSG|',
_queue = [];
/*
* 检测window.name变化情况
* @return {Void}
*/
var _doCheckWindowName = function(){
// check name
var _name = unescape(window.name||'').trim();
if (!_name||_name.indexOf(_key)!=0) return;
window.name = '';
// check result
var _result = _u._$string2object(_name.replace(_key,''),'|'),
_origin = (_result.origin||'').toLowerCase();
// check origin
if (!!_origin&&_origin!='*'&&
location.href.toLowerCase().indexOf(_origin)!=0){
return;
}
// dispatch onmessage event
_v._$dispatchEvent(window,'message',{
data:JSON.parse(_result.data||'null'),
source:window.frames[_result.self]||_result.self,
origin:_h.__formatOrigin(_result.ref||document.referrer)
});
};
/*
* 检测window.name设置队列
* @return {Void}
*/
var _doCheckNameQueue = (function(){
var _checklist;
// set window.name
var _doSetWindowName = function(_map,_index,_list){
if (_u._$indexOf(_checklist,_map.w)<0){
_checklist.push(_map.w);
_list.splice(_index,1);
_map.w.name = _map.d;
}
};
return function(){
_checklist = [];
_u._$reverseEach(_queue,_doSetWindowName);
_checklist = null;
};
})();
/**
* 跨文档发送数据
* @param {Window} 窗体对象
* @param {Object} 发送配置
* @return {Void}
*/
_h.__postMessage = (function(){
// serialize send data
var _doSerialize = function(_data){
var _result = {};
_data = _data||_o;
_result.origin = _data.origin||'';
_result.ref = location.href;
_result.self = _data.source;
_result.data = JSON.stringify(_data.data);
return _key+_u._$object2string(_result,'|',!0);
};
// function body
return function(_window,_options){
_queue.unshift({
w:_window,
d:escape(_doSerialize(_options))
});
};
})();
// init window onmessage event
_t._$$CustomEvent._$allocate({
element:window,
event:'message'
});
setInterval(_doCheckNameQueue,100);
setInterval(_doCheckWindowName,20);
});
return _h;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'../proxy/xhr.js',
'../proxy/flash.js',
'../proxy/frame.js',
'../proxy/upload.js'
],function(_t0,_t1,_t2,_t3,_p,_o,_f,_r){
/**
* 根据模式返回代理实例,模式说明
* 0 - 自动模式,高版本使用HTML5的CORS协议,低版本采用Frame代理方式
* 1 - 高版本使用HTML5的CORS协议,普通请求低版本采用Flash代理方式
* 2 - 全部使用Frame代理方式
* 3 - 全部使用Flash代理方式
* @param {Number} 模式
* @param {Boolean} 是否文件上传
* @param {Object} 构造配置参数
* @return {_$$ProxyAbstract} 代理实例
*/
_p.__getProxyByMode = function(_mode,_upload,_options){
var _map = !!_upload
? {2:_t3._$$ProxyUpload}
: {2:_t2._$$ProxyFrame,3:_t1._$$ProxyFlash};
return (_map[_mode]||_t0._$$ProxyXHR)._$allocate(_options);
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./xdr.js'
],function(_h,_p,_o,_f,_r){
// for ie9-
NEJ.patch('TR<=5.0',function(){
/**
* 根据模式返回代理实例,模式说明
* 0 - 自动模式,高版本使用HTML5的CORS协议,低版本采用Frame代理方式
* 1 - 高版本使用HTML5的CORS协议,普通请求低版本采用Flash代理方式
* 2 - 全部使用Frame代理方式
* 3 - 全部使用Flash代理方式
* @param {Number} 模式
* @param {Boolean} 是否文件上传
* @param {Object} 构造配置参数
* @return {_$$ProxyAbstract} 代理实例
*/
_h.__getProxyByMode = (function(){
var _pmap = {0:2,1:3};
return _h.__getProxyByMode._$aop(function(_event){
var _args = _event.args,
_mode = _args[0]||0;
_args[0] = !!_args[1] ? 2 :
_pmap[_mode]||_mode;
});
})();
});
return _h;
});
/*
* ------------------------------------------
* Ajax FLASH方式代理实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/proxy/flash */
NEJ.define([
'./proxy.js',
'base/klass',
'base/config',
'base/util',
'util/flash/flash'
],function(_t,_k,_c,_u,_e,_p,_o,_f,_r){
var _pro,
_cache = {},
_seed = _u._$uniqueID();
/*
* 代理请求正常回调
* @param {String} 请求标识
* @param {String} 返回数据
* @return {Void}
*/
this['ld'+_seed] = function(_key,_text){
var _proxy = _cache[_key];
if (!_proxy) return;
delete _cache[_key];
_proxy.__onLoadRequest({
status:200,
result:_text
});
};
/*
* 代理请求异常回调
* @param {String} 请求标识
* @param {Number} 请求状态
* @return {Void}
*/
this['er'+_seed] = function(_key,_status){
var _proxy = _cache[_key];
if (!_proxy) return;
delete _cache[_key];
_proxy.__onLoadRequest({
status:_status||0
});
};
/**
* Flash代理方式Ajax请求对象
*
* @class module:util/ajax/proxy/flash._$$ProxyFlash
* @extends module:util/ajax/proxy/proxy._$$ProxyAbstract
*
* @param {Object} config - 构造配置参数
*/
_p._$$ProxyFlash = _k._$klass();
_pro = _p._$$ProxyFlash._$extend(_t._$$ProxyAbstract);
/**
* 往服务器发送请求
*
* @protected
* @method module:util/ajax/proxy/flash._$$ProxyFlash#__doSendRequest
* @param {Object} arg0 - 请求信息
* @return {Void}
*/
_pro.__doSendRequest = function(_options){
var _flash = _cache.flash;
// callback list
if (_u._$isArray(_flash)){
_flash.push(
this.__doSendRequest.
_$bind(this,_options)
);
return;
}
// build flash proxy
if (!_flash){
_cache.flash = [
this.__doSendRequest.
_$bind(this,_options)
];
_e._$flash({
hidden:!0,
src:_c._$get('ajax.swf'),
onready:function(_flash){
if (!_flash) return;
var _list = _cache.flash;
_cache.flash = _flash;
_u._$reverseEach(
_list,function(_handler,_index,_list){
try{
_handler();
}catch(ex){
// ignore
}
}
);
}
});
return;
}
// send request by flash
this.__rkey = _u._$uniqueID();
_cache[this.__rkey] = this;
var _data = _u._$fetch({
url:'',
data:null,
method:'GET'
},_options.request);
_data.key = this.__rkey;
_data.headers = _options.headers;
_data.onerror = 'cb.er'+_seed;
_data.onloaded = 'cb.ld'+_seed;
var _policy = _c._$getFlashProxy(_data.url);
if (!!_policy){
_data.policyURL = _policy;
}
_flash.request(_data);
};
/**
* 中断请求
*
* @method module:util/ajax/proxy/flash._$$ProxyFlash#_$abort
* @return {Void}
*/
_pro._$abort = function(){
delete _cache[this.__rkey];
this.__onLoadRequest({status:0});
};
return _p;
});
/*
* ------------------------------------------
* Ajax FRAME方式代理实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/proxy/frame */
NEJ.define([
'./proxy.js',
'base/util',
'base/klass',
'base/event',
'base/config',
'base/element',
'util/ajax/message'
],function(_t,_u,_k,_v,_c,_e,_j,_p,_o,_f,_r){
var _pro,
_cache = {};
/**
* Frame代理方式Ajax请求对象
*
* @class module:util/ajax/proxy/frame._$$ProxyFrame
* @extends module:util/ajax/proxy/proxy._$$ProxyAbstract
*
* @param {Object} config - 构造配置参数
*/
_p._$$ProxyFrame = _k._$klass();
_pro = _p._$$ProxyFrame._$extend(_t._$$ProxyAbstract);
/**
* 控件初始化
*
* @protected
* @method module:util/ajax/proxy/frame._$$ProxyFrame#__init
* @return {Void}
*/
_pro.__init = (function(){
var _flag = 'NEJ-AJAX-DATA:',
_init = !1;
// receive message
var _doReceiveMessage = function(_event){
var _data = _event.data;
if (_data.indexOf(_flag)!=0) return;
_data = JSON.parse(_data.replace(_flag,''));
var _proxy = _cache[_data.key];
if (!_proxy) return;
delete _cache[_data.key];
_data.result = decodeURIComponent(_data.result||'');
_proxy.__onLoadRequest(_data);
};
// init message listener
var _doInitMessage = function(){
if (!_init){
_init = !0;
_v._$addEvent(
window,'message',
_doReceiveMessage
);
}
};
return function(){
this.__super();
_doInitMessage();
};
})();
/**
* 往服务器发送请求
*
* @protected
* @method module:util/ajax/proxy/frame._$$ProxyFrame#__doSendRequest
* @param {Object} arg0 - 请求信息
* @return {Void}
*/
_pro.__doSendRequest = function(_options){
var _request = _options.request,
_proxy = _c._$getFrameProxy(_request.url),
_frame = _cache[_proxy];
// callback list
if (_u._$isArray(_frame)){
_frame.push(
this.__doSendRequest.
_$bind(this,_options)
);
return;
}
// build frame proxy
if (!_frame){
_cache[_proxy] = [
this.__doSendRequest.
_$bind(this,_options)
];
_e._$createXFrame({
src:_proxy,visible:!1,
onload:function(_event){
var _list = _cache[_proxy];
_cache[_proxy] = _v.
_$getElement(_event).contentWindow;
_u._$reverseEach(
_list,function(_handler){
try{
_handler();
}catch(ex){
// ignore
}
}
);
}
});
return;
}
// send message to frame
this.__rkey = _u._$uniqueID();
_cache[this.__rkey] = this;
var _data = _u._$fetch({
url:'',data:null,
timeout:0,method:'GET'
},_request);
_data.key = this.__rkey;
_data.headers = _options.headers;
_j._$postMessage(_cache[_proxy],{data:_data});
};
/**
* 中断请求
*
* @method module:util/ajax/proxy/frame._$$ProxyFrame#_$abort
* @return {Void}
*/
_pro._$abort = function(){
delete _cache[this.__rkey];
this.__onLoadRequest({status:0});
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define(function(_p,_o,_f,_r){
/**
* 取XHR对象
* @return {XMLHttpRequest} XHR对象
*/
_p.__getXMLHttpRequest = function(){
return new XMLHttpRequest();
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
NEJ.define([
'./xhr.js',
'base/util'
],function(_h,_u,_p,_o,_f,_r){
// for ie6-
NEJ.patch('TR<=2.0',function(){
/**
* 取XHR对象
* @return {XMLHttpRequest} XHR对象
*/
_h.__getXMLHttpRequest = (function(){
// http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
var _msxml = [
'Msxml2.XMLHTTP.6.0',
'Msxml2.XMLHTTP.3.0',
'Msxml2.XMLHTTP.4.0',
'Msxml2.XMLHTTP.5.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP'
];
return function(){
var _xhr = null;
_u._$forIn(
_msxml,function(_name){
try{
_xhr = new ActiveXObject(_name);
return !0;
}catch(e){
// ignore exception
}
}
);
return _xhr;
};
})();
});
return _h;
});
/*
* ------------------------------------------
* Ajax代理实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/proxy/proxy */
NEJ.define([
'base/klass',
'base/util',
'base/element',
'base/config',
'base/constant',
'util/event',
'util/cache/cookie',
'util/encode/json'
],function(_k,_u,_e,_c,_g,_t,_j,JSON,_p,_o,_f,_r){
var _pro;
/**
* Ajax代理对象
*
* @class module:util/ajax/proxy/proxy._$$ProxyAbstract
* @extends module:util/event._$$EventTarget
*
* @param {Object} config - 构造配置参数
* @property {String} url - 请求地址
* @property {Boolean} sync - 是否同步请求
* @property {String} type - 返回数据格式,text/json/xml
* @property {String} method - 请求方式,GET/POST
* @property {Number} timeout - 超时时间,0表示禁止超时监测
* @property {Object} headers - 头信息
*/
/**
* 载入回调
*
* @event module:util/ajax/proxy/proxy._$$ProxyAbstract#onload
* @param {Object} event - 服务器返回数据信息
*/
/**
* 异常回调
*
* @event module:util/ajax/proxy/proxy._$$ProxyAbstract#onerror
* @param {Object} event - 错误信息
* @property {Number} code - 错误代码
* @property {String} message - 错误描述
* @property {Variable} data - 出错时携带数据
*/
/**
* [hr]
* 请求之前对数据处理回调
* @event module:util/ajax/proxy/proxy._$$ProxyAbstract#onbeforerequest
* @param {Object} event - 请求信息
* @property {Object} request - 请求参数,数据信息 url/sync/cookie/type/method/timeout
* @property {Object} headers - 请求头信息
*/
_p._$$ProxyAbstract = _k._$klass();
_pro = _p._$$ProxyAbstract._$extend(_t._$$EventTarget);
/**
* 控件重置
*
* @protected
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__reset
* @param {Object} arg0 - 配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
// reset request information
this.__request = _u._$fetch({
url:'',
sync:!1,
cookie:!1,
type:'text',
method:'GET',
timeout:60000
},_options);
// for csrf attack
var _csrf = _c._$get('csrf');
if (!!_csrf.cookie&&!!_csrf.param){
var _query = encodeURIComponent(_csrf.param)+'='+
encodeURIComponent(_j._$cookie(_csrf.cookie)||''),
_split = this.__request.url.indexOf('?')<0?'?':'&';
this.__request.url += _split+_query;
}
// reset headers
this.__headers = _options.headers||{};
var _content = this.__headers[_g._$HEAD_CT];
if (_content==null){
this.__headers[_g._$HEAD_CT] = _g._$HEAD_CT_FORM;
}
};
/**
* 回收控件
*
* @protected
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__rkey;
delete this.__request;
delete this.__headers;
};
/**
* 请求载入回调
*
* @protected
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__onLoadRequest
* @param {Object} arg0 - 数据信息
* @property {Number} status - 请求状态
* @property {String} result - 请求结果,纯文本形式
* @return {Void}
*/
_pro.__onLoadRequest = function(_event){
var _status = _event.status;
// timeout error
if (_status==-1){
this._$dispatchEvent('onerror',{
code:_g._$CODE_TIMEOUT,
message:'请求['+this.__request.url+']超时!'
});
return;
}
// check status
if ((''+_status).indexOf('2')!=0){
this._$dispatchEvent('onerror',{
data:_status,
result:_event.result,
code:_g._$CODE_ERRSERV,
message:'服务器返回异常状态['+_status+']!'
});
return;
}
// onload
this._$dispatchEvent(
'onload',_e._$text2type(
_event.result,
this.__request.type
)
);
};
/**
* 往服务器发送请求,子类实现具体业务逻辑
*
* @abstract
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__doSendRequest
* @param {Object} arg0 - 请求信息
* @return {Void}
*/
_pro.__doSendRequest = _f;
/**
* 取头信息,子类实现具体业务逻辑
*
* @abstract
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__getResponseHeader
* @param {String} arg0 - 要取的头信息名称
* @return {String} 头信息结果或集合
*/
_pro.__getResponseHeader = _f;
/**
* 发送请求
*
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#_$send
* @param {Variable} arg0 - 要发送的数据
* @return {Void}
*/
_pro._$send = function(_data){
var _url = this.__request.url;
if (!_url){
this._$dispatchEvent('onerror',{
code:_g._$CODE_NOTASGN,
message:'没有输入请求地址!'
});
return;
}
try{
this.__request.data = _data==null?null:_data;
var _event = {
request:this.__request,
headers:this.__headers
};
// adjust param before request
try{
this._$dispatchEvent('onbeforerequest',_event);
}catch(ex){
// ignore exception
console.error(ex.message);
console.error(ex.stack);
}
this.__doSendRequest(_event);
}catch(e){
this._$dispatchEvent('onerror',{
code:_g._$CODE_ERRSERV,
message:'请求['+_url+']失败:'+e.message+'!'
});
}
};
/**
* 中断请求,子类实现具体业务逻辑
*
* @abstract
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#_$abort
* @return {Void}
*/
_pro._$abort = _f;
/**
* 取头信息
*
* @method module:util/ajax/proxy/proxy._$$ProxyAbstract#_$header
* @param {String|Array} arg0 - 要取的头信息名称
* @return {String|Object} 头信息结果或集合
*/
_pro._$header = function(_key){
if (!_u._$isArray(_key)){
return this.__getResponseHeader(_key)||'';
}
var _result = {};
_u._$forEach(
_key,function(_value){
_result[_value] = this._$header(_value);
},this
);
return _result;
};
return _p;
});
/*
* ------------------------------------------
* 文件上传代理实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/proxy/upload */
NEJ.define([
'./proxy.js',
'base/klass',
'base/util',
'base/event',
'base/element',
'base/constant',
'util/ajax/xdr',
'util/ajax/message'
],function(_t,_k,_u,_v,_e,_g,_j0,_j1,_p,_o,_f,_r){
var _pro,
_cache = {},
_xflag = 'NEJ-UPLOAD-RESULT:';
/**
* 文件上传代理
*
* @class module:util/ajax/proxy/upload._$$ProxyUpload
* @extends module:util/ajax/proxy/proxy._$$ProxyAbstract
*
* @param {Object} config - 构造配置参数
*/
_p._$$ProxyUpload = _k._$klass();
_pro = _p._$$ProxyUpload._$extend(_t._$$ProxyAbstract);
/**
* 控件初始化
*
* @protected
* @method module:util/ajax/proxy/upload._$$ProxyUpload#__init
* @return {Void}
*/
_pro.__init = (function(){
var _init = !1;
// receive message callback
var _doReceiveMessage = function(_event){
var _data = _event.data;
if (_data.indexOf(_xflag)!=0) return;
_data = JSON.parse(_data.replace(_xflag,''));
var _proxy = _cache[_data.key];
if (!_proxy) return;
delete _cache[_data.key];
_proxy.__onLoadRequest(
decodeURIComponent(_data.result)
);
};
// init message listener
var _doInitMessage = function(){
if (!_init){
_init = !0;
_v._$addEvent(
window,'message',
_doReceiveMessage
);
}
};
return function(){
this.__super();
_doInitMessage();
};
})();
/**
* 控件销毁
*
* @protected
* @method module:util/ajax/proxy/upload._$$ProxyUpload#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
_e._$remove(this.__frame);
delete this.__frame;
window.clearTimeout(this.__timer);
delete this.__timer;
};
/**
* 请求载入回调
*
* @protected
* @method module:util/ajax/proxy/upload._$$ProxyUpload#__onLoadRequest
* @param {String} arg0 - 数据信息
* @return {Void}
*/
_pro.__onLoadRequest = function(_text){
var _json;
try{
_json = JSON.parse(_text);
this._$dispatchEvent('onload',_json);
}catch(ex){
this._$dispatchEvent('onerror',{
code:_g._$CODE_ERREVAL,
message:_text
});
}
};
/**
* 往服务器发送请求
*
* @protected
* @method module:util/ajax/proxy/upload._$$ProxyUpload#__doSendRequest
* @param {Object} arg0 - 请求信息
* @return {Void}
*/
_pro.__doSendRequest = (function(){
// same domain upload result check
var _doCheckResult = function(){
var _body,_text;
try{
var _body = this.__frame.contentWindow.document.body,
_text = (_body.innerText||_body.textContent||'').trim();
// check result for same domain with upload proxy html
if (_text.indexOf(_xflag)>=0||
_body.innerHTML.indexOf(_xflag)>=0){
// use post message path
return;
}
}catch(ex){
// ignore if not same domain
return;
}
this.__onLoadRequest(_text);
};
// check upload progress
var _doProgress = function(_url,_mode,_cookie){
_j0._$request(_url,{
type:'json',
method:'POST',
cookie:_cookie,
mode:parseInt(_mode)||0,
onload:function(_data){
if (!this.__timer) return;
this._$dispatchEvent('onuploading',_data);
this.__timer = window.setTimeout(
_doProgress._$bind(
this,_url,_mode,_cookie
),1000
);
}._$bind(this),
onerror:function(_error){
if (!this.__timer) return;
this.__timer = window.setTimeout(
_doProgress._$bind(
this,_url,_mode,_cookie
),1000
);
}._$bind(this)
});
};
return function(_options){
var _request = _options.request,
_headers = _options.headers,
_form = _request.data,
_name = _u._$uniqueID();
_cache[_name] = this;
_form.target = _name;
_form.method = 'POST';
_form.enctype = _g._$HEAD_CT_FILE;
_form.encoding = _g._$HEAD_CT_FILE;
var _url = _form.action||'',
_sep = _url.indexOf('?')<=0?'?':'&';
_form.action = _url+_sep+'_proxy_=form';
this.__frame = _e._$createXFrame({
name:_name,
onload:function(_event){
var _frame = _v._$getElement(_event);
_v._$addEvent(
_frame,'load',
_doCheckResult._$bind(this)
);
_form.submit();
var _qurl = (_form.nej_query||_o).value;
if (!_qurl) return;
var _mode = (_form.nej_mode||_o).value,
_cookie = (_form.nej_cookie||_o).value==='true';
this.__timer = window.setTimeout(
_doProgress._$bind(
this,_qurl,_mode,_cookie
),100
);
}._$bind(this)
});
};
})();
/**
* 中断请求
*
* @method module:util/ajax/proxy/upload._$$ProxyUpload#_$abort
* @return {Void}
*/
_pro._$abort = function(){
this._$dispatchEvent('onerror',{
code:_g._$CODE_ERRABRT,
message:'客户端终止文件上传'
});
};
return _p;
});
/*
* ------------------------------------------
* XHR方式Ajax代理实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/proxy/xhr */
NEJ.define([
'./proxy.js',
'base/util',
'base/klass',
'base/constant',
'{platform}xhr.js'
],function(_t,_u,_k,_g,_h,_p,_o,_f,_r){
var _pro;
/**
* Ajax代理对象
*
* @class module:util/ajax/proxy/xhr._$$ProxyXHR
* @extends module:util/ajax/proxy/proxy._$$ProxyAbstract
*
* @param {Object} config - 构造配置参数
*/
_p._$$ProxyXHR = _k._$klass();
_pro = _p._$$ProxyXHR._$extend(_t._$$ProxyAbstract);
/**
* 控件销毁
*
* @protected
* @method module:util/ajax/proxy/xhr._$$ProxyXHR#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
// clear timeout
window.clearTimeout(this.__timer);
delete this.__timer;
// clear request
try{
this.__xhr.onreadystatechange = _f;
this.__xhr.abort();
}catch(e){
// ignore
}
delete this.__xhr;
};
/**
* 往服务器发送请求
*
* @protected
* @method module:util/ajax/proxy/xhr._$$ProxyXHR#__doSendRequest
* @param {Object} arg0 - 请求信息
* @return {Void}
*/
_pro.__doSendRequest = (function(){
// set header
var _doSetHeader = function(_value,_key){
this.__xhr.setRequestHeader(_key,_value);
};
// split input.file for multiple files
var _doSplitMultFiles = function(_form){
var _result = [];
_u._$reverseEach(
_form.getElementsByTagName('input'),
function(_input){
if (_input.type!='file'){
return;
}
// remove file without name
if (!_input.name){
_input.parentNode.removeChild(_input);
return;
}
// for multiple file per-input
if (_input.files.length>1){
_u._$forEach(_input.files,function(_file){
_result.push({name:_input.name,file:_file});
});
_input.parentNode.removeChild(_input);
}
}
);
return _result.length>0?_result:null;
};
return function(_options){
var _request = _options.request,
_headers = _options.headers;
this.__xhr = _h.__getXMLHttpRequest();
// add event listener
// upload progress
if (_headers[_g._$HEAD_CT]===_g._$HEAD_CT_FILE){
delete _headers[_g._$HEAD_CT];
this.__xhr.upload.onprogress =
this.__onStateChange._$bind(this,1);
if (_request.data.tagName==='FORM'){
var _files = _doSplitMultFiles(_request.data);
_request.data = new FormData(_request.data);
_u._$forEach(_files,function(_ret){
var _file = _ret.file;
_request.data.append(
_ret.name||_file.name||
('file-'+_u._$uniqueID()),_file
);
});
}
}
// state change
this.__xhr.onreadystatechange =
this.__onStateChange._$bind(this,2);
// timeout
if (_request.timeout!==0){
this.__timer = window.setTimeout(
this.__onStateChange._$bind(this,3),
_request.timeout
);
}
// prepare and send request
this.__xhr.open(
_request.method,
_request.url,
!_request.sync
);
_u._$loop(_headers,_doSetHeader,this);
// support credential
if (!!this.__request.cookie&&
('withCredentials' in this.__xhr)){
this.__xhr.withCredentials = !0;
}
this.__xhr.send(_request.data);
};
})();
/**
* 请求状态变化事件
*
* @protected
* @method module:util/ajax/proxy/xhr._$$ProxyXHR#__onStateChange
* @param {Number} arg0 - 状态变化类型
* @return {Void}
*/
_pro.__onStateChange = function(_type){
switch(_type){
// upload progress
case 1 :
this._$dispatchEvent('onuploading',arguments[1]);
break;
// state change
case 2 :
if (this.__xhr.readyState==4){
this.__onLoadRequest({
status:this.__xhr.status,
result:this.__xhr.responseText||''
});
}
break;
// timeout
case 3:
this.__onLoadRequest({status:-1});
break;
}
};
/**
* 取头信息
*
* @protected
* @method module:util/ajax/proxy/xhr._$$ProxyXHR#__getResponseHeader
* @param {String} arg0 - 要取的头信息名称
* @return {String} 头信息结果或集合
*/
_pro.__getResponseHeader = function(_key){
return !this.__xhr?'':this.__xhr.getResponseHeader(_key);
};
/**
* 中断请求
*
* @method module:util/ajax/proxy/xhr._$$ProxyXHR#_$abort
* @return {Void}
*/
_pro._$abort = function(){
this.__onLoadRequest({status:0});
};
return _p;
});
/*
* ------------------------------------------
* REST交互接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/rest */
NEJ.define([
'base/global',
'base/event',
'base/util',
'base/constant',
'util/ajax/xdr',
'util/event/event'
],function(NEJ,_v,_u,_g,_j,_t,_p,_o,_f,_r){
/**
* 使用REST进行数据交互接口
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/event',
* 'util/ajax/rest'
* ],function(_v,_j){
* // 通用错误处理,所有请求异常均会调用此回调处理
* _v._$addEvent(
* window,'resterror',function(_error){
* // _error.code
* // _error.message
* // _error.data
* // 通过设置_error.stopped阻止事件回调到请求的onerror中
* }
* );
*
* var url = "http://a.b.com/rest/list";
* var opt = {
* param:{brand:'nokia',model:'9'},
* data:'123',
* method:'post',
* onload:function(_data){
* // 请求正常回调
* },
* onerror:function(_error){
* // _error.code
* // _error.message
* // _error.data
* // 如果window的resterror回调中stopped了事件则不会进入此回调
* },
* onbeforerequest:function(_event){
* // _event.request
* // _event.headers
* }
* }
* _j._$request(url,opt);
* });
* ```
*
* @method module:util/ajax/rest._$request
* @param {String} arg0 - 请求地址
* @param {Object} arg1 - 可选配置参数
* @property {Boolean} sync - 是否同步请求
* @property {Variable} data - 要发送的数据
* @property {Object} param - 请求参数,包括模板地址里使用的参数
* @property {String} method - 请求方式,GET/POST/PUT/DELETE
* @property {Number} timeout - 超时时间,0 禁止超时监测
* @property {Object} headers - 头信息
* @property {Object} result - onload回调输入时需包含的额外信息
*
* @property {module:util/ajax/xdr.onload} onload - 请求载入成功回调
* @property {module:util/ajax/xdr.onerror} onerror - 请求载入失败回调
* @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 发起请求之前回调
*
* @return {Void}
*/
_p._$request = (function(){
var _cache = {}, // request cache - sn:{s:funciton(){},f:function(){}}
_reg0 = /\{(.*?)\}/gi,
_reg1 = /^get|delete|head$/i,
_jsn = /json/i,
_xml = /xml/i;
// clear request
var _doClear = function(_key){
var _request = _cache[_key];
if (!_request) return;
delete _request.s;
delete _request.f;
delete _cache[_key];
};
// request callback
var _doCallback = function(_key,_type){
var _request = _cache[_key];
if (!_request) return;
var _callback = _request[_type],
_args = _r.slice.call(arguments,2);
try{
(_callback||_f).apply(null,_args);
}catch(ex){
// ignore
if (DEBUG) throw ex;
console.error(ex.message);
console.error(ex);
}
_doClear(_key);
};
// request success
var _onLoad = function(_key,_data){
_doCallback(_key,'s',_data);
};
// request error
var _onError = function(_key,_error){
_error = _error||{};
// status 204 is ok
if (_error.code==_g._$CODE_ERRSERV&&
_error.data==204){
_onLoad(_key,null);
return;
}
// do error filter
// set error attr stopped=!0 will stop request error callback
_v._$dispatchEvent(
window,'resterror',_error
);
if (!!_error.stopped){
_doClear(_key);
return;
}
// do request fail callback
_doCallback(_key,'f',_error);
};
// check default headers
var _doCheckWithDefault = function(_headers,_key,_default){
var _value = _headers[_key]||
_headers[_key.toLowerCase()];
if (!_value){
_value = _default;
_headers[_key] = _value;
}
return _value;
};
// pre convert array
var _doCheckData = function(_data,_key,_map){
if (_u._$isArray(_data)){
_map[_key] = JSON.stringify(_data);
}
};
return function(_url,_options){
_options = _u._$merge({},_options);
var _exist = {},
_param = _options.param||_o;
// parse uri template
_url = _url.replace(_reg0,function($1,$2){
var _value = _param[$2];
if (_value!=null) _exist[$2] = !0;
return encodeURIComponent(_value||'')||$1;
});
// parse remain param
var _data = _options.data||{};
_u._$loop(
_param,function(_value,_key){
if (!_exist[_key]){
_data[_key] = _value;
}
}
);
// parse headers
var _type = 'text',
_headers = _options.headers||{},
_accept = _doCheckWithDefault(_headers,'Accept','application/json'),
_content = _doCheckWithDefault(_headers,'Content-Type','application/json');
// response data format
if (_jsn.test(_accept)){
_type = 'json';
}else if(_xml.test(_accept)){
_type = 'xml';
}
// do request
var _key = _u._$uniqueID();
_cache[_key] = {
s:_options.onload||_f,
f:_options.onerror||_f
};
// add params to url with GET/HEAD/DELETE method
_options.method = _options.method||'GET';
if (_reg1.test(_options.method.trim())){
_u._$forIn(_data,_doCheckData);
_options.query = _data;
_data = null;
}else if (_jsn.test(_content)){
_data = JSON.stringify(_data);
}
_options.type = _type;
_options.data = _data;
_options.headers = _headers;
_options.onload = _onLoad._$bind(null,_key);
_options.onerror = _onError._$bind(null,_key);
_j._$request(_url,_options);
};
})();
/**
* 通用载入出错回调函数,所有REST请求的异常均会进入此事件的回调逻辑中
*
* @event external:window.onresterror
* @param {Object} event - 错误信息
* @property {Number} code - 错误代码
* @property {String} message - 错误描述
* @property {Variable} data - 出错时携带数据
* @property {Boolean} stopped - 是否阻止单个请求中的onerror回调
*/
_t._$$CustomEvent._$allocate({
element:window,
event:'resterror'
});
if (CMPT){
NEJ.P('nej.j')._$requestByREST = _p._$request;
}
return _p;
});
/*
* ------------------------------------------
* 脚本载入控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/tag */
NEJ.define([
'base/global',
'./loader/text.js',
'./loader/html.js',
'./loader/style.js',
'./loader/script.js'
],function(NEJ,_t0,_t1,_t2,_t3,_p,_o,_f,_r){
/**
* 载入完成回调函数
*
* @callback module:util/ajax/tag.onload
* @param {Variable} event - 请求返回数据
*/
/**
* 载入出错回调函数
*
* @callback module:util/ajax/tag.onerror
* @param {Object} event - 错误信息
* @property {Number} code - 错误码
* @property {String} message - 错误信息
*/
/**
* 载入脚本文件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/tag'
* ],function(_j){
* _j._$loadScript('../../../javascript/log.js',{
* onload:function(){
* // 载入成功的回调方法
* },
* onerror:function(_error){
* // 抛出异常回调
* }
* });
* });
* ```
*
* @method module:util/ajax/tag._$loadScript
* @see module:util/ajax/tag._$queueScript
* @param {String} arg0 - 请求地址
* @param {Object} arg1 - 可选配置参数
* @property {Boolean} async - 异步载入并立刻执行,默认为!0
* @property {Number} timeout - 超时时间,0表示禁止超时监测
* @property {String} version - 版本信息
* @property {String} charset - 脚本编码
* @property {module:util/ajax/tag.onload} onload - 载入回调
* @property {module:util/ajax/tag.onerror} onerror - 异常回调
* @return {Void}
*/
_p._$loadScript = function(_url,_options){
_t3._$$LoaderScript._$allocate(_options)._$load(_url);
};
/**
* 载入队列脚本并依次执行
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/tag'
* ],function(_j){
* _j._$queueScript([
* '../../../javascript/log.js',
* 'http://123.163.com/a.js'
* ],{
* onload:function(){
* // 载入成功的回调方法
* },
* onerror:function(_error){
* // 异常回调方法
* }
* });
* });
* ```
*
* @method module:util/ajax/tag._$queueScript
* @see module:util/ajax/tag._$loadScript
* @param {Array} arg0 - 脚本队列
* @param {Object} arg1 - 可选配置参数
* @property {String} version - 版本信息
* @property {String} charset - 脚本编码
* @property {Number} timeout - 每个脚本超时时间,0表示禁止超时监测
* @property {module:util/ajax/tag.onload} onload - 载入回调
* @property {module:util/ajax/tag.onerror} onerror - 异常回调
* @return {Void}
*/
_p._$queueScript = function(_list,_options){
_t3._$$LoaderScript._$allocate(_options)._$queue(_list);
};
/**
* 载入样式文件
* ```javascript
* NEJ.define([
* 'util/ajax/tag'
* ],function(_j){
* _j._$loadStyle('http://123.163.com/a.css',{
* onload:function(){
* // 载入成功的回调方法
* },
* onerror:function(_error){
* // 异常回调方法
* }
* });
* });
* ```
*
* @method module:util/ajax/tag._$loadStyle
* @see module:util/ajax/tag._$queueStyle
* @param {String} arg0 - 样式文件地址
* @param {Object} arg1 - 可选配置参数
* @property {Number} timeout - 超时时间,0表示禁止超时监测
* @property {String} version - 版本信息
* @property {module:util/ajax/tag.onload} onload - 载入回调
* @property {module:util/ajax/tag.onerror} onerror - 异常回调
* @return {Void}
*/
_p._$loadStyle = function(_url,_options){
_t2._$$LoaderStyle._$allocate(_options)._$load(_url);
};
/**
* 载入样式队列
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/tag'
* ],function(_j){
* _j._$queueStyle([
* 'http://123.163.com/a.css',
* 'http://123.163.com/b.css'
* ],{
* onload:function(){
* // 载入成功的回调方法
* },
* onerror:function(_error){
* // 异常回调方法
* }
* });
* });
* ```
*
* @method module:util/ajax/tag._$queueStyle
* @see module:util/ajax/tag._$loadStyle
* @param {Array} arg0 - 样式队列
* @param {Object} arg1 - 可选配置参数
* @property {Number} timeout - 超时时间,0表示禁止超时监测
* @property {String} version - 版本信息
* @property {module:util/ajax/tag.onload} onload - 载入回调
* @property {module:util/ajax/tag.onerror} onerror - 异常回调
* @return {Void}
*/
_p._$queueStyle = function(_list,_options){
_t2._$$LoaderStyle._$allocate(_options)._$queue(_list);
};
/**
* 载入HTML文件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/tag'
* ],function(_j){
* _j._$loadHtml('http://123.163.com/a.html',{
* onload:function(){
* // 载入成功的回调方法
* },
* onerror:function(_error){
* // 异常回调方法
* }
* });
* });
* ```
*
* @method module:util/ajax/tag._$loadHtml
* @param {String} arg0 - 文件地址
* @param {Object} arg1 - 可选配置参数
* @property {String} version - 版本信息
* @property {module:util/ajax/tag.onload} onload - 载入回调
* @property {module:util/ajax/tag.onerror} onerror - 异常回调
* @return {Void}
*/
_p._$loadHtml = function(_url,_options){
_t1._$$LoaderHtml._$allocate(_options)._$load(_url);
};
/**
* 载入HTML文件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/tag'
* ],function(_j){
* _j._$loadText('http://123.163.com/a.txt',{
* onload:function(){
* // 载入成功的回调方法
* },
* onerror:function(_error){
* // 异常回调方法
* }
* });
* });
* ```
*
* @method module:util/ajax/tag._$loadText
* @param {String} arg0 - 文件地址
* @param {Object} arg1 - 可选配置参数
* @property {String} version - 版本信息
* @property {module:util/ajax/tag.onload} onload - 载入回调
* @property {module:util/ajax/tag.onerror} onerror - 异常回调
* @return {Void}
*/
_p._$loadText = function(_url,_options){
_t0._$$LoaderText._$allocate(_options)._$load(_url);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.j'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>message测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./message.test.js"></script>
</body>
</html>
var f = function(){
var _ = NEJ.P,
_v = _('nej.v'),
_j = _('nej.j');
_v._$addEvent(window,'message',function(_event){
nej.j._$postMessage(_event.source,{
data:'你好!',
origin:_event.origin
});
});
}
NEJ.define('{pro}message.test.js',
['{lib}util/ajax/message.js'],f);
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>tag测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit xdr test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./tag.test.js"></script>
</body>
</html>
NEJ.define([
'util/ajax/tag'
],function(_t){
module('tag');
var _j = NEJ.P('nej.j');
test('loadScript',function(){
expect(1);
stop();
_j._$loadScript('../rest.js',{
onload:function(){
ok(true, '载入成功的回调方法');
start();
// 载入成功的回调方法
},
onerror:function(_error){
start();
// 抛出异常回调
}
});
});
test('queueScript',function(){
expect(1);
stop();
_j._$queueScript(['../xdr.js','../dwr.js'],{
onload:function(){
ok(true, '载入成功的回调方法');
start();
// 载入成功的回调方法
},
onerror:function(_error){
start();
// 抛出异常回调
}
});
});
test('loadStyle',function(){
expect(1);
stop();
_j._$loadStyle('./x.css',{
onload:function(){
ok(true, '载入成功的回调方法');
start();
// 载入成功的回调方法
},
onerror:function(_error){
start();
// 抛出异常回调
}
});
});
test('queueStyle',function(){
expect(1);
stop();
_j._$queueStyle(['./x.css','./xx.css'],{
onload:function(){
ok(true, '载入成功的回调方法');
start();
// 载入成功的回调方法
},
onerror:function(_error){
start();
// 抛出异常回调
}
});
});
test('loadHtml',function(){
expect(1);
stop();
_j._$loadHtml('./message.test.html',{
onload:function(){
ok(true, '载入成功的回调方法');
start();
// 载入成功的回调方法
},
onerror:function(_error){
start();
// 抛出异常回调
}
});
});
test('loadText',function(){
expect(1);
stop();
_j._$loadText('./xxx.txt',{
onload:function(){
ok(true, '载入成功的回调方法');
start();
// 载入成功的回调方法
},
onerror:function(_error){
start();
// 抛出异常回调
}
});
});
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>xdr测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit xdr test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<form id="upload" name="upload" action="http://123.163.com:3000/xhr/uploadCallback">
<input type="file" name="fileUpload" id="fileUpload" multiple="multiple" />
<input type="text" id="progress" />
<input type="hidden" name="nej_cookie" value="false"/>
<input type="hidden" name="nej_mode" value="2" />
<input type="hidden" name="nej_query" value="http://123.163.com:3000/xhr/progress" />
</form>
<script id="hiddenlpsubmitdiv" style="display: none;"></script>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./xdr.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("xdr",{
setup:function(){
this._p = NEJ.P('nej.p');
this._e = NEJ.P('nej.e');
this._j = NEJ.P('nej.j');
},
teardown:function(){
}
});
//开始单元测试
test('正常的xdr', function() {
expect(0);
stop();
var _url = 'http://123.163.com:3000/xhr/getLog';
var _obj = {};
this._j._$request(_url,{
type:'json',
method:'post',
data:_obj,
timeout:1000,
onload:function(_data){
start();
if(!!_data)
ok(true,'请求正常返回,返回值是' + _data.name);
},
onerror:function(_error){
start();
}}
);
});
// test('设置过滤器的xdr', function() {
// stop();
// this._j._$filter(function(_event){
// if(_event.type == 'onerror'){
// // 如果过滤掉,测试无法完成
// if(_event.result.data == 404)
// _event.stopped = false;
// }
// });
// this._j._$request('http://123.163.com:3003/xhr/xxx',{
// type:'json',
// method:'POST',
// data:{name:'cheng-lin'},
// timeout:3000,
// onload:function(_data){
// if(!!_data)
// ok(true,'请求正常返回,返回值是' + _data.name);
// start();
// },
// onerror:function(_error){
// start();
// }}
// );
// });
//
// test('中途中断请求',function(){
// stop();
// var _reqID = this._j._$request('http://123.163.com:3003/xhr/xxx',{
// type:'json',
// method:'POST',
// data:{name:'cheng-lin'},
// timeout:60000,
// onload:function(_data){
// start();
// },
// onerror:function(_error){
// start();
// }}
// );
// // 1秒后中断掉这个请求
// window.setTimeout(function(){
// this._j._$abort(_reqID);
// }._$bind(this),1000);
// });
//
// test('upload表单,高级浏览器',function(){
// var _upload = this._e._$get('upload');
// this._j._$upload(_upload,{mode:0,nocookie:false,
// onuploading:function(_data){
// if(!!_data.total&&_data.progress){
// ok(true,'打印出一个进度来'+_data.progress)
// }
// },onload:function(_url){
// start();
// }
// });
// });
//
test('upload表单,低版本浏览器',function(){
stop();
var _upload = this._e._$get('upload');
var _progress = this._e._$get('progress');
this._j._$upload(_upload,{mode:0,nocookie:true,
onuploading:function(_data){
if(!!_data.total&&_data.progress){
_progress.value = _data.progress;
ok(true,'打印出一个进度来'+_data.progress)
}
},
onload:function(_url){
ok(true,_url.url);
start();
}});
});
}
NEJ.define(['{lib}util/ajax/xdr.js'],f);
/*
* ------------------------------------------
* XDR控件实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/ajax/xdr */
NEJ.define([
'base/global',
'base/constant',
'base/util',
'base/element',
'./proxy/xhr.js',
'{platform}xdr.js'
],function(NEJ,_g,_u,_e,_t,_h,_p,_o,_f,_r){
/**
* 载入回调
*
* @callback module:util/ajax/xdr.onload
* @param {Variable|Object} event - 请求返回数据,根据请求时type指定格式返回,
* 如果请求时指定了result参数,则此处输入为包含额外信息的对象,
* 数据结果从此对象的data属性中取,如{headers:{'x-res-0':'12345', ...},data:{a:'aaa', ...}}
*/
/**
* 出错回调
*
* @callback module:util/ajax/xdr.onerror
* @param {Object} event - 错误信息
* @property {Number} code - 错误代码
* @property {String} message - 错误描述
* @property {Variable} data - 出错时携带数据
*/
/**
* 请求之前对数据处理回调
*
* @callback module:util/ajax/xdr.onbeforerequest
* @param {Object} event - 请求信息
* @property {Object} request - 请求参数,数据信息 url/sync/cookie/type/method/timeout
* @property {Object} headers - 请求头信息
*/
/**
* 上传进度回调
*
* @callback module:util/ajax/xdr.onuploading
* @param {Object} event - 进度信息
* @property {Number} loaded - 载入数量
* @property {Number} total - 总量
*/
// sn:{req:proxy,onload:function(){},onerror:function(){}}
var _xcache = {},
_doFilter = _f;
/**
* 中断请求
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/xdr'
* ],function(_j){
* var _id = _j._$request(
* 'http://123.163.com/xhr/',{
* type:'json',
* method:'POST',
* data:{name:'ABC'},
* timeout:60000,
* onload:function(_data){
* // TODO
* },
* onerror:function(_error){
* // TODO
* }
* }
* );
* // 1秒后中断掉这个请求
* window.setTimeout(
* function(){
* _j._$abort(_id);
* },1000
* );
* });
* ```
*
* @method module:util/ajax/xdr._$abort
* @param {String} arg0 - 请求标识
* @return {Void}
*/
_p._$abort = function(_sn){
var _cache = _xcache[_sn];
if (!!_cache){
_cache.req._$abort();
}
};
/**
* 全局请求过滤器,过滤器中可以通过设置输入事件对象的stopped值阻止继续回调
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/xdr'
* ],function(_j){
* _j._$filter(function(_event){
* // _event.type 请求过滤类型
* // _event.result 请求结果
* // _event.stopped 是否阻止后续逻辑
*
* // 过滤掉404的异常,如果type是onload不做处理
* if (_event.type == 'onerror'){
* if (_event.result.data == 404){
* _event.stopped = false;
* }
* }
* });
* _j._$request('xxxx',{
* type:'json',
* method:'POST',
* data:{name:'abc'},
* timeout:3000,
* onload:function(_data){
* // TODO
* },
* onerror:function(_error){
* // TODO
* }
* });
* });
* ```
*
* @method module:util/ajax/xdr._$filter
* @param {Function} arg0 - 过滤器
* @return {Void}
*/
_p._$filter = function(_filter){
_doFilter = _filter||_f;
};
/**
* 发送ajax请求
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/xdr'
* ],function(_p){
* var _id = _p._$request(
* 'http://a.b.com/api',{
* sync:true,
* type:'json',
* data:'hello',
* query:'a=1&b=2',
* method:'post',
* timeout:3000,
* mode:0||1||2||3,
* onload:function(_data){
* // 正常回调处理
* },
* onerror:function(_error){
* // 异常处理
* },
* onbeforerequest:function(_data){
* // 请求发送前,对请求数据处理
* }
* }
* );
* });
* ```
*
* @method module:util/ajax/xdr._$request
* @param {String} arg0 - 请求地址
* @param {Object} arg1 - 配置参数
* @property {Boolean} sync - 是否同步请求
* @property {String} type - 返回数据格式,text/json/xml
* @property {Variable} data - 要发送的数据
* @property {Variable} query - 查询参数,字符串格式a=b&c=d,对象格式{a:'b',c:'d'}
* @property {String} method - 请求方式,GET/POST
* @property {Number} timeout - 超时时间,0 禁止超时监测
* @property {Object} headers - 头信息表
* @property {Boolean} cookie - 跨域请求是否带cookie,仅对CORS方式有效
* @property {Number} mode - 请求模式,针对跨域请求采用的请求方式
*
* * 0 - 自动模式,高版本使用HTML5的CORS协议,低版本采用Frame代理方式
* * 1 - 高版本使用HTML5的CORS协议,低版本采用Flash代理方式
* * 2 - 全部使用Frame代理方式
* * 3 - 全部使用Flash代理方式
*
* @property {Object} result - onload回调输入时需包含的额外信息,已处理额外数据
*
* * headers - 服务器返回头信息,如{headers:'x-res-0'}或者{headers:['x-res-0','x-res-1']}
*
* @property {module:util/ajax/xdr.onload} onload - 数据载入回调
* @property {module:util/ajax/xdr.onerror} onerror - 请求异常回调
* @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 请求之前回调
*
* @return {String} 分配给请求的ID
*/
_p._$request = (function(){
var _location = (location.protocol+'//'
+location.host).toLowerCase();
// check cross-domain request
var _isXDomain = function(_url){
var _origin = _u._$url2origin(_url);
return !!_origin&&_origin!=_location;
};
// check file upload
var _isUpload = function(_headers){
return (_headers||_o)[_g._$HEAD_CT]==_g._$HEAD_CT_FILE;
};
// get ajax proxy
var _getProxy = function(_options){
var _upload = _isUpload(_options.headers);
if (!_isXDomain(_options.url)&&!_upload)
return _t._$$ProxyXHR._$allocate(_options);
return _h.__getProxyByMode(_options.mode,_upload,_options);
};
// parse ext result
var _doParseExtData = function(_cache,_result){
var _data = {
data:_result
};
// parse ext headers
var _keys = _cache.result.headers;
if (!!_keys){
_data.headers = _cache.req._$header(_keys);
}
// TODO parse other ext data
return _data;
};
// clear cache
var _doClear = function(_sn){
var _cache = _xcache[_sn];
if (!_cache) return;
if (!!_cache.req)
_cache.req._$recycle();
delete _xcache[_sn];
};
// do callback
var _doCallback = function(_sn,_type){
var _cache = _xcache[_sn];
if (!_cache) return;
var _data = arguments[2];
if (_type=='onload'&&!!_cache.result){
_data = _doParseExtData(_cache,_data);
}
_doClear(_sn);
try{
var _event = {
type:_type,
result:_data
};
_doFilter(_event);
if (!_event.stopped){
(_cache[_type]||_f)(_event.result);
}
}catch(ex){
// ignore
if (DEBUG) throw ex;
console.error(ex.message);
console.error(ex);
}
};
// onload callback
var _onLoad = function(_sn,_data){
_doCallback(_sn,'onload',_data);
};
// onerror callback
var _onError = function(_sn,_error){
_doCallback(_sn,'onerror',_error);
};
// function body
return function(_url,_options){
_options = _options||{};
// cache request callback
var _sn = _u._$uniqueID(),
_cache = {
result:_options.result,
onload:_options.onload||_f,
onerror:_options.onerror||_f
};
_xcache[_sn] = _cache;
_options.onload = _onLoad._$bind(null,_sn);
_options.onerror = _onError._$bind(null,_sn);
// append request query
if (!!_options.query){
var _sep = _url.indexOf('?')<0?'?':'&',
_query = _options.query;
if (_u._$isObject(_query))
_query = _u._$object2query(_query);
if (!!_query) _url += _sep+_query;
}
_options.url = _url;
_cache.req = _getProxy(_options);
_cache.req._$send(_options.data);
return _sn;
};
})();
/**
* 文件上传
*
* 结构举例
* ```html
* <form id="upload" name="upload" action="http://123.163.com:3000/xhr/uploadCallback">
* <input type="text" id="progress" />
* <input type="hidden" name="nej_mode" value="2" />
* <input type="hidden" name="nej_query" value="http://123.163.com:3000/xhr/progress" />
* </form>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/ajax/xdr'
* ],function(_j){
* _j._$upload('upload',{
* mode:2,
* cookie:true,
* onuploading:function(_data){
* // 后台处理http://123.163.com:3000/xhr/progress,返回一个json对象
* // 前台会去轮询此接口获取进度
* if(!!_data.total&&_data.progress){
* _progress.value = _data.progress;
* }
* },
* onload:function(_url){
* // 此前会把进度轮询终止掉。如果要显示进度100%,可在此设置一次
* // 后台处理http://123.163.com:3000/xhr/uploadCallback,返回url
* // 文件上传完成的回调,url为返回的地址
* }
* });
* });
* ```
*
* @method module:util/ajax/xdr._$upload
* @see module:util/ajax/xdr._$request
* @param {HTMLFormElement} arg0 - 表单对象,待上传的文件及目标地址信息封装在此对象中
* @param {Object} arg1 - 可选配置参数
* @property {String} type - 返回数据格式
* @property {Variable} query - 查询参数
* @property {Number} mode - 跨域类型,0/2,见_$request接口说明
* @property {Object} headers - 头信息
* @property {Boolean} cookie - 跨域请求是否带cookie,仅对CORS方式有效
*
* @property {module:util/ajax/xdr.onload} onload - 数据载入回调
* @property {module:util/ajax/xdr.onerror} onerror - 请求异常回调
* @property {module:util/ajax/xdr.onuploading} onuploading - 上传进度回调
* @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 请求之前回调
*
* @return {String} 分配给请求的ID
*/
_p._$upload = function(_form,_options){
_form = _e._$get(_form);
if (!_form){
return '';
}
// init param
var _option = _u._$fetch({
mode:0,
type:'json',
query:null,
cookie:!1,
headers:{},
onload:null,
onerror:null,
onuploading:null,
onbeforerequest:null
},_options);
_option.data = _form;
_option.method = 'POST';
_option.timeout = 0;
_option.headers[_g._$HEAD_CT] =
_g._$HEAD_CT_FILE;
return _p._$request(_form.action,_option);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.j'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 动画基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/animation */
NEJ.define([
'base/global',
'base/klass',
'util/event',
'util/timer/animation'
],function(NEJ,_k,_t,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 动画基类
*
* @class module:util/animation/animation._$$Animation
* @extends module:util/event._$$EventTarget
*
* @param {Object} config - 可选配置参数
* @property {Object} to - 动画结束信息
* @property {Object} from - 动画初始信息
* @property {Number} delay - 延时时间,单位毫秒,默认0
*/
/**
* 动画结束回调事件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bounce'
* ],function(_t){
* var _bounce = _t._$$AnimBounce._$allocate({
* from: {
* offset: 100,
* velocity: 100
* },
* acceleration:100,
* onstop: function(){
* // 动画停止后回收控件
* _bounce = nej.ut._$$AnimBounce._$recycle(_bounce);
* }
* });
* });
* ```
*
* @event module:util/animation/animation._$$Animation#onstop
*/
/**
* 动画过程回调事件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bounce'
* ],function(_t){
* var _bounce = _t._$$AnimBounce._$allocate({
* from: {
* offset: 100,
* velocity: 100
* },
* acceleration:100,
* onupdate: function(_event){
* // 坐标
* console.log(_event.offset + 'px');
* // 初速度
* console.log(_event.velocity);
* }
* });
* });
* ```
*
* @event module:util/animation/animation._$$Animation#onupdate
* @param {Object} event - 可选配置参数
* @property {Number} offset - 偏移量
* @property {Number} velocity - 初速度(px/s)
*/
_p._$$Animation = _k._$klass();
_pro = _p._$$Animation._$extend(_t._$$EventTarget);
/**
* 控件重置
*
* @protected
* @method module:util/animation/animation._$$Animation#__reset
* @param {Object} arg0 - 可选配置参数
* @property {Number} to - 结束坐标
* @property {Number} from - 起始坐标
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__end = _options.to||_o;
this.__begin = _options.from||{};
this.__delay = Math.max(
0,parseInt(_options.delay)||0
);
};
/**
* 控件销毁
*
* @protected
* @method module:util/animation/animation._$$Animation#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
this._$stop();
if (!!this.__dtime){
window.clearTimeout(this.__dtime);
delete this.__dtime;
}
delete this.__end;
delete this.__begin;
};
/**
* 动画帧逻辑
*
* @protected
* @method module:util/animation/animation._$$Animation#__onAnimationFrame
* @param {Number} arg0 - 时间值
* @return {Void}
*/
_pro.__onAnimationFrame = function(_time){
if (!this.__begin) return;
if ((''+_time).indexOf('.')>=0){
_time = +new Date;
}
if (this.__doAnimationFrame(_time)){
this._$stop();
return;
}
this.__timer = _t0.requestAnimationFrame(
this.__onAnimationFrame._$bind(this)
);
};
/**
* 动画帧回调,子类实现具体算法
*
* @abstract
* @method module:util/animation/animation._$$Animation#__doAnimationFrame
* @param {Number} arg0 - 时间值
* @return {Boolean} 是否停止动画
*/
_pro.__doAnimationFrame = _f;
/**
* 注册动画监听事件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bounce'
* ],function(_t){
* var _bounce = _t._$$AnimBounce._$allocate({
* from: {
* offset: 100,
* velocity: 100
* },
* acceleration:100,
* onupdate: function(_event){
* // 坐标
* console.log(_event.offset + 'px');
* // 初速度
* console.log(_event.velocity);
* }
* });
* // 进行弹性动画
* _bounce._$play();
* });
* ```
*
* @method module:util/animation/animation._$$Animation#_$play
* @return {Void}
*/
_pro._$play = (function(){
var _doPlayAnim = function(){
this.__dtime = window.clearTimeout(this.__dtime);
this.__begin.time = +new Date;
this.__timer = _t0.requestAnimationFrame(
this.__onAnimationFrame._$bind(this)
);
};
return function(){
this.__dtime = window.setTimeout(
_doPlayAnim._$bind(this),
this.__delay
);
};
})();
/**
* 取消动画监听事件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bounce'
* ],function(_t){
* var _bounce = _t._$$AnimBounce._$allocate({
* from: {
* offset: 100,
* velocity: 100
* },
* acceleration:100,
* onupdate: function(_event){
* // 坐标
* console.log(_event.offset + 'px');
* // 初速度
* console.log(_event.velocity);
* }
* });
* // 进行动画
* _bounce._$play();
* // 停止动画,触发onstop
* _bounce._$stop();
* });
* ```
*
* @method module:util/animation/animation._$$Animation#_$stop
* @return {Void}
*/
_pro._$stop = function(){
this.__timer = _t0.cancelAnimationFrame(this.__timer);
this._$dispatchEvent('onstop');
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 贝塞尔曲线算法实现文件
* 算法参考webkit动画实现
* WebCore/platform/graphics/UnitBezier.h
* WebCore/page/animation/AnimationBase.cpp
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/bezier */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'./animation.js'
],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 贝塞尔曲线算法
*
* 初始信息包括
*
* * offset [Number] 偏移量
*
* 结束信息包括
*
* * offset [Number] 偏移量
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bezier'
* ],function(_t){
* var _easein = nej.ut._$$AnimBezier._$allocate({
* from: {
* offset: 100
* },
* to:{
* offset: 0
* },
* timing:'easein',
* onupdate:function(_event){
* // 坐标
* console.log(_event.offset + 'px');
* // 更新节点位置
* },
* onstop:function(){
* // 动画停止后回收控件
* this._$recycle();
* }
* });
* // 进行弹性动画
* _easein._$play();
* });
* ```
*
* @class module:util/animation/bezier._$$AnimBezier
* @extends module:util/animation/animation._$$Animation
*
* @param {Object} config - 可选配置参数
* @property {Number} duration - 持续时间,单位毫秒,默认为200ms
* @property {String} timing - 时间函数,默认为ease,ease/easein/easeout/easeinout/linear/cubic-bezier(x1,y1,x2,y2)
*/
_p._$$AnimBezier = _k._$klass();
_pro = _p._$$AnimBezier._$extend(_t0._$$Animation);
/**
* 控件重置
*
* @protected
* @method module:util/animation/bezier._$$AnimBezier#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__duration = _options.duration||200;
this.__epsilon = 1/(200*this.__duration);
this.__doParseTiming(_options.timing);
this.__doCalPolynomialCoefficients();
};
/**
* 控件销毁
*
* @protected
* @method module:util/animation/bezier._$$AnimBezier#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__pointer;
delete this.__coefficient;
};
/**
* 解析时间动画为坐标信息
*
* @protected
* @method module:util/animation/bezier._$$AnimBezier#__doParseTiming
* @param {String} arg0 - 时间动画
* @return {Void}
*/
_pro.__doParseTiming = (function(){
var _reg0 = /^cubic\-bezier\((.*?)\)$/i,
_reg1 = /\s*,\s*/i,
_pointers = {
linear:[0,0,1,1]
,ease:[0.25,0.1,0.25,1.0]
,easein:[0.42,0,1,1]
,easeout:[0,0,0.58,1]
,easeinout:[0,0,0.58,1]
};
var _doParseFloat = function(_value,_index,_list){
_list[_index] = parseFloat(_value);
};
return function(_timing){
_timing = (_timing||'').toLowerCase();
this.__pointer = _pointers[_timing];
if (_reg0.test(_timing)){
this.__pointer = RegExp.$1.split(_reg1);
_u._$forEach(this.__pointer,_doParseFloat);
}
if (!!this.__pointer) return;
this.__pointer = _pointers.ease;
};
})();
/**
* 计算贝塞尔曲线多项式系数
*
* @protected
* @method module:util/animation/bezier._$$AnimBezier#__doCalPolynomialCoefficients
* @return {Void}
*/
_pro.__doCalPolynomialCoefficients = function(){
var _pt = this.__pointer,
_cx = 3*_pt[0],
_bx = 3*(_pt[2]-_pt[0])-_cx,
_ax = 1-_cx-_bx,
_cy = 3*_pt[1],
_by = 3*(_pt[3]-_pt[1])-_cy,
_ay = 1-_cy-_by;
this.__coefficient = {
ax:_ax, ay:_ay,
bx:_bx, by:_by,
cx:_cx, cy:_cy
};
};
/**
* 计算目标接近率
*
* @protected
* @method module:util/animation/bezier._$$AnimBezier#__doCalCubicBezierAtTime
* @param {Number} arg0 - 当前时间
* @return {Float} 终点接近率
*/
_pro.__doCalCubicBezierAtTime = (function(){
var _doSampleCurveX = function(_time,_coef){
return ((_coef.ax*_time+_coef.bx)*_time+_coef.cx)*_time;
};
var _doSampleCurveY = function(_time,_coef){
return ((_coef.ay*_time+_coef.by)*_time+_coef.cy)*_time;
};
var _doSampleCurveDerivativeX = function(_time,_coef){
return (3*_coef.ax*_time+2*_coef.bx)*_time+_coef.cx;
};
var _doSolveCurveX = function(_time,_epsilon,_coef){
var t0,t1,t2,x2,d2,i;
// First try a few iterations of Newton's method -- normally very fast.
for(t2=_time,i=0;i<8;i++){
x2 = _doSampleCurveX(t2,_coef)-_time;
if (Math.abs(x2)<_epsilon)
return t2;
d2 = _doSampleCurveDerivativeX(t2,_coef);
if (Math.abs(d2)<1e-6)
break;
t2 = t2-x2/d2;
}
// Fall back to the bisection method for reliability.
t0 = 0; t1 = 1; t2 = _time;
if (t2<t0) return t0;
if (t2>t1) return t1;
while(t0<t1) {
x2 = _doSampleCurveX(t2,_coef);
if (Math.abs(x2-_time)<_epsilon)
return t2;
if (_time>x2)
t0 = t2;
else
t1 = t2;
t2 = (t1-t0)*0.5+t0;
}
// Failure.
return t2;
};
return function(_delta){
return _doSampleCurveY(
_doSolveCurveX(_delta/this.__duration,
this.__epsilon,this.__coefficient),this.__coefficient);
};
})();
/**
* 动画帧回调
*
* @protected
* @method module:util/animation/bezier._$$AnimBezier#__doAnimationFrame
* @param {Number} arg0 - 时间值
* @return {Boolean} 是否停止
*/
_pro.__doAnimationFrame = function(_time){
var _delta = _time-this.__begin.time,
_percent = this.__doCalCubicBezierAtTime(_delta),
_offset = _u._$fixed(this.__begin.offset*(1-_percent)+
this.__end.offset*_percent,2),
_stop = !1;
// offset out of begin and end range
if (_delta>=this.__duration){
_offset = this.__end.offset;
_stop = !0;
}
this._$dispatchEvent('onupdate',{
offset:1*_offset
});
return _stop;
};
/**
* 取消动画监听事件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bezier'
* ],function(_t){
* var _easein = nej.ut._$$AnimBezier._$allocate({
* from: {
* offset: 100
* },
* to:{
* offset: 0
* },
* timing:'easein',
* onupdate: function(_event){
* // 坐标
* console.log(_event.offset + 'px');
* }
* });
* // 进行弹性动画
* _easein._$play();
* // 结束动画
* _easein._$stop();
* });
* ```
* @method module:util/animation/bezier._$$AnimBezier#_$stop
* @return {Void}
*/
_pro._$stop = function(){
this._$dispatchEvent('onupdate',{
offset:this.__end.offset
});
this.__super();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 弹跳动画实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/bounce */
NEJ.define([
'base/global',
'base/klass',
'./animation.js'
],function(NEJ,_k,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 弹跳动画
*
* 初始信息包括
*
* * offset [Number] | 偏移量
* * velocity [Number] | 初速度,单位 px/s
*
* 无结束信息
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bounce'
* ],function(_t){
* var _bounce = _t._$$AnimBounce._$allocate({
* from: {
* offset: 100,
* velocity: 100
* },
* acceleration:100,
* onupdate: function(_event){
* // 坐标
* console.log(_event.offset + 'px');
* // 初速度
* console.log(_event.velocity);
* }
* });
* // 进行弹性动画
* _bounce._$play();
* });
* ```
*
* @class module:util/animation/bounce._$$AnimBounce
* @extends module:util/animation/animation._$$Animation
*
* @param {Object} config - 可选配置参数
* @property {Number} acceleration - 加速度,值越小弹跳越快
* @property {Number} springtension - 张紧度,0-1之间,值越小弹跳距离越大
*/
_p._$$AnimBounce = _k._$klass();
_pro = _p._$$AnimBounce._$extend(_t0._$$Animation);
/**
* 控件重置
*
* @protected
* @method module:util/animation/bounce._$$AnimBounce#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__acceleration = _options.acceleration||30;
this.__springtension = _options.springtension||0.3;
};
/**
* 动画帧回调
*
* @protected
* @method module:util/animation/bounce._$$AnimBounce#__doAnimationFrame
* @param {Number} arg0 - 时间值
* @return {Void}
*/
_pro.__doAnimationFrame = function(_time){
var _elapse = _time-this.__begin.time,
_factor = _elapse/this.__acceleration,
_pwtime = _factor*Math.pow(Math.E,-this.__springtension*_factor),
_delta = this.__begin.velocity*_pwtime,
_offset = this.__begin.offset+_delta,
_stop = !1;
if (_elapse>1&&Math.abs(_delta)<1){
_stop = !0;
_offset = this.__begin.offset;
}
this._$dispatchEvent('onupdate',{
offset:_offset
});
return _stop;
};
/**
* 取消动画监听事件
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/bounce'
* ],function(_t){
* var _bounce = _t._$$AnimBounce._$allocate({
* from: {
* offset: 100,
* velocity: 100
* },
* acceleration:100,
* onupdate: function(_event){
* // 坐标
* console.log(_event.offset + 'px');
* // 初速度
* console.log(_event.velocity);
* }
* });
* // 进行弹性动画
* _bounce._$play();
* // 停止动画,触发onstop
* _bounce._$stop();
* });
* ```
*
* @method module:util/animation/bounce._$$AnimBounce#_$stop
* @return {Void}
*/
_pro._$stop = function(){
this._$dispatchEvent('onupdate',{
offset:this.__begin.offset
});
this.__super();
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 减速动画实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/decelerate */
NEJ.define([
'base/global',
'base/klass',
'./animation.js'
],function(NEJ,_k,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 减速动画
*
* 初始信息包括
*
* * offset [Number] 偏移量
* * velocity [Number] 初速度,单位 px/s
*
* 无结束信息
*
* 结构举例
* ```html
* <div id='id-bounce1'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/decelerate'
* ],function(_t){
* // 创建减速动画实例
* var _decelerate = _t._$$AnimDecelerate._$allocate({
* from:{
* offset: 100,
* velocity: 10
* },
* onupdate: function(_event){
* // 更新盒子的位置
* _box.style.left = _event.offset + 'px';
* },
* onstop: function(){
* this._$recycle();
* }
* });
* // 开始动画
* _decelerate._$play();
* });
* ```
*
* @class module:util/animation/decelerate._$$AnimDecelerate
* @extends module:util/animation/animation._$$Animation
*
* @param {Object} config - 可选配置参数
* @property {Number} friction - 阻力系数,0-1之间,阻力越大减速距离越短
* @property {Number} acceleration - 加速度,值越小减速越快
*/
_p._$$AnimDecelerate = _k._$klass();
_pro = _p._$$AnimDecelerate._$extend(_t0._$$Animation);
/**
* 控件重置
*
* @protected
* @method module:util/animation/decelerate._$$AnimDecelerate#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this.__friction = _options.friction||0.5;
this.__theta = Math.log(1-(this.__friction/10));
this.__acceleration = _options.acceleration||30;
};
/**
* 动画帧回调
*
* @protected
* @method module:util/animation/decelerate._$$AnimDecelerate#__doAnimationFrame
* @param {Number} arg0 - 时间值
* @return {Boolean} 是否停止
*/
_pro.__doAnimationFrame = function(_time){
var _factor = Math.exp((_time-this.__begin.time)/this.__acceleration*this.__theta),
_offset = this.__begin.offset-this.__begin.velocity*(1-_factor)/this.__theta,
_velocity = this.__begin.velocity*_factor,
_stop = !1;
if (Math.abs(_velocity)<=1){
_stop = !0;
}
this._$dispatchEvent('onupdate',{
offset:_offset,
velocity:_velocity
});
return _stop;
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 先慢后快动画实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/easein */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'./bezier.js'
],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 先慢后快动画
*
* 结构举例
* ```html
* <div id='id-bounce1'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/easein'
* ],function(_t){
* // 创建动画实例
* var _easein = _t._$$AnimEaseIn._$allocate({
* from:{
* offset:100
* },
* to:{
* offset:200
* },
* duration:1000,
* onupdate:function(_event){
* _box.style.left = _event.offset + 'px';
* },
* onstop:function(){
* this._$recycle();
* }
* });
* // 开始动画
* _easein._$play();
* });
* ```
*
* @class module:util/animation/easein._$$AnimEaseIn
* @extends module:util/animation/bezier._$$AnimBezier
*
* @param {Object} config 可选配置参数
*/
_p._$$AnimEaseIn = _k._$klass();
_pro = _p._$$AnimEaseIn._$extend(_t0._$$AnimBezier);
/**
* 控件重置
*
* @protected
* @method module:util/animation/easein._$$AnimEaseIn#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
_options = _u._$merge({},_options);
_options.timing = 'easein';
this.__super(_options);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 先慢后快再慢动画实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/easeinout */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'./bezier.js'
],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 先慢后快再慢动画
*
* 结构举例
* ```html
* <div id='id-bounce1'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/easeinout'
* ],function(_t){
* // 创建动画实例
* var _easeinout = _t._$$AnimEaseInOut._$allocate({
* from:{
* offset:100
* },
* to:{
* offset:200
* },
* duration:1000,
* onupdate:function(_event){
* _box.style.left = _event.offset + 'px';
* },
* onstop:function(){
* this._$recycle();
* }
* });
* // 开始动画
* _easeinout._$play();
* });
* ```
*
* @class module:util/animation/easeinout._$$AnimEaseInOut
* @extends module:util/animation/bezier._$$AnimBezier
*
* @param {Object} config 可选配置参数
*/
_p._$$AnimEaseInOut = _k._$klass();
_pro = _p._$$AnimEaseInOut._$extend(_t0._$$AnimBezier);
/**
* 控件重置
*
* @protected
* @method module:util/animation/easeinout._$$AnimEaseInOut#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
_options = _u._$merge({},_options);
_options.timing = 'easeinout';
this.__super(_options);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 先快后慢动画实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/easeout */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'./bezier.js'
],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 先快后慢动画
*
* 结构举例
* ```html
* <div id='id-bounce1'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/easeout'
* ],function(_t){
* // 创建动画实例
* var _easeout = _t._$$AnimEaseOut._$allocate({
* from:{
* offset:100
* },
* to:{
* offset:200
* },
* duration:1000,
* onupdate:function(_event){
* _box.style.left = _event.offset + 'px';
* },
* onstop:function(){
* this._$recycle();
* }
* });
* // 开始动画
* _easeout._$play();
* });
* ```
*
* @class module:util/animation/easeout._$$AnimEaseOut
* @extends module:util/animation/bezier._$$AnimBezier
*
* @param {Object} config 可选配置参数
*/
_p._$$AnimEaseOut = _k._$klass();
_pro = _p._$$AnimEaseOut._$extend(_t0._$$AnimBezier);
/**
* 控件重置
*
* @protected
* @method module:util/animation/easeout._$$AnimEaseOut#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
_options = _u._$merge({},_options);
_options.timing = 'easeout';
this.__super(_options);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
/*
* ------------------------------------------
* 线性动画实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/animation/linear */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'./bezier.js'
],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){
// variable declaration
var _pro;
/**
* 线性动画
*
* 结构举例
* ```html
* <div id='id-bounce1'></div>
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/animation/linear'
* ],function(_t){
* // 创建动画实例
* var _linear = _t._$$AnimLinear._$allocate({
* from:{
* offset:100
* },
* to:{
* offset:200
* },
* duration:1000,
* onupdate:function(_event){
* _box.style.left = _event.offset + 'px';
* },
* onstop:function(){
* this._$recycle();
* }
* });
* // 开始动画
* _linear._$play();
* });
* ```
*
* @class module:util/animation/linear._$$AnimLinear
* @extends module:util/animation/bezier._$$AnimBezier
*
* @param {Object} config - 可选配置参数
*/
_p._$$AnimLinear = _k._$klass();
_pro = _p._$$AnimLinear._$extend(_t0._$$AnimBezier);
/**
* 控件重置
*
* @protected
* @method module:util/animation/linear._$$AnimLinear#__reset
* @param {Object} arg0 - 可选配置参数
* @return {Void}
*/
_pro.__reset = function(_options){
_options = _u._$merge({},_options);
_options.timing = 'linear';
this.__super(_options);
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>animation测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit animation test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<div id="id-bounce0" style="width:20px;height:20px;background:red;position:absolute;bottom:120px;"></div>
<div id="id-bounce1" style="width:20px;height:20px;background:green;position:absolute;bottom:100px;"></div>
<div id="id-bounce2" style="width:20px;height:20px;background:#ccc;position:absolute;bottom:80px;"></div>
<div id="id-bounce3" style="width:20px;height:20px;background:#578543;position:absolute;bottom:60px;"></div>
<div id="id-bounce4" style="width:20px;height:20px;background:#df3563;position:absolute;bottom:40px;"></div>
<div id="id-bounce5" style="width:20px;height:20px;background:#7b21f3;position:absolute;bottom:20px;"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./animation.test.js"></script>
</body>
</html>
var f = function(){
//定义测试模块
module("animation");
//开始单元测试
test('正常的测试弹性动画', function() {
stop();
var _bounce;
var _box = document.getElementById('id-bounce0');
var options = {
from: {
offset: 100,
velocity: 100
},
acceleration:100,
onupdate: function(offset){
_box.style.left = offset.offset + 'px';
ok(true,"成功调用"+offset.offset);
},
onstop: function(){
_bounce = nej.ut._$$AnimBounce._$recycle(_bounce);
start();
}
}
_bounce = nej.ut._$$AnimBounce._$allocate(options);
_bounce._$play();
});
test('正常的减速动画', function() {
stop();
var _decelerate;
var _box = document.getElementById('id-bounce1');
var options = {
from:{
offset: 100,
velocity: 10
},
onupdate: function(offset){
ok(true,"成功调用"+offset.offset);
_box.style.left = offset.offset + 'px';
},
onstop: function(){
_decelerate = nej.ut._$$AnimDecelerate._$recycle(_decelerate);
start();
}
}
_decelerate = nej.ut._$$AnimDecelerate._$allocate(options);
_decelerate._$play();
});
test('正常的先快后慢动画', function() {
stop();
var _easeout;
var _box = document.getElementById('id-bounce2');
var options = {
from: {
offset: 100,
velocity: 10
},
to: {
offset:200
},
duration:1000,
onupdate: function(offset){
ok(true,"成功调用"+offset.offset);
_box.style.left = offset.offset + 'px';
},
onstop: function(){
_easeout = nej.ut._$$AnimEaseOut._$recycle(_easeout);
start();
}
}
_easeout = nej.ut._$$AnimEaseOut._$allocate(options);
_easeout._$play();
});
test('正常的线性动画', function() {
stop();
var _linear;
var _box = document.getElementById('id-bounce3');
var options = {
from: {
offset: 100,
velocity: 10
},
to: {
offset:200
},
duration:1000,
onupdate: function(offset){
ok(true,"成功调用"+offset.offset);
_box.style.left = offset.offset + 'px';
},
onstop: function(){
_linear = nej.ut._$$AnimLinear._$recycle(_linear);
start();
}
}
_linear = nej.ut._$$AnimLinear._$allocate(options);
_linear._$play();
});
test('正常的先慢后快动画', function() {
stop();
var _easein;
var _box = document.getElementById('id-bounce4');
var options = {
from:{
offset: 100,
velocity: 10
},
to: {
offset:200
},
duration:1000,
onupdate: function(offset){
ok(true,"成功调用"+offset.offset);
_box.style.left = offset.offset + 'px';
},
onstop: function(){
_easein = nej.ut._$$AnimEaseIn._$recycle(_easein);
start();
}
}
_easein = nej.ut._$$AnimEaseIn._$allocate(options);
_easein._$play();
});
test('先慢后快再慢动画实现文件', function() {
stop();
var _easeinout;
var _box = document.getElementById('id-bounce5');
var options = {
from:{
offset: 100,
velocity: 10
},
to: {
offset:200
},
duration:1000,
onupdate: function(offset){
ok(true,"成功调用"+offset.offset);
_box.style.left = offset.offset + 'px';
},
onstop: function(){
_easeinout = nej.ut._$$AnimEaseInOut._$recycle(_easeinout);
start();
}
}
_easeinout = nej.ut._$$AnimEaseInOut._$allocate(options);
_easeinout._$play();
});
}
module('依赖模块');
test('define',function(){expect(0);
define('{pro}animationTest.js',
['{lib}util/animation/bounce.js','{lib}util/animation/linear.js','{lib}util/animation/decelerate.js',
'{lib}util/animation/easeout.js','{lib}util/animation/easein.js','{lib}util/animation/easeinout.js','{pro}log.js'],f);
});
/**
* ------------------------------------------
* 语音接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/audio/audio */
NEJ.define([
'base/global',
'base/util',
'{platform}audio.js'
],function(NEJ,_u,_h,_p,_o,_f,_r){
/**
* 取音频播放器实例
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/audio/audio'
* ],function(_e){
* // 取音频播放器实例
* var _audio = _e._$audio({
* preload:false,
* url:'http://127.0.0.1:8000/nej-baseline/res/test.mp3',
* onstatechange:function(_event){
* // 状态改变的回调
* // 0 | 当前停止状态
* // 1 | 当前缓冲状态
* // 2 | 当前播放状态
* // 3 | 当前暂停状态
* // 4 | 播放结束状态
* }
* });
* // 播放
* _audio._$play();
* // 暂停
* _audio._$pause();
* // 停止
* _audio._$stop();
* });
* ```
*
* @method module:util/audio/audio._$audio
* @param {Object} arg0 - 配置信息
* @return {module:util/media/media._$$Media} 音频播放器实例
*/
_p._$audio = function(_options){
return _h.__getAudioInst(_options);
};
/**
* 作为背景播放音频
*
* 播放状态值说明
*
* | 状态值 | 说明 |
* | :--- | :--- |
* | 0 | 当前停止状态 |
* | 1 | 当前缓冲状态 |
* | 2 | 当前播放状态 |
* | 3 | 当前暂停状态 |
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'util/audio/audio'
* ],function(_e){
* // 播放音频
* // 如果之前有音频在播放
* // 则会先触发之前音频的0状态onstatechange事件
* _e._$play(
* 'http://a.b.com/a/a.mp3',{
* key:'test-audio'
* extra:'xxx_id',
* onstatechange:function(_event){
* // _event.state -> 状态值
* // _event.data -> extra值
* },
* onerror:function(_event){
* // _event.code -> 错误类型
* }
* }
* );
* // 停止音频播放
* // 如果有音频在播放
* // 则会触发0状态的onstatechange事件
* _e._$stop('test-audio');
* });
* ```
*
* @method module:util/audio/audio._$play
* @param {String} arg0 - 音频文件地址
* @param {Object} arg1 - 可选配置参数
* @property {String} key - 播放标识,同一标识只允许一个播放实例
* @property {Variable} extra - onstatechange/onerror时传回数据
* @property {Number} retry - 出错重试次数,0表示不重试,默认为0
* @property {Number} interval - 如果设置了retry则通过此参数指定每次重试间隔,单位毫秒,默认500
* @property {Function} onstatechange - 播放状态变化回调事件,state值见说明
* @property {Function} ontimeupdate - 时间轴变化事件,输入{current:1.000,duration:50.000,data:'extra data'}
* @property {Function} onerror - 播放异常回调事件
* @return {Void}
*/
_p._$play = (function(){
// audio player cache
// url - audio url
// conf - play config
// audio - audio instance
// timer - retry timer
var _pcache = {};
// callback
var _doCallback = function(_key,_name,_event,_cleared){
var _cch = _pcache[_key];
if (!_cch) return;
var _conf = _cch.conf,
_func = _conf[_name]||_f,
_extr = _conf.extra;
if (!!_cleared){
delete _pcache[_key];
}
_event.data = _extr;
_func(_event);
};
// state change callback
var _doStateChangeCallback = function(_key,_state){
_doCallback(
_key,'onstatechange',
{state:_state},_state==0
);
};
// error callback
var _doErrorCallback = function(_key,_code){
_doCallback(_key,'onerror',{code:_code},!0);
};
// timeupdate callback
var _doTimeUpdateCallback = function(_key,_event){
_doCallback(_key,'ontimeupdate',_event);
};
// state change action
var _doStateChangeAction = function(_key,_event){
if (_event.state==0){
_doClearAction(_key);
}
_doStateChangeCallback(_key,_event.state);
};
// play action
var _doPlayAction = function(_key){
var _cch = _pcache[_key];
if (!_cch) return;
_cch.audio = _h.__getAudioInst({
url:_cch.url,
onerror:_doErrorAction._$bind(null,_key),
ontimeupdate:_doTimeUpdateCallback._$bind(null,_key),
onstatechange:_doStateChangeAction._$bind(null,_key)
});
_cch.audio._$play();
};
// stop action
var _doClearAction = function(_key){
var _cch = _pcache[_key];
if (!_cch) return;
if (!!_cch.audio){
_cch.audio = _cch.audio._$recycle();
}
if (!!_cch.timer){
_cch.timer = window.clearTimeout(_cch.timer);
}
};
// error action
var _doErrorAction = function(_key,_event){
var _cch = _pcache[_key];
if (!_cch) return;
_doClearAction(_key);
var _conf = _cch.conf;
if (_conf.retry>0){
_conf.retry--;
_cch.timer = window.setTimeout(
_doPlayAction._$bind(null,_key),
_conf.interval||500
);
}else{
_doErrorCallback(_key,_event.code);
}
};
/**
* 停止单例音频播放
* @method module:util/audio/audio._$stop
* @see module:util/audio/audio._$play
* @param {String} arg0 - 播放标识
* @return {Void}
*/
_p._$stop = function(_key){
var _cch = _pcache[_key||'auto-audio'];
if (!!_cch){
_cch.audio._$stop();
}
};
return function(_url,_options){
if (!_url) return;
var _playing = _u._$merge({},_options),
_key = _playing.key||'auto-audio',
_cch = _pcache[_key];
// stop last
if (!!_cch){
_doClearAction(_key);
_doStateChangeCallback(_key,0);
}
// save audio config
_pcache[_key] = {
url:_url,
conf:_playing
};
// play current
_doPlayAction(_key);
};
})();
if (CMPT){
var _x = NEJ.P('nej.e');
_x._$audio = _p._$audio;
_x._$playBgSound = _p._$play;
_x._$stopBgSound = _p._$stop;
}
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
define([
'util/media/audio'
],function(_t,_p,_o,_f,_r){
/**
* 取音频播放器实例d
* @param {Object} 配置信息
* @return {_$$Media} 音频播放器实例
*/
_p.__getAudioInst = function(_options){
return _t._$$MediaAudio._$allocate(_options);
};
return _p;
});
/*
* ------------------------------------------
* 平台适配接口实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
define([
'./audio.js'
],function(_h,_p,_o,_f,_r){
// for ie8-
NEJ.patch('TR<=4.0',['util/media/flash'],function(_t){
/**
* 取音频播放器实例d
* @param {Object} 配置信息
* @return {_$$Media} 音频播放器实例
*/
_h.__getAudioInst = function(_options){
return _t._$$MediaFlash._$allocate(_options);
};
});
return _h;
});
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>audio测试页</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
</head>
<body>
<h1 id="qunit-header">Qunit xdr test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
<script src="../../../define.js?pro=./"></script>
<script type="text/javascript" src="./audio.test.js"></script>
</body>
</html>
NEJ.define(['util/audio/audio'],function(){
var _ = NEJ.P,
_e = _('nej.e'),
_v = _('nej.v');
test('audio',function(){
expect(0);
// _e._$audio(
// {
// key:'test-audio',
// extra:'xxx_id',
// onstatechange:function(_event){
// ok('回调成功' + 'state ' +_event.state + 'data ' + _event.data);
// debugger;
// // _event.state -> 状态值
// // _event.data -> extra值
// _e._$stopBgSound('test-audio');
// start()
// },
// onerror:function(_event){
// // _event.code -> 错误类型
// }
// }
// );
// _e._$playBgSound('')
var _audio = _e._$audio({
preload:true,
url:'http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',
onstatechange:function(_event){
// ok('回调成功' + 'state ' +_event.state + 'data ' + _event.data);
// debugger;
// _audio._$pause();
// // 停止
// _audio._$stop();
}
});
// 播放
_audio._$play();
});
});
/*
* ------------------------------------------
* 列表缓存管理基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/cache/abstract */
NEJ.define([
'base/global',
'base/klass',
'./list.js'
],function(NEJ,_k,_t,_p,_o,_f,_r){
var _pro;
/**
* 列表缓存管理基类
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'util/ajax/xdr',
* 'util/cache/abstract'
* ],function(_k,_j,_t,_p){
* // 创建自己的listCache管理类
* _p._$$CacheListCustom = _k._$klass();
* _pro = _p._$$CacheListCustom._$extend(_t._$$CacheListAbstract);
*
* // 实现取列表的方法
* // 根据offset+limit取列表
* // data表示取列表可能需要的额外数据信息
* // 数据返回的回调是onload
* _pro.__doLoadList = function(_options){
* var _key = _options.key;
* var _data = _options.data;
* var _offset = _options.offset;
* var _limit = _options.limit;
* var _rkey = _options.rkey;
* var _onload = _options.onload;
* _j._$request(
* '/xhr/list',{
* type:'json',
* method:'POST',
* data:{offset:_offset,limit:_limit},
* timeout:1000,
* onload:_onload._$bind(this),
* onerror:function(_error){
* // TODO
* }
* }
* );
* };
*
* // 实现取列表的方法
* // 根据id和key取一项数据
* // 数据返回的回调是onload
* _proCacheListCustom.__doLoadItem = function(_options){
* var _id = _options.id;
* var _key = _options.key;
* var _rkey = _options.rkey;
* var _onload = _options.onload;
* _j._$request(
* '/xhr/get',{
* type:'json',
* method:'POST',
* data:{id:_id,key:_key},
* timeout:1000,
* onload:_onload._$bind(this),
* onerror:function(_error){
* // TODO
* }
* }
* );
* };
* });
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* '/path/to/custom/cache.js'
* ],function(_p){
* // 实例化一个上面的对象
* var _cache = c._$$CacheListCustom._$allocate({
* // id作为cache的标识
* id:'a',
* // 根据key,也就是上面的id,到缓存中取数据,然后处理数据
* onlistload:function(_ropt){
* _cache._$getListInCache(_ropt.key);
* },
* // 根据key,也就是上面的id,到缓存中取数据,然后处理数据
* onitemload:function(_ropt){
* _cache._$getItemInCache(_ropt.key);
* }
* });
*
* // 第一个列表的请求
* _cache._$getList({key:'abc',data:{},offset:0,limit:10})
* // 不会发请求,直接走缓存
* _cache._$getList({key:'abc',data:{},offset:0,limit:10})
* // 第一个项请求
* _cache._$getItem({id:'abc',key:'123',data:{})
* // 不会发请求,直接走缓存
* _cache._$getItem({id:'abc',key:'123',data:{})
* });
* ```
*
* @class module:util/cache/abstract._$$CacheListAbstract
* @extends module:util/cache/list._$$CacheList
*
* @param {Object} config - 可选配置参数
*/
/**
* 列表载入完成回调
*
* @event module:util/cache/abstract._$$CacheListAbstract#onlistload
* @param {Object} event - 可选配置参数
* @property {String} key - 列表标识
* @property {Variable} ext - 传入数据原样返回
*/
/**
* 缓存项载入完成回调
*
* @event module:util/cache/abstract._$$CacheListAbstract#onitemload
* @param {Object} event - 可选配置参数
* @property {String} id - 项标识
* @property {String} key - 列表标识
* @property {Variable} ext - 传入数据原样返回
*/
/**
* 缓存项添加完成回调
*
* @event module:util/cache/abstract._$$CacheListAbstract#onitemadd
* @param {Object} event - 可选配置参数
* @property {String} id - 项标识
* @property {String} key - 列表标识
* @property {Variable} ext - 传入数据原样返回
*/
/**
* 缓存项删除完成回调
*
* @event module:util/cache/abstract._$$CacheListAbstract#onitemdelete
* @param {Object} event - 可选配置参数
* @property {String} id - 项标识
* @property {String} key - 列表标识
* @property {Variable} ext - 传入数据原样返回
*/
/**
* 缓存项更新完成回调
*
* @event module:util/cache/abstract._$$CacheListAbstract#onitemupdate
* @param {Object} event - 可选配置参数
* @property {String} id - 项标识
* @property {String} key - 列表标识
* @property {Variable} ext - 传入数据原样返回
*/
/**
* 服务器最新列表拉取完成回调
*
* @event module:util/cache/abstract._$$CacheListAbstract#onpullrefresh
* @param {Object} event - 可选配置参数
* @property {String} key - 列表标识
* @property {Variable} ext - 传入数据原样返回
*/
_p._$$CacheListAbstract = _k._$klass();
_pro = _p._$$CacheListAbstract._$extend(_t._$$CacheList);
/**
* 控件初始化
*
* @protected
* @method module:util/cache/abstract._$$CacheListAbstract#__init
* @return {Void}
*/
_pro.__reset = function(_options){
this.__super(_options);
this._$batEvent({
doloadlist:this.__doLoadList._$bind(this),
doloaditem:this.__doLoadItem._$bind(this),
doadditem:this.__doAddItem._$bind(this),
dodeleteitem:this.__doDeleteItem._$bind(this),
doupdateitem:this.__doUpdateItem._$bind(this),
dopullrefresh:this.__doPullRefresh._$bind(this)
});
};
/**
* 从服务器端载入列表,子类实现具体逻辑
*
* @abstract
* @method module:util/cache/abstract._$$CacheListAbstract#__doLoadList
* @param {Object} arg0 - 请求信息
* @property {String} key - 列表标识
* @property {Number} offset - 偏移量
* @property {Number} limit - 数量
* @property {String} data - 请求相关数据
* @property {Function} onload - 列表项载入回调
* @return {Void}
*/
_pro.__doLoadList = _f;
/**
* 从服务器端前向刷新列表,子类实现具体逻辑
*
* @abstract
* @method module:util/cache/abstract._$$CacheListAbstract#__doPullRefresh
* @param {Object} arg0 - 请求信息
* @property {String} key - 列表标识
* @property {String} data - 请求相关数据
* @property {Function} onload - 列表项载入回调
* @return {Void}
*/
_pro.__doPullRefresh = _f;
/**
* 从服务器端载入列表项,子类实现具体逻辑
*
* @abstract
* @method module:util/cache/abstract._$$CacheListAbstract#__doLoadItem
* @param {Object} arg0 - 请求信息
* @property {String} key - 列表标识
* @property {Number} id - 列表项标识
* @property {String} data - 请求相关数据
* @property {Function} onload - 列表项载入回调
* @return {Void}
*/
_pro.__doLoadItem = _f;
/**
* 添加列表项至服务器,子类实现具体逻辑
*
* @abstract
* @method module:util/cache/abstract._$$CacheListAbstract#__doAddItem
* @param {Object} arg0 - 请求信息
* @property {String} key - 列表标识
* @property {Number} id - 列表项标识
* @property {String} data - 请求相关数据
* @property {Function} onload - 列表项载入回调
* @return {Void}
*/
_pro.__doAddItem = _f;
/**
* 从服务器上删除列表项,子类实现具体逻辑
*
* @abstract
* @method module:util/cache/abstract._$$CacheListAbstract#__doDeleteItem
* @param {Object} event - 请求信息
* @property {String} key - 列表标识
* @property {Number} id - 列表项标识
* @property {String} data - 请求相关数据
* @property {Function} onload - 列表项载入回调
* @return {Void}
*/
_pro.__doDeleteItem = _f;
/**
* 更新列表项至服务器,子类实现具体逻辑
*
* @abstract
* @method module:util/cache/abstract._$$CacheListAbstract#__doUpdateItem
* @param {Object} event - 请求信息
* @property {String} key - 列表标识
* @property {Number} id - 列表项标识
* @property {String} data - 请求相关数据
* @property {Function} onload - 列表项载入回调
* @return {Void}
*/
_pro.__doUpdateItem = _f;
if (CMPT){
NEJ.P('nej.ut')._$$AbstractListCache = _p._$$CacheListAbstract;
}
return _p;
});
/*
* ------------------------------------------
* 缓存管理基类实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/cache/cache */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'util/event',
'./storage.js'
],function(NEJ,_k,_u,_t,_j,_p,_o,_f,_r){
var _pro,
_ckey = 'dat-'+(+new Date);
/**
* 缓存对象基类
*
* 脚本举例
* ```javascript
* NEJ.define([
* 'base/klass',
* 'util/ajax/xdr',
* 'util/cache/cache'
* ],function(_k,_j,_t,_p){
* var _pro;
*
* _p._$$CacheCustom = _k._$klass();
* _pro = _p._$$CacheCustom._$extend(_t._$$CacheAbstract);
*
* // 取缓存数据,先从内存中取,没有从服务器上取
* _pro._$getDataInCache = function(_key){
* this.__setDataInCache(_key,_value);
* };
*
* // 取数据
* _pro._$getData = function(_key){
* var _data = this._$getDataInCache(_key);
* // 数据已在缓存中
* if (_data!=null){
* this._$dispatchEvent('ondataload',{
* key:_key
* });
* return;
* }
* // 从服务器端载入数据
* // rkey为请求唯一标识,可以是URL,也可以是某种算法的结果
* var _rkey = this.__doGenReqKey(_key),
* _callback = this._$dispatchEvent._$bind(
* this,'ondataload',{key:_key}
* );
* if (!this.__doQueueRequest(_rkey,_callback)){
* _j._$request({
* onload:function(_data){
* // 缓存数据
* this.__setDataInCache(_key,_data);
* // 触发队列中同请求的回调逻辑
* this.__doCallbackRequest(_rkey);
* }._$bind(this)
* });
* }
* };
*
* return _p;
* });
* ```
*
* 脚本举例
* ```javascript
* NEJ.define([
* '/path/to/custom/cache.js'
* ],function(_p){
* // 使用Cache
* var _cache = _p._$$CacheCustom._$allocate({
* ondataload:function(_event){
* // get data in cache
* var _data = this._$getDataInCache(_event.key);
* // TODO
* }
* });
* // 第一个请求
* _cache._$getData('a');
* // 第二个请求
* _cache._$getData('b');、
* // 不会发请求,直接走缓存
* _cache._$getData('a');
* });
* ```
*
* @class module:util/cache/cache._$$CacheAbstract
* @extends module:util/event._$$EventTarget
*
* @param {Object} config - 配置参数
*/
_p._$$CacheAbstract = _k._$klass();
_pro = _p._$$CacheAbstract._$extend(_t._$$EventTarget);
/**
* 初始化函数
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__init
* @return {Void}
*/
_pro.__init = function(){
this.__super();
this.__cache = this.constructor[_ckey];
if (!this.__cache){
this.__cache = {};
// request loading information
this.__cache[_ckey+'-l'] = {};
this.constructor[_ckey] = this.__cache;
}
};
/**
* 从缓存中取数据
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__getDataInCache
* @param {String} arg0 - 缓存键值
* @return {Variable} 缓存数据
*/
_pro.__getDataInCache = function(_key){
return this.__cache[_key];
};
/**
* 数据存入缓存
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__setDataInCache
* @param {String} arg0 - 缓存键值
* @param {Variable} arg1 - 缓存数据
* @return {Void}
*/
_pro.__setDataInCache = function(_key,_value){
this.__cache[_key] = _value;
};
/**
* 带默认值取本地数据
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__getDataInCacheWithDefault
* @param {String} arg0 - 键值
* @param {Variable} arg1 - 默认值
* @return {Void}
*/
_pro.__getDataInCacheWithDefault = function(_key,_default){
var _data = this.__getDataInCache(_key);
if (_data==null){
_data = _default;
this.__setDataInCache(_key,_data);
}
return _data;
};
/**
* 删除缓存数据,不传键值则清除所有缓存
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__delDataInCache
* @param {String} arg0 - 缓存键值
* @return {Void}
*/
_pro.__delDataInCache = function(_key){
if (_key!=null){
delete this.__cache[_key];
return;
}
_u._$loop(
this.__cache,function(_item,_key){
if (_key!=(_ckey+'-l')){
this.__delDataInCache(_key);
}
},this
);
};
/**
* 从本地存储中删除数据
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__delDataInStorage
* @param {String} arg0 - 存储键值
* @return {String} 存储数据
*/
_pro.__delDataInStorage = function(_key){
return _j._$delDataInStorage(_key);
};
/**
* 从本地存储中取数据
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__getDataInStorage
* @param {String} arg0 - 存储键值
* @return {String} 存储数据
*/
_pro.__getDataInStorage = function(_key){
return _j._$getDataInStorage(_key);
};
/**
* 数据存入本地缓存
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__setDataInStorage
* @param {String} arg0 - 存储键值
* @param {Variable} arg1 - 存储数据
* @return {Void}
*/
_pro.__setDataInStorage = function(_key,_value){
_j._$setDataInStorage(_key,_value);
};
/**
* 带默认值取本地数据
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__getDataLocalWithDefault
* @param {String} arg0 - 键值
* @param {Variable} arg1 - 默认值
* @return {Variable} 数据
*/
_pro.__getDataLocalWithDefault = function(_key,_default){
var _data = this.__getDataLocal(_key);
if (_data==null){
_data = _default;
this.__setDataLocal(_key,_data);
}
return _data;
};
/**
* 取本地数据,检测内存和本地存储
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__getDataLocal
* @param {String} arg0 - 键值
* @return {Variable} 数据
*/
_pro.__getDataLocal = function(_key){
// get from memory
var _data = this.__getDataInCache(_key);
if (_data!=null){
return _data;
}
// get from storage
_data = this.__getDataInStorage(_key);
if (_data!=null){
this.__setDataInCache(_key,_data);
}
return _data;
};
/**
* 存本地数据
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__setDataLocal
* @param {String} arg0 - 键值
* @param {Variable} arg1 - 数据
* @return {Void}
*/
_pro.__setDataLocal = function(_key,_value){
this.__setDataInStorage(_key,_value);
this.__setDataInCache(_key,_value);
};
/**
* 清除本地缓存,不传键值则清除所有缓存
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__delDataLocal
* @param {String} arg0 - 缓存键值
* @return {Void}
*/
_pro.__delDataLocal = function(_key){
if (_key!=null){
delete this.__cache[_key];
_j._$delDataInStorage(_key);
return;
}
_u._$loop(
this.__cache,function(_item,_key){
if (_key!=(_ckey+'-l')){
this.__delDataLocal(_key);
}
},this
);
};
/**
* 清除缓存数据
*
* 脚本举例
* ```javascript
* var _cache = new c._$$CacheAbstract();
* j._$clearDataLocal('name','jack');
* // 清空所有hash值
* j._$clearDataInStorage();
* ```
*
* @method module:util/cache/cache._$$CacheAbstract#_$clearDataLocal
* @return {Void}
*/
_pro._$clearDataLocal = function(){
this.__delDataLocal();
};
/**
* 请求回调
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__doCallbackRequest
* @param {String} arg0 - 请求标识
* @return {Void}
*/
_pro.__doCallbackRequest = function(_key){
var _data = this.__cache[_ckey+'-l'],
_args = _r.slice.call(arguments,1);
_u._$forEach(
_data[_key],function(_callback){
try{
_callback.apply(this,_args);
}catch(ex){
// ignore
if (DEBUG) throw ex;
console.error(ex.message);
console.error(ex.stack);
}
}
);
delete _data[_key];
};
/**
* 锁定请求,同样的请求只发送一次
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__doQueueRequest
* @param {String} arg0 - 请求标识
* @param {Function} arg1 - 请求回调
* @return {Boolean} 是否已存在相同请求
*/
_pro.__doQueueRequest = function(_key,_callback){
_callback = _callback||_f;
var _list = this.__cache[_ckey+'-l'][_key];
if (!_list){
_list = [_callback];
this.__cache[_ckey+'-l'][_key] = _list;
return !1;
}
_list.push(_callback);
return !0;
};
/**
* 检测列表中是否已存在指定片段数据
*
* @protected
* @method module:util/cache/cache._$$CacheAbstract#__hasFragment
* @param {Array} arg0 - 列表
* @param {Number} arg1 - 偏移量
* @param {Number} arg2 - 数量,0表示全列表,默认为0
* @return {Boolean} 是否已经存在
*/
_pro.__hasFragment = function(_list,_offset,_limit){
if (!_list) return !1;
_offset = parseInt(_offset)||0;
_limit = parseInt(_limit)||0;
if (!_limit){
if (!_list.loaded)
return !1;
_limit = _list.length;
}
// length is list total number
if (!!_list.loaded)
_limit = Math.min(_limit,
_list.length-_offset);
for(var i=0;i<_limit;i++)
if (!_list[_offset+i])
return !1;
return !0;
};
if (CMPT){
NEJ.copy(NEJ.P('nej.ut'),_p);
}
return _p;
});
// link to util/cache/abstract for compatible
// use util/cache/abstract for new project
NEJ.define(['./abstract.js'],function(_t){return _t;});
// link to util/cache/list for compatible
// use util/cache/list for new project
NEJ.define(['./list.js'],function(_t){return _t;});
// link to util/cache/share for compatible
// use util/cache/share for new project
NEJ.define(['./share.js'],function(_t){return _t;});
This file has been truncated, but you can view the full file.
/*
* ------------------------------------------
* IndexedDB数据库管理器实现文件
* @version 1.0
* @author genify([email protected])
* ------------------------------------------
*/
/** @module util/cache/database */
NEJ.define([
'base/global',
'base/klass',
'base/util',
'util/event',
'base/chain'
],function(NEJ,_k,_u,_t,_x,_p,_o,_f,_r){
var _pro;
/**
* IndexedDB数据库管理器
*
* 代码举例:
* ```javascript
* NEJ.define([
* 'util/cache/database'
* ],function(_t){
* // 使用控件取数据
* var _db = _t._$$DataBase._$allocate({
* namespace:'music.track'
* });
* _db._$get([1,2,3],{
* onload:function(_result){
* // result ->
* // [{id:1,...},{id:2,...},{id:3,...}]
* }
* });
*
* // 使用API取数据
* _t._$requestByDB({
* namespace:'music.track',
* action:'get',
* param:[1,2,3],
* onload:function(_result){
* // result ->
* // [{id:1,...},{id:2,...},{id:3,...}]
* }
* });
* });
* ```
*
* @class module:util/cache/database._$$DataBase
* @extends module:util/event._$$EventTarget
*
* @param {Object} config - 配置参数
* @property {String} namespace - 名字空间,默认随机生成,格式[DB].[TB],如 music.track
* @property {Number} version - 版本信息,默认使用时间戳作为版本,必须确保在新的namespace下给的version是递增的
* @property {String} key - 标识字段名,默认为id
*/
/**
* 数据库准备完成回调
*
* @event module:util/cache/database._$$DataBase#onready
* @param {Object} event - 数据库信息
* @property {module:util/cache/database._$$DataBase} target - 数据库实例
*/
/**
* 数据库操作失败回调
*
* @event module:util/cache/database._$$DataBase#onerror
* @param {Object} event - 错误信息
* @property {Number} code - 错误代码
* @property {String} message - 错误描述
*/
_p._$$DataBase = _k._$klass();
_pro = _p._$$DataBase._$extend(_t._$$EventTarget);
/**
* 控件重置
*
* @protected
* @method module:util/cache/database._$$DataBase#__reset
* @param {Object} arg0 - 配置参数
* @return {Void}
*/
_pro.__reset = (function(){
var _doUpgrade = function(_event){
//console.log('Upgrade -> '+this.__tbname);
var _db = _event.target.result;
this.__database = _db;
var _index = _u._$indexOf(
_db.objectStoreNames,
this.__tbname
);
if (_index>=0) return;
_db.createObjectStore(
this.__tbname,
{keyPath:this.__key}
);
};
var _doDBOpened = function(_event){
//console.log('Success -> '+this.__tbname);
this.__database = _event.target.result;
this._$dispatchEvent('onready',{target:this});
// flush action queue
_u._$forEach(
this.__queue,function(_handler){
_handler.call(this);
},this
);
delete this.__queue;
};
return function(_options){
this.__super(_options);
var _arr = (_options.namespace||'').split('.'),
_dbname = _arr[0]||('db-'+_u._$uniqueID());
this.__tbname = _arr[1]||('tb-'+_u._$uniqueID());
this.__key = _options.key||'id';
// open database
var _request = indexedDB.open(
_dbname,_options.version||_u._$uniqueID()
);
_request.onsuccess = _doDBOpened._$bind(this);
_request.onupgradeneeded = _doUpgrade._$bind(this);
};
})();
/**
* 控件回收
*
* @protected
* @method module:util/cache/database._$$DataBase#__destroy
* @return {Void}
*/
_pro.__destroy = function(){
this.__super();
delete this.__dbname;
delete this.__tbname;
delete this.__queue;
delete this.__key;
if (!!this.__database){
this.__database.close();
delete this.__database;
}
};
/**
* 判断数据库是否已经准备好
*
* @protected
* @method module:util/cache/database._$$DataBase#__isDBReady
* @return {Boolean} 是否已经准备好
*/
_pro.__isDBReady = function(_method,_args){
if (!this.__database){
if (!this.__queue) this.__queue = [];
var _argc = _r.slice.call(_args,0)||[];
_argc.unshift(this);
this.__queue.push(
_method._$bind.apply(_method,_argc)
);
return !1;
}
return !0;
};
/**
* 取存储操作对象
*
* @protected
* @method module:util/cache/database._$$DataBase#__getTransaction
* @param {Object} arg0 - 配置信息
* @return {IDBObjectStore} 存储操作对象
*/
_pro.__getTransaction = function(_options){
_options = _opti
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment