mirror of https://github.com/helloxz/onenav.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
418 lines
11 KiB
418 lines
11 KiB
|
|
/*! lay 基础 DOM 操作 | MIT Licensed */ |
|
|
|
;!function(window){ //gulp build: lay-header |
|
"use strict"; |
|
|
|
var MOD_NAME = 'lay' //模块名 |
|
,document = window.document |
|
|
|
//DOM查找 |
|
,lay = function(selector){ |
|
return new LAY(selector); |
|
} |
|
|
|
//DOM构造器 |
|
,LAY = function(selector){ |
|
var index = 0 |
|
,nativeDOM = typeof selector === 'object' ? [selector] : ( |
|
this.selector = selector |
|
,document.querySelectorAll(selector || null) |
|
); |
|
for(; index < nativeDOM.length; index++){ |
|
this.push(nativeDOM[index]); |
|
} |
|
}; |
|
|
|
/* |
|
lay 对象操作 |
|
*/ |
|
|
|
LAY.prototype = []; |
|
LAY.prototype.constructor = LAY; |
|
|
|
//普通对象深度扩展 |
|
lay.extend = function(){ |
|
var ai = 1, args = arguments |
|
,clone = function(target, obj){ |
|
target = target || (layui._typeof(obj) === 'array' ? [] : {}); //目标对象 |
|
for(var i in obj){ |
|
//如果值为普通对象,则进入递归,继续深度合并 |
|
target[i] = (obj[i] && obj[i].constructor === Object) |
|
? clone(target[i], obj[i]) |
|
: obj[i]; |
|
} |
|
return target; |
|
} |
|
|
|
args[0] = typeof args[0] === 'object' ? args[0] : {}; |
|
|
|
for(; ai < args.length; ai++){ |
|
if(typeof args[ai] === 'object'){ |
|
clone(args[0], args[ai]); |
|
} |
|
} |
|
return args[0]; |
|
}; |
|
|
|
//lay 模块版本 |
|
lay.v = '1.0.8'; |
|
|
|
//ie版本 |
|
lay.ie = function(){ |
|
var agent = navigator.userAgent.toLowerCase(); |
|
return (!!window.ActiveXObject || "ActiveXObject" in window) ? ( |
|
(agent.match(/msie\s(\d+)/) || [])[1] || '11' //由于 ie11 并没有 msie 的标识 |
|
) : false; |
|
}(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
* 获取 layui 常见方法,以便用于组件单独版 |
|
*/ |
|
|
|
lay.layui = layui || {}; |
|
lay.getPath = layui.cache.dir; //获取当前 JS 所在目录 |
|
lay.stope = layui.stope; //中止冒泡 |
|
lay.each = function(){ //遍历 |
|
layui.each.apply(layui, arguments); |
|
return this; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
//数字前置补零 |
|
lay.digit = function(num, length, end){ |
|
var str = ''; |
|
num = String(num); |
|
length = length || 2; |
|
for(var i = num.length; i < length; i++){ |
|
str += '0'; |
|
} |
|
return num < Math.pow(10, length) ? str + (num|0) : num; |
|
}; |
|
|
|
//创建元素 |
|
lay.elem = function(elemName, attr){ |
|
var elem = document.createElement(elemName); |
|
lay.each(attr || {}, function(key, value){ |
|
elem.setAttribute(key, value); |
|
}); |
|
return elem; |
|
}; |
|
|
|
//当前页面是否存在滚动条 |
|
lay.hasScrollbar = function(){ |
|
return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight); |
|
}; |
|
|
|
//元素定位 |
|
lay.position = function(elem, elemView, obj){ |
|
if(!elemView) return; |
|
obj = obj || {}; |
|
|
|
//如果绑定的是 document 或 body 元素,则直接获取鼠标坐标 |
|
if(elem === document || elem === lay('body')[0]){ |
|
obj.clickType = 'right'; |
|
} |
|
|
|
//绑定绑定元素的坐标 |
|
var rect = obj.clickType === 'right' ? function(){ |
|
var e = obj.e || window.event || {}; |
|
return { |
|
left: e.clientX |
|
,top: e.clientY |
|
,right: e.clientX |
|
,bottom: e.clientY |
|
} |
|
}() : elem.getBoundingClientRect() |
|
,elemWidth = elemView.offsetWidth //控件的宽度 |
|
,elemHeight = elemView.offsetHeight //控件的高度 |
|
|
|
//滚动条高度 |
|
,scrollArea = function(type){ |
|
type = type ? 'scrollLeft' : 'scrollTop'; |
|
return document.body[type] | document.documentElement[type]; |
|
} |
|
|
|
//窗口宽高 |
|
,winArea = function(type){ |
|
return document.documentElement[type ? 'clientWidth' : 'clientHeight'] |
|
}, margin = 5, left = rect.left, top = rect.bottom; |
|
|
|
//相对元素居中 |
|
if(obj.align === 'center'){ |
|
left = left - (elemWidth - elem.offsetWidth)/2; |
|
} else if(obj.align === 'right'){ |
|
left = left - elemWidth + elem.offsetWidth; |
|
} |
|
|
|
//判断右侧是否超出边界 |
|
if(left + elemWidth + margin > winArea('width')){ |
|
left = winArea('width') - elemWidth - margin; //如果超出右侧,则将面板向右靠齐 |
|
} |
|
//左侧是否超出边界 |
|
if(left < margin) left = margin; |
|
|
|
//判断底部和顶部是否超出边界 |
|
if(top + elemHeight + margin > winArea()){ |
|
//优先顶部是否有足够区域显示完全 |
|
if(rect.top > elemHeight + margin){ |
|
top = rect.top - elemHeight - margin*2; //顶部有足够的区域显示 |
|
} else { |
|
//如果面板是鼠标右键弹出,且顶部没有足够区域显示,则将面板向底部靠齐 |
|
if(obj.clickType === 'right'){ |
|
top = winArea() - elemHeight - margin*2; |
|
if(top < 0) top = 0; //不能溢出窗口顶部 |
|
} |
|
} |
|
} |
|
|
|
//定位类型 |
|
var position = obj.position; |
|
if(position) elemView.style.position = position; |
|
|
|
//设置坐标 |
|
elemView.style.left = left + (position === 'fixed' ? 0 : scrollArea(1)) + 'px'; |
|
elemView.style.top = top + (position === 'fixed' ? 0 : scrollArea()) + 'px'; |
|
|
|
//防止页面无滚动条时,又因为弹出面板而出现滚动条导致的坐标计算偏差 |
|
if(!lay.hasScrollbar()){ |
|
var rect1 = elemView.getBoundingClientRect(); |
|
//如果弹出面板的溢出窗口底部,则表示将出现滚动条,此时需要重新计算坐标 |
|
if(!obj.SYSTEM_RELOAD && (rect1.bottom + margin) > winArea()){ |
|
obj.SYSTEM_RELOAD = true; |
|
setTimeout(function(){ |
|
lay.position(elem, elemView, obj); |
|
}, 50); |
|
} |
|
} |
|
}; |
|
|
|
//获取元素上的参数配置上 |
|
lay.options = function(elem, attr){ |
|
var othis = lay(elem) |
|
,attrName = attr || 'lay-options'; |
|
try { |
|
return new Function('return '+ (othis.attr(attrName) || '{}'))(); |
|
} catch(ev) { |
|
hint.error('parseerror:'+ ev, 'error'); |
|
return {}; |
|
} |
|
}; |
|
|
|
//元素是否属于顶级元素(document 或 body) |
|
lay.isTopElem = function(elem){ |
|
var topElems = [document, lay('body')[0]] |
|
,matched = false; |
|
lay.each(topElems, function(index, item){ |
|
if(item === elem){ |
|
return matched = true |
|
} |
|
}); |
|
return matched; |
|
}; |
|
|
|
//追加字符 |
|
LAY.addStr = function(str, new_str){ |
|
str = str.replace(/\s+/, ' '); |
|
new_str = new_str.replace(/\s+/, ' ').split(' '); |
|
lay.each(new_str, function(ii, item){ |
|
if(!new RegExp('\\b'+ item + '\\b').test(str)){ |
|
str = str + ' ' + item; |
|
} |
|
}); |
|
return str.replace(/^\s|\s$/, ''); |
|
}; |
|
|
|
//移除值 |
|
LAY.removeStr = function(str, new_str){ |
|
str = str.replace(/\s+/, ' '); |
|
new_str = new_str.replace(/\s+/, ' ').split(' '); |
|
lay.each(new_str, function(ii, item){ |
|
var exp = new RegExp('\\b'+ item + '\\b') |
|
if(exp.test(str)){ |
|
str = str.replace(exp, ''); |
|
} |
|
}); |
|
return str.replace(/\s+/, ' ').replace(/^\s|\s$/, ''); |
|
}; |
|
|
|
//查找子元素 |
|
LAY.prototype.find = function(selector){ |
|
var that = this; |
|
var index = 0, arr = [] |
|
,isObject = typeof selector === 'object'; |
|
|
|
this.each(function(i, item){ |
|
var nativeDOM = isObject ? item.contains(selector) : item.querySelectorAll(selector || null); |
|
for(; index < nativeDOM.length; index++){ |
|
arr.push(nativeDOM[index]); |
|
} |
|
that.shift(); |
|
}); |
|
|
|
if(!isObject){ |
|
that.selector = (that.selector ? that.selector + ' ' : '') + selector |
|
} |
|
|
|
lay.each(arr, function(i, item){ |
|
that.push(item); |
|
}); |
|
|
|
return that; |
|
}; |
|
|
|
//DOM遍历 |
|
LAY.prototype.each = function(fn){ |
|
return lay.each.call(this, this, fn); |
|
}; |
|
|
|
//添加css类 |
|
LAY.prototype.addClass = function(className, type){ |
|
return this.each(function(index, item){ |
|
item.className = LAY[type ? 'removeStr' : 'addStr'](item.className, className) |
|
}); |
|
}; |
|
|
|
//移除 css 类 |
|
LAY.prototype.removeClass = function(className){ |
|
return this.addClass(className, true); |
|
}; |
|
|
|
//是否包含 css 类 |
|
LAY.prototype.hasClass = function(className){ |
|
var has = false; |
|
this.each(function(index, item){ |
|
if(new RegExp('\\b'+ className +'\\b').test(item.className)){ |
|
has = true; |
|
} |
|
}); |
|
return has; |
|
}; |
|
|
|
//添加或获取 css style |
|
LAY.prototype.css = function(key, value){ |
|
var that = this |
|
,parseValue = function(v){ |
|
return isNaN(v) ? v : (v +'px'); |
|
}; |
|
return (typeof key === 'string' && value === undefined) ? function(){ |
|
if(that.length > 0) return that[0].style[key]; |
|
}() : that.each(function(index, item){ |
|
typeof key === 'object' ? lay.each(key, function(thisKey, thisValue){ |
|
item.style[thisKey] = parseValue(thisValue); |
|
}) : item.style[key] = parseValue(value); |
|
}); |
|
}; |
|
|
|
//添加或获取宽度 |
|
LAY.prototype.width = function(value){ |
|
var that = this; |
|
return value === undefined ? function(){ |
|
if(that.length > 0) return that[0].offsetWidth; //此处还需做兼容 |
|
}() : that.each(function(index, item){ |
|
that.css('width', value); |
|
}); |
|
}; |
|
|
|
//添加或获取高度 |
|
LAY.prototype.height = function(value){ |
|
var that = this; |
|
return value === undefined ? function(){ |
|
if(that.length > 0) return that[0].offsetHeight; //此处还需做兼容 |
|
}() : that.each(function(index, item){ |
|
that.css('height', value); |
|
}); |
|
}; |
|
|
|
//添加或获取属性 |
|
LAY.prototype.attr = function(key, value){ |
|
var that = this; |
|
return value === undefined ? function(){ |
|
if(that.length > 0) return that[0].getAttribute(key); |
|
}() : that.each(function(index, item){ |
|
item.setAttribute(key, value); |
|
}); |
|
}; |
|
|
|
//移除属性 |
|
LAY.prototype.removeAttr = function(key){ |
|
return this.each(function(index, item){ |
|
item.removeAttribute(key); |
|
}); |
|
}; |
|
|
|
//设置或获取 HTML 内容 |
|
LAY.prototype.html = function(html){ |
|
var that = this; |
|
return html === undefined ? function(){ |
|
if(that.length > 0) return that[0].innerHTML; |
|
}() : this.each(function(index, item){ |
|
item.innerHTML = html; |
|
}); |
|
}; |
|
|
|
//设置或获取值 |
|
LAY.prototype.val = function(value){ |
|
var that = this; |
|
return value === undefined ? function(){ |
|
if(that.length > 0) return that[0].value; |
|
}() : this.each(function(index, item){ |
|
item.value = value; |
|
}); |
|
}; |
|
|
|
//追加内容 |
|
LAY.prototype.append = function(elem){ |
|
return this.each(function(index, item){ |
|
typeof elem === 'object' |
|
? item.appendChild(elem) |
|
: item.innerHTML = item.innerHTML + elem; |
|
}); |
|
}; |
|
|
|
//移除内容 |
|
LAY.prototype.remove = function(elem){ |
|
return this.each(function(index, item){ |
|
elem ? item.removeChild(elem) : item.parentNode.removeChild(item); |
|
}); |
|
}; |
|
|
|
//事件绑定 |
|
LAY.prototype.on = function(eventName, fn){ |
|
return this.each(function(index, item){ |
|
item.attachEvent ? item.attachEvent('on' + eventName, function(e){ |
|
e.target = e.srcElement; |
|
fn.call(item, e); |
|
}) : item.addEventListener(eventName, fn, false); |
|
}); |
|
}; |
|
|
|
//解除事件 |
|
LAY.prototype.off = function(eventName, fn){ |
|
return this.each(function(index, item){ |
|
item.detachEvent |
|
? item.detachEvent('on'+ eventName, fn) |
|
: item.removeEventListener(eventName, fn, false); |
|
}); |
|
}; |
|
|
|
//暴露 lay 到全局作用域 |
|
window.lay = lay; |
|
|
|
//如果在 layui 体系中 |
|
if(window.layui && layui.define){ |
|
layui.define(function(exports){ //layui 加载 |
|
exports(MOD_NAME, lay); |
|
}); |
|
} |
|
|
|
}(window, window.document); |
|
|
|
|