2011年12月25日星期日

书写整洁优雅的CSS3代码 – Leeiio Chaos Made.

书写整洁优雅的CSS3代码 – Leeiio Chaos Made.

CSS 3.0 中文参考手册(CHM版) – Leeiio Chaos Made.

CSS 3.0 中文参考手册(CHM版) – Leeiio Chaos Made.

2011年12月22日星期四

ie6 getElementById/getElementsByName bug

ref
in ie6:
document.getElementsByName(nameValue) will return the element which id attribute equals to nameValue
document.getElementById(idValue) will return the element which name attribute equals to idValue
so prevent to use the same id and name attribute value in dom!

getElementsByAttribute

//属性选择符
//author:司徒正美 ref:http://www.cnblogs.com/rubylouvre/archive/2009/10/26/1590102.html
//正则支持 tag[attrName ^\$\*\~\!=attrValue]
var getElementsByAttribute = function(search) {
    var tag = /([\*a-zA-Z1-6]*)?(\[(\w+)\s*(\^|\$|\*|\||~|!)?=?\s*([\w\u00C0-\uFFFF\s\-_\.]+)?\])?/,
            node = arguments[1] || document,
            agent = search.match(tag),
            tag = agent[1] || "*",  //html标签
            attribute = agent[3],  //属性名
            type = agent[4] + "=", //比较符号 ^ $ * | ~ !
            value = agent[5],//属性值
            ieAttrFix = {"class": "className","for": "htmlFor"},  //特殊属性名
            returnElements = [],
        //IE5.5不支持“*”
            elements = (tag === "*" && node.all) ? node.all : node.getElementsByTagName(tag),
            length = elements.length;
    if ((!!document.querySelectorAll) && type != "!=") {//ie8+ 标准browser
        elements = document.querySelectorAll(search);
        for (var i = 0,length = elements.length; i < length; i++) {
            returnElements.push(elements[i]);
        }
        return returnElements
    }
    if (!+"\v1")  //ie检测
        attribute = ieAttrFix[attribute] ? ieAttrFix[attribute] : attribute;
    while (length--) {
        var current = elements[length],
                _value = !+"\v1" ? current[attribute] : current.getAttribute(attribute);
        if (typeof _value === "string" && _value.length > 0) {
            if (!!value) {
                var condition =
                        type === "=" ? //完全等于
                                _value === value :
                                type === "!=" ? //不等于
                                        _value != value :
                                        type === "*=" ? //包含
                                                _value.indexOf(value) >= 0 :
                                                type === "~=" ? //匹配当中的某个单词,如警告
                                                        (" " + _value + " ").indexOf(value) >= 0 :
                                                        type === "^=" ? //以XX开头
                                                                _value.indexOf(value) === 0 :
                                                                type === "$=" ? //以XX结尾
                                                                        _value.slice(-value.length) === value :
                                                                        type === "|=" ? //匹配属性值为XX或以XX-打头的元素
                                                                                _value === value || _value.substring(0, value.length + 1) === value + "-" :
                                                                                false;
                condition && returnElements.push(current);
            } else {
                returnElements.push(current)
            }
        }
    }
    return returnElements;
}

Node.contains

/*
 code ref  http://www.cnblogs.com/rubylouvre/archive/2009/10/14/1583523.html
 IE有contains方法。如果A元素包含B元素,则返回true,否则false。唯一不支持这个方法的是firefox。
 不过火狐支持compareDocumentPosition() 方法,这是W3C制定的方法,标准浏览器都支持。
 它的使用形式与contains差不多,但返回的不是一个布尔值,而是一个很奇怪的数值,它是通过如下方式累加计算出来的:
 二进制   数值 含义
 000000 0    元素一致
 000001 1    节点在不同的文档(或者一个在文档之外)
 000010 2    节点 B 在节点 A 之前
 000100 4    节点 A 在节点 B 之前
 001000 8    节点 B 包含节点 A
 010000 16   节点 A 包含节点 B
 100000 32    浏览器的私有使用
 A.compareDocumentPosition(B);//B与A不相连,B在A的后面,B被A包含 4+16 = 20
 B.compareDocumentPosition(A);//A与B不相连,A在B的前面,A包含B 2+8 = 10
 */
//PPK给出如下解决方法。
if (window.Node && Node.prototype && !Node.prototype.contains) {
    Node.prototype.contains = function (arg) {
        return !!(this.compareDocumentPosition(arg) & 16);//位运算 小于16结果为0
    }
} 
//2011.9.24 by 司徒正美
var contains = function(root, el) {
    if (root.compareDocumentPosition)
        return root === el || !!(root.compareDocumentPosition(el) & 16);
    if (root.contains && el.nodeType === 1) {
        return root.contains(el) && root !== el;
    }
    //两种原生方法都不支持的话 -_-||| 递归吧
    while ((el = el.parentNode))
        if (el === root) return true;
    return false;
}

getElementsByClassName

//code ref  http://www.cnblogs.com/rubylouvre/archive/2009/07/24/1529640.html
//支持 多class搜索   ie:getElementsByClassName("classA classB")
var getElementsByClassName = function (searchClass, node, tag) {
    var node = node || document;
    var tag = tag || "*";
    if (document.getElementsByClassName) {//尽量用原生方法
        var nodes = node.getElementsByClassName(searchClass),result = [];
        if (tag === "*") {//直接return
            return nodes;
        } else {
            for (var node  in nodes) {
                if (node.tagName === tag.toUpperCase()) {
                    result.push(node)
                }
            }
            return result
        }
    } else {
        var classes = searchClass.split(" "),
                elements = (tag === "*" && node.all) ? node.all : node.getElementsByTagName(tag),
                patterns = [],
                current,
                match;
        var i = classes.length;
        while (i--) {
            patterns.push(new RegExp("(^|\\s)" + classes[i] + "(\\s|$)"));
        }
        var j = elements.length;
        while (j--) {
            current = elements[j];
            match = false;
            for (var pattern in patterns) {
                match = pattern.test(current.className);
                if (!match)  break;
            }
            if (match)  result.push(current);
        }
        return result;
    }
}

2011年12月21日星期三

自定义radio和checkbox

ref

p:not(#foo) > input + label { background: url(gr_custom-inputs.png) 0 -1px no-repeat; height: 16px; padding: 0 0 0 18px; } p:not(#foo) > input[type=radio]:hover + label, p:not(#foo) > input[type=radio]:focus + label, p:not(#foo) > input[type=radio] + label:hover { background-position: 0 -181px; } p:not(#foo) > input[type=radio]:hover:checked + label, p:not(#foo) > input[type=radio]:focus:checked + label, p:not(#foo) > input[type=radio]:checked + label:hover { background-position: 0 -261px; } p:not(#foo) > input[type=radio]:disabled + label, p:not(#foo) > input[type=radio]:hover:disabled + label, p:not(#foo) > input[type=radio]:focus:disabled + label, p:not(#foo) > input[type=radio]:disabled + label:hover, p:not(#foo) > input[type=radio]:disabled + label:hover:active { background-position: 0 -221px; } p:not(#foo) > input[type=radio]:disabled:checked + label, p:not(#foo) > input[type=radio]:hover:disabled:checked + label, p:not(#foo) > input[type=radio]:focus:disabled:checked + label, p:not(#foo) > input[type=radio]:disabled:checked + label:hover, p:not(#foo) > input[type=radio]:disabled:checked + label:hover:active { background-position: 0 -301px; } p:not(#foo) > input[type=radio]:active + label, p:not(#foo) > input[type=radio] + label:hover:active { background-position: 0 -201px; } p:not(#foo) > input[type=radio]:active:checked + label, p:not(#foo) > input[type=radio]:checked + label:hover:active { background-position: 0 -281px; }

2011年12月20日星期二

javascript clone

ref
1.基本类型string boolean undefined null number皆可直接用=赋值
2.普通object clone
//最简单clone
function objectClone(){
 var ret=new Object();
 for(var p in this){
  ret[p]=this[p];
 }
 return ret;
}
//deep clone
function objectDeepClone(){
 var ret=new Object();
 for(var p in this){
  if(typeof this[p]!=object){
   ret[p]=this[p];
  }else{ 
   ret[p]=objectDeepClone.call(this[p]);
  }
 }
 return ret;
}
//利用构造器prototype属性赋值进行clone
function objectPrototypeClone(){
 var tmp=function(){};
 tmp.prototype=this;
 return new tmp;
}
这样clone出来的对象只读地共享一个原型的属性,它的最大优势是速度非常快,当我们希望快速复制大型对象时,可以使用这种方式,
但是它会造成访问速度降低,而且它实时反映父节点的变化。
3.内置对象的clone 3.1Function 对Function来说,完全产生一个副本是不可能的,因为我们无法保证构造的函数跟原来的函数在同一作用域,但是不包含作用域的实现是很容易的:eval(this);或者使用Function构造 return Function(new String("return ")+this)(); Function本身是个Object 因此必须加上Object的clone 实现functionPrototypeClone需要一点小花招 function functionDeepClone(){ var ret=Function(new String("return ")+this)(); for(var p in this){ if(typeof this[p]!=object){ ret[p]=this[p]; }else{ ret[p]=objectDeepClone.call(this[p]); } } return ret; } //原型clone function functionPrototypeClone(){ var tmp=Function.prototype;//备份 Function.prototype=this;//改变原型 var ret=(new Function(new String("return ")+this))(); Function.prototype=tmp;//恢复原型 return ret; } 3.2Array function arrayDeepClone(){ var ret=new Array(); //用for in考虑var a = [1,2,3];a["x"] = 100;这种情况 arrObj.slice(0)就有问题 for(var p in this){ if(typeof this[p]!=object){ ret[p]=this[p]; }else{ ret[p]=objectDeepClone.call(this[p]); } } return ret; } function arrayPrototypeClone(){ var tmp=Array.prototype; Array.prototype=this; var ret=new Array(); Array.prototype=tmp; return ret; } //其他的一些实现arrayClone的方法,如: function(){ return Array.apply([],this); } function(){ return [].concat(this); } 3.3Date function dateDeepClone(){ var ret=new Date(); ret.setTime(this.getTime()); for(var p in this){ if(typeof this[p]!=object){ ret[p]=this[p]; }else{ ret[p]=objectDeepClone.call(this[p]); } } return ret; } function datePrototypeClone(){ var tmp=Date.prototype; Date.prototype=this; var ret=new Date(); ret.setTime(this.getTime()); Date.prototype=tmp; return ret; } 3.4String Boolean Number都是只读的对象,所以只要=就可以了 3.5完整的clone function clone(){ var ret; if(this instanceof Function){ ret=Function(new String("return ")+this)(); }else if(this instanceof Array){ ret=new Array(); }else if(this instanceof Date){ ret=new Date(); ret.setTime(this.getTime()); }else if( (this instanceof String) || (this instanceof Boolean) || (this instanceof Number) ){ return this; }else{ ret=new Object(); } for(var p in this){ ret[p]=this[p]; } return ret; } function deepClone() { var ret; if(this instanceof Function){ ret=Function(new String("return ")+this)(); }else if(this instanceof Array){ ret=new Array(); }else if(this instanceof Date){ ret=new Date(); ret.setTime(this.getTime()); }else if( (this instanceof String) || (this instanceof Boolean) || (this instanceof Number) ){ return this; }else{ ret=new Object(); } for(var p in this){ if(typeof this[p]!=object){ ret[p]=this[p]; }else{ ret[p]=objectDeepClone.call(this[p]); } } return ret; } function prototypeClone(){ if(this instanceof Function){ var tmp=Function.prototype; Function.prototype=this; var ret=(new Function(new String("return ")+this))(); Function.prototype=tmp; return ret; }else if(this instanceof Array){ var tmp=Array.prototype; Array.prototype=this; var ret=new Array(); Array.prototype=tmp; return ret; }else if(this instanceof Date){ var tmp=Date.prototype; Date.prototype=this; var ret=new Date(); ret.setTime(this.getTime()); Date.prototype=tmp; return ret; }else if( (this instanceof String) || (this instanceof Boolean) || (this instanceof Number) ){ return this; }else{ var constructor=function(){}; constructor.prototype=this; return new constructor; } } 前面讨论了三种Clone的实现方法,它们各自具有适合的语义环境,比如对一个数组来说 若是把它理解为一个集合Collection 则应该使用浅clone(假如集合A是B的子集,则应保证A.clone()亦是B的子集),若是把它理解为一个向量Vector,则应使用深clone(保证对向量A的分量操作不应影响向量A.clone()的分量)。prototypeClone的一个最常见的应用场景是深度优先搜索算法算法,为了扩展解空间树,我们通常需要快速的构造一个副本,如果使用clone或者deepClone 这将非常慢,而深度优先搜索的特点是在字节点被销毁之前,父节点不会变化,所以prototypeClone是非常合适的。 附:Prototype-oriented Programming和Prototype Pattern 面向原型的语言思想跟原型模式是完全一致的:从同一原型clone出来的对象就是一类对象。Prototype-oriented的语言对这种模式提供了语言级别的支持,即所有"类"的定义都是通过指定该类的一个原型来实现的(Class-Based Programming是通过类结构声明来描述一类对象,meta-class则是通过构造一个"类对象"来描述一类对象)。每次实例话就clone一次原型,然而这种方式会造成信息的冗余:所有对象都持有原型对象的一个clone的副本,而且一旦某一对象被构造,修改原型不会对它造成任何影响,这对于希望在程序中统一改变某一类对象的人来说很不方便。于是,一种变通的方法产生了:引用型原型对象,与之相对,原来的原型对象使用方法被称为 复制型原型对象。引用型原型对象不再clone原型,而是保存一个指向原型的指针,当访问属性时,首先检查自己的属性,当查到不存在时,则通过指针向原型索取相应属性。而引用型原型就是javascript的面向原型特性的实现方式。

2011年12月18日星期日

弹出窗口显示图片

src
$(".view-full-size").click(function() {

  var mainScreenshot = $("#main-screenshot");

  var theImage = new Image();
  theImage.src = mainScreenshot.attr("src");

  var winWidth = theImage.width + 20;
  var winHeight = theImage.height + 20;

  window.open(this.href,  null, 'height=' + winHeight + ', width=' + winWidth + ', toolbar=0, location=0, status=0, scrollbars=0, resizable=0'); 

  return false;

});
demo