UNPKG

s94-web

Version:

常用的web工具方法封装---牧人与鱼

676 lines (665 loc) 28.7 kB
import s94 from '../../s94-js/s94.mjs.js' var s94_web = (function (global) { let document = global?.document; if (!document) return console.error('缺少 document 对象!'); /**执行回调函数或者返回dom对象 * @param {Function|String} data 如果传入 Function ,等效于s94方法,如果传入字符,会返回s94_web.dom对象 * @param {Number} os s94方法的os参数 * @returns {s94_web.dom|Promise<*>|void} */ var s94_web = function(data, os) { if(typeof data === "function") { return s94(data, os); }else { return new s94_web.dom(data || []); } } for (var k in s94) {s94_web[k] = s94[k];} s94_web.cache.default_engine = global.sessionStorage; s94_web.jsonp = s94.unifyRequest({ send(setup){ setup.jsonpCallback = setup.jsonpCallback || 'jsonp_'+(new Date().getTime()); setup.jsonp = setup.jsonp || 'callback'; let _this = this; global[setup.jsonpCallback] = function(res){ setup.response.data = res; setup.response.body = setup.jsonpCallback+'('+JSON.stringify(res)+')'; _this.callback(setup, 'success'); }; let script = setup.script = document.createElement("script"); script.onload = function(e) { setup.response.code = 200; setup.response.headers['content-type'] = 'application/javascript'; _this.callback(setup, 'complete'); document.documentElement.removeChild(script); } script.onerror = function(e){ setup.response.data = setup.response.body = (e.message || 'js加载失败:'+script.src); _this.callback(setup, 'error'); _this.callback(setup, 'complete'); document.documentElement.removeChild(script); } script.src = setup.url + (setup.url.indexOf('?') == -1?'?':'&') + setup.jsonp + '=' + setup.jsonpCallback; document.documentElement.appendChild(script); return setup; } }) function get_os(){ if (typeof global.navigator !== 'object') return; let res = 0; if (/MicroMessenger/i.test(global.navigator.userAgent)) res |= s94.OS_H5_WECHAT; if (/Android/i.test(global.navigator.userAgent)) { res |= s94.OS_H5_ANDROID; }else if (/iPhone|iPad/i.test(global.navigator.userAgent)){ res |= s94.OS_H5_IOS }else{ res |= s94.OS_H5_PC } return res; } if ("loading" == document.readyState) { document.addEventListener("DOMContentLoaded", function (){ s94.load.init(get_os()) }) }else { s94.load.init(get_os()); } s94_web.filename = typeof module === "object" && module.filename ? module.filename : s94.__stack(1)['file']; s94_web.dom = function(selector) { if(!(this instanceof s94_web.dom)) return new s94_web.dom(selector); if(selector instanceof s94_web.dom) return selector; Object.defineProperty(this, 'length', {value: 0,writable: true}); if(selector.nodeType || selector == global || selector == document) { //document或者window对象 this.push(selector); } else if(typeof(selector) == "string") { var doms = selector.indexOf('<')!=-1 ? s94_web.strtonodes(selector) : document.querySelectorAll(selector); for(let i = 0; i < doms.length; i++) { doms[i].nodeType == 1 && this.push(doms[i]); } } else if(typeof(selector) == "object" && selector.length) { for(var i = 0; i < selector.length; i++) { selector[i].nodeType == 1 && this.push(selector[i]); } } return this; } s94_web.dom.extend = function(obj, options){ s94.extend(s94_web.dom.prototype, obj, options) } s94_web.dom.extend({ forEach: Array.prototype.forEach, push: Array.prototype.push, splice: Array.prototype.splice, }) s94_web.dom.extend({ each: function(callback){ s94.each(this, callback) return this; }, eachloop: function(callback){ s94.eachloop(this, 'children', callback); return this; } }) s94_web.loadCss = function (src){ if (!src || typeof src !== 'string') return; src = s94.url(src).href; let list = []; document.querySelectorAll('link[rel="stylesheet"]').forEach(function (dom){ list.push(s94.url(dom.href).href) }) if (~list.indexOf(src)) return; let css = document.createElement('link'); css.rel = "stylesheet"; css.href = src; document.querySelector('head').appendChild(css); } /**加载js * @param {String|Array|Object} setup js地址(String|Array),或者包含地址(src)的配置参数 * @param {Function} callback 所有js加载完成后的回调函数,也可以使用返回的Promise * @returns {Promise<unknown>} */ s94_web.loadJs = function(setup, callback){ let cache_list = s94_web.loadJs.list || {}; let callback_promise; //数据整理 if (!setup) return; if (typeof setup === 'string' || setup instanceof Array) setup = {src: setup}; var parent = setup.parent && setup.parent.nodeType==1 ? setup.parent : document.querySelector("head"); var srcs = typeof(setup.src)=="string"?[setup.src] : setup.src; var callback_load = typeof(setup.load )=="function" ? setup.load : function(){}; var callback_error = typeof(setup.error )=="function" ? setup.error : function(){}; (new s94_web.dom('script[src]')).each(function(){ var k = s94.url(this.src); if(!cache_list[k]) cache_list[k] = this; }) var length = srcs.length; var scriptNodes=[]; function callback_action(){ if (--length > 0) return; typeof(callback)=="function" && callback.call(scriptNodes, scriptNodes); callback_promise(scriptNodes); } for (var i = 0; i < srcs.length; i++) { var k = s94.url(srcs[i]); var row = cache_list[k]; if (row && !setup.refresh){ row.loading ? row.loadCallbacks.push(callback_action) : callback_action(); }else{ row = document.createElement("script"); row.type = setup.type || ''; row.loading = true; row.loadCallbacks=[callback_action]; row.onload = function() { callback_load.call(this, this); delete this.loading; for (; 0 < this.loadCallbacks.length;) { this.loadCallbacks[0](); this.loadCallbacks.splice(0,1); } } row.onerror = function(e){ callback_error.call(this, this); delete this.loading; parent.removeChild(row); } row.src = srcs[i]; parent.appendChild(row); } scriptNodes.push(row); cache_list[k] = row; } s94_web.loadJs.list = cache_list; return new Promise(function (resolve){callback_promise=resolve;}); } /*--------------------Document------------------*/ //hasClass、addClass、removeClass、toggleClass s94_web.hasClass = function(dom,className){ return dom.classList ? dom.classList.contains(className) : (dom.className && dom.className.split(' ').indexOf(className)!=-1); } s94_web.addClass = function(dom,className){ if (s94_web.hasClass(dom,className)) return; dom.classList ? dom.classList.add(className) : (dom.className += (dom.className?' ':''+className)); } s94_web.removeClass = function(dom,className){ if (!s94_web.hasClass(dom,className)) return; if (dom.classList) { dom.classList.remove(className) }else{ var classList = dom.className.split(' '); classList.splice(classList.indexOf(className),1); dom.className = classList.join(' '); } } s94_web.toggleClass = function(dom,className){ dom.classList ? dom.classList.toggle(className) : (s94_web.hasClass(dom,className)?s94_web.removeClass(dom,className):s94_web.addClass(dom,className)); } s94_web.dom.extend({ hasClass: function(className){ for (var i = 0; i < this.length; i++) { if(s94_web.hasClass(this[i],className)) return true; } return false; }, addClass: function(className){ this.forEach(function(dom){ s94_web.addClass(dom,className); }) return this; }, removeClass: function(className){ this.forEach(function(dom){ s94_web.removeClass(dom,className); }) return this; }, toggleClass: function(className){ this.forEach(function(dom){ s94_web.toggleClass(dom,className); }) return this; } }) //text、html、attr、removeAttr、val、css s94_web.dom.extend({ text:function(str){ if(typeof(str)=="undefined") return this.length ? this[0].innerText : false; this.forEach(function(dom){ dom.innerText = str; }) return this; }, html: function(str){ if(typeof(str)=="undefined") return this.length ? this[0].innerHTML : false; this.forEach(function(dom){ dom.innerHTML = str; }) return this; }, attr: function(name, value){ if(typeof(name)=="string" && typeof(value)=="undefined") return this.length ? this[0].getAttribute(name) : false; this.forEach(function(dom){ if (typeof(name)=="string") { dom.setAttribute(name,value); } else{ for (var k in name) { dom.setAttribute(k,name[k]); } } }) return this; }, removeAttr: function(name){ this.forEach(function(dom){ dom.removeAttribute(name); }) return this; }, val: function(value){ if(typeof(value)=="undefined") return this.length ? this[0].value : false; this.forEach(function(dom){ dom.value = value; }) return this; }, css: function(name, value){ var obj = {}; if (typeof(name)=="string") { if(name.indexOf(';')!==-1){ name.split(';').forEach(function(row){ if(!row) return; var kv = row.split(':',2); obj[s94.trim(kv[0])] = s94.trim(kv[1]); }) }else if(typeof(value)=="undefined"){ return (this[0] instanceof Element) ? global.getComputedStyle(this[0]).getPropertyValue(name) : ''; }else{ obj[name] = value; } }else if(typeof(name)=="object"){ obj = name; } this.forEach(function(dom){ for (var k in obj) { dom.style[k] = obj[k]; } }) return this; } }) //eq、find、parent、parents s94_web.dom.extend({ eq: function(index){ index = index < 0 ? (this.length+index) : index; return new s94_web.dom(this[index] || []); }, find: function(selector){ if(!selector) return false; var doms = []; this.forEach(function(dom){ s94.each(dom.querySelectorAll(selector),function(){doms.push(this)}) }) return new s94_web.dom(doms); }, parent: function(selector){ var limt_nodes = []; if(selector) s94.each(document.querySelectorAll(selector),function(){limt_nodes.push(this)}); var docs=[]; this.forEach(function(dom){ if(!dom.parentNode || dom.parentNode.nodeType !== 1) return; if(docs.indexOf(dom.parentNode) == -1 && (!selector || limt_nodes.indexOf(dom.parentNode) !== -1)) docs.push(dom.parentNode); }) return new s94_web.dom(docs); }, parents: function(selector){ var limt_nodes = []; if(selector) s94.each(document.querySelectorAll(selector),function(){limt_nodes.push(this)}); var docs=[]; this.forEach(function(dom){ while (dom.parentNode && dom.parentNode.nodeType == 1){ dom = dom.parentNode; if(docs.indexOf(dom) == -1 && (!selector || limt_nodes.indexOf(dom) !== -1)) docs.push(dom); } }) return new s94_web.dom(docs); } }) //append、prepend、after、before、remove //字符串转DOM节点 s94_web.strtonodes = function(str){ var istbody = !!str.match(/^<tbody[^>]*>([\s\S.]*)<\/tbody>$/); var istr = !!str.match(/^<tr[^>]*>([\s\S.]*)<\/tr>$/); var istd = !!str.match(/^<td[^>]*>([\s\S.]*)<\/td>$/); var isth = !!str.match(/^<th[^>]*>([\s\S.]*)<\/th>$/); var hasbody = /<body[\s>]/i.test(str); var hashead = /<head/i.test(str); var outer = document.createElement(istd||isth?'tr':(istr?'tbody':(istbody?'table': (hasbody?'html':'body') ))); outer.innerHTML = str; var nodes = []; for (var i = (hasbody && !hashead ? 1 : 0); i < outer.childNodes.length; i++) { nodes.push(outer.childNodes[i]); } return nodes; } s94_web.dom.extend({ append: function(content){ if(typeof(content)=="undefined") return this; this.forEach(function(dom){ if (dom.nodeType !== 1 && dom.nodeType !== 11 && dom.nodeType !== 9) return; s94_web(content).each(function(){ dom.appendChild(typeof(content)=='string' ? this.cloneNode(true) : this); }) }) return this; }, prepend: function(content){ if(typeof(content)=="undefined") return this; this.forEach(function(dom){ if (dom.nodeType !== 1 && dom.nodeType !== 11 && dom.nodeType !== 9) return; var target = dom.firstChild; s94_web(content).each(function(){ dom.insertBefore(typeof(content)=='string' ? this.cloneNode(true) : this, target); }) }) return this; }, after: function(content){ if(typeof(content)=="undefined") return this; this.forEach(function(dom){ var parent = dom.parentNode; if(!parent || (parent.nodeType !== 1 && parent.nodeType !== 9 && parent.nodeType !== 11) )return; var target = dom.nextSibling; s94_web(content).each(function(){ if(target){ parent.insertBefore(typeof(content)=='string' ? this.cloneNode(true) : this, target); }else{ parent.appendChild(typeof(content)=='string' ? this.cloneNode(true) : this); } }) }) return this; }, before: function(content){ if(typeof(content)=="undefined") return this; this.forEach(function(dom){ var parent = dom.parentNode; if(!parent || (parent.nodeType !== 1 && parent.nodeType !== 9 && parent.nodeType !== 11) )return; s94_web(content).each(function(){ parent.insertBefore(typeof(content)=='string' ? this.cloneNode(true) : this, dom); }) }) return this; }, remove: function(selector){ var limt_nodes = []; if(selector) s94.each(document.querySelectorAll(selector),function(){limt_nodes.push(this)}); this.forEach(function(dom){ if (!dom.parentNode) return; if((!selector || limt_nodes.indexOf(dom) !== -1)) dom.parentNode.removeChild( dom ); }) return this; } }) //on、off、trigger s94_web.dom.extend({ on: function(etype, callback, useCapture){ var k = etype+'EventCallbackList'+(useCapture?'Capture':'Bubbling') this.forEach(function(dom){ dom[k] = dom[k] || []; dom[k].push(callback); dom.addEventListener(etype,callback,useCapture); }) return this; }, off: function(etype, useCapture){ var k = etype+'EventCallbackList'+(useCapture?'Capture':'Bubbling') this.forEach(function(dom){ dom[k] = dom[k] || []; if(dom[k]) for(;dom[k].length;){ dom.removeEventListener(etype,dom[k][0]); dom[k].splice(0,1); } }) return this; }, trigger: function(etype, extendData){ if (typeof(Event)=="function") { var e = new Event(etype,{bubbles: true,cancelable: true,composed: true}); } else{ var e = document.createEvent('HTMLEvents'); e.initEvent(etype, true, true); } if(typeof(extendData)=='object') for (var k in extendData) { if(typeof(e[k])=="undefined")e[k] = extendData[k]; } this.forEach(function(dom){ if (dom.dispatchEvent) dom.dispatchEvent(e); }) } }) var extend_fns={}; ['blur','focus','focusin','focusout','resize','scroll','click','dblclick','mousedown','mouseup','mousemove','mouseover','mouseout','mouseenter','mouseleave','change','select','submit','keydown','keypress','keyup','contextmenu'].forEach(function(name){ extend_fns[name] = function(callback){ return callback ? this.on(name,callback) : this.forEach(function(dom){ typeof(dom[name])=="function" && dom[name](); }) } }); s94_web.dom.extend(extend_fns); //show、hide s94_web.dom.extend({ show: function(time){ this.forEach(function(dom){ dom.hideTimeoutHander && clearTimeout(dom.hideTimeoutHander); if(dom.style.display=='none'){ dom.style.display = dom.oldDisplay ? dom.oldDisplay : ''; } if(s94_web(dom).css('display')=='none'){ dom.style.display = 'block'; } if (time) { dom.style.opacity = 0; dom.style.transition = 'opacity '+(time/1000)+'s'; setTimeout(function(){dom.style.opacity=1;}); dom.showTimeoutHander = setTimeout(function(){dom.style.transition='';dom.style.opacity='';},time); } }) return this; }, hide: function(time){ this.forEach(function(dom){ dom.showTimeoutHander && clearTimeout(dom.showTimeoutHander); if(dom.style.display!='none') dom.oldDisplay = dom.style.display; if (time) { dom.style.opacity = 1; dom.style.transition = 'opacity '+(time/1000)+'s'; setTimeout(function(){dom.style.opacity=0;}); dom.hideTimeoutHander = setTimeout(function(){dom.style.transition='';dom.style.opacity='';dom.style.display = 'none';},time); }else{ dom.style.display = 'none'; } }) return this; } }) //serializeArray、serialize s94_web.dom.extend({ serializeArray: function(){ var arr = []; this.forEach(function(dom){ var inputs = dom.querySelectorAll('input,select,textarea'); for (var i = 0; i < inputs.length; i++) { if(!inputs[i].name) continue; if(['submit','button'].indexOf(inputs[i].type)!==-1) continue; if(['checkbox','radio'].indexOf(inputs[i].type)!==-1 && !inputs[i].checked) continue; if(inputs[i].type=='file'){ for (var f = 0; f < inputs[i].files.length; f++) { arr.push({name: inputs[i].name, value: inputs[i].files[f]}); } }else{ arr.push({name: inputs[i].name, value: inputs[i].value}); } } }) return arr; }, serialize: function(notencode){ var arr = this.serializeArray(); var param=''; arr.forEach(function(row){ param += '&'+row.name+'='+(notencode ? row.value : encodeURIComponent(row.value)); }) return param.substring(1); } }) //screenOffsetPage、domOffsetScreen、domOffsetPage、domOffsetParent、eventOffsetScreen、eventOffsetTarget、eventOffsetDom /** * 屏幕相对于页面的偏移 * @param {Object|Number} to 偏移跳转到坐标to,格式{x:像素,y:像素} * @param {Object|Number} op [speed]动画执行速度(px/s)/[time]动画执行时间(毫秒),传入Number表示time * @param {Function} callback 动画执行结束后执行的回调函数 */ s94_web.screenOffsetPage = function(to, op, callback){ var res = {x: 0, y: 0}; res.x = document.documentElement.scrollLeft || document.body.scrollLeft || 0; res.y = document.documentElement.scrollTop || document.body.scrollTop || 0; //没有to参数,直接返回定位,不执行锚点跳转 if(typeof(to)=='undefined') return res; function removeAction(){ s94_web.screenOffsetPage.th && (global.cancelAnimationFrame || global.webkitCancelAnimationFrame || global.mozCancelAnimationFrame || global.clearTimeout)(s94_web.screenOffsetPage.th) } removeAction(); if(typeof(op) == 'number') op = {time: op}; op = typeof(op)=='undefined'?{time: 1}:(typeof(op) == 'number'?{time: op}:op); to = typeof(to) == 'number' ? {y:to} : to; to.x = typeof(to.x) == 'undefined' ? res.x : to.x; to.y = typeof(to.y) == 'undefined' ? res.y : to.y; var start_time = (new Date()).getTime(); var time = op.time; if(op.speed){ time = Math.max(Math.abs(to.x - res.x), Math.abs(to.y - res.y)) / op.speed * 1000; } function loop(){ var run_time = (new Date()).getTime() - start_time; var bn = Math.min(run_time/time,1); var now = { x: res.x + ((to.x - res.x) * bn), y: res.y + ((to.y - res.y) * bn) }; document.body.scrollLeft = now.x; document.body.scrollTop = now.y; document.documentElement.scrollLeft = now.x; document.documentElement.scrollTop = now.y; if(bn >= 1) return typeof(callback)=="function" && callback(); s94_web.screenOffsetPage.th = requestAnimationFrame(loop); } setTimeout(loop, 1000 / 60);//此处需要延迟执行,否则可能会被系统默认还原 return res; } /** * 元素相对于屏幕的偏移 * @param {Object} dom Document元素 */ s94_web.domOffsetScreen = function(dom){ var r = dom.getBoundingClientRect(); return {x:r.left ,y:r.top}; } /** * 元素相对于页面的偏移【fixed定位的子元素相对于fixed定位元素】 * @param {Object} dom Document元素 */ s94_web.domOffsetPage = function(dom){ //循环获取父级元素的offsetTop var dos = s94_web.domOffsetScreen(dom); var sop = s94_web.screenOffsetPage(); return {x: dos.x + sop.x, y: dos.y + sop.y}; } /** * 元素doc相对于父级元素parent的偏移 * @param {Object} dom Document元素 * @param {Object} parent 指定父元素【不填为第一个父级元素】 */ s94_web.domOffsetParent = function(dom, parent){ parent = parent || dom.parentNode; if(!parent) return {x: 0, y: 0}; var m = s94_web.domOffsetScreen(dom); var p = s94_web.domOffsetScreen(parent); return {x: m.x - p.x, y: m.y - p.y} } /** * 获取事件触发定位,相对于屏幕 * @param {Event} e */ s94_web.eventOffsetScreen = function(e){ if (e instanceof TouchEvent){ if (e.type == 'touchend') return {x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY}; if (e.touches?.length) { let points = []; for (let i = 0; i < e.touches.length; i++) { points.push({x: e.touches[i].clientX, y: e.touches[i].clientY}) } return {x: points[0].s, y: points[0].y, points:points}; } }else if (e instanceof MouseEvent){ return {x: e.clientX, y: e.clientY}; } return {x:0,y:0}; } /** * 获取事件触发定位,相对于触发DOM节点 * @param {Event} e */ s94_web.eventOffsetTarget = function(e){ if (e instanceof TouchEvent){ let res = this.eventOffsetScreen(e); let d_xy = this.domOffsetScreen(e.target); if (res.points) res.points.forEach(function (p){ p.x = p.x - d_xy.x; p.y = p.y - d_xy.y; }) res.x = res.x - d_xy.x; res.y = res.y - d_xy.y; return res; }else if (e instanceof MouseEvent){ return {x: e.offsetX, y: e.offsetY}; } return {x:0,y:0}; } /** * 获取事件触发定位,相对于DOM节点 * @param {Object} dom 指定DOM节点元素【不填返回{x:0,y:0}】 * @param {Event} e window.event对象,默认为window.event */ s94_web.eventOffsetDom = function(dom,e){ if(typeof(dom)=='undefined') return {x:0,y:0}; if(dom===e.target) return this.eventOffsetTarget(e); let res = this.eventOffsetScreen(e); let d_xy = this.domOffsetScreen(dom); if (res.points) res.points.forEach(function (p){ p.x = p.x - d_xy.x; p.y = p.y - d_xy.y; }) res.x = res.x - d_xy.x; res.y = res.y - d_xy.y; return res; } s94_web.dom.extend({ domOffsetPage : function(){ return s94_web.domOffsetPage(this[0]); }, domOffsetScreen: function(){ return s94_web.domOffsetScreen(this[0]); }, domOffsetParent: function(parent){ return s94_web.domOffsetParent(this[0], parent); }, eventOffsetDom: function(){ return s94_web.eventOffsetDom(this[0]); } }) return s94_web })(typeof globalThis !== 'undefined' ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}); export default s94_web;