Actually,simplicity is not simple

innerHTML操作的改进

function asyncInnerHTML(HTML, callback) {
    var temp = document.createElement('div'),
        frag = document.createDocumentFragment();
    temp.innerHTML = HTML;
    (function(){
        if(temp.firstChild){
            frag.appendChild(temp.firstChild);
            setTimeout(arguments.callee, 0);
        } else {
            callback(frag);
        }
    })();
}

看看上面的代码,对平常我们用的innerHTML做了些许改进,不管在用处上还是浏览器呈现上都有所进化。

  • 使用setTimeout防止出现浏览器堵塞现象(及长时间没反应,突然一下子呈现的现象)
  • 使用DocumentFragment提升效率

再来看下它的作用吧

var htmlStr = '<div><p>...</p><p>...</p><div><div>...</div>';
asyncInnerHTML(htmlStr, function(fragment){
    // You can treat 'fragment' as a regular node.
    document.body.appendChild(fragment);
});

我想这已经很明了了,这函数强于 string 转 DOM 并得到转化后的DOM对象,做点记录方便以后使用吧!

这函数的出处看这里

用JS动态监听CSS加载

周五时有个工作时需求等CSS加载完后后再执行些JS代码,但发现使用onload在Firefox chrome下不行但IE8下却可以。

第一次发现IE也有让我省心的时候啊!

问谷大叔得知研究这问题的人还挺多的:

  • 在射雕的lab中发现有两个测试 load js css css preload,讲得挺多的,而且在其seajs中已经运用上了,拜之~~
  • 在国外一相当大的专业问答网站中找到相同问题,也有不少人给出了解答 javascript capturing load event on link。主要讲到两种方案:
    1. 使用settimeout循环判断不同浏览器中当CSS加载完或失败时的特性,射雕使用的方案也是这种,但特性有所不同;
    2. 方案挺有意思的,同时创建link、img标签并将CSS的URL同时赋于两个标签,用img标签的onerror事件做为加载监听器,但这种方案会产生两个请求,并且img标签所发出的请求会标注不支持gzip。
  • Cross Browser Stylesheet Preloading中也提供了一解决方案,但代码是基于mootools写的,最重要的一点是延时判断link标签的ownerNode或owningElement属性,没用过这两个属性,不懂!!!

继续问谷大叔找到关于ownerNode(返回节点与此相关联的样式表文件的。)以及owningElement(返回附加到元素节点上的属性)的定义。

this.link.id = this.getID(); // 创建link标签时给标签加上了ID属性
// 注意 这里的file = document.styleSheets[0]; 或 document.getElementsByTagName('link')[0].sheet;
var owner = file.ownerNode ? file.ownerNode : file.owningElement;
if(owner && owner.id == this.getID()) {
    this._onready();
    return;
}

并且看到了对link标签事件支持情况:

IE6-IE9、opera  都支持link标签的 onload  onerror事件
firefox chrome  safari 都不支持link标签的 onload  onerror事件

input只能输入数字的方法

昨天写后台的表单时的需求,发现自己对这方面的了解很不够,在网友steven_2005的这博文中的实现方式不错,但和我的需求还差一点,所以改进了下(一个输入字符不能是小数点):

// input只能输入数字和小数点
function DigitInput(el,e) {
    //8:退格键、46:delete、37-40: 方向键
    //48-57:小键盘区的数字、96-105:主键盘区的数字
    //110、190:小键盘区和主键盘区的小数
    //189、109:小键盘区和主键盘区的负号
    var e = e || window.event; //IE、FF下获取事件对象
    var cod = e.charCode||e.keyCode; //IE、FF下获取键盘码
    //小数点处理
    if (cod == 110 || cod == 190){
        (el.value.indexOf(".")>=0 || !el.value.length) && notValue(e);
    } else {
        if(cod!=8 && cod != 46 && (cod<37 || cod>40) && (cod<48 || cod>57) && (cod<96 || cod>105)) notValue(e);
    }
    function notValue(e){
        e.preventDefault ? e.preventDefault() : e.returnValue=false;
    }
}

使用方式很简单,要注意的是函数得绑定在onKeydown事件上

<input type="text" onkeydown = "DigitInput(this,e);" />

或用事件绑定的方式(jQuery的代码):

$('input').bind('keydown', function(e){
    DigitInput(this, e);
});

实现IE下Array.indexOf函数

我一直觉得Array的indexOf函数很好用,可惜微软的IE浏览到IE8都还不支持,只有自己拓展了,下面的代码我认为是比较的实现。

if(!Array.prototype.indexOf){
    Array.prototype.indexOf=function(el, index){
        var n = this.length>>>0, i = ~~index;
        if(i < 0) i += n;
        for(; i < n; i++) if(i in this && this[i] === el) return i;
        return -1;
    }
}

这函数里的~~很有意思。~~是由两个~(按位“非”)运行符组成,发现实用性还是有的。

~~true; //1 Number
~~false; //0  Number
~~'123'; //123  Number
~~'0fs'; //0  Number

上面的测试代码可以告诉我们‘~~’对来对纯数字的String或布尔值转为数字很有用。以前写过这样的代码

[console.log, alert][!!document.all?1:0]('nootn.com简单其实不简单!');

现在可以这样写了

[console.log, alert][~~!!document.all]('nootn.com简单其实不简单!');

速记: jQuery两DOM比较

今天在写基于jQuery的一项目时遇到的问题,先看代码:

var a = $('#sR_Tab');
var b = $('#sR_Tab');
console.log(a == b);   // return false

看到测试返回的值第一时间我感到很差异,但细想下后就明白了,用jQuery有几年了,居然到现在才注意到这问题,失败啊!

在这也给自己理一理吧,再让自己记牢点。

看到上面测试如果还不能想明白的可以测试以下代码:

var a = $('#sR_Tab');
console.log(typeof a);  // return object

结果返回说是Object类型,实际上a是个Array类型的Object,在JS类型中没有这种说法,但切能很让我们很清楚的了解这变量的真正类型,谁叫JS的类型总是含糊不清的。

明白上面的a是个Array类型的Object后就能很好的解释为什么a != b了。在JS的变量中,Array、Object类型的变量其值是指向数据的指针,而非数据本身。而jQuery的$()函数是会返回一个全新的Array类型的Object。所以虽然a、b变量的值是指向不同空间的地址,其值自然不同。

那要如何才能返回真正的比较结果呢?其实jQuery中的$()函数返回的是所选DOM的数组,所以只要得到真正DOM的引用进行比较就能得到我们真正要的比较结果,写法也很简单:

var a = $('#sR_Tab');
var b = $('#sR_Tab');
console.log(a[0] == b[0]);   // return true

呵呵,就这么简单。只是到现在才注意到两jQuery对象比较返回的结果是false让我很郁闷。真郁闷!