iOS5 innerHTML插入内联touch事件的问题

2011-10-19 评论(2) 分类:技术文章 Tags:

iOS5一出来,很多对safari的溢美之声,那些新增的特性确实好,但这个版本的safari很有问题。

document.getElementById("test").innerHTML = '<div ontouchstart="alert(\'touchstart\')"></div>'

一般,这样的代码是没问题的,一段HTML字符串赋给DOM的innerHTML后,自动生成DOM,并且上面的内联事件都是有效的。在至今所有浏览器都可以这样,但现在在iOS5的Safari不行,生成的DOM中ontouchstart事件无效,目前测试ontouchstart/ontouchmove/ontouchend都不行,若改成onmousedown,onclick等都是可以的。这个问题导致了jquerysencha的一些应用都挂了。

目前的解决办法就是,先把HTML加入一个新建的DOM里,再用cloneNode把创建好的DOM取出来加入目标位置,这样才可以。如果不用cloneNode而是直接把创建好的元素塞进去还是不行的。

var dom = document.createElement("div");                                    
dom.innerHTML = '<span ontouchstart="alert(\'touchstart\')">touchstart dom create</span>    ';                                                                          
document.getElementById("testTSdom") .appendChild(dom.childNodes[0].cloneNode(true));

可以在这里 http://bangswork.googlecode.com/svn/trunk/lab/ios5touchstart/index.html 看到效果

这应该属于一个bug,居然就带着这么明显的bug发布出来了,要折腾死做移动版的前端了。

此外,还发现iOS5下Safari的一些其他问题,例如缓存很奇怪js excution timeout,还有一些已经碰到但未明原因的,总之,这个safari很有问题。

node.js源码研究—模块组织加载

2011-6-8 评论(1) 分类:技术文章 Tags:

粗略研究了一下node.js源码,它有8000行C++代码,2000行javascript代码,来看看js和C++间是怎么组织连接起来,以及各个模块是怎样互相调用的。

本文使用的node.js版本是0.4.8,可以在https://github.com/joyent/node/tree/v0.4.8这里看到源码。

js2c.py

node.js使用了V8附带的js2c.py工具把所有内置的js代码转换成C++里的数组,生成node_natives.h直接include到程序中,成了C++源码的一部分。这样做能提高内置js模块的编译效率。

node.js里内置的javascript包括了主程序src/node.js和模块程序lib/*.js,通过js2c.py让每一个js文件都生成一个源码数组,存放在build/src/node_natives.h里,node_natives.h在node.js编译后才会生成(编译的脚本wscript中调用了js2c.py),可以看到大致的结构如下:

namespace node {
    const char node_native[] = {47, 47, 32, 67, 112 ......}
    const char console_native[] = {47, 47, 32, 67, 112 ......}
    const char buffer_native[] = {47, 47, 32, 67, 112 ......}
    .....
}
struct _native {  const char* name;  const char* source;  size_t source_len;};
static const struct _native natives[] = {
  { "node", node_native, sizeof(node_native)-1 },
  { "dgram", dgram_native, sizeof(dgram_native)-1 },
  { "console", console_native, sizeof(console_native)-1 },
  { "buffer", buffer_native, sizeof(buffer_native)-1 },
    ....
}

这个文件被包含在node_javascript.cc里,node_javascript.cc提供了两个接口:
MainSource() 处理node_native源码返回v8::Handle类型的数据可供编译。
DefineJavaScript(target) 把其他所有模块源码变成v8::Handle类型后加载到传入的target对象上。

所有的js模块都被转换成了C数组,接下来看看它们怎么执行和互相调用。
(更多…)

simple node.js web server with js server page

2011-2-19 评论(0) 分类:技术文章 Tags:

一开始捣鼓node.js时我就想用它快速建一个网页,但它没有自带的像jsp asp php那样可以把脚本嵌入页面的功能,尝试用john的micro-Template做一个很简单的能在页面嵌入脚本的web server
(更多…)

移动浏览器的viewport

2011-1-2 评论(9) 分类:技术文章 Tags:

对于移动web开发,最好了解一下viewport的概念,在quirksmode.org有两篇文章详细介绍了它,A tale of two viewport(1 2),感觉非常好,本来想翻译的,但这两篇文章实在太长了,没耐性,于是抽取了其中重点讲viewport的部分,用半翻译半自己写的方式写出来,这也是为了让自己能够理解得更好一些。

其中CSS像素和设备像素的概念,还有js获取各种宽高和位置的内容都没有提及,要想了解得更清楚还是推荐看看那两篇文章。以下图片均来自quirksmode.org

桌面浏览器

先说说桌面浏览器上viewport的概念,在桌面浏览器上viewport就是浏览器内容的可视范围,它决定了<html>元素的默认宽高。举个例子:

在一个流动布局的页面上,你给侧栏设置了width:30%,放在<body>下,正常情况下你拖动浏览器,改变浏览器的大小,这个侧栏会自动调整宽度使它的宽度为浏览器宽度的30%,那么这个自动调整的过程具体是怎样的呢?
(更多…)

解析豆瓣前端轻量框架Do

2010-11-8 评论(6) 分类:技术文章 Tags:

豆瓣使用了jquery框架,但jquery没有提供大型网站所需要的模块化管理,所以豆瓣前端团队就在jquery之前再包裹一层轻量级的框架,用来组织js模块并管理模块之间的依赖关系,按依赖关系自动加载js模块。这个keynote有相关信息。

do的源码压缩后基本都是单字符的变量,读起来相当费劲,整理了一下,给各个变量加上适当的名字,也是理解和学习这个轻量框架的过程。

源码很简单,主要思路就是:通过Do.add()全局存储各个模块的信息,在执行do时把各模块的依赖和执行函数整理成一个有先后顺序的队列,依次加载/执行这个队列。

例:

//uibase模块地址是ui.js
//dialog依赖ui模块
Do.add('uibase', {path: 'ui.js', type: 'js'});
Do.add('dialog', {path: 'dialog.js', type: 'js', requires: ["uibase"]});

Do("dialog", function(){
//使用dialog
});

do里的makeQueue方法会生成这样一个队列:[“jquery.js”, “uibase”, “dialog”, function()]

jquery.js是core_lib里的。接着队列执行器Execute就会依次加载jquery.js ui.js dialog.js,最后执行那个依赖dialog模块的function()

整理后的源码:
(更多…)

iQuery实现CSS3 transition动画接口

2010-8-24 评论(2) 分类:技术文章 Tags:

给iquery加了跟jquery差不多的动画接口animate,不过实现上是通过CSS3的transition。

效果点这里 (桌面浏览器只支持webkit内核,如chrome/safari)

iQuery源码

(更多…)

简化代码学习jquery动画源码

2010-8-18 评论(4) 分类:技术文章 Tags:

效果见这里:http://bangswork.googlecode.com/svn/trunk/lab/effect/index.html

jquery的动画总体思路是:

有一个fx类专门处理动画,fx的各个实例共享一个timers数组和一个setInterval。对每个传进来的dom的每个属性值都新建一个fx实例去处理,一个fx实例对应一个dom的一个属性的变化。fx里有个step函数,可以计算出当前这个时刻这个属性要达到什么值。

这个step会通过共用的一个setInterval每13毫秒执行一次,这就可以使得它行成动画。另外如果浏览器速度太慢无法达到13毫秒执行一次step,动画也会按时完成,因为是根据当前系统时间计算属性要达到的值的。

每一个fx实例的step都会放进timers数组,实际上setInterval是持续执行timers里的每一个函数,这样只用一个setInterval就让众多属性“一起动”了。step里判断到超过了动画运行的时间,就会返回false让它从timers里移除,timers为空时clearInterval。

下面简单实现这整个过程:
(更多…)

javascript关于数组的几个常用伎俩

2010-8-16 评论(1) 分类:技术文章 Tags:

1.把对象变成类数组

var a = { name : "jquery" },
b = ["elem1", "elem2", "elem3"];
Array.prototype.push.apply(a, b);
alert(a)	//[Object object]

//可以像遍历数组一样遍历这个对象
for ( var i = 0; i &lt; a.length; i ++ ) {
	alert(a[i])
}

jquery就是用这种方法把jquery对象变成类数组的,效率还很高。

2.去掉一层嵌套数组

var a = [[1,2], 3, [4,5,6]];
var b = Array.prototype.concat.apply([], a);
console.info(b) 	//1,2,3,4,5,6

concat方法:

arrayObject.concat(arrayX,arrayX,……,arrayX)
concat() 方法用于连接两个或多个数组。arrayX为n个数组or元素参数
console.info([1].concat([2,3], 4)) //1,2,3,4

apply方法:

fn.apply(obj, args)
在obj的作用域下调用函数fn,并把数组args里的第i个元素作为第i个参数传给fn
例如
fn.apply(window, [1,2,3]) 等于 fn(1,2,3) (直接调用一个函数作用域就是window)

合起来就有上面那个效果了。

3.复制数组

利用Array.splice(0)可以快速复制一个数组

var a = [1,2,3],
b = a.splice(0);
alert(b)//1,2,3
alert(a==b)//false

4.高效合并字符串

var a = [“<div>”,”<span>”,”</span>”,”</div>”];
alert(a.join(“”)) //”<div><span></span></div>”

通过这种方式合并字符串效率比 + 号高了近七八倍,因为js的机制导致每次给字符串追加内容都是抛弃原有字符串新建另一个追加后的字符串,所以效率会低。

在firefox下测试:

var a = []
for (var i = 0; i &lt; 100000; i++) {
	a.push("&lt;div&gt;");
}
console.time("arr");
a.join("");
console.timeEnd("arr");console.time("str");

var b = "";
for (var i = 0; i &lt; 100000; i++) {
	b += "&lt;div&gt;";
}
console.timeEnd("str");
//arr:19ms
//str:141ms

通过PHP curl向腾讯微博发送广播全过程

2010-8-15 评论(26) 分类:技术文章 Tags:

效果见这里:http://cnbang.net/lab/txwb/

由于朋友分布在不同的微博,我希望有个同步到twitter、新浪微博、腾讯微博的工具,但等这么久都没出现这样的工具,微博通似乎停工了,也不支持twitter和腾讯微博,于是想自己做个。

新浪微博和twitter都开放API,要实现同步发送很简单,腾讯微博未开放,就需要hack一下了。这次把研究过程都记录下来了,写得很长~实际上在curl实现那部分我花的时间比较多,走的弯路也多,但由于篇幅原因那部分都简省了~

(更多…)

ThinkPHP数据自动验证中unique的缺陷

2010-6-23 评论(8) 分类:技术文章 Tags:

ThinkPHP可以为Model添加$_validate属性,使得在使用create方法创建数据对象时能自动对数据进行验证,详细看这里

这其中有个unique的方法,即是验证指定栏的数据在表中是否唯一。向数据表里插入“唯一”字段时可以自动判断并且提示错误,但ThinkPHP这个功能有个缺陷,导致这个unique验证基本上只能在添加数据的时候使用,不能在编辑数据的时候用。

unique验证的源码在ThinkPHP/Lib/Think/Core/model.class.php第944行,对unique验证时就是查找整个数据表这一栏这个值是否存在,这样做在添加数据时没问题,但如果在编辑状态下就有问题了。例如编辑一个用户名和密码,现在不修改用户名只修改密码,因为用户名要进行唯一验证,此时这个用户名没有修改,数据表上是有这个用户名的(就是在编辑的这行数据),于是就提示已存在此数据,无法保存。

我想解决的办法可以是:在验证的时候判断是否传进了此表主键的值,例如判断是否传进了$_POST[“admin_id”],如果传进了,对搜索到的数据提取admin_id判断是否相等,相等则不存在unique错误,不相等才出现错误。在这么核心的地方调用$_POST似乎破坏结构,那可以改改$_validate传递的参数。还不熟悉ThinkPHP,就不动手改了。

目前在我的应用中是只在新增数据时检测unique,编辑时不检测,如果编辑时unique的栏有重复了,再在save()时判断是否插入成功和提示,暂时是这样。