/*
- @caiquan (396022671.qq.com)
- @version 1.0 / 2015-09-14
- 创建
- @version 2.0 / 2015-11-16
- SLIDER:移动端轮播图
- LOAD:移动端顶部下拉刷新、底部加载更多、左右侧边栏滑动
- @version 3.0 / 2016-1-14
- 使用原型链重写
*/
- 使用原型链重写
(function(){
/*
给构造函数Function的原型添加方法method
Function / Object / String / Array 实质上都是一个函数
是函数就能继承method方法
通过method方法添加框架方法
*/
Function.prototype.method = function(name,fn){
this.prototype[name] = fn;
}
var _O = Object;
var _S = String;
var _A = Array;
// 全局变量$cq,用于外部调用
var _F = new Function();
window.$cq = new _F();
/* element string array 操作 */
_F.method('id' ,_id); // 选取id
_S.method('trim' ,_trim); // 清除string前后空格
_S.method('trimL' ,_trimLeft);
_S.method('trimR' ,_trimRight);
_O.method('text' ,_text); // 输入text纯文本(带html标签用innerHTML)
_O.method('textAppend' ,_textAppend); // 追加text纯文本(带html标签用innerHTML)
_O.method('getIndex' ,_getIndex); // 获取指定对象在数组中的序列号(group中排在第几个)
_O.method('getStyle' ,_getStyle); // 获取样式,不能获取复合样式,如background,只能获取background-color这样的
_O.method('setStyle' ,_setStyle); // 设置行内style
_F.method('htmlCollectionToArr' ,_htmlCollectionToArr); // 将getElementsByTagName(Name)获取到的对象,转换成数组返回
_F.method('removeBlankNode' ,_removeBlankNode); // childNodes获取的对象,删除空文本节点后,数组形式返回
/* event */
_F.method('e' ,_e); // 获取event兼容对象
_F.method('getEvent' ,_getEvent); // 获得event对象
_F.method('getTarget' ,_getTarget); // 获取事件对象
/* 事件侦听 / 取消冒泡 / 阻止默认事件 */
_O.method('aEvent' ,_addEvent); // 添加事件侦听
_O.method('rEvent' ,_removeEvent); // 移除事件侦听
_F.method('cancelBubble' ,_cancelBubble); // 取消冒泡
_F.method('preventDefault' ,_preventDefault); // 取消默认事件
/* 浏览器 */
_F.method('getScrollTop' ,_getScrollTop); // 获取scrollTop
_F.method('getScrollLeft' ,_getScrollLeft); // 获取scrollLeft
_F.method('getBrower' ,_getBrower); // 获取浏览器名称和版本
_F.method('isMobile' ,_isMobile); // 判断是否是移动设备
_O.method('animate' ,_animate); // 动画
/* cookie */
_F.method('getCookie' ,_getCookie); // 获取指定cookie
_F.method('getCookieAll' ,_getCookieAll); // 获取所有cookie
_F.method('setCookie' ,_setCookie); // 设置cookie
_F.method('removeCookie' ,_removeCookie); // 删除cookie
/* AJAX */
_F.method('AJAX' ,_AJAX); //AJAX请求
/* plug */
_F.method('slider' ,_slider); // 轮播图
_F.method('loadMobile' ,_loadMobile); // mobile顶部刷新 + 底部加载更多 + 侧边栏
_F.method('selectCheckbox' ,_selectCheckbox); // 复选框全选/取消全选
_F.method('cb' ,_cb);
_F.method('grade' ,_grade);
_F.method('SLIDBLOCK' ,_SLIDBLOCK); // checkbox滑块(打开/关闭)
_F.method('tabControl' ,_tabControl); // 选项卡切换
/* 类操作 */
_F.method('extend' ,_extend); // 类的继承
_F.method('mixin' ,_mixin); // 类的聚合
_F.method('interfaceAttrImplement' ,_interfaceAttrImplement); // 接口:属性检验法
_F.method('interfaceCreate' ,_interfaceCreate); // 接口:鸭式变形法(新建接口)
_F.method('interfaceEnsuerImpletement' ,_interfaceEnsuerImpletement); // 接口:鸭式变形法(检验实现)
/*
解释:切换选项卡
示例:
DOM:
-
t1
t2
t3
-
m1
m2
m3
调用:
var titleArr = document.getElementsByTagName('h3');
var mainArr = document.getElementsByTagName('div');
cn = 'tSelect';
new $cq.tabControl().start(titleArr,mainArr,cn);
*/
function _tabControl(){
var t,m,c;
this.start = function(titleArr,mainArr,cn){
init(titleArr,mainArr,cn);
bindEvent();
}
function init(titleArr,mainArr,cn){
t = titleArr;
m = mainArr;
c = cn;
}
function bindEvent(){
for (var i = 0; i < t.length; i++) {
_addEvent('click',action,t[i])
};
}
function action(){
var index = _getIndex(t,this);
for (var i = 0; i < t.length; i++) {
if (i==index) {
t[i].className = c;
_setStyle('display:block',m[i]);
}else{
t[i].className = '';
_setStyle('display:none',m[i]);
}
};
}
}
/*
解释:滑块打开/关闭
示例:
DOM:
CSS:
.slidOpen, .slidClose{
line-height: 1.5em;
width: 3em;
position: relative;
padding: 1px;
cursor: pointer;
overflow: hidden;
border-radius: 0.7em;
}
.slidOpen dt, .slidClose dt{
background-color: #fff;
width: 1.5em;
height: 1.5em;
line-height: 1.5em;
text-align: center;
border-radius: 0.7em;
box-shadow: 0em 0em 0.2em #666;
position: relative;
left: 1.5em;
}
.slidOpen{
animation :slidOpenColor 500ms forwards;
-moz-animation :slidOpenColor 500ms forwards;
-webkit-animation :slidOpenColor 500ms forwards;
-o-animation :slidOpenColor 500ms forwards;
}
.slidOpen dt{
animation :slidOpenOffset 500ms forwards ;
-moz-animation :slidOpenOffset 500ms forwards ;
-webkit-animation :slidOpenOffset 500ms forwards ;
-o-animation :slidOpenOffset 500ms forwards ;
}
.slidClose{
animation :slidCloseColor 500ms forwards;
-moz-animation :slidCloseColor 500ms forwards;
-webkit-animation :slidCloseColor 500ms forwards;
-o-animation :slidCloseColor 500ms forwards;
}
.slidClose dt{
animation :slidCloseOffset 500ms forwards ;
-moz-animation :slidCloseOffset 500ms forwards ;
-webkit-animation :slidCloseOffset 500ms forwards ;
-o-animation :slidCloseOffset 500ms forwards ;
}
@keyframes slidOpenColor{
0% {background-color: #ccc}
100%{background-color: #4cd964}
}
@-moz-keyframes slidOpenColor{
0% {background-color: #ccc}
100%{background-color: #4cd964}
}
@-webkit-keyframes slidOpenColor{
0% {background-color: #ccc}
100%{background-color: #4cd964}
}
@-o-keyframes slidOpenColor{
0% {background-color: #ccc}
100%{background-color: #4cd964}
}
@keyframes slidOpenOffset{
0% {left: 0em;}
100%{left: 1.5em;}
}
@-moz-keyframes slidOpenOffset{
0% {left: 0em;}
100%{left: 1.5em;}
}
@-webkit-keyframes slidOpenOffset{
0% {left: 0em;}
100%{left: 1.5em;}
}
@-o-keyframes slidOpenOffset{
0% {left: 0em;}
100%{left: 1.5em;}
}
@keyframes slidCloseColor{
0% {background-color: #4cd964;}
100%{background-color: #ccc;}
}
@-moz-keyframes slidCloseColor{
0% {background-color: #4cd964;}
100%{background-color: #ccc;}
}
@-webkit-keyframes slidCloseColor{
0% {background-color: #4cd964;}
100%{background-color: #ccc;}
}
@-o-keyframes slidCloseColor{
0% {background-color: #4cd964;}
100%{background-color: #ccc;}
}
@keyframes slidCloseOffset{
0% {left: 1.5em;}
100% {left: 0em;}
}
@-moz-keyframes slidCloseOffset{
0% {left: 1.5em;}
100% {left: 0em;}
}
@-webkit-keyframes slidCloseOffset{
0% {left: 1.5em;}
100% {left: 0em;}
}
@-o-keyframes slidCloseOffset{
0% {left: 1.5em;}
100% {left: 0em;}
}
调用:
new $cq.SLIDBLOCK().start();
*/
function _SLIDBLOCK(){
var slidBlocks = [];
var init = function(){
var dl = document.getElementsByTagName('dl');
var className = null;
for (var i = 0; i < dl.length; i++) {
className = dl[i].className;
if (className == 'slidOpen' || className == 'slidClose') {
slidBlocks.push(dl[i]);
};
};
}
var slidActive = function(){
var className = this.className;
if (className == 'slidOpen') { this.className = 'slidClose'; }
else if (className == 'slidClose') { this.className = 'slidOpen';};
this.blur();
this.getElementsByTagName('dt')[0].blur();
}
var bindEvent = function(){
if (slidBlocks.length <=0) { console.log('未获取到滑动块');return; };
for (var i = 0; i < slidBlocks.length; i++) {
_addEvent('click',slidActive,slidBlocks[i]);
};
}
this.start = function(){
init();
bindEvent();
}
}
/*
解释:类似五星☆好评
示例:
DOM:
CSS:
ul{zoom:1;background-color: #f1f1f1;overflow: hidden;}
ul:after{content: '';display: block;height: 0;overflow: hidden;clear: both;}
li{width: 20px;height: 20px;float:left; list-style: none;margin:20px; border-radius: 12px; background-position: center;background-repeat: no-repeat;background-size: auto 100%;}
调用:
var arg = {
tips :['非常差','差','一般','好','非常好'],
iconBg :{bad:'../images/starGray.png',good:'../images/starYellow.png',normal:'../images/star.png'},
iconBox :document.getElementsByTagName('ul')[0],
iconList :document.getElementsByTagName('li'),
tipBox :document.getElementsByTagName('p')[0]
};
new $cq.grade(arg).start();
*/
function _grade(_agr){
var iconBox, // icon 外壳: ul标签
iconList, // icon 列表:li标签集合
iconBg, // icon 图片类型:{bad:'', good:'',normal:''}
iconBgNow, // icon 此时的图片类型
tipBox, // 提示框: p标签
tips, // 提示 ['非常差','差','一般','好','非常好']
dataNum; // 表示高亮的icon数
this.start = function(){
// 初始化
init();
// 绑定事件
bindEvent();
}
function init(){
// 初始化变量,从参数获取值
iconBox = _agr.iconBox;
iconList = _agr.iconList
tipBox = _agr.tipBox
iconBg = _agr.iconBg;
tips = _agr.tips
// 从iconBox获取高亮数
dataNum = iconBox.getAttribute('data-num');
// 初始化icon的颜色和高亮数,输出提示
BgColor(dataNum);
changeColor(dataNum);
Tip(dataNum)
}
// 绑定事件
function bindEvent(){
for (var i = 0; i < iconList.length; i++) {
_addEvent('mouseover',toChange,iconList[i]);
_addEvent('click',toChange,iconList[i])
};
_addEvent('mouseout',toChange,iconBox);
}
// 选择当前icon的颜色/图片
function BgColor(num){
num<2?iconBgNow=iconBg.bad:iconBgNow=iconBg.good;
}
// 改变icon状态
function toChange(){
var event = $cq.getEvent();
var _this = $cq.getTarget(event);
var num = _getIndex(iconList,_this);
BgColor(num);
Tip(num)
switch(event.type){
case 'click' : dataNum = num; iconBox.setAttribute('data-num',dataNum); break;
case 'mouseover' : changeColor(num);break;
case 'mouseout' : if (_this == iconBox) {BgColor(dataNum);Tip(dataNum);changeColor(dataNum);};break;
}
}
// 改变icon颜色/图片
function changeColor(num){
for (var i = 0; i < iconList.length; i++) {
i<=num?iconList[i].style.backgroundImage = 'url('+iconBgNow+')':iconList[i].style.background = 'url('+iconBg.normal+')';
};
}
// 输出提示
function Tip(num){
tipBox.innerHTML = tips[num];
}
}
/*
解释:自定义复选框
示例:
DOM:
CSS:
#cb{display: inline-block;}
#cb input{visibility: hidden;}
调用:
new $cq.cb().start({
id:'cb',
width:'2.32em',
height:'2.32em',
def:'images/cbDef.png',
ok:'images/cbOk.png'
});
*/
function _cb(){
var lab = null, inp = null, args=null,styleBase=null;
this.start = function(arg){
init(arg);
bindEvent();
}
function init(arg){
args = arg;
lab = _id(arg.id);
inp = lab.getElementsByTagName('input')[0];
styleBase = 'width:'+arg.width+';height:'+arg.height+';display: inline-block;';
var sty = styleBase + 'background: url('+arg.def+') no-repeat center center / '+arg.width+' '+arg.height;
_setStyle(sty,lab)
_setStyle('visibility: hidden;',inp)
}
function bindEvent(){
_addEvent('change',changeState,inp);
}
function changeState(){
switch(this.checked){
case true:_setStyle(styleBase + 'background: url('+args.ok+') no-repeat center center / '+args.width+' '+args.height,lab); break;
case false:_setStyle(styleBase + 'background: url('+args.def+') no-repeat center center / '+args.width+' '+args.height,lab); break;
}
}
}
/*
功能: 复选框全选/取消全选
示例:
DOM:
调用:
var list = $cq.id('clist').getElementsByTagName('input');
var btn = $cq.id('btn');
var cb = new $cq.selectCheckbox(list,btn);
cb.start();
备注:_cbList:checkbox列表数组,_cbAll:全选chechbox
*/
function _selectCheckbox(_cbList,_cbAll){
this.start = function(){
init();
bindEvent();
}
var _this = this;
var oInps = _cbList;
var oInpAll = _cbAll;
function init(){
for (var i = 0; i < oInps.length; i++) {
if (!oInps[i].checked) {
oInpAll.checked = false;
break;
}
if (i == oInps.length-1) {
oInpAll.checked = true;
};
};
}
function bindEvent(){
_addEvent('change',cList,oInpAll);
for (var i = 0; i < oInps.length; i++) {
_addEvent('change',cAll,oInps[i])
};
}
function cList(){
var e = $cq.getEvent();
oInpAll.checked?listCheck(true):listCheck(false);
}
function listCheck(_isTrue){
for (var i = 0; i < oInps.length; i++) {
oInps[i].checked = _isTrue;
};
}
function cAll(){
var e = $cq.getEvent();
var o = $cq.getTarget(e);
var check = o.checked;
if (!check) {
oInpAll.checked = false;
}else{
for (var i = 0; i < oInps.length; i++) {
if (!oInps[i].checked) {
oInpAll.checked = false;
break;
};
if (i == oInps.length-1) {
oInpAll.checked = true;
};
};
}
}
}
/*
功能: 顶部刷新 + 底部加载更多 + 侧边栏
示例:
DOM:
正文内容
调用方法:
// 1. 实例化
// 2. 设置参数
// 4. 启动
// 实例化
var page = new $cq.loadMobile();
// 顶部下拉刷新 refreshTop
page.refreshTop.isOpen = true;
page.refreshTop.ele = $cq.id('refreshBar');
page.refreshTop.heightMin = 100;
page.refreshTop.heightMax = 2000;
page.refreshTop.active.openHalf = function(){ page.refreshTop.ele.innerHTML = '外部:下拉刷新!'; };
page.refreshTop.active.openAll = function(){ page.refreshTop.ele.innerHTML = '外部:松开刷新!'; };
page.refreshTop.active.ajaxAndClose = function(){ page.refreshTop.ele.innerHTML = '外部:AJAX请求,完成后隐藏'; };
// 底部加载更多 loadMoreBottom
page.loadMoreBottom.isOpen = true;
page.loadMoreBottom.ele = $cq.id('loadMoreBottom');
page.loadMoreBottom.active.load = function(){ page.loadMoreBottom.ele.innerHTML = '提示正在加载更多,并ajax请求' };
// 左侧边栏
page.subBar.left.isOpen = true;
page.subBar.left.active.open = function(){ alert('左侧边栏打开'); };
page.subBar.left.active.close = function(){ alert('左侧边栏关闭'); };
// 右侧边栏
page.subBar.right.isOpen = true;
page.subBar.right.active.open = function(){ alert('右侧边栏打开'); };
page.subBar.right.active.close = function(){ alert('右侧边栏关闭'); };
// 启动
page.start();
*/
function _loadMobile(){
// 顶部刷新栏
this.refreshTop = {
isOpen :false, // 开启顶部刷新(true开启 / false关闭)
ele :'', // 顶部刷新栏的标签
heightMin :60, // 高度超过60就提示刷新
heightMax :120, // 高度最大120
status :'close', // (不建议重写)默认值close
active :{
controller :function(){}, // (不建议重写)总控制器,判断各状态执行的动作
close :function(){}, // (不建议重写)关闭
openHalf :function(){}, // 打开一半,提示 “下拉可刷新” 时执行的动作
openAll :function(){}, // 打开超过一半,提示 “松手刷新” 时执行的动作
ajaxAndClose :function(){} // 松开后,提示正在加载数据,并ajax请求,完成后调用close关闭
}
};
// 底部加载更多
this.loadMoreBottom = {
isOpen :false, // 开启底部加载更多(true开启 / false关闭)
ele :'', // 底部加载栏标签对象
active :{
load:function(){} // 加载更多,执行的动作,
}
}
// 侧边栏
this.subBar = {
left:{
isOpen:false, // 开启左侧边栏(true开启 / false关闭)
status:'close', // (不建议重写)默认值close
active:{
open:function(){}, // 打开的动作
close:function(){} // 关闭的动作
}
},
right:{
isOpen:false, // 开启右侧边栏(true开启 / false关闭)
status:'close', // (不建议重写)默认值close
active:{
open:function(){}, // 打开的动作
close:function(){} // 关闭的动作
}
}
}
// 坐标
this.pos = { // 坐标
x:{
push :null, // 页面滑到顶部(scrollTop==0)时,记录的坐标
start :null, // touchstart 坐标
move :null, // touchmove 坐标
end :null // touchend 坐标
},
y:{
push :null,
start :null,
move :null,
end :null
}
};
this.start = function(){
init();
bindEvent();
};
var _this = this;
var ev = { // 使用的事件(mouse or touch)
start :'touchstart',
move :'touchmove',
end :'touchend'
};
var w = {
client :0,
scrollLeftStart :0,
scrollLeftMove :0
}
var h = { // 存储高度
client :0, // 客户端屏幕高
body :0, // body的高度
scrollTopStart:0, // touchstart时候的scrollTop
scrollTopMove :0 // touchmove时候的scroll
};
var init = function(){};
// 绑定事件
var bindEvent = function(){
_addEvent(ev.start, pushStart,document.documentElement);
_addEvent(ev.move , pushMove,document.documentElement );
_addEvent(ev.end , pushOver,document.documentElement );
};
/***********************************pushStart - start **********************************/
var pushStart = function(){
var event = $cq.getEvent();
// 获取初始坐标
_this.pos.x.start = event.touches[0].clientX;
_this.pos.y.start = event.touches[0].clientY;
// 获取高度 & 宽度
h.client = document.documentElement.clientHeight;
h.body = document.documentElement.offsetHeight;
h.scrollTopStart = $cq.getScrollTop();
w.client = document.documentElement.clientWidth;
}
/***********************************pushStart - end **********************************/
/***********************************pushMove - start **********************************/
// 页面拉到底部,自动加载更多内容
var pushMove = function(){
var event = $cq.getEvent();
event.preventDefault();
// 获取移动坐标
_this.pos.x.move = event.touches[0].clientX;
_this.pos.y.move = event.touches[0].clientY;
pushMovePageScroll();
pushMoveScrollTop(event);
pushMoveLoadMoreBottom();
};
// 手指滑动时,页面滚动
var pushMovePageScroll = function(){
var tmpScrollTop = parseInt(h.scrollTopStart - (_this.pos.y.move-_this.pos.y.start)*1.5);
var tmpScrollLeft = parseInt(h.scrollLeftStart - (_this.pos.x.move-_this.pos.x.start)*1.5);
window.scrollTo(0,tmpScrollTop);
}
// 手指滑动时,顶部刷新蓝 执行的操作
var pushMoveScrollTop = function(event){
// _this.refreshTop.标记为true,并且记录坐标
h.scrollTopMove = $cq.getScrollTop();
if (_this.refreshTop.status == 'close' && h.scrollTopMove == 0) {
_this.refreshTop.status = 'open';
_this.pos.x.push = event.touches[0].clientX;
_this.pos.y.push = event.touches[0].clientY;
};
// status为true,并且开启顶部刷新功能时,执行顶部刷新栏下拉动作
var yx = {};
yx.y = Math.abs(_this.pos.y.start - _this.pos.y.move);
yx.x = Math.abs(_this.pos.x.start - _this.pos.x.move);
if (_this.refreshTop.status == 'open' && _this.refreshTop.isOpen && yx.y>=yx.x) {
_this.refreshTop.active.controller();
};
}
// 手指滑动时,底部加载更多 执行的操作
var pushMoveLoadMoreBottom = function(){
console.log('s'+h.scrollTopMove)
console.log('b-c'+(h.body-h.client))
if (h.scrollTopMove >= h.body-h.client-10 && _this.loadMoreBottom.isOpen) {
_this.loadMoreBottom.active.load();
};
}
/***********************************pushMove - end **********************************/
/***********************************pushOver - start *********************************/
var pushOver = function(){
var event = $cq.getEvent();
// 获取结束坐标
_this.pos.x.end = event.changedTouches[0].clientX;
_this.pos.y.end = event.changedTouches[0].clientY;
pushOverRefreshTop();
pushOverSubBar();
};
// 松手后,判断顶部刷新栏需要执行的动作
var pushOverRefreshTop = function(){
// 关闭状态,当scrollTop为0的时候,设置status
if (_this.refreshTop.status == 'open') { _this.refreshTop.status = 'close'; };
// 开启顶部刷新功能时,松手后执行顶部刷新请求
if (_this.refreshTop.isOpen) {
var loadBarHeight = parseInt(_getStyle('height',_this.refreshTop.ele));
if (loadBarHeight<_this.refreshTop.heightMin) {
_this.refreshTop.active.close();
}else{
_this.refreshTop.active.ajaxAndClose()
}
};
}
// 松手后,判断侧边栏需要执行的动作
var pushOverSubBar = function(){
// 手指滑动超过屏幕 1/3 ,则执行
var levelMove = _this.pos.x.end - _this.pos.x.start;
if (levelMove > w.client/3) {
if (_this.subBar.left.isOpen && _this.subBar.left.status == 'close') {
_this.subBar.left.active.open();
}else if (_this.subBar.right.isOpen) {
_this.subBar.right.active.close();
};
}
if (-1*levelMove > w.client/3) {
if (_this.subBar.right.isOpen && _this.subBar.right.status == 'close') {
_this.subBar.right.active.open();
}else if (_this.subBar.left.isOpen) {
_this.subBar.left.active.close();
};
};
}
/***********************************pushOver - end **********************************/
/****************************顶部刷新栏 在各个状态执行的动作 start*******************/
this.refreshTop.active.controller = function(){
var loadBarHeight = _this.pos.y.move - _this.pos.y.push;
_setStyle('height:'+loadBarHeight+'px', _this.refreshTop.ele);
if (loadBarHeight<_this.refreshTop.heightMin) {
_this.refreshTop.active.openHalf();
}else if (loadBarHeight<_this.refreshTop.heightMax){
_this.refreshTop.active.openAll();
}else{
_setStyle('height:'+_this.refreshTop.heightMax+'px', _this.refreshTop.ele);
};
};
// 刷新栏拉开,提示继续下拉可以刷新
// 刷新栏拉开,提示松开就可以刷新
// 刷新栏关闭
// 刷新栏松手后的操作:AJAX请求,完成后关闭刷新栏
this.refreshTop.active.openHalf = function(){ _this.refreshTop.ele.innerHTML = '下拉刷新!'; }
this.refreshTop.active.openAll = function(){ _this.refreshTop.ele.innerHTML = '松开刷新!'; }
this.refreshTop.active.close = function(){ _setStyle('height:0',_this.refreshTop.ele); }
this.refreshTop.active.ajaxAndClose = function(){ _this.refreshTop.ele.innerHTML = 'AJAX请求,完成后隐藏'; /*模拟ajax请求的延时*/ setTimeout(function(){ _this.refreshTop.active.close(); },1000); }
/****************************顶部刷新栏 在各个状态执行的动作 end *******************/
/****************************底部加载更多 在各个状态执行的动作 start ***************/
// 执行底部加载更多
this.loadMoreBottom.active.load = function(){ _this.loadMoreBottom.ele.innerHTML = '正在加载更多。。。';/*模拟ajax请求的延时*/ setTimeout(function(){ _this.loadMoreBottom.ele.innerHTML = '上拉加载';},1000);}
/****************************底部加载更多 在各个状态执行的动作 end *****************/
/*******************************侧边栏 在各个状态执行的动作 start ******************/
this.subBar.left.active.open = function(){ alert('左侧边栏打开'); }
this.subBar.left.active.close = function(){ alert('左侧边栏关闭'); }
this.subBar.right.active.open = function(){ alert('右侧边栏打开'); }
this.subBar.right.active.close = function(){ alert('右侧边栏关闭'); }
/*******************************侧边栏 在各个状态执行的动作 end ********************/
}
/*
功能: 轮播图
示例:
DOM:
CSS:
调用:
new $cq.slider('sliderID').start();
*/
function _slider(_sliderId){
var id = null; // 幻灯片ID
var ele = { // 各种对象
sliderBox :null, // 幻灯片盒子
ul :null,
lis :null,
dotP :null, // 点的外壳
dotIs :null // 每个店
}
var posX = { // 手指触发的 X 坐标
start :0,
move :0,
end :0
}
var mark = 'mark'; // 当前显示图片的标记 data-mark='mark'
var clientWidth = 0; // 页面宽度
var speed = 20; // 滑动速度(1s移动多少像素,值为屏幕宽度的倍数)
var intervalTime = 2000; // 滚动隔间时间(单位:ms)
var intervalAuto = null; // 自动滚动
//入口
this.start = function(){
init(); // 初始化
bindEvent(); // 绑定事件
autoSlid(0); // 自动播放开始
};
// 初始化
var init = function(){
clientWidth = document.documentElement.clientWidth;
speed *= clientWidth; // 1s内移动的距离
id = _sliderId; // 从参数获取id
printDot(); // 向页面输出点
getElement(); // 获取元素
setLiWidth(); // 设置li的宽度,img宽度 == li.width
ele.lis[0].setAttribute('data-mark','mark');// 将第一个li标记成当前显示项
}
// 输出点(数量跟li图片的数量一样)
var printDot = function() {
var dotP = document.createElement('p');
var dotI = null;
var num = $cq.id(id).getElementsByTagName('li').length;
for (var i = 0; i < num; i++) {
dotI = document.createElement('i');
if (i == 0) {
dotI.className = 'selectI';
};
dotP.appendChild(dotI);
};
$cq.id(id).appendChild(dotP);
}
// 获取元素,存入ele
var getElement = function(){
ele.sliderBox = $cq.id(id);
ele.ul = ele.sliderBox.getElementsByTagName('ul')[0];
ele.lis = ele.ul.getElementsByTagName('li');
ele.dotP = ele.sliderBox.getElementsByTagName('p')[0];
ele.dotIs = ele.dotP.getElementsByTagName('i');
}
// 设置li的宽度,img宽度 == li.width
var setLiWidth = function() {
for (var i = 0; i < ele.lis.length; i++) {
_setStyle( 'width:' + clientWidth + 'px',ele.lis[i]);
};
}
// 获取当前图片的序列号
var getIndex = function() {
for (var i = 0; i < ele.lis.length; i++) {
if (ele.lis[i].getAttribute('data-mark') == mark) {
return i;
};
};
}
//绑定事件
var bindEvent = function(){
for (var i = 0; i < ele.lis.length; i++) {
_addEvent( 'touchstart',function(){ slidActivePos('start');},ele.lis[i]);
_addEvent( 'touchmove' ,function(){ slidActivePos('move' );},ele.lis[i]);
_addEvent( 'touchend' ,function(){ slidActivePos('end' );},ele.lis[i]);
_addEvent('click' ,dotClickActive,ele.dotIs[i]);
};
}
// 点击圆点的动作
var dotClickActive = function() {
var event = $cq.getEvent();
var _this = _getTarget(event);
_this.setAttribute('data-mark', mark);
for (var i = 0; i < ele.dotIs.length; i++) {
if (ele.dotIs[i].getAttribute('data-mark') == mark) {
slidActive(i);
break;
};
};
_this.setAttribute('data-mark', '')
}
// 手指滑动时触发的事件
var slidActivePos = function(touchName) {
event = $cq.getEvent();
switch (touchName) {
case 'start':
// 设置起始坐标
console.log('event.touches[0]')
posX.start = event.touches[0].clientX;
break;
case 'move':
event.preventDefault();
//设置移动时的坐标
posX.move = event.touches[0].clientX;
break;
case 'end':
posX.end = event.changedTouches[0].clientX;
// 当前显示的图片序列号
var showNum = getIndex();
// distance 手指划过的距离
var distance = posX.end - posX.start;
// 当距离大于屏幕 1/6 时,进行切换,否则回复原状
if (distance > (clientWidth / 6) && showNum > 0) {
slidActive(--showNum);
} else if ((-1 * distance) > (clientWidth / 6) && showNum < (ele.lis.length - 1)) {
slidActive(++showNum);
} else {
slidActive(showNum);
}
break;
}
}
// 滑动:显示_showNum指向的图片
var slidActive = function(_showNum){
// 禁止自动播放,等手动播放结束后,再重新开启
clearInterval(intervalAuto);
// 滑动的时候,显示影响圆点,并标记最新显示li的mark
for (var i = 0; i < ele.lis.length; i++) {
if (i == _showNum) {
ele.dotIs[_showNum].className = 'selectI';
ele.lis[_showNum].setAttribute('data-mark', mark);
} else {
ele.dotIs[i].className = '';
ele.lis[i].setAttribute('data-mark', '');
}
};
// 滑动图片
var leftNew = -1*clientWidth*_showNum;
var leftOld = parseInt(_getStyle('left',ele.ul));
var leftNow = leftOld;
if (leftNew < leftOld) {
if (speed > 0) {
speed *= -1;
};
var interval1 = setInterval(function() {
leftNow += Math.round(speed / 1000);
if (leftNow > leftNew) {
_setStyle( 'left:' + leftNow + 'px',ele.ul);
} else if (leftNow <= leftNew && leftNow > leftNew + speed / 1000) {
_setStyle( 'left:' + leftNew + 'px',ele.ul);
} else {
clearInterval(interval1);
}
}, 1)
} else if (leftNew > leftOld) {
if (speed < 0) {
speed *= -1;
};
var interval2 = setInterval(function() {
leftNow += Math.round(speed / 1000);
if (leftNow < leftNew) {
_setStyle( 'left:' + leftNow + 'px',ele.ul);
} else if (leftNow >= leftNew && leftNow < leftNew + speed / 1000) {
_setStyle( 'left:' + leftNew + 'px',ele.ul);
} else {
clearInterval(interval2);
}
}, 1)
};
// 恢复自动播放
autoSlid(_showNum);
}
// 自动播放
var autoSlid = function(_autoNum) {
var autoNum = _autoNum;
intervalAuto = setInterval(function() {
if (autoNum >= ele.lis.length - 1) {
autoNum = 0;
} else {
autoNum++;
}
slidActive(autoNum);
}, intervalTime)
};
}
/*
功能:接口:鸭式变形法
原理:用$cq.interfaceCreate创建带 接口名 和 方法名数组 的接口
在接口实现类中调用$cq.interfaceEnsuerImpletement,
ensureImpletement会将接口中的方法,匹配接口实现类中的方法
如果接口中的方法,全部匹配到了,就说明已全部实现
示例:
// 创建接口
var inter1 = new $cq.interfaceCreate('inter1',['add1','remove1'])
// 实现接口类
function imp(){
this.add1 = function(){ console.log('sdf')}
this.remove1 = function(){ console.log('123')}
// 检查接口中的方法是否都已经实现
$cq.interfaceEnsureImpletement(this,inter1);
}
// 实例化调用
var d1 = new imp();
d1.add1();
*/
function _interfaceCreate(InterfaceName,InterfaceMethods){
if (arguments.length != 2 ) { throw new Error('创建接口,必须有2个参数(接口名,接口方法array)');};
this.name = InterfaceName;
this.methods = [];
for (var i = 0; i < InterfaceMethods.length; i++) {
if ((typeof InterfaceMethods[i]).toLowerCase() == 'string') {
this.methods.push(InterfaceMethods[i])
}else{
throw new Error('创建接口时,第二个参数为接口方法的数组,每个成员必须是string类型');
}
};
}
function _interfaceEnsuerImpletement(ImpletementInterfaceObj){
if (arguments.length<2) { console.log('ensureInterfaceImpletement()至少传2个及以上的参数:第一个是实现接口的类,其他是需要实现的接口'); };
for (var i = 1; i < arguments.length; i++) {
var thisInterface = arguments[i];
if (thisInterface.constructor != _interfaceCreate) { throw new Error('接口必须由CreateInterface实例化创建'); };
for(var j = 0; j < thisInterface.methods.length; j++){
var methodName = thisInterface.methods[j];
if (!ImpletementInterfaceObj[methodName] || typeof ImpletementInterfaceObj[methodName] != 'function') {
throw new Error(thisInterface.name+' 内的 '+methodName+' 方法没有实现');
};
}
};
}
/*
解释:接口:属性检验法
原理:在接口类中,定义interfaceImplement属性
检查接口是否已经实现(未实现return false,否则true)
示例:
// 定义接口
// interface PersonDao(){
// function add(){}
// function remove(){}
// function find(){}
// }
// 实现接口类
function PersonDao(){
this.interfaceImplement = ['add','remove'];
};
PersonDao.prototype.add = function(){}
PersonDao.prototype.remove = function(){}
// 实例化类
var Tom = new PersonDao();
// 检查PersonDao是否已经实现'add','remove'等接口
var result = $cq.interfaceAttrImplement(Tom,'add','remove',……);
if(result){
Tom.add();
}else{
throw new Error('接口未实现');
}
*/
function _interfaceAttrImplement(Obj){
for (var i = 1; i < arguments.length; i++) {
var interfaceName = arguments[i];
var interfaceFound = false;
var interfaceList = Obj.interfaceImplement;
for (var j = 0; j < interfaceList.length; j++) {
if (interfaceName == interfaceList[j]) {
interfaceFound = true;
};
};
};
if (!interfaceFound) {
return false;
}else{
return true;
}
}
/*
功能:聚合类(将givingClass中的属性和方法,如果receivingClass没有,则加到receivingClass.prototype中)
示例:
function PERSON(){
this.name = 'Tom';
this.speek = 'OK';
}
function AUTHOR(){
this.name = 'Jim';
this.book = 'books';
}
$cq.mixin(AUTHOR,PERSON);
*/
function _mixin(receivingClass, givingClass){
var givingObj = null;
if (typeof givingClass == 'function') {
givingObj = new givingClass();
}else if (typeof givingClass == 'object') {
givingObj = givingClass;
}else{
console.log('参数givingClass必须是对象{}或函数function')
}
var status = true;
for(gKey in givingObj){
for(rKey in receivingClass.prototype){
if (gKey == rKey) { status = false };
}
status?receivingClass.prototype[gKey] = givingObj[gKey]:status = true;
}
}
/*
功能:类的继承
示例:
teacher 继承 person
function person(name){
this.name = name;
}
function teacher(name,course){
// 调用父类并传参,将父类this指向teacher的实例,
teacher.superClass.constructor.call(this,name);
this.course = course;
}
// 实现继承
$cq.extend(teacher,person);
// 实例化
var t1 = new teacher('Tom','English');
console.log(t1.name) === 'Tom';
console.log(t1.course) === 'English'
*/
function _extend(subClass,superClass){
function F(){}
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
subClass.superClass = superClass.prototype;
// 如果父类的原型类是Object,那么把构造函数级别降下来
if (superClass.prototype.constructor == Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
};
}
/*
功能:动画
示例:
1. ele.animate('left',500,15,fn1);
2. function fn1(){ ele.animate('height',200,5,fn1)}
参数:
this: 需要改变的对象
_attr:需要改变的属性
_speed:改变的速度(int)
_target:目标值(int)
_callBack:执行完成后,可以触发的动作(可选)
*/
function _animate( _attr, _target, _speed, _callBack, _this) {
_this = _this || this;
_speed = parseInt(_getStyle(_attr,_this)) < _target ? _speed : -_speed;
clearInterval(_this.timer);
_this.timer = setInterval(function() {
var speed = parseInt(_getStyle( _attr,_this)) + _speed;
if (speed > _target && _speed > 0 || speed < _target && _speed < 0) {
speed = _target;
}
_this.style[_attr] = speed + 'px';
if (speed == _target) {
clearInterval(_this.timer);
_callBack && _callBack();
}
}, 30);
}
/*
功能:获取scrollTop / scrollLeft
*/
function _getScrollTop(){
return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
}
function _getScrollLeft(){
return document.documentElement.scrollLeft || window.pageXOffset || document.body.scrollLeft;
}
/*
功能:childNodes获取的对象,删除空文本节点后,数组形式返回
*/
function _removeBlankNode(_child){
var child = [];
for (var i = 0; i < _child.length; i++) {
child.push(_child[i]);
};
for (var i = 0; i < child.length; i++) {
if (child[i].nodeType == 3 && /^\s+$/gi.test(child[i].textContent)) {
child.splice(i,1)
};
};
return child;
}
/*
功能:将getElementsByTagName(Name)获取到的对象,转换成数组返回
*/
function _htmlCollectionToArr(_htmlCollection){
var arr = [];
for (var i = 0; i < _htmlCollection.length; i++) {
arr.push(_htmlCollection[i]);
};
return arr;
}
/*
功能:判断是否是移动设备
返回:是移动设备返回true, 否就返回false
*/
function _isMobile() {
return (navigator.userAgent.match(/Android/i) || navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPod') != -1 || navigator.userAgent.indexOf('iPad') != -1) ? true : false;
}
/*
功能:AJAX
示例:
1. var temp = new $cq.AJAX('json'); 如果返回json,则参数里写json
2. temp.get(url, before, after, true);
temp.post(url, before, after, true, _params, _paramsType);
备注:
before/after为请求前后要执行的函数
实例化时,参数代表返回数据类型:返回字符串则不用传参,返回json,传‘json’
*/
function _AJAX(_type) {
/*
ajax = {
type : 返回的数据格式,由实例化AJAX的时候传入,
xhr : XMLHttpRequest对象,
versions : IE的XMHttpRequest的版本分类数组,
after : 请求完成后执行的操作
str : 返回到值
}
*/
var ajax = {};
ajax.type = _type;
// 获取XMLHttpRequest对象
ajax.getXhr = function() {
var http;
try{
http = new XMLHttpRequest();
// 将获取getXhr方法变成直接返回对象,以后请求就不需要判断
getXhr = function(){
return new XMLHttpRequest();
}
}catch(e){
var msxml = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML.XMLHTTP.3.0', 'MSXML.XMLHTTP'];
for (var i = 0; i < msxml.length; i++) {
try{
http = new ActiveXObject(msxml[i]);
// 将获取getXhr方法变成直接返回对象,以后请求就不需要判断
getXhr = function(){
return new ActiveXObject(msxml[i]);
};
break;
}catch(e){}
};
}
ajax.xhr = http;
}
// get请求
this.get = function(_url, _before, _after, _asyn) {
ajax.after = _after;
ajax.getXhr();
if (ajax.xhr) {
try {
_before()
} catch (e) {}
ajax.xhr.open("GET", _url, _asyn);
if (ajax.after) {
ajax.xhr.onreadystatechange = ajax.doAfter;
};
ajax.xhr.send();
};
}
// post请求:自动从form中获取name和value,组成url参数
// _paramsType:如果传入的_params为form的id,就传入'formId';否则不传
this.post = function(_url, _before, _after, _asyn, _params, _paramsType) {
ajax.getXhr();
ajax.after = _after;
if (ajax.xhr) {
try {
_before();
} catch (e) {};
ajax.xhr.open("POST", _url, _asyn);
ajax.xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
if (ajax.after) {
ajax.xhr.onreadystatechange = ajax.doAfter;
};
if (_paramsType == 'formId') {
ajax.urlParameter = ajax.getUrlParameter(_params);
}else{
ajax.urlParameter = _params;
}
ajax.xhr.send(ajax.urlParameter);
};
}/*
// post请求:手动传入url参数
this.postUrl = function(_url, _before, _after, _asyn, _urlParameter) {
ajax.getXhr();
ajax.after = _after;
if (ajax.xhr) {
try {
_before();
} catch (e) {};
ajax.xhr.open("POST", _url, _asyn);
ajax.xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
if (ajax.after) {
ajax.xhr.onreadystatechange = ajax.doAfter;
};
ajax.xhr.send(_urlParameter);
};
}*/
// 请求成功后执行的操作
ajax.doAfter = function() {
if (ajax.xhr.readyState == 4 && ajax.xhr.status == 200) {
if (ajax.type == 'json') {
ajax.str = eval("(" + ajax.xhr.responseText + ")");
} else {
ajax.str = ajax.xhr.responseText;
}
ajax.after(ajax.str);
};
}
// 获取表单中所有key和val,返回: key1=val1&key2=val2&……
ajax.getUrlParameter = function(_formID) {
var urlParameter = '';
var inputs = document.getElementById(_formID).getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
if (i == 0) {
urlParameter = inputs[i].name + '=' + inputs[i].value;
} else {
urlParameter += '&' + inputs[i].name + '=' + inputs[i].value;
}
};
return urlParameter;
}
}
/*
功能:cookie:获取 / 获取全部 / 设置 / 删除
*/
function _getCookie(key) {
var arrStr = document.cookie.split('; ');
for (var i = 0; i < arrStr.length; i++) {
var temp = arrStr[i].split('=');
if (temp[0] == key) {
return unescape(temp[1]);
}
}
}
function _getCookieAll() {
var cookies = {};
console.log(cookies)
var arr = document.cookie.split('; ');
if (arr.length <= 0) alert('没有cookie!');
else {
for (var i = 0; i < arr.length; i++) {
var keyval = arr[i].split('=');
var key = keyval[0];
var val = unescape(keyval[1]);
cookies[key] = val;
}
}
return cookies;
}
function _setCookie(key, val, h) {
var str = key + '=' + escape(val);
if (h > 0) {
var date = new Date();
date.setTime(date.getTime() + h * 3600 * 1000);
str += ";expires=" + date.toGMTString();
}
document.cookie = str;
}
function _removeCookie(key) {
var date = new Date();
date.setTime(-1000);
var str = key + '=a; expires=' + date.toGMTString();
document.cookie = str;
}
/*
功能:取消默认事件
*/
function _preventDefault(e) {
if (e && e.preventDefault) {
e.preventDefault();
} else {
window.event.returnValue = false;
}
}
/*
功能:取消冒泡
*/
function _cancelBubble(e) {
e.stopPropagation ? (e.stopPropagation()) : (e.cancelBubble);
}
/*
功能:设置行内style
*/
function _setStyle(attr,_this) {
_this = _this || this;
// console.log(_this);
typeof(window.getComputedStyle) != 'undefined'?_this.setAttribute('style', attr):_this.style.cssText =_attr;
}
/*
功能:获取样式,不能获取复合样式,如background,只能获取background-color这样的
示例:div.getStyle('background-color');
备注:获取行内style,使用div.style.cssText
*/
function _getStyle(attr,_this) {
_this = _this || this;
var styleInfo = window.getComputedStyle ? window.getComputedStyle(_this, "") : _this.currentStyle;
return styleInfo[attr];
}
/*
功能:获取浏览器名称和版本
备注:return {all='',name='',version=''}
*/
function _getBrower() {
var browers = {};
browers.all = navigator.userAgent.toLowerCase();
if (browers.all.match(/firefox\/\d+/)) {
var browersNameVersion = browers.all.match(/firefox\/\d+/)[0].split('/');
browers.name = browersNameVersion[0];
browers.version = browersNameVersion[1];
} else if (browers.all.match(/msie \d+/)) {
var browersNameVersion = browers.all.match(/msie \d+/)[0].split(' ');
browers.name = browersNameVersion[0];
browers.version = browersNameVersion[1];
} else if (browers.all.match(/chrome\/\d+/)) {
var browersNameVersion = browers.all.match(/chrome\/\d+/)[0].split('/');
browers.name = browersNameVersion[0];
browers.version = browersNameVersion[1];
} else if (browers.all.match(/safari\/\d+/)) {
var browersNameVersion = browers.all.match(/safari\/\d+/)[0].split('/');
browers.name = browersNameVersion[0];
browers.version = browersNameVersion[1];
} else {
console.log('未识别的浏览器');
}
return browers;
}
/*
功能:获取指定对象在数组中的序列号(group中排在第几个)
示例:li.index(liArr);
参数:liArr为数组,li为数组中的一个对象
备注:
*/
function _getIndex(_group, _this){
_this = _this || this;
_this.setAttribute('data-indexmark','mark');
for (var i = 0; i < _group.length; i++) {
if (_group[i].getAttribute('data-indexmark') == 'mark') {
_group[i].setAttribute('data-indexmark','');
return i;
};
};
};
/*
功能:获取事件对象
*/
function _getTarget(e) {
return e.target || e.srcElement;
}
/*
功能:获得event对象
*/
function _getEvent(){
return window.event || arguments.callee.caller.arguments[0];
}
/*
功能:获取event兼容对象
*/
function _e(e){
return window.event || e;
}
/*
功能:选择id元素
*/
function _id(idName){
return document.getElementById(idName);
}
/*
功能:选择元素(id/class/tagName,first/last/eq)
执行:
示例:$cq.ele('#idname .className tagName, .className');
参数:
备注:
*/
function _ele(selector){
/*
var eles = [];
var eleBlocks = selector.split(',');
eleBlocks = delSpace(eleBlocks);
console.log('eleBlocks:↓')
console.log(eleBlocks)
for (var i = 0; i < eleBlocks.length; i++) {
var eleLine= eleBlocks[i].split(/\s+/);
console.log('i'+i+'->'+eleLine);
var one = document;
for(var j = 0; j'+eleLine[j])
var keyName;
switch(eleLine[j].charAt(0)){
case '#':
keyName = getKeyName(eleLine[j]);
one = one.getElementById(keyName);
break;
case '.':
keyName = getKeyName(eleLine[j]);
if (isGetPart(keyName)) {
var keyNameArr = keyName.split(':');
.cn:eq(3)
.cn:first
.cn:last
}else{
// div:eq(2)
// div:first
// div:last