1.处理键盘事件,禁止后退键(Backspace)密码或单行、多行文本框除外,作用于IE、Chrome
document.onkeydown = function banBackSpace(e){
var ev = e || window.event;//获取event对象
var obj = ev.target || ev.srcElement;//获取事件源
var t = obj.type || obj.getAttribute('type');//获取事件源类型
//获取作为判断条件的事件类型
var vReadOnly = obj.getAttribute('readonly');
var vDisabled = obj.getAttribute('disabled');
//处理null值情况
vReadOnly = (vReadOnly == null) ? false : true;
vDisabled = (vDisabled == null) ? false : true;
//当敲Backspace键时,事件源类型为密码或单行、多行文本的,
//并且readonly属性为true或enabled属性为false的,则退格键失效
var flag1 = (ev.keyCode == 8 && (t=="password" || t=="text" || t=="textarea") && (vReadOnly==true || vDisabled==true)) ? true : false;
//当敲Backspace键时,事件源类型非密码或单行、多行文本的,则退格键失效
var flag2 = (ev.keyCode == 8 && t != "password" && t != "text" && t != "textarea") ? true : false;
//判断
if(flag1 || flag2){
return false;
}
}
2.滚动延时加载
$(window).scroll(function(){
var scrollTop = $(this).scrollTop();
var scrollHeight = $(document).height();
var windowHeight = $(this).height();
if(scrollTop + windowHeight == scrollHeight){
HListApp.update(0, TempApps.get()); //0:追加
}
});
3.图片居中显示缩略图
function fixThumImg(){
var handle = $(this);
var pHandle = handle.parent();
var width = handle.width();
var height = handle.height();
var pWidth = pHandle.width();
var pHeight = pHandle.height();
if(width/height > pWidth/pHeight){
handle.css("width", "100%");
var cur_height = (height * pWidth) / width;
handle.css("margin-top", (pHeight - cur_height)/2);
}else {
handle.css("height", "100%");
var cur_width = (width * pHeight) / height;
handle.css("margin-left", (pWidth - cur_width)/2);
}
handle.show();
}
4.检测页面是否含有frameset
if(top.document.getElementsByTagName("FRAME").length > 0){
console.log("yes");
}
5.input的checked批量操作
//批量改变checked属性的话,直接用下面语句会有BUG:
$(".select").attr("checked", false);
//要用map来轮询操作:
$(".select").map(function(){
$(this)[0].checked = false;
});
6.文件大小单位转换,保留最多两位小数
function sizeFormat(size)
{
var unit = ["B", "K", "M", "G", "T"];
var tmp = size;
for(var i=0; i
7.获取静态页面参数值
function getParameter (sProp )
{
var re = new RegExp (sProp + "=([^\&]*)" , "i" );
var a = re . exec (document . location . search );
if (a == null )
return null ;
return a [ 1 ];
};
8.阻止滚动冒泡
//DIV的滚动冒泡不可用,只能阻止默认滚动,然后自己实现
document.getElementById("scroll_div").onmousewheel =(function(e){
$(this)[0].scrollTop += e.wheelDelta > 0 ? -60 : 60;
return false;
});
9.template变量替换函数
function replaceTplData(tpl, data){
return tpl.replace(/\{([\w\.]*)\}/g, function(key, $1){
return data[$1];
})
}
10.时间戳格式化函数
/**
* 和PHP一样的时间戳格式化函数
* @example stampFormat2Date("Y-m-d H:i", new Date().getTime()/1000);
* @param {string} format 格式 如'Y-m-d H:i:s'
* @param {int} timestamp 要格式化的时间 默认为当前时间(如:new Date().getTime()/1000)
* @return {string} 格式化的时间字符串
*/
function stampFormat2Date(format, timestamp){
var a, jsdate=((timestamp) ? new Date(timestamp*1000) : new Date());
var pad = function(n, c){
if((n = n + "").length < c){
return new Array(++c - n.length).join("0") + n;
} else {
return n;
}
};
var txt_weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var txt_ordin = {1:"st", 2:"nd", 3:"rd", 21:"st", 22:"nd", 23:"rd", 31:"st"};
var txt_months = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var f = {
// Day
d: function(){return pad(f.j(), 2)},
D: function(){return f.l().substr(0,3)},
j: function(){return jsdate.getDate()},
l: function(){return txt_weekdays[f.w()]},
N: function(){return f.w() + 1},
S: function(){return txt_ordin[f.j()] ? txt_ordin[f.j()] : 'th'},
w: function(){return jsdate.getDay()},
z: function(){return (jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5 >> 0},
// Week
W: function(){
var a = f.z(), b = 364 + f.L() - a;
var nd2, nd = (new Date(jsdate.getFullYear() + "/1/1").getDay() || 7) - 1;
if(b <= 2 && ((jsdate.getDay() || 7) - 1) <= 2 - b){
return 1;
} else{
if(a <= 2 && nd >= 4 && a >= (6 - nd)){
nd2 = new Date(jsdate.getFullYear() - 1 + "/12/31");
return date("W", Math.round(nd2.getTime()/1000));
} else{
return (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0);
}
}
},
// Month
F: function(){return txt_months[f.n()]},
m: function(){return pad(f.n(), 2)},
M: function(){return f.F().substr(0,3)},
n: function(){return jsdate.getMonth() + 1},
t: function(){
var n;
if( (n = jsdate.getMonth() + 1) == 2 ){
return 28 + f.L();
} else{
if( n & 1 && n < 8 || !(n & 1) && n > 7 ){
return 31;
} else{
return 30;
}
}
},
// Year
L: function(){var y = f.Y();return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0},
//o not supported yet
Y: function(){return jsdate.getFullYear()},
y: function(){return (jsdate.getFullYear() + "").slice(2)},
// Time
a: function(){return jsdate.getHours() > 11 ? "pm" : "am"},
A: function(){return f.a().toUpperCase()},
B: function(){
// peter paul koch:
var off = (jsdate.getTimezoneOffset() + 60)*60;
var theSeconds = (jsdate.getHours() * 3600) + (jsdate.getMinutes() * 60) + jsdate.getSeconds() + off;
var beat = Math.floor(theSeconds/86.4);
if (beat > 1000) beat -= 1000;
if (beat < 0) beat += 1000;
if ((String(beat)).length == 1) beat = "00"+beat;
if ((String(beat)).length == 2) beat = "0"+beat;
return beat;
},
g: function(){return jsdate.getHours() % 12 || 12},
G: function(){return jsdate.getHours()},
h: function(){return pad(f.g(), 2)},
H: function(){return pad(jsdate.getHours(), 2)},
i: function(){return pad(jsdate.getMinutes(), 2)},
s: function(){return pad(jsdate.getSeconds(), 2)},
//u not supported yet
// Timezone
//e not supported yet
//I not supported yet
O: function(){
var t = pad(Math.abs(jsdate.getTimezoneOffset()/60*100), 4);
if (jsdate.getTimezoneOffset() > 0) t = "-" + t; else t = "+" + t;
return t;
},
P: function(){var O = f.O();return (O.substr(0, 3) + ":" + O.substr(3, 2))},
//T not supported yet
//Z not supported yet
// Full Date/Time
c: function(){return f.Y() + "-" + f.m() + "-" + f.d() + "T" + f.h() + ":" + f.i() + ":" + f.s() + f.P()},
//r not supported yet
U: function(){return Math.round(jsdate.getTime()/1000)}
};
return format.replace(/[\\]?([a-zA-Z])/g, function(t, s){
if( t!=s ){
// escaped
ret = s;
} else if( f[s] ){
// a date function exists
ret = f[s]();
} else{
// nothing special
ret = s;
}
return ret;
});
}
11.JS中文拼音排序
var arr = ["中","华","人","民","共","和","国"];
console.log(arr.sort(function(a,b){return a.localeCompare(b)}));
注意到localeCompare方法是在当前区域中进行比较的,即比较的环境为当前操作系统设备的地理区域,比如数字、货币、日期时间等的表现方式(在”控制面板“中可以查看修改),如果设备排序的方式为笔划,那上面的结果则为:人,中,民,共,华,和,国(笔划升序)。
12.对象和数组的深拷贝
//对象和数组的深拷贝
Object.clone = function(sObj){
if(typeof sObj !== "object"){ //数组和对象的type都是"object"
return sObj;
}
var s = {};
if(sObj.constructor == Array){
s = [];
}
for(var i in sObj){
s[i] = Object.clone(sObj[i]); //递归复制所有属性,包括子对象属性
}
return s;
}
13.对象扩展
//对象扩展
//tObj被扩展对象,sObj扩展对象
Object.extend = function(tObj,sObj){
for(var i in sObj){
if(typeof sObj[i] !== "object"){
tObj[i] = sObj[i];
}else if (sObj[i].constructor == Array){
tObj[i] = Object.clone(sObj[i]);
}else{
tObj[i] = tObj[i] || {};
Object.extend(tObj[i],sObj[i]);
}
}
}
//测试用例
var a = {};
var b = {
"a":1,
"b":{
"c":function(t){
alert(t);
}
},
"d":{
"e":2,
"f":[1,4,5,7,9]
}
};
Object.extend(a,b);//a获得了b的所有属性
14. NaN解释
NaN(Not a Number,非数),是计算机科学中数值数据类型的一个值,表示未定义或不可表示的值
1)首先它是一个浮点数,所以不能用来比较,如:
alert(NaN==NaN) // false
2)类型为"number",如:
alert(typeof(NaN)) // "number"
alert(NaN==undefined) // false
15.判断变量是否为undefined
alert(typeof a == "undefined");
不能直接用以下方法:
alert(a == undefined);
因为当变量a未声明时,则会导致JS错误
16.JS数组格式化
很多时候我们会想通过一个存有数据的数组来组成一个特定格式的列表,比如数组["aaa","bbb","ccc"],要把它输出到列表1)aaa, 2)bbb, 3)ccc形式,
我们可以通过map函数来简单实现:
1)通过map来格式化一个新数组:
var arr = ["aaa","bbb","ccc"];
var tmp = arr.map(function(item, i){
return i + ")" + item;
});
//此时tmp数组为["1)aaa","2)bbb","3)ccc"]
2)通过join把新数组转换到string
var str = tmp.join('\n');
//此时str为"1)aaa\n2)bbb\n3)ccc"
当然,我们也可以一步到位:
var arr = ["aaa","bbb","ccc"];
var str = arr.map(function(item, i){
return i + ")" + item;
).join('\n');
17.可配置函数-闭包用法
//如Nodejs里Connect的中间件函数,是指定了req,res和next三个参数的,如:
require('connect')().use(function(req, res, next){
//middleware logic
console.log(req.url);
next();
});
//要想把参数传递给中间件函数,可用闭包的方法,如:
function setup(options) {
// setup logic
return function (req, res, next) {
// middleware logic
//options still accessible even though outer function has returned
console.log(req.url);
next();
}
}
require('connect')().use(setup{name: "Eric"}) //成功把name="Eric"传递到中间件函数
18.图像置灰
.filter_gray{
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
filter: gray;
}
19.字符串的实际长度
平时很多时候要获取字符串的实际长度,但是string.length是不分中英文的,也就是说单双字节的字都算是长度1.
要想获取字符串的实际长度,可以先把双字节的替换成两个单字节的再获取长度,如下
function getRealLength(str) {
return str.replace(/[^\x00-\xff]/g,"aa").length;
};
alert(getRealLength('测试测试ceshiceshi'));
20.禁止页面右键菜单
document.oncontextmenu = function(event) {
event.returnValue = false;
}
21.限制input标签只能输入数字
$(".digit-only").keydown(function(e){
var k = window.event ? e.keyCode : e.which;
if((k >= 48 && k <=57) || (k >= 96 && k <=105) || k == 8 || k == 0 || (k >= 37 && k <= 40)) {
}else {
if((k==67 || k == 86) && e.ctrlKey){ //ctrl + (v/c)
}else {
return false;
}
}
});
22.$(document).ready() 与window.onload的区别
(1).执行时间
window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行。
$(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。
(2).编写个数不同
window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个
$(document).ready()可以同时编写多个,并且都可以得到执行
(3).简化写法
window.onload没有简化写法
$(document).ready(function(){})可以简写成$(function(){});
23.JS数组根据下标删除元素
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
24.在数组指定位置插入元素
//在数组(arr)指定位置(i)插入元素(item)
function insertArray (arr, i, item) { arr.splice(i, 0, item); }
25.压缩稀疏数组(ES5)
function(arr) {
//filter方法会跳过稀疏数组中缺少的元素,比如delete a[i]后,可调用该函数去重新压缩成稠密的
return arr.filter(function() { return true; });
}
压缩空缺并删除undefined和null元素
function(arr) {
return arr.filter(function(x) { return x != undefined && x != null;});
}
26.富文本
function encodeHTML(a) {
if (a.length == 0) {
return ""
}
a = a.replace(/&/g, "&");
a = a.replace(//g, ">");
a = a.replace(/\'/g, "´");
a = a.replace(/\"/g, """);
a = a.replace(/\n/g, "
");
return a
}
function decodeHTML(a) {
if (a.length == 0) {
return ""
}
a = a.replace(/&/g, "&");
a = a.replace(//g, ">");
a = a.replace(/´/g, "'");
a = a.replace(/"/g, '"');
a = a.replace(/
/g, "\n");
return a
}
27.用Ajax请求的时候,怎么才能捕捉到因为跨域限制而导致的失败?
网上查了好久,找到了这句话:
If you end up with an XMLHttpRequest having status=0 and statusText=null, it means that the request was not allowed to be performed.
再看看Ajax源码,看到以下:
ajaxError(xhr.statusText || null, xhr.status ? 'error' : 'abort', xhr, settings, deferred)
再看看Ajax的error函数的触发:
settings.error.call(context, xhr, type, error)
第一个参数是xhr;第二个是type,由xhr.status转换过来,0为'error', 1为'abort';第三个参数是error代表xhr.statusText。
综上所述,只要判断type==='abort' && error === null就可以了,如下:
$.ajax({
type: 'get',
url: 'http://xxxxxxx',
dataType: 'json',
data: {},
success: function(ret){
console.log(ret);
},
error: function(xhr, type, error) {
if(type === 'abort' && error === null) {
// 因跨域请求被拦截
console.log('type:' + type + ', error:' + error);
}
}
});
28.怎么也记不住但又最常用的CSS代码
1)单行显示,超过显示点点点
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
2)多行显示,超过最近显示点点点
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
3)去除移动端点击出现的蓝色背景
.tapNone{
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none;
}
29.判断div是否在可视区域
$(window).scroll(function () {
var a = document.getElementById("eq").offsetTop;
if (a >= $(window).scrollTop() && a < ($(window).scrollTop()+$(window).height())) {
alert("div在可视范围");
}
});
30.JS实现异或加/解密
var Xor = (function() {
var _e = {},
_seed = 7;
_e.encode = function(str, seed) {
seed = seed || _seed;
var ret = '';
for(var i=0; i
再进化一下,加密的seed不只是一个数字,而是支持一串字符串,按顺序一个一个异或,解密的时候再反序来一个一个异或,另外加密后再通过base64加密
// 异或加/解密(base64)
var Xor = (function() {
var _e = {},
_seed = '[email protected]';
_e.encode = function(str, seed) {
seed = seed || _seed;
var ret = '';
for(var i=0; i0; j--) {
ret1 = String.fromCharCode(ret1.charCodeAt(0) ^ seed.charCodeAt(j));
}
ret += ret1;
}
return ret;
};
return _e;
})();
31. new Event() 报错 "Uncaught Type Error: Illegal constructor**"
在安卓自带的浏览器,系统版本<5.0,会有可能报以上错误。
解决方法:
try {
event = new Event(eventName, {
bubbles: true
});
} catch(e){
event = document.createEvent('Event');
event.initEvent(eventName, true, false);
}
参考:https://github.com/silviomoreto/bootstrap-select/issues/1286
32. 动画优化
1) 用requestAnimationFrame代替setTimeout
const raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || (f) => setTimeout(f, 1000 / 60);
2) 尽快的调用下一帧
requestAnimationFrame(function tick() {
requestAnimationFrame(tick);
// do something
});
3) 用translateZ代替z-index
z-index会形成不再预期内的复合层。
33. 图片上传前预览
图片上传,很多时候需要做下预览,这时就需要用到 FileReader 类来读取图片了。
编辑头像
$('#userAvatar').change(function(ev) {
var file = this.files[0];
if(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e){
$('#avatarImg').attr('src', this.result);
};
}
});
34. 文章关键词标红(源数据为html)
var str = '213你好啊123你好你好啊
';
str.replace(/(你好)(?=[^>]*(<|$))/gmi, '$1');
出来的结果是:
213你好啊123你好你好啊