原生JS获取元素样式属性值的方法

实际应用中, 获取元素样式在实际应用中一定常用到, 若是纯粹html中, 直接elem.style.attr就可获取, 但更多的时候我们是要从CSS中获取元素的最终样式属性.所以, 我们得利用IE的currentStyle和W3C的getPropertyValue获取.
elem.style.attr获取样式的方法就不说了. 先来看currentStyle方法, 此对象ie专属, 代表了在全局样式表、内嵌样式和 HTML 标签属性中指定的对象格式和样式. IE下通过它, 就可以获取元素的CSS属性值.
而针对其他标准浏览器, W3C也提供了一个方法getPropertyValue, 此方法, 稍有点复杂, 首先要通过document.defaultView.getComputedStyle获得CSS的样式对象, 然后通过该对象的getPropertyValue获取属性值.
上述两种方法, 无论IE还是W3C的, 有一点是相同的, 它们所获取的是元素CSS属性最终值. 这一点与CSS的优先级是相同的.
有一点不同的是, IE的方法是通过CSS属性的驼峰式名(如textAlign)获取, 而W3C的方法是通过元素CSS原来的属性名(如text-align)获取的, 所以, 在使用W3C方法时, 需要对CSS属性名做个简单的处理.
基于此, 我们可以封装一个获取元素属性值的方法, 如下:

function attrStyle(elem,attr){
	if(elem.style[attr]){
		//若样式存在于html中,优先获取
		return elem.style[attr];
	}else if(elem.currentStyle){
		//IE下获取CSS属性最终样式(同于CSS优先级)
		return elem.currentStyle[attr];
	}else if(document.defaultView && document.defaultView.getComputedStyle){
		//W3C标准方法获取CSS属性最终样式(同于CSS优先级)
		//注意,此法属性原格式(text-align)获取的,故要转换一下
		attr=attr.replace(/([A-Z])/g,'-$1').toLowerCase();
		//获取样式对象并获取属性值
		return document.defaultView.getComputedStyle(elem,null).getPropertyValue(attr);
	}else{
		return null;
	}
}

记得精通JavaScript一书中获取元素位置那一节(忘了是第6还是第7章), 有获取元素样式属性值更详细的解释. 第一次知道document.defaultVies.getComputedStyle就是从这本书来的. 很棒的一本书, 有兴趣的朋友话一定要看看.

实现checkbox的全选/全不选/点选/行内点选(原生JS版和jQ版)

日常项目中, 对于列表类文章或数据, 大概都会用到checkbox的全选或全不选的功能, 以前的项目中也写过checkbox的选择js, 但都没有整理过. 正好前几天一个兄弟遇到了这个问题, 索性, 我花了点时间, 用原生JS与jQuery分别写了一个版本, 考虑到使用时灵活性问题, 未封装, 需要的童鞋使用时自行改下相关参数.
实现checkbox的全选/全不选/点选/行内点选
功能介绍点此查看DEMO
1. 全选/全不选 选框一体实现, 即列表中选框的状态与全选/全不选框前的选框状态一致;
2. 自动更改 全选/全不选 选框的状态, 即列表中选框都选中时, 全选/全不选 选框也选中, 反之亦然;
3. 列表行内点击也可选中行内的checkbox, 并与1,2中的功能联动.
另,本文重在写全选, 鼠标划入划出背景变色为简易实现, 更加完善的请参考: http://mrthink.net/javascript-tagnames-highlight/.
原生JS版本核心代码

var js_chk = document.forms['js'].chk_can;
var jsitems = document.forms['js'].jsitems;
var jsrows = document.getElementById('js').getElementsByTagName('dd');

//判断选中个数与实际选框个数实现全选/全不选框的状态
var chk_canle = function(){
    var checkedLen = 0;
	//计算列表中选中状态的选框个数
    for (var m = 0; m < jsitems.length; m++) {
        if (jsitems[m].checked) {
            checkedLen += 1;
        }
    }
	//判断选中个数与实际个数是否相同,以确定全选/全不选状态
    for (var m = 0; m < js_chk.length; m++) {
        js_chk[m].checked = (jsitems.length == checkedLen);
    }
}

//全选与全不选一体实现
for (var i = 0; i < js_chk.length; i++) {
    js_chk[i].onclick = function(){
		//列表中选框与全选选框统一状态
        for (var m = 0; m < jsitems.length; m++) {
            jsitems[m].checked = this.checked;
        }
		//全选选框统一状态
        for (var m = 0; m < js_chk.length; m++) {
            js_chk[m].checked = this.checked;
        }
    }
}

//列表中选框点击
for (var i = 0; i < jsitems.length; i++) {
    jsitems[i].onclick = function(e){
		//阻止冒泡,避免行点击事件中,直接选择选框无效
        e && e.stopPropagation ? e.stopPropagation() : window.event.cancelBubble=true;
        chk_canle();
    }
}

//行内点击
for (var i = 0; i < jsrows.length; i++) {
    jsrows[i].onclick = function(){
		//行内点击时,行内的选框状态为原状态取反
        this.getElementsByTagName('input')[0].checked = !this.getElementsByTagName('input')[0].checked;
        chk_canle();
    }
}

jQ版本核心代码

var _jq_chk = $('#jq>dl>dt>label>:checkbox');
var _jqitems = $(':checkbox[name=jqitems]');
var _rows = $('#jq>dl>dd');

//全选与全不选一体实现
_jq_chk.click(function(){
	//列表中选框和全选选框统一状态
    _jqitems.add(_jq_chk).attr('checked', this.checked);
});

//选框的点击事件
_jqitems.click(function(e){
    //阻止冒泡,避免行点击事件中,直接选择选框无效
    e.stopPropagation();
	//判断选中个数与实际个数是否相同,以确定全选/全不选状态
    _jq_chk.attr('checked', _jqitems.size() == _jqitems.filter(':checked').size());
});

//点选行时选中行内的checkbox
_rows.bind({
    mouseenter: function(){
        $(this).addClass('hover');
    },
    mouseleave: function(){
        $(this).removeClass('hover');
    },
	//点选
    click: function(){
		//行内点击时,行内的选框状态为原状态取反
        $(this).find(':checkbox').attr('checked', !$(this).find(':checkbox').get(0).checked)
		//判断选中个数与实际个数是否相同,以确定全选/全不选状态
        _jq_chk.attr('checked', _jqitems.size() == _jqitems.filter(':checked').size());
    }
});

JS计时器setTimeout()与setInterval()方法的区别

计时器setTimeout()与setInterval()是原生JS很重要且用处很多的两个方法, 但很多人一直误以为是相同的功能: 间隔时间重复执行传入的句柄函数. 但实际上, 并非如此, 既然JS给出了两个不同的命名, 肯定有其迥异之处.
先来看看两者JS手册及英文词典上的解释:
JS手册»setTimeout() : 用于在指定的毫秒数后调用函数或计算表达式;
英文释义»timeout() : 超时;暂时休息;工间休息;
JS手册»setInterval() : 按照指定的周期(以毫秒计)来调用函数或计算表达式. 会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭;
英文释义»interval() : 间隔;间距;幕间休息;
不难看出, 只要我们仔细体会JS手册及命名释义, 就能很容易的区分开两者的区别. 简单的说, 两才的区别在于, setTimeout()方法是在等待指定时间后执行函数, 且只执行一次传入的句柄函数. setInterval()方法是每指定间隔时间后执行一次传入的句柄函数,循环执行直至关闭窗口或clearInterval().
为了使迷惑者更容易理解, 特意写了个例子: 点此查看DEMO
至于用法, 就不用多说了, 明白两者区别后, 该知道怎么取舍了.

区分中英文字符的两种方法: 正则和charCodeAt()方法

最近在为项目写登录注册系列页面, 表单验证无疑是不可缺少的部分, 在这个jQ插件满天飞的web年代, 表单验证倒也不是难事. 但再好的插件, 也并不能做到十全十美, 比如这次用到的我先前介绍过的Vanadium表单验证插件, 因为是E文中不存在占2个字符的字, 所以, 区分中英文字符就得自己扩展. 本文就将介绍两种区分中英文字符的方法: 利用正则和charCodeAt方法区分中英文字符.点此查看DEMO
正则无疑是最强大的判断各种条件的方法, 最近也在研习它, 虽然枯燥, 但仍有乐趣. 用它来判断一个双字节的中文字符也是轻而易举地. 而判断中文字符, Mr.Think也是非常推荐用这种方法的, 简单且执行效率高.
核心代码如下:

regExpForm.onblur=function(){
		entryVal=this.value;
		entryLen=entryVal.length;
		cnChar=entryVal.match(/[^\x00-\x80]/g);//利用match方法检索出中文字符并返回一个存放中文的数组
		if(cnChar!=null){
			entryLen+=cnChar.length;//算出实际的字符长度
		}
	}

第二种方法是通过charCodeAt()方法判断Unicode码值, 若大于255即为中文字符(为什么? 请Google). Mr.Think并不建议用这种方法的, 它的执行效率没有正则高, 也没有正则简单.
核心代码如下:

entryVal=this.value;
entryLen=entryVal.length;
for(var i=0;i<entryVal.length;i++){
	if(entryVal.charCodeAt(i)>255){//遍历判断字符串中每个字符的Unicode码,大于255则为中文
		cnArr.push(entryVal[i]);//讲符合条件的值插入到中文字符数组中
		//注意一个小bug,push是向数组的末尾添加一个或多个元素并返回新的长度,所以未刷新的情况下反复blur会累加字符值
	}
}
entryLen+=cnArr.length;

利用sort()和Math.random()实现元素的随机排列

一个随机排列元素的方法, 其实之前是在摄影页面写的一个小效果.
查看演示: 点此查看DEMO
实现方法
利用Math.random()产生随机数, 再通过sort()进行随机排列.
核心代码

function randomFun(){
	var h5=document.getElementsByTagName('h5')[0]
	var spanItem=document.getElementsByTagName('span');
	var random=function(){return Math.random()>0.5 ? -1 : 1};//为sort()传入的随机排列参数
	var spanArr=new Array();//用来存放元素的数组
	var cssArr=new Array();//用来存放样式值的数组
	var k,m;
	for(var i=0; i<spanItem.length; i++){
		spanArr.push(spanItem[i]);//将元素存入元素数组
		cssArr.push(i);//将对应的下标值存入样式值数组
	}
	spanArr.sort(random);//打乱元素数组排列顺序
	cssArr.sort(random);//打乱样式值数组排列顺序
	for(k=0; k<spanArr.length; k++){
		h5.appendChild(spanArr[k]);//将打乱后的元素重新插入到页面中
	}
	for(m in cssArr){
		spanArr[m].className='color_'+cssArr[m];//将打乱后的样式加给元素
	}
}