xei
Version:
一套实用的前端工具、代码集合
1,031 lines (974 loc) • 32 kB
JavaScript
// 仓库地址:https://github.com/sxei/xei
//-------------------------最好放在head里面的代码开始----------------------------//
/** 完善旧浏览器可能不支持的方法 */
;(function()
{
// 如果不支持trim
if(!String.prototype.trim)
{
String.prototype.trim = function()
{
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};
}
// 如果不支持startsWith
if (!String.prototype.startsWith)
{
String.prototype.startsWith = function(searchString, position)
{
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}
// 如果不支持endsWith
if (!String.prototype.endsWith)
{
String.prototype.endsWith = function(searchString, position)
{
var subjectString = this.toString();
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length)
{
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
};
}
})();
/* 移动字体适配,这段代码不是必须的,根据需要取舍 */
;(function(window, document)
{
function resize()
{
var originalWidth = 720, // 设计稿默认宽度
originalFontSize = 100, // 设计稿字体默认大小
elem = document.documentElement, // html根元素
clientWidth = elem.clientWidth, // 由于宽度一般不存在被系统通知栏或者输入法挡住,所以不需要获取整个屏幕的宽度
// 高度最好取整个屏幕的,否则输入法弹出来字体会变小,但是不同浏览器获取的高度会不同,Chrome获取的是显示高度,UC获取的真实分辨率高度
clientHeight = (screen.height > 0 && screen.height <= elem.clientHeight) ? screen.height : elem.clientHeight,
// 横屏 landscape ,竖屏 portrait ,0或180表示竖屏,90或-90表示横屏
isPortrait = window.orientation === undefined ? (clientWidth < clientHeight) : (window.orientation % 180 == 0);
var width = (isPortrait ? clientWidth : clientHeight) || originalWidth;
width = width < 240 ? 240 : (width > originalWidth ? originalWidth : width);
elem.style.fontSize = Math.round(originalFontSize * width / originalWidth) + 'px';
}
if('onorientationchange' in window) window.addEventListener('onorientationchange', resize, false);
else window.addEventListener('resize', resize, false); // 输入法弹出来时会触发resize,所以手机上最好不开启resize
resize(); // 管它三七二十一,先执行一遍再说(不同浏览器可能会有少部分问题)
document.addEventListener('DOMContentLoaded', resize, false);
})(window, document);
//-------------------------最好放在head里面的代码结束----------------------------//
/**
* xei对象的初始化
*/
;(function(window, document)
{
var slice = [].slice;
var xei = function(selector, context)
{
return new xei.fn.init(selector, context);
};
xei.fn = xei.prototype =
{
version: '1.0.0', // 版本
constructor: xei, // 构造器
selector: '', // 选择器
length: 0, // 默认对象长度为0
/**
* 初始化mJquery对象
* 目前支持的有:
* $('字符串') -> 直接调用 document.querySelectorAll
* $(DOM对象)
* $(mJquery对象) 返回自身
* $(fn) 如果参数是一个function,注册DOMContentLoaded事件
* @param selector 选择器
* @param context 这个东西
* @returns 返回一个mJquery对象
*/
init: function(selector, context)
{
//以下5种情况视为无效: undefined、null、 ''、 0、 false
if(!selector) return this;
if(selector.nodeType)//如果是DOM元素
{
this.context = this[0] = selector;
this.length = 1;
return this;
}
if(typeof selector === 'string' && document.querySelectorAll)
{
selector = document.querySelectorAll(selector);
}
// 如果是伪数组(如 HTMLCollection、NodeList等)
if(typeof selector === 'object' && selector.length)
{
this.context = document;
for(var i=0; i<selector.length; i++) this[this.length++] = selector[i];
return this;
}
// 如果selector本来就是mJquery对象
if(selector.constructor === xei) return selector;
if(typeof selector === 'function' && document.addEventListener)
{
document.addEventListener('DOMContentLoaded', selector, false);
}
return this;
},
size: function()
{
return this.length;
},
toArray: function()
{
return slice.call(this);
},
/**
* 这个属性很重要,加上这个之后返回的东西就是一个类数组的东西了
*/
splice: [].splice,
/**
* 获取指定索引的对象,如果num为空,返回所有对象的数组
* 否则按索引取,没有返回undefined,如果是-1,取倒数第一个
* @param num 索引
* @returns
*/
get: function(num)
{
return num === undefined ? this.toArray() : (num < 0 ? this[this.length + num] : this[num]);
},
/**
* 简单的添加,不考虑重复问题
* @param obj
*/
add: function(obj)
{
var temp = this(obj);
for(var i=0; i<temp.length; i++) this[this.length++] = temp[i];
}
};
xei.fn.init.prototype = xei.fn;
//扩展方法,类似于jquery的插件扩展
xei.extend = xei.fn.extend = function(params)
{
for(var i in params)
{
if(params[i] != undefined) this[i] = params[i];
}
return this;
};
window.xei = xei;
})(window, document);
/**
* =====================================
* 日期相关方法
* =====================================
*/
;(function($)
{
$.extend(
{
/**
* 将日期格式化成指定格式的字符串
* @param date 要格式化的日期,不传时默认当前时间,也可以是一个时间戳
* @param fmt 目标字符串格式,支持的字符有:y,M,d,q,w,H,h,m,S,默认:yyyy-MM-dd HH:mm:ss
* @returns 返回格式化后的日期字符串
*/
formatDate: function(date, fmt)
{
date = date == undefined ? new Date() : date;
date = typeof date == 'number' ? new Date(date) : date;
fmt = fmt || 'yyyy-MM-dd HH:mm:ss';
var obj =
{
'y': date.getFullYear(), // 年份,注意必须用getFullYear
'M': date.getMonth() + 1, // 月份,注意是从0-11
'd': date.getDate(), // 日期
'q': Math.floor((date.getMonth() + 3) / 3), // 季度
'w': date.getDay(), // 星期,注意是0-6
'H': date.getHours(), // 24小时制
'h': date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, // 12小时制
'm': date.getMinutes(), // 分钟
's': date.getSeconds(), // 秒
'S': date.getMilliseconds() // 毫秒
};
var week = ['天', '一', '二', '三', '四', '五', '六'];
for(var i in obj)
{
fmt = fmt.replace(new RegExp(i+'+', 'g'), function(m)
{
var val = obj[i] + '';
if(i == 'w') return (m.length > 2 ? '星期' : '周') + week[val];
for(var j = 0, len = val.length; j < m.length - len; j++) val = '0' + val;
return m.length == 1 ? val : val.substring(val.length - m.length);
});
}
return fmt;
},
/**
* 将字符串解析成日期
* @param str 输入的日期字符串,如'2014-09-13'
* @param fmt 字符串格式,默认'yyyy-MM-dd',支持如下:y、M、d、H、m、s、S,不支持w和q
* @returns 解析后的Date类型日期
*/
parseDate: function(str, fmt)
{
fmt = fmt || 'yyyy-MM-dd';
var obj = {y: 0, M: 1, d: 0, H: 0, h: 0, m: 0, s: 0, S: 0};
fmt.replace(/([^yMdHmsS]*?)(([yMdHmsS])\3*)([^yMdHmsS]*?)/g, function(m, $1, $2, $3, $4, idx, old)
{
str = str.replace(new RegExp($1+'(\\d{'+$2.length+'})'+$4), function(_m, _$1)
{
obj[$3] = parseInt(_$1);
return '';
});
return '';
});
obj.M--; // 月份是从0开始的,所以要减去1
var date = new Date(obj.y, obj.M, obj.d, obj.H, obj.m, obj.s);
if(obj.S !== 0) date.setMilliseconds(obj.S); // 如果设置了毫秒
return date;
},
/**
* 将一个日期格式化成友好格式,比如,1分钟以内的返回“刚刚”,
* 当天的返回时分,当年的返回月日,否则,返回年月日
* @param {Object} date
*/
formatDateToFriendly: function(date)
{
date = date || new Date();
date = typeof date === 'number' ? new Date(date) : date;
var now = new Date();
if((now.getTime() - date.getTime()) < 60*1000) return '刚刚'; // 1分钟以内视作“刚刚”
var temp = this.formatDate(date, 'yyyy年M月d');
if(temp == this.formatDate(now, 'yyyy年M月d')) return this.formatDate(date, 'HH:mm');
if(date.getFullYear() == now.getFullYear()) return this.formatDate(date, 'M月d日');
return temp;
},
/**
* 将一段时长转换成友好格式,如:
* 147->“2分27秒”
* 1581->“26分21秒”
* 15818->“4小时24分”
* @param {Object} second
*/
formatDurationToFriendly: function(second)
{
if(second < 60) return second + '秒';
else if(second < 60*60) return (second-second%60)/60+'分'+second%60+'秒';
else if(second < 60*60*24) return (second-second%3600)/60/60+'小时'+Math.round(second%3600/60)+'分';
return (second/60/60/24).toFixed(1)+'天';
},
/**
* 将时间转换成MM:SS形式
*/
formatTimeToFriendly: function(second)
{
var m = Math.floor(second / 60);
m = m < 10 ? ( '0' + m ) : m;
var s = second % 60;
s = s < 10 ? ( '0' + s ) : s;
return m + ':' + s;
},
/**
* 判断某一年是否是闰年
* @param year 可以是一个date类型,也可以是一个int类型的年份,不传默认当前时间
*/
isLeapYear: function(year)
{
if(year === undefined) year = new Date();
if(year instanceof Date) year = year.getFullYear();
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
},
/**
* 获取某一年某一月的总天数,没有任何参数时获取当前月份的
* 方式一:$.getMonthDays();
* 方式二:$.getMonthDays(new Date());
* 方式三:$.getMonthDays(2017, 2);
* 方式四:$.getMonthDays('2017-02');
*/
getMonthDays: function(date, month)
{
var y, m;
if(date == undefined) date = new Date();
if(date instanceof Date)
{
y = date.getFullYear();
m = date.getMonth();
}
else if(typeof date == 'number')
{
y = date;
m = month-1;
}
else if(typeof date == 'string')
{
let temp = date.split('-');
y = parseInt(temp[0]);
m = parseInt(temp[1]) - 1;
}
var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // 非闰年的一年中每个月份的天数
//如果是闰年并且是2月
if(m == 1 && this.isLeapYear(y)) return days[m]+1;
return days[m];
},
/**
* 计算2日期之间的天数,用的是比较毫秒数的方法
* 传进来的日期要么是Date类型,要么是yyyy-MM-dd格式的字符串日期
* @param date1 较新日期
* @param date2 较旧日期
*/
countDays: function(date1, date2)
{
var fmt = 'yyyy-MM-dd';
// 将日期转换成字符串,转换的目的是去除“时、分、秒”
if(date1 instanceof Date && date2 instanceof Date)
{
date1 = this.formatDate(fmt, date1);
date2 = this.formatDate(fmt, date2);
}
if(typeof date1 === 'string' && typeof date2 === 'string')
{
date1 = this.parseDate(date1, fmt);
date2 = this.parseDate(date2, fmt);
return (date1.getTime() - date2.getTime()) / (1000*60*60*24);
}
else
{
console.error('参数格式无效!');
return 0;
}
}
});
})(xei);
/**
* =====================================
* URL相关方法
* =====================================
*/
;(function($)
{
$.extend(
{
/**
* 从URL中获取string参数
* @param {Object} 参数名
* @param {Object} 默认值
*/
getParam: function(name, defaultValue, url)
{
defaultValue = defaultValue == undefined ? '' : defaultValue;
var result = new RegExp('(\\?|&)'+name+'=(.*?)(&|$)', 'g').exec(url || location.search);
return result ? result[2] : defaultValue;
},
/**
* 从URL中获取int形参数
* @param {Object} 参数名
* @param {Object} 默认值
*/
getParamInt: function(name, defaultValue, url)
{
defaultValue = defaultValue == undefined ? '0' : defaultValue;
return parseInt(this.getParam(name, defaultValue, url));
},
/**
* 从URL中获取boolean形参数
* @param {Object} name
* @param {Object} defaultValue
*/
getParamBoolean: function(name, defaultValue, url)
{
defaultValue = defaultValue == undefined ? 'false' : defaultValue;
return this.getParam(name, defaultValue, url) == 'true';
},
/**
* 给URL设置参数,如果已经存在,替换之,会自动处理存在hash的情况
* @param {Object} name 参数名
* @param {Object} value 参数值
* @param {Object} url 如果不传默认当前页面URL
*/
setParam: function(name, value, url)
{
url = this.delParam(name, url || location.href); // 无论如何,先删除可能已经存在的参数
var temp = url.split('#'); // 处理存在hash的情况
return temp[0] + (url.indexOf('?')<0?'?':'&') + name + '=' + value + (temp[1]?('#'+temp[1]):'');
},
/**
* 从一个URL中删除某一个或者多个参数,会正确处理包含hash的情况
* @param {Object} name 可以是单个参数,也可以是参数数组
* @param {Object} url 如果不传默认当前页面URL
*/
delParam: function(name, url)
{
name = name instanceof Array ? name : [name];
url = url || location.href;
for(var i=0; i<name.length; i++)
{
/* 这种方法的缺点是最多只能删除一个参数 */
/*url = url.replace(new RegExp('(\\?|&)'+name[i]+'=(.*?)(&|#|$)', 'g'), function(m, $1, $2, $3)
{
return $3 == '&' ? $1 : ($3 == '#' ? $3 : '');
});*/
/* 这种方法可以删除多个参数,但是会出现"index.html?&a=1#abc"的情况,当然这种情况是合法的 */
url = url.replace(new RegExp('(\\?|&)'+name[i]+'=(.*?)(?=&|#|$)', 'g'), function(m, $1, $2)
{
return $1 == '?' ? '?' : '';
});
}
return url;
}
});
})(xei);
/**
* =====================================
* localStorage相关方法
* =====================================
*/
;(function($)
{
$.extend(
{
/**
* 将数据放入缓存,如果不是字符串,自动转字符串
* @param {Object} name
* @param {Object} value
* @Deprecated 已过时,不推荐使用
*/
setStorage: function(name, value)
{
this.setLocalStorage(name, value);
},
/**
* 从缓存中获取数据,如果检测到是字符串转换成的对象,会自动解析成对象
* @param {Object} name
* @param {Object} defaultValue
* @Deprecated 已过时,不推荐使用
*/
getStorage: function(name, defaultValue)
{
return this.getLocalStorage(name, defaultValue);
},
/**
* 从缓存中删除某一个数据
* @param {Object} name
* @Deprecated 已过时,不推荐使用
*/
delStorage: function(name)
{
this.delLocalStorage(name);
},
/**
* 将数据放入缓存,如果不是字符串,自动转字符串
* @param {Object} name
* @param {Object} value
*/
setLocalStorage: function(name, value)
{
// 保存之前一律使用JSON.stringify转换,注意,stringify可以正确处理boolean、int、string等非对象类型
// 在处理String时,JSON.stringify('abc') == '"abc"',这样可以使用JSON.parse解析
localStorage[name] = JSON.stringify(value);
},
/**
* 从缓存中获取数据,如果检测到是字符串转换成的对象,会自动解析成对象
* @param {Object} name
* @param {Object} defaultValue
*/
getLocalStorage: function(name, defaultValue)
{
var value = localStorage[name] || defaultValue;
var rNeedParse = /^(\[.*\]|\{.*\}|true|false|\d+|".*")$/g;
// 理论上只要是通过这里的setStorage设置的都能正常解析,这里为了防止出现解析不了报错的情况,统一做了一下判断
return (typeof value == 'string' && value && rNeedParse.test(value)) ? JSON.parse(value) : value;
},
/**
* 从缓存中删除某一个数据
* @param {Object} name
*/
delLocalStorage: function(name)
{
localStorage.removeItem(name);
}
});
})(xei);
/**
* =====================================
* cookie相关方法
* =====================================
*/
;(function($)
{
$.extend(
{
/**
* 获取cookie
* @param cookieName cookie名字
* @param defaultValue 默认值
* @param parseToNumber 是否强转数字
* @returns
*/
getCookie: function(cookieName, defaultValue, parseToNumber)
{
var temp = new RegExp('(^|;| )'+cookieName+'=([^;]*)(;|$)', 'g').exec(document.cookie);
if(temp == null) return defaultValue;
var value = temp[2];
if(value == '') return defaultValue;
if(parseToNumber == true) return parseFloat(value);
return decodeURIComponent(value);
},
/**
* 设置cookie,对于中文和特殊字符必须先进行编码
* @param name cookie名称
* @param value cookie内容,注意cookie内容不能有分号、逗号、等号、空格等特殊字符,中文就更不可以,所以注意使用escape
* @param day cookie失效天数,默认30天
* @param path cookie的作用范围,默认“/”
* @param domain cookie作用域名,不写默认当前域名,域名只能<=当前域名,比如当前是 blog.test.com,可以作用到.test.com
*/
setCookie: function(name, value, day, path, domain)
{
day = day || 30;
path = path || '/';
var str = name + '=' + encodeURIComponent(value) + '; ';
if(day) str += 'expires=' + new Date(Date.now() + day * 24 * 3600 * 1000).toGMTString() + '; ';
if(path) str += 'path=' + path + '; ';
if(domain) str += 'domain=' + domain;
document.cookie = str;//注意,cookie这样设置并不会覆盖之前所有的cookie!除非同名同path
},
/**
* 删除cookie
* @param name cookie的名字
* @param path cookie所在的path,默认contextPath
* @param domain cookie作用域名
*/
delCookie: function(name, path, domain)
{
this.setCookie(name, null, -1, path, domain);
}
});
})(xei);
/**
* =====================================
* ajax相关方法
* =====================================
*/
;(function($)
{
'use strict';
var lastScriptId; // 注入jsonp时上一次使用的script的id
$.extend(
{
/**
* 类似jQuery的get方法<br>
* 与jQuery不同的是,如果dataType是function类型,那么看成是error
*/
get: function(url, data, success, dataType)
{
return ajaxGetOrPost(url, data, success, dataType, null, 'GET');
},
/**
* 类似jQuery的post方法<br>
* 与jQuery不同的是,如果dataType是function类型,那么看成是error
*/
post: function(url, data, success, dataType)
{
return ajaxGetOrPost(url, data, success, dataType, null, 'POST');
},
/**
* GET加载一个json接口
* 与jQuery不同的是,最后面多了一个error参数
*/
getJSON: function(url, data, success, error)
{
return ajaxGetOrPost(url, data, success, 'json', error, 'GET');
},
/**
* 全局的ajax设置
*/
ajaxSettings:
{
url: '',
type: 'POST', // 默认post
async: true, // 默认异步
data: null, // 需要传递的数据
processData: true, // 是否自动处理data,默认true
dataType: '', // 响应的数据类型,可以是text、html、json、jsonp、script,目前仅支持json、jsonp
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: function(data, textStatus, xhr)
{
console.log(data);
},
error: function(xhr, textStatus, errorThrown)
{
console.error(xhr);
}
},
/**
* 可以是$.ajax(url, settings),也可以是$.ajax(settings)
* @param url
* @param settings
* @returns {___xhr0}
*/
ajax: function(url, settings)
{
if(typeof url == 'object') settings = url;
else if(typeof url == 'string') settings.url = url;
var s = {};
for(var i in this.ajaxSettings)
{
s[i] = settings[i] == undefined ? this.ajaxSettings[i] : settings[i];
}
s.type = s.type.toUpperCase(); // 转大写
if(s.dataType == 'jsonp')
{
this.jsonp(s);
return;
}
var xhr = null;
if(window.XMLHttpRequest) xhr = new XMLHttpRequest();
else if(window.ActiveXObject) xhr = new ActiveXObject("Microsoft.XMLHTTP");
if(!xhr)
{
console.error('对不起,您的浏览器不支持ajax!');
return;
}
xhr.onreadystatechange = function()
{
if(xhr.readyState == 4) // 4代表数据发送完毕
{
var rsp = xhr.responseText || xhr.responseXML; // 服务器端响应
//200到300代表访问服务器成功,304代表没做修改访问的是缓存,0为访问的本地
if((xhr.status >= 200 && xhr.status <300) || xhr.status == 304|| xhr.status == 0)
{
var contentType = xhr.getResponseHeader('content-type');
if(s.dataType == 'json' || (contentType && contentType.indexOf('application/json')>=0))
{
try { rsp = eval('(' + rsp + ')'); }
catch(e)
{
console.error('服务器返回的内容不是json格式!');
console.error(e);
}
}
s.success(rsp, '', xhr);
}
else s.error(xhr, '');
}
};
if(s.type == 'GET' && s.data && s.processData)
{
s.url += (s.url.indexOf('?') >= 0 ? '&' : '?') + formatObjectToParams(s.data);
}
xhr.open(s.type, s.url, s.async);
var sendData = s.data;
if(s.type == 'POST' && s.data)
{
xhr.setRequestHeader('Content-Type', s.contentType);
if(typeof s.data == 'object' && s.processData) sendData = formatObjectToParams(s.data);
}
xhr.send(sendData);
return xhr;
},
/**
* 说实话真心不看好jsonp这种方式,以前写的代码,还是保留着吧
* @param s
*/
jsonp: function(s)
{
var fnName = '_jsonp_' + Date.now();
window[fnName] = s.success;
var url = s.url;
url += (url.indexOf('?') >= 0 ? '&' : '?') + 'callback='+fnName;
if(lastScriptId)
{
document.getElementById(lastScriptId).src = url;
}
else //否则,需要自己创建一个script
{
var element = document.createElement('script');
element.id = 'auto_jsonp_'+Date.now();
element.setAttribute('type', 'text/javascript');
element.setAttribute('src', url);
document.body.appendChild(element);
}
}
});
/**
* get或者post,调用和jquery完全一样
* @param url 非空必填
* @param data 数据,可以直接写回调函数,可以为空
* @param success 成功的回调函数,可以为空
* @param dataType 返回的数据类型,可以为空,如果是function,那么看做是error
* @param _error 失败回调,这个参数仅仅是给getJSON这个方法预留的
* @param _type 是get还是post
* @returns
*/
function ajaxGetOrPost(url, data, success, dataType, _error, _type)
{
if(typeof data == 'function')
{
dataType = success;
success = data;
data = null;
}
if(typeof dataType == 'function')
{
_error = dataType;
dataType = undefined;
}
return $.ajax({url: url, data: data, success: success, error: _error, dataType: dataType, type: _type});
}
/**
* 将一个对象转换成url参数格式
*/
function formatObjectToParams(obj)
{
var str = '';
for(var i in obj) str += (str ? '&' : '') + i + '=' + obj[i];
return str;
}
})(xei);
/**
* =====================================
* 一些简单的方法集中写在这里
* =====================================
*/
;(function($)
{
$.extend(
{
/**
* 获取各种随机数,支持如下几种调用方式:<br>
* getRandom() 返回0-1的随机小数,等同于Math.random(),0 <= result < 1
* getRandom(start, end) 返回start-end的随机整数,start <= result < end
* getRandom(end) 返回0-end的随机整数,0 <= result < end
* getRandom(array) 随机返回数组中的某一个内容
* getRandom(array, count) 随机从数组中返回长度为count的不重复内容组成的新数组,如果不足count个,返回全部 并乱序
* @param {Object} start
* @param {Object} end
* @return {Object}
*/
getRandom: function(start, end)
{
if(typeof start == 'number')
{
if(typeof end == 'undefined')
{
end = start;
start = 0;
}
return start + Math.floor( Math.random() * (end - start) );
}
else if(start instanceof Array)
{
if(typeof end == 'undefined')
{
if(start.length == 0) return null;
if(start.length == 1) return start[0];
return start[Math.floor( Math.random() * start.length )];
}
else
{
start.sort(function(a, b){return Math.random() > 0.5 ? 1 : -1;});
return start.slice(0, end);
}
}
return Math.random();
},
/**
* 获取随机字符串
* @param length 字符串长度
* @param type all 表示所有,number表示仅数字,默认所有
* @return string
*/
getRandomStr: function(length, type)
{
length = length || 18;
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789'.split('');
if(type == 'number') chars = '0123456789'.split('');
var result = '';
for(var i=0; i<length; i++) result += this.getRandom(chars);
return result;
},
/**
* 填充数字到指定长度,比如fixNumber(42, 4)返回'0042'
* @param num 可以是int或者string类型的数字
* @param length 目标长度,如果目标长度比当前长度小,则忽略
* @return string
*/
fixNumber: function(num, length)
{
if(typeof num == 'number') num = num + '';
if(num.length < length)
{
for(var i=num.length; i< length; i++)
{
num = '0' + num;
}
}
return num;
},
/**
* 字符串转下划线形式,示例:getParam 转 get_param<br>
* @param str
* @param flag 默认下划线-,也可以传其它字符
*/
toUnderline: function(str, flag)
{
return str.replace(/([A-Z])/g, function(m, $1, idx, str){ return (flag || '_') + $1.toLowerCase(); });
},
/**
* 字符串转驼峰形式<br>
* 示例一:xei.toHump('get_param'),返回getParam<br>
* 示例二:xei.toHump('font-size','-'),返回fontSize
* @param str
* @param 分割的标志,默认为“_”
*/
toHump: function(str, flag)
{
return str.replace(new RegExp((flag || '_')+'(\\w)', 'g'), function(m, $1, idx, str){ return $1.toUpperCase(); });
}
});
})(xei);
/**
* =====================================
* 格式化相关方法
* =====================================
*/
;(function($)
{
$.extend(
{
/**
* 格式化一段JSON字符串,支持解析非标准JSON
* 不同于绝大多数格式化工具,本方法支持设置缩进方式以及左大括号是否换行
* @start 2016-08-24
* @param {Object} json 要格式化的json串
* @param {Object} indent 缩进方式,可以是若干个空格和tab,默认tab缩进,如 2个空格:" "、4个空格:" "、tab:" "
* @param {Object} leftBracesInSameLine 左大括号是否保持在同一行,默认 false
*/
formatJSON: function (json, indent, leftBracesInSameLine)
{
function getIndentStr(level)
{
var str = '';
for(var i=0; i<level; i++) str += (indent || ' ');
return str;
}
function format(obj, level)
{
level = level == undefined ? 0 : level;
var result = '';
if(typeof obj == 'object' && obj != null) // 如果是object或者array
{
var isArray = obj instanceof Array, idx = 0;
result += (isArray ? '[' : '{') + '\n';
for(var i in obj)
{
result += (idx++ > 0 ? ',\n' : ''); // 如果不是数组或对象的第一个内容,追加逗号
var nextIsObj = (typeof obj[i] == 'object' && obj[i] != null), indentStr = getIndentStr(level+1);
result += (isArray && nextIsObj) ? '' : indentStr; // 如果当前是数组并且子项是对象,无需缩进
result += isArray ? '' : ('"' + i + '": ' + (nextIsObj && !leftBracesInSameLine ? '\n' : '') );
result += (!nextIsObj || (nextIsObj && leftBracesInSameLine && !isArray)) ? '' : indentStr;
result += format(obj[i], level+1); // 递归调用
}
result += '\n' + getIndentStr(level) + (isArray ? ']' : '}') + '';
}
else // 如果是 null、number、boolean、string
{
var quot = typeof obj == 'string' ? '"' : '';//是否是字符串
result += (quot + obj + quot + '');
}
return result;
}
return format(eval('(' + json + ')')); // 使用eval的好处是可以解析非标准JSON
}
});
})(xei);
/**
* =====================================
* 键值封装
* =====================================
*/
;(function($)
{
// 封装所有的键值,使用示例:xei.keys.ctrl == 17
var keys =
{
backspace: 8,
tab: 9,
clear: 12,
enter: 13,
shift: 16,
ctrl: 17,
alt: 18,
esc: 27,
space: 32,
pageup: 33,
pagedown: 34,
end: 35,
home: 36,
left: 37,
up: 38,
right: 39,
down: 40,
insert: 45,
delete: 46
};
// 数字0-9
for(var i=48; i<=57; i++)
{
keys[String.fromCharCode(i)] = i;
}
// 字母a-z
for(var i=65; i<=90; i++)
{
keys[String.fromCharCode(i).toLowerCase()] = i;
}
// 小键盘数字0-9,这里用n0-n9表示
for(var i=96; i<=105; i++)
{
keys['n' + (i - 96)] = i;
}
// f1-f12功能键
for(var i=112; i<=123; i++)
{
keys['f' + (i - 111)] = i;
}
$.extend(
{
keys: keys
});
})(xei);
/**
* =====================================
* 身份证校验
* =====================================
*/
;(function($)
{
/**
* 获取身份证号第18位校验码
* @params cid 身份证号码,17或18位均可
*/
function getIdCardLastChar(cid)
{
if(!cid || cid.length <17) return '';
var weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; // 十七位数字权重
var validates = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; // 校验码
var sum = 0;
for(var i=0; i<17; i++) sum += parseInt(cid.charAt(i)) * weights[i];
return validates[sum % 11];
}
/**
* 检测某个身份证ID是否合法
* @params cid 身份证号码,必须是18位
*/
function checkIdCardValidate(cid)
{
if(!cid) return false;
if(typeof cid !== 'string') return false;
if(cid.length !== 18) return false;
return getIdCardLastChar(cid) == cid.charAt(17)
}
xei.getIdCardLastChar = getIdCardLastChar;
xei.checkIdCardValidate = checkIdCardValidate;
})(xei);