无聊哥的代码 — “鸡”查询

刚上班,首先是文档哥,之后就是无聊哥了,真杯具。但是杯具下就好了,人不杯具。消遣的最好方式就是练练脑,写代码,query就是杯具下的产物。先出土个雏形,有时间还成无聊哥了再来扩展下。

query根据CSS规则来查询DOM,提供了基础的CSS选择符:

tag,.class,#id,[attr],tag[attr],tag[attr="value"]...

在测试跟jquery的查询速度比较的时候,再添加了对querySelectorAll(语法是:baseElement.querySelectorAll(selector),这里的baseElement其实是可以为除了文本节点和空节点之外的任何的DOM节点的,别以为只是document而已)的支持。编写的代码中加入了本人认为不错的编写方式,如果你对阅读代码有兴趣,那就看看吧,欢迎提出更好的方式(如果这里显得难看了,就自己下载来看:query.js):
(全文…)

图片导航设计方案

2010-7-29 Update:

在第一种实现方案中,如果图片的父元素设置了padding、margin之后,就会使得FF、Chrome等逻辑判断失误,而IE还完好。

———————-纠错分界线————————–

说“图片导航”或许很迷糊,我也迷糊不知道怎么描述,就是类似于Google、QQ空间、百度图片搜索中的在图片中出现上下箭头或者左右箭头来指示下一个和上一个图片的功能。昨天同事问到我这方面的实现方式,也就暂时想了两种。

之前查看过Google的方法是在图片上添加两个HTML元素作为逻辑操作对象(包括切换鼠标样式、点击事件等),这样就显得比较复杂了,需要确定图片的在页面中的位置、图片的宽高、之后还要判断鼠标的位置……QQ空间的相册导航,是在图片本身来操作逻辑的,这同我第一种方案很类似,而百度图片搜索结果页中图片导航是在图片的父元素中做逻辑的,这样就避免了图片大小对导航的干扰的问题(主要是如果图片太小,在图片上做导航就显得迷糊了,特别是鼠标的样式切换)。下面来说说我的方法。

第一种,直接在图片上做逻辑。事件参数e有这么两个参数,在FF等浏览器下是layerX,layerY,在IE下是offsetX,offsetY,用于在一个DOM元素触发事件的时候,鼠标在该元素上的偏移量。这个是好方法啊,在结合offsetHeight和offsetWidth,就可以直接在图片上做判断了,给图片添加mousemove、onclick事件来处理鼠标样式切换、点击事件逻辑等等。《测试用例1》,可是这种方法的一个缺点是:在IE6下,当鼠标移动到鼠标的时候,会默认的弹出一个框,很杯具。

第二中方式就是根据上面的技巧,在图片上覆盖一个div(或者其他的能覆盖的元素都成),覆盖就得获取到图片在页面中的坐标以及宽高了,通过offsetLeft和offsetTop可以方便的得到,兼容性也还好,对于不是非常复杂的DOM结构和CSS布局,应该都是没啥问题的。《测试用例》,这样就避免了IE6下弹出框的问题。不过这样代码就得写多几行了。

具体的实现方式可以查看上面给出了两个实例。

随便写的一个Node代码

2010-6-29 update

判断是IE6、7浏览器的方法还可以通过检测:document.documentElement.hasAttribute这个方法是否存在来判断。IE6、7下document.documentElement是不支持hasAttribute方法的;IE8、FF、Chrome、Opera等都支持。这样就可以避免丑陋的@cc_on判断方式了,不过在性能上,或许还是会@cc_on比较好。

——————–完美的分界线——————-
昨天想起了之前在口碑的时候就想写的一个代码:把HTML标签名作为方法来连缀性的插入元素,比如下面的操作方式:

var root=Node("div","",{"id":"test","class":"div","onclick":"alert(this.innerHTML);",
"style":"background-color:#f00;"})
.h1("P Element in DIV Element",{"class":"p"})
.em("EM Element",{"class":"em"}).appendTo(document.body);
//==========================================
Node("div","",{"class":"div","onclick":"alert(this.innerHTML);"})
.h1("P Element in DIV Element",{"class":"p"})
.em("EM Element",{"class":"em"}).appendTo(root);

如上代码所示,将HTML的标签名作为方法,在Node方法执行的时候就动态生成一个DOM元素,之后调用的HTML标签名形式的方法会一步一步的appendChild到前面的一个DOM元素中,调用每一个HTML标签名形式的方法都会动态生成一个相应的DOM元素,最后调用appendTo或者beforeTo方法将Node方法动态生成的DOM元素插入到这两个方法参数指定的父元素中。同时,还可以设置DOM元素的attribute、style、text。是不是有点意思呢?^_^

但是在写这个代码的时候,遇到的最大困难,就是setAttribute了,一来IE6、7对一些属性使用了不同的DOM属性名,在设置style的时候,也存在cssText和直接setAttribute style的差别,这些都是比较纠结的。幸好,下面的几个知识点可以解决大部分的冲突:

  1. 利用IE下setAttribute方法的第三个参数,可以解决IE6、7下对于一些属性大小写的差别。《setAttribute Method》、《setAttribute()方法参数问题
  2. 对于一些IE6、7跟其他浏览器的属性名完全不同(比如:class、for、checked、selected),这可以通过一个字面量对象来纠正,可以看下面我写的源码的解决办法。
  3. IE6、7无法给onxxx属性(事件)直接赋值为字符串,需要赋给它函数才行。这个就需要做判断了,本人使用了@cc_on来判断IE的版本,并通过new Function的方式给IE6、7设置onxxx这样的属性。
  4. 同时,还有一个小陷阱,在HTML标签中直接声明onxxx属性的时候,不能够使用匿名函数的方式,比如:onclick=”function(){alert(‘hello’);}”,这将会造成语法错误。

(全文…)

javascript代码性能优化

在这篇文章叙述的关于Javascript代码优化,其实并没有什么新意,关于这方面的优化,一直都是Nicholas C. Zakas的专利。我在这里将要说的是对当前众多关于Javascript代码优化的方式一个小总结,并尝试去归类各种不同的优化方式,方便于记忆众说纷纭的优化技巧。本人归类的结果如下图所示:

Javascript代码优化无非主要围绕:DOM操作、循环、闭包、对象重复出现、对象的声明方式、作用域链、字符串操作、类的声明方式等等。循环、闭包、对象重复出现是从作用域链的角度去优化的;DOM操作主要围绕HTMLCollection、NodeList等来优化;对象的声明方式主要是对象(Object)、数组(Array)、字符串(String)、函数(Function)、正则(RegExp)等内置的对象使用字面量的方式来声明,这个比使用new来实例化相应的对象在性能上要强很多;字符串操作的优化方式主要是通过数组的push和join方法;类的声明方式优化方式主要是分清属性和方法的声明的方式,方法使用prototype的方式来声明;Javascript语言本身的流程操作语句的优化(if、switch、with、eval等等)。

因此,我将Javascript代码优化主要分为六类:DOM“真空”空间缩短作用域链字面量声明方式字符串操作类声明方式流程操作语句。下面将逐个叙述:

(全文…)

fireTest—类似于firebug查看元素padding、margin等等的方法

//////////////////// 2010-2-27 update //////////////////

根据需要,增加了使用和禁用开关模式(右下角),在页面中直接加载fireTest.js文件即可:

<script src="fireTest.js" type="text/javascript"></script>

或者直接链接到本站fireTest.js文件:http://www.ilovejs.net/lab/fireTest/fireTest.js
点击查看测试页面

///////////////////////////////////////////////////////////////////

昨晚睡觉的时候脑子突然想实现这么个东东 — 类似于firebug的查看DOM元素padding、margin的情况。虽然firebug已经发布了Lite版本,可以在非火狐的浏览器下测试网页的各种信息,但是由于Lite版本是用js实现的,在某些浏览器下(特别是IE下),影响了整体的性能,使用上也不太方便查看。目前各主流浏览器都内置了这项功能,Google Chrome,Safari,Opera,IE8等等都已经有非常强大的开发人员测试工具。

写这个工具一方面是为了方便自己在非火狐浏览器下类似于firebug的查看DOM元素的padding,margin的情况(除了IE6),但是目前还不支持IE6(fuck 框模型hack),日后有时间完善这个。

点击查看测试页面

获取DOM元素的真实高度和宽度

以前在做动画脚本的时候,遇到过这样的一个问题:当DOM元素display:none;之后,你将得不到它的实际高度和宽度。这个在fadein等类似效果的时候就有些问题了。这个问题困扰了一些时间,最后觉得还是元素隐藏导致的结果,因此采用了这样的方法:将隐藏的元素的display暂时设置为block,获取到真实的高度和宽度之后,再还原隐藏元素。下面是我封装好的获取元素的真实高度和宽度的对象:

var Style = {
    //获取元素最终的样式
    getFinalStyle: function(elem, css){
        if (window.getComputedStyle) {
            return window.getComputedStyle(elem, null)[css];
        } else if (elem.currentStyle) {
            return elem.currentStyle[css];
        } else {
            return elem.style[css];
        }
    },
    height: function(elem){
        if (this.getFinalStyle(elem, "display") !== "none") {
            return elem.offsetHeight || elem.clientHeight;
        } else {
            //获取隐藏掉的函数的高度,先让它显示,获取到高度之后再隐藏,下同
            elem.style.display = "block";
            var h = elem.offsetHeight || elem.clientHeight;
            elem.style.display = "none";
            return h;
        }
    },
    width: function(elem){
        if (this.getFinalStyle(elem, "display") !== "none") {
            return elem.offsetWidth || elem.clientWidth;
        } else {
            elem.style.display = "block";
            var w = elem.offsetWidth || elem.clientWidth;
            elem.style.display = "none";
            return w;
        }
    }
};

//Usage:
onload = function(){
     alert(Style.height(document.getElementById("div")));
}