Archive for the HTML Category

JavaScript类继承与属性定义

Extjs的类继承——$.extend

Extjs是比较早期的web企业组件,代表了面向对象编程思想在js中的实践,其中最基本的就是类的继承,通过对prototype和constructor的复制和设置实现,但实现代码并不是那么容易,看过extjs的extend代码就会明白其难度,没有相当js经验很难看懂,当年看这块儿费了不少精力,后来考虑到版权问题,以及代码简化的需要,自己实现相关功能,经历几番修改才得以稳定

下面是最简化的实现,以及测试例子,当然这个实现存在些问题,比如对于javascript 1.8中的get set不支持,需要自行改造

function extend(sb, sp) {
	var sbp = sb.prototype;
	var F = function() { };
	F.prototype = sp.prototype;
	sb.prototype = new F();
	sp.prototype.constructor = sp;
	for (var name in sbp) {
		sb.prototype[name] = sbp[name];
	}
}
//test
function A() { }
A.prototype.name = "A";
function B() { }
extend(B, A);

var a = new A();
var b = new B();
console.log(b.name == "A");
console.log(b instanceof B);
console.log(b instanceof A);

打印结果全为true

JavaScript 1.8

到HTML5,出现了很多新的东西,很多高级应用不再考虑IE6,甚至IE7, 8,主流浏览器开始支持JavaScript 1.8,增加了新功能,支持严格模式-”use strict”,而getter, setter也有了更多的实现方式

Getter/Setter

get set语法

首先是直接语法上的支持,写法类似ActionScript

var foo = {
    get test(){ return this._test; },
    set test(value){
        console.log(value);
        this._test = value;
    }
};
foo.test = "abc";

函数支持 – Object.defineProperty/ defineProperties

此外还可以通过函数调用的方式实现,Object上定义了一些有用的方法,可以实现类的构造,函数扩展,属性扩展等功能,详见:https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Working_with_Objects

示例:

var Canvas = function(){};
Object.defineProperties(Canvas.prototype, {
    name: {
        get: function(){
            return this._name;
        },
        set: function(value){
            console.log(value);
            this._name = value;
        }
    }
});
var g = new Canvas();
g.name = "Qunee.com";

这里需要注意两点:

  • 只支持Object – 而不能是Function,比如上面的例子,只能是Canvas.prototype而不是Canvas
  • 部分属性名不可使用 – 比如”length”

严格模式 – “use strict”;

严谨模式就是在代码前加上下面这行代码:

"use strict";

“strict mode”限制了一些不安全的语法,使代码可读性增加,更便于调试,此外js引擎可以完全抛开老的兼容语法,从而提升性能

可参阅这篇文章:http://www.alloyteam.com/2012/06/it-is-time-to-use-the-javascript-strict-mode-strict-mode-to-enhance-the-efficiency-of-team-development/
详见:https://developer.mozilla.org/en/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode

famo.us是什么?

初次访问famo.us,被他的动画和交互效果所震撼,研究过其代码后,发现用到三种技术:matrix3d变换,requestAnimationFrame实现动画,以及物理运动引擎,单从技术上看三者都不难实现,但事物表面背后往往隐藏深意,famo.us的由来和目标却是野心勃勃。

famo.us2

创始人为web apps性能低下困扰已久,后受到Twitter Bootstrap的启发,试图提供一种用于开发本地级运行效率的web app框架,什么Sencha touch, jQuery Mobile等都是低效的代名词,这些为website而生的东西不适合复杂的web apps应用,应绕开浏览器固有的一些缺陷(document 渲染机制,CSS3导致的性能问题,浏览器之间的差异等等),实现一种针对web app的渲染引擎。

对于famo.us能否真正带来一波web app开发的热潮,尚不可知,从各种资料来看,已经有了一些app示例,但我未曾亲眼所见,目前公开的只有官网的元素周期表的例子,平板上运行也算流畅,但耗电厉害,实用性有待考证。

对技术感兴趣的朋友,可以看看这篇演示文稿:http://www.slideshare.net/befamous/html5-devconf-oct-2012-tech-talk ,作者详细介绍了famo.us 技术上的由来,作为演示文稿,循序渐进,简洁明了的思路也是值得借鉴的

famo.us

下面是2012年九月,famo.us的第一封简报,原文:http://us5.campaign-archive1.com/?u=4656ba2b0a364690c8530bc1e&id=675bbf010f

为什么我们如此特别

尝试使用HTML5构建一个web应用,实现可靠的本地程序级的运行效率,通过诸如Sencha Touch,jQuery Mobile和Appcelerator Titanium这样的框架是不可能实现的,实际上,很多公司,譬如Facebook,已经宣布放弃一些在HTML5上的努力,因为浏览器的一些固有问题需要很长时间来解决。Famo.us之所以特别,是因为我们实现了一种渲染引擎,绕开了浏览器的这些固有问题,从而实现可靠的本地级别高性能的复杂web应用,兼容多种设备,简单的说,经过多年的开发,我们解决了困扰复杂web应用的性能问题,应用的布局,动画和设计这些原本只存在于本地应用的东西,现在也可以用于web开发中,我们希望能带来一波从未有过的web app开发浪潮

一旦我们有了突破,下一步我们将寻求一种方式来分享这些成果,以社区驱动,检验,接受和合理分析

famo.us是什么?

如果你喜欢Twitter Bootstrap,那么你将爱上famo.us,很多方面我们都视Bootstrap为灵感来源
Bootstrap 引导web开发者构建跨设备访问的网站,给开发者提供视图图层,网站布局,框架,UI(用户界面)和UX(用户体验)组件,主题,字体和JavaScript插件
Famo.us 引导web开发者构建跨设备访问的应用程序,给开发者提供视图图层,应用布局,框架,UI和UX组件,主题,字体和JavaScript插件

路线图

我们将参照Bootstrap类似的展示方式,当我们正式启动,我们将公开我们GitHub上的工程,这样你可以分享和连接,我们还会创建Google组,你可以提问,Mark和我会直接回复,我们还会通过简报,博客(当它发布的时候),twitter @befamous 进行更新,我们将花费大量的时间保证文档完整和示例打包,就时机而言,我们希望第一个完整版本能在今年晚些时候发布(主要取决于文档)

使用 famo.us

famo.us的开发与Bootstrap类似,使用famo.us你可以先从应用布局开始,然后混合和匹配相应的famo.us 的UI和UX组件和部件

在我们的”hello world”应用中,你将使用famo.us 的卡片布局(Spotify, Twitter, Facebook和很多其他应用都使用这样的布局)构建一个Twitter iPad 应用的复制品,并采用了famo.us的UI和UX组件,并填充了一些演示数据,一旦你掌握了famo.us的窍门,你可以选择替代的应用布局,并按你所喜欢的修改,实际上你可以创建自己的应用布局,组件和主题,并将他们分享到famo.us市场,我们的目标是所有本地应用的主流布局,另外我们希望能和社区合作创造出更多东西,每个应用布局将能用于iOS和Android,同时作为Web app或者包装进一个本地app,实现手机,平板和PC上布局的灵活转换。

JavaScript模板

原文:https://developer.mozilla.org/en-US/docs/JavaScript_templates
翻译:ycoder.com

补充说明:原文列举了不少模板方案,但很多都已经不再维护或者久未更新,此外他所说的标准可能是mozilla自己的标准,而非w3c的标准,我简单试用了一些,感觉 PURE 方案还不错,此外大家还可以参阅这里的推荐:http://stackoverflow.com/questions/7788611/what-javascript-template-engines-you-recommend

除(Firefox)自带的XUL模板系统外,还可以使用JavaScript模板,这种方法也可以实现内容格式与结构的分离,但依赖于JavaScript模板引擎通过JavaScript业务逻辑将内容注入到模板中,不需要使用RDF/XML这样的技术

按语法风格

100%基于标准(没有自定义语法)

纯JavaScript(JavaScript函数调用生成HTML)

纯HTML(使用JavaScript选择器找出正常的HTML,按业务逻辑填充)

XSL

  • XSLTJS (实现跨浏览器支持的XSL模板)

E4X

标准友好的(自定义属性或者语法,但大部分采用标准兼容的用法)

X/HTML/E4X/XUL 自定义属性和元素

纯JavaScript嵌入在HTML/XML设计逻辑(ASP/JSP/PHP或者大括号{}风格)

自定义用法

HTML + 大括号{} 使用自定义的设计逻辑

HTML + 没有名称空间的自定义元素和属性

ASP/JSP风格的自定义逻辑,使用<%…%>

按特性

通过元素/节点匹配模板,将整个文档翻译到另一个

XSL

  • XSLTJS (跨浏览器使用的XSL模板)

通过JavaScript访问和修改CSS3动画

原文:Accessing & Modifying CSS3 Animations with Javascript By Joe
翻译:yCoder.com

昨天Chris Heilmann在Mozilla博客上写了篇关于使用javascript查找和生成CSS动画的文章,文中用了我的一个小例子,详细的说明了代码访问css动画的相关技术

Chris最后写道:

我希望用一个CSSAnimations集合类,通过json或者string存放不同的动画,并使用他们的名字作为key,这样,可以动态的创建一个新的css rule,并添加到document或者rule集合中(以保证跨浏览器),思考中

听起来是个好主意,所以我写了一段JavaScript代码来实现这样的接口

CSS Animation Store

这个主意是通过一个简单的接口来访问CSS动画,实际上之前的Morf.jsCSSA中都有这样的处理,大部分代码已经有了,只需要整整,按照Chris所建议的接口风格写下来

从GitHub下载CSS Animation Store

下面是CSS Animation Store的基本接口(关于代码如何工作的信息),将代码放在标签之前,会创建一个全局的对象 CSSAnimations,这个对象包含所有当前可以使用的CSS动画

比如,获取名称为”spin”的动画,你可以按下面的代码:

var spin = CSSAnimations.spin;

参数spin是一个KeyframeAnimation实例,有下面的属性和函数:

  • keyframes – KeyframeRule 集合
  • original – 原始对象 WebKitCSSKeyframesRule 或者MozCSSKeyframesRule 类型
  • getKeyframeTexts() – 返回所有keyframe文本集合, e.g. ['0%', '50%', '100%']
  • getKeyframe(text) – 返回指定文字的 KeyframeRule 对象, e.g. getKeyframe(’0%’)
  • setKeyframe(text, css) – 设置新的CSS, e.g.setKeyframe(’10%’, {background: ‘red’, ‘font-size’: ’2em’})

可以看出,KeyframeRule提供了一些方法和函数,是对 WebKitCSSKeyframeRule 和MozCSSKeyframeRule (注意是frame不是frames)的封装,具有下面的属性和方法

  • css – 该keyframe的css内容, e.g. {background: ‘red’, ‘font-size’: ’2em’}
  • keyText – 该帧的名称, e.g. 10%
  • original – 原始对象 WebKitCSSKeyframeRule 或者MozCSSKeyframeRule

示例

获取动画中的所有帧

var spin = CSSAnimations.spin;

for(var i=0; i<spin.keyframes.length; i++)
    console.log(spin.keyframes[i].css);

修改动画中的某一帧

var spin = CSSAnimations.spin;
spin.setKeyframe('10%', {background: 'red', 'font-size': '2em'});

反馈

给我博客或者GitHub留言,让我知道你的想法,我还开放了修改和增加的权限

使用原生JavaScript访问和创建CSS动画

如果你不想使用CSS Animation Store,或者只是想知道它的实现原理,可以参看下面的介绍

访问CSS动画

可以通过CSSOM访问keyframe动画,下面是我CSSA中的代码,用于访问指定的CSS动画

CSSAnimation.find = function(a) {
    var ss = document.styleSheets;
    for (var i = ss.length - 1; i >= 0; i--) {
        try {
            var s = ss[i],
                rs = s.cssRules ? s.cssRules :
                     s.rules ? s.rules :
                     [];

            for (var j = rs.length - 1; j >= 0; j--) {
                if ((rs[j].type === window.CSSRule.WEBKIT_KEYFRAMES_RULE || rs[j].type === window.CSSRule.MOZ_KEYFRAMES_RULE) && rs[j].name == a){
                    return rs[j];
                }
            }
        }
        catch(e) { /* Trying to interrogate a stylesheet from another domain will throw a security error */ }
    }
    return null;
};

使用如下:

var animation = CSSAnimation.find("spin"); // Get the animation named 'spin'

返回对象为 WebKitCSSKeyframesRule 或者MozCSSKeyframesRule 类型,取决于你的浏览器

创建CSS动画

下面是我现在找到的唯一的创建动画的方法,有点变通,通过代码生成CSS文本,然后插入到CSSOM或者通过添加一个<style>标签到当前document中

下面是在我的 Morf.js中的实现代码:

// Adds the CSS to the current page
addKeyframeRule = function(rule) {
    if (document.styleSheets && document.styleSheets.length)
        // Insert the style into the first attached stylesheet
        document.styleSheets[0].insertRule(rule, 0);
    else
    {
        // No attached stylesheets so append to the DOM
        var style = document.createElement('style');
        style.innerHTML = rule;
        document.head.appendChild(style);
    }
}

当你生成了你的CSS动画文本,你可以按下面的方式调用

var css = '@-webkit-keyframes spin { ... }';
addKeyframeRule(css);

JSProfiler v0.2 更新

JSProfiler v0.2 更新,改善了分析界面,增加了使用实例,打包了新的Chrome插件:
下载地址:JSProfiler v0.2

可二次开发

除了通过Chrome浏览器插件方式使用JSProfiler外,新增加了另一种使用方式:直接引入Profiler.js和Profiler.css到自己的网页中,类似下面的代码:

<!-- include profiler.js and profiler.css -->
<script type="text/javascript" src="../jsprofiler/Profiler.js"></script><script type="text/javascript">// <![CDATA[
window.addEventListener("load", function(){
//init js profiler ------ 1
var profiler = Profiler.init(window);

//start js profiler ----- 2
profiler.start();

//do some thing --------- 3
doTest();

//stop js profiler ------ 4
setTimeout(function(){
profiler.stop();
});
}, false);

// ]]></script>

JSProfiler API

这里简单介绍一下JSProfiler的API使用
Profiler.init: function(window) – 初始化分析器,并创建一个分析面板,并得到一个Profiler类的实例对象,用于后面使用,这里的传入参数是需要调试的window对象,默认是当前window,如果被测试window与当前window不同(比如在网页a.html中分析页面b.html中函数调用情况),则需要传入此参数。
Profiler#start: function() – 开始分析
Profiler#stop: function() – 停止分析,如果有分析面板,则会自动显示分析报表。

分析面板 – Profiler.Panel
调用Profiler.init()会自动创建一个分析面板实例,界面呈现如下:

完整实例

下面的例子演示了如何使用JSProfiler来分析自己的web项目,比如分析某次处理过程,通常的步骤是:
1、初始化Profiler对象
2、开始分析
3、测试用例,用户处理过程
4、定制分析,生成报表

sample.html
<!DOCTYPE html>
<html>
<head>
    <title>JSProfiler Sample</title>
    <style>
    body{
        margin:0;
        color: #333;
        font-family: verdana, helvetica, arial, sans-serif;
        font-size: 8pt;
    }
    h2{
        text-align: center;
    }
    .Panel{
        color: #DDD;
        -khtml-user-select : none;
        -webkit-user-select : none;
        -moz-user-select : none;
        width: 500px;
        height: 260px;
        background-color: black;
        margin: 20px auto;
        border: solid 16px #EEEEEE;
        box-shadow: 0 0 16px #000000;
        border-radius: 8px;
        position : relative;
        overflow: auto;
    }
    .Node{
        cursor: default;
        padding: 3px;
        border-radius: 2px;
        background-color: #EEEEEE;
        position: absolute;
    }
    </style>
    <script type="text/javascript" src="sample.js"></script>
    <script type="text/javascript">
    function doTest(){
        var sample = new yCoder.ProfilerSample(document.getElementById("canvas"));
        sample.loadNodes(100);
    }
    </script>
    
    <!-- include profiler.js and profiler.css -->
    <link rel="stylesheet"  href="../jsprofiler/Profiler.css" />
    <script type="text/javascript" src="../jsprofiler/Profiler.js"></script>
    <script type="text/javascript">
    window.addEventListener("load", function(){
        //init js profiler ------ 1
        var profiler = Profiler.init(window);
        
        //start js profiler ----- 2
        profiler.start();
        
        //do some thing --------- 3
        doTest();
        
        //stop js profiler ------ 4
        setTimeout(function(){
            profiler.stop();
        });
    }, false);
    </script>
</head>
<body>
<h2>JSProfiler Sample</h2>
<div id='canvas' class="Panel" ></div>
</body>
</html>

sample.js

var yCoder = {
__index: 0,
createNodes : function(parent, w, h, count, backgroundColor){
var i = 0;
while(i++ < count){
var x = Math.floor(Math.random()*w);
var y = Math.floor(Math.random()*h);
var div = document.createElement("div");
div.id = yCoder.__index++;
div.setAttribute("class", "Node");
div.style.backgroundColor = backgroundColor;
div.innerHTML = "" + x + " - " + y;
var tx = div.clientWidth / 2;
var ty = div.clientWidth / 2;
div.style.left = (x - tx) + "px";
div.style.top = (y - ty) + "px";
parent.appendChild(div);
}
}
};
yCoder.ProfilerSample = function(canvas){
this.init(canvas);
}
yCoder.ProfilerSample.prototype = {
init : function(canvas){
this.canvas = canvas;
var _this = this;
this.canvas.addEventListener("mousemove", function(evt){
_this.onmousemove.call(_this, evt);
}, false);
},
onmousemove : function(evt){
var target = evt.target;
if(!target || target.getAttribute("class") != "Node"){
return;
}
this.unhighlight();
this.highlight(target);
},
highlight: function(target){
this.currentElement = target;
this.currentElement.style.zIndex = "10";
this.currentElement.style.border = "2px solid";
},
unhighlight: function(){
if(this.currentElement){
this.currentElement.style.border = "";
this.currentElement.style.zIndex = "0";
}
},
loadNodes: function(){
var w = this.canvas.clientWidth;
var h = this.canvas.clientHeight;
yCoder.createNodes(this.canvas, w, h, 100, "green");
yCoder.createNodes(this.canvas, w, h, 100, "red");
yCoder.createNodes(this.canvas, w, h, 100, "blue");
this.deleteNodes("green");
},
deleteNodes: function(backgroundColor){
var childNodes = this.canvas.childNodes;
for(var i = 0, length = childNodes.length; i < length; i++){
var div = childNodes.item(i);
if(div && div.nodeType == 1 && div.style.backgroundColor == backgroundColor){
this.canvas.removeChild(div);
}
}
}
}

运行界面:

JSProfiler – JS性能分析工具

最近我做了一个javascript分析的工具,类似Java中的JProfiler,用于监测javascript类和函数调用时间,调用次数以及其调用路径等,JSProfiler使用树形结果直观的显示这些信息,让开发者能快速定位性能瓶颈所在之处,便于js类库和web应用程序的调优和分析。

为了更方便的使用,特意做了一个chrome插件的版本,赶在回家过年之前发布出来供大家使用,本来要放到chrome app store上去,但china不在服务地区,没法上传,于是只能先提供zip下载
chrome插件下载地址:JSProfiler Chrome Extension 0.1

详见:http://www.ycoder.com/jsprofiler/

关于CSS长度单位

很久没有更新日志了,乘着夜色休息前的一点时间,记下一些关于CSS的东西,比如长度单位,字体大小,文字高度等。

CSS中的尺寸单位

CSS中的长度单位很多种:cm, mm, em, pt, px …其中“px”也就是像素用处最多。这些单位分两种类型,一种是绝对长度,或者称为“真实长度”,比如厘米,毫米,英寸,这些都是物理学中标准的长度单位,在打印文档时有重要意义,因为你设置多大尺寸,打印出来就是真实的尺寸,但对于电脑屏幕来说,这些所谓的“真实长度”也并非真实的长度,你可以用尺子对着电脑屏幕测量,一个10cm宽度的div通常不会是10cm,如果你问我到底有多长,我会告诉你电脑中的“10cm”约等于378像素,至于这378个像素到底有多长,不同的显示器会是不同的结果,比如iPhone4的视网膜(这里有误,视网膜技术与分辨率没有实际关系)屏幕上面378像素宽度可能不到5厘米,这就是绝对长度与像素长度的区别

下面引用w3school中的列表:http://www.w3school.com.cn/css/css_units.asp

单位 描述
% 百分比
in 英寸
cm 厘米
mm 毫米
em 1em 等于当前的字体尺寸。2em 等于当前字体尺寸的两倍。

例如,如果某元素以 12pt 显示,那么 2em 是24pt。

在 CSS 中,em 是非常有用的单位,因为它可以自动适应用户所使用的字体。

ex 一个 ex 是一个字体的 x-height。 (x-height 通常是字体尺寸的一半。)
pt 磅 (1 pt 等于 1/72 英寸)
pc 12 点活字 (1 pc 等于 12 点(作者注:此处应该为磅,也就是pt))
px 像素 (计算机屏幕上的一个点)

与像素的关系

前面说到屏幕上的10厘米等于378像素,那么其他单位与像素是什么样的比例关系呢,除了“%”是一个相对长度外,每个长度单位都与像素有个固定的比例,下面我用个简单的脚本来寻求答案:

结果约为;

1pt = 1.3px, 1mm = 3.8px, 1ex = 6px, 1em = 11px, 1pc = 16px, 1com = 37.8px, 1in = 96px;

测试代码

<!DOCTYPE html>
<html>
<head><!-- yCoder.com -->
    <title>Measure Demo</title>
    <style>
    body{
        margin:0;
        background-color: gray;
        font-size: 11px;
        font-family: RedCircleRegular, verdana, helvetica, arial, sans-serif;
    }
    .Panel{
        width: 800px;
        height: 800px;
        background-color: white;
        margin: 20px auto;
        border: solid 16px #EEEEEE;
        box-shadow: 0 0 16px #000000;
        border-radius: 8px;
        overflow: auto;
        position: relative;
        padding: 20px;
    }
    .Node{
        background-color: white;
        border: solid 1px red;
        position: absolute;
        white-space:nowrap;
    }
    </style>
    <script type="text/javascript">
    function init(){
        var canvas = document.getElementById("canvas");
        var units = ["%", "px", "pt", "mm", "ex", "em", "pc", "cm", "in"];
        var width = 10;
        for(var i=0,l=units.length; i<l; i++){
            var div = createNode(units[i], canvas);
            div.style.top = (50 + 30 * i) + "px";
            div.style.width = width + units[i];
            div.innerHTML = "width : " + width + units[i] + " = " + div.clientWidth + "px";
        }

    }
    var index = 0;
    function createNode(innerHTML, parent){
        var div = document.createElement("div");
        div.id = index++;
        div.setAttribute("class", "Node");
        div.innerHTML = innerHTML;
        if(parent){
            parent.appendChild(div);
        }
        return div;
    }
    </script>
</head>
<body onload="init()">
<div id='canvas' class="Panel" >
canvas width: 800px; padding: 20px;
</div>
</body>
</html>

运行结果

译:HTML5演示文稿资源列表

http://blogs.msdn.com/b/cbowen/archive/2011/07/13/list-of-html5-presentation-resources.aspx

原作者:Chris Bowen
翻译:sam.sha – ycoder.com
备注:这些都是学习HTML5的绝佳资料,强烈建议收藏

在最近的web,编程分会和用户组会议中,我参加了很多关于HTML5, Internet Explorer 9/10, CSS3 等课程,这些会议展示和提及了很多资源,所以我在这里列出来,希望能对你有所帮助

HTML5

  • HTML5 at W3C –  标准和学习资料
  • HTML5 W3C Logo – HTML5和相关logo
  • HTML5 Labs – web标准的早期原型(比如 IndexedDB, FileAPI 等等)
  • ScriptJunkie.com –  web开发文章和信息
  • CanIUse.com –  各个浏览器对HTML5, CSS3以及其他技术支持的详细信息
  • Modernizr – HTML 和 CSS3特性探测变得容易
  • HTML5 Cross Browser Polyfills – Shims, polyfills helpful for implementing features while supporting a range of browsers – 被大部分浏览器支持的,有益于改进特性的 shims, polyfills (注释:polyfill是浏览器本地支持的一段代码或者插件,参看:http://remysharp.com/2010/10/08/what-is-a-polyfill/)
  • HTML5 Boilerplate –  一个HTML5模版,可以作为好的参考