Archive for the ‘Javascript’ category

twitter前端简单分析(一)

May 28th, 2011

今天在上twitter时,偶然发现twitter前端也采用了JS模板引擎,于是便整体浏览了下twitter使用到的js,做个简单的记录分析。

以http://twitter.com/#!/mops_2010 为研究对象

主要采用的分析工具:Firebug以及http://www.strictly-software.com/unpacker

内嵌JS待分析
以下为加载的JS:
1. 加载GA
2. 加载http://a3.twimg.com/sticky/base.21.bundle.js
3. 加载http://a1.twimg.com/a/1306441242/javascripts/api.bundle.js
4. 加载http://a3.twimg.com/a/1306441242/javascripts/phoenix_plugins.bundle.js
5. 加载http://a2.twimg.com/a/1306441242/javascripts/phoenix.bundle.js

1. 跳过。
2. base.21.bundle.js中包含jQuery, easyXDM(Using for Cross-Domain), 以及Twitter自己的our JavaScript rules:
function h(A) 采用div的text()和html()方法来过滤html标签
function _(B, A) 貌似是语言包?待确定,涉及3个对象方法twttr.is.object(B), twttr.util.getTranslation(C, D), Mustache.to_html(C, A)
接下来是一个闭包,闭包中function C(G, K)用来注册全局对象
下面就是用这个C方法来注册一系列的全局对象
首先是twttr对象,其属性有
provide = C
augmentObject
aug
augmentString
augString
each
localize
filter
map
every
inject
reduce
memoizing
merge
extend
method
methods
statics
at
klass
magic
bind
然后是设置twttr.klass.mixin(E, D) = twttr.magic(E, D)
接着再注册twttr.is对象,其属性有:
element
bool
nil
def
number
fn
array
string
blank
falsy
object
regex
inArray
接着注册twttr.assets对象,其属性有:
getPathFromAbsoluteURL
path
stringToBucket
然后是注册twttr.EventProvider对象,其属性有:
events: null
_provider
_createEvent
trigger
bind
one
unbind
(完)

  • Share/Save/Bookmark

部分HTML5功能的教学代码

March 20th, 2011
/******************************************************
 * @Web Storage
 ******************************************************/
//一直有效,关闭窗口和重启浏览器后数据依然存在
window.localStorage["key"] = value;

//当前装口有效,关闭窗口和重启浏览器后数据消失
window.sessionStorage["key"] = value;

//不能存放函数,如果是函数会被转换成字符串
//每个域的数据是不能共享的

/******************************************************
 * @Web SQL Database
 ******************************************************/
//1.打开数据库
db = openDatabase("DBTest", "1.0", "HTML5 Database API example", 200000);

//2.判断是否打开成功
if (!db) {
    alert("数据库打开失败");
}
else {
    //3.执行sql查询
    db.transaction(function(tx){
        tx.executeSql("SELECT * FROM Table1Test", [], function(tx, result){
            console.log(r = result);
            for (var i = 0, item = null; i < result.rows.length; i++) {
                //提取结果中第i行数据对象,存入item变量,通过item["id"]这种方式获得该行id字段的值
                item = result.rows.item(i);
                console.log(item);
            }
        });
    });

    //4.插入一条记录
    db.transaction(function(tx){
        tx.executeSql("INSERT INTO Table1Test (id, text) VALUES (?, ?)", [num, document.querySelector('#todoitem').value], function(tx, result){
        }, onError);
    });
}
//查询函数,data为替代sql语句中?的变量的数组
tx.executeSql("sql", data, successCallback, errorCallback)
//例如
tx.executeSql("INSERT INTO Table1Test (id, text) VALUES (?, ?)", [10,"text"], successCallback, errorCallback)

/******************************************************
 * @Web Workers
 ******************************************************/
//main.js:父进程脚本
var worker = new Worker('extra_work.js');
worker.onmessage = function(event){
    alert(event.data);
};

//extra_work.js: 被调用的脚本,子进程

// 这里进行你所需要的计算
postMessage(some_data);//当需要通知父进程时调用,参数传入到父进程的onmessage方法中

/******************************************************
 * @Web Sockets
 ******************************************************/
//连接sockets服务器
var socket = new WebSocket("ws://bloga.jp:80/mychat1");

socket.readyState; //连接状态 0:连接中 1:连接成功 2:连接关闭
//当连接成功时
socket.onopen = function(event){
    console.log("connected!");
}
//当从服务器接收到信息时
socket.onmessage = function(event){
    console.log(event.data);
}
//当连接关闭时
socket.onclose = function(event){
    console.log("closed");
}

/******************************************************
 * @Notifications
 ******************************************************/

window.webkitNotifications.checkPermission();//检查是否允许桌面提示 0:允许 1:禁止。桌面提示的允许状态是按域保存的
window.webkitNotifications.requestPermission();//请求用户允许桌面提示

tip = window.webkitNotifications.createNotification("src/dwd1.png", "提示框的标题", "提示框的内容!!!")
tip.show(); //弹出提示框
tip.close(); //关闭提示框

/******************************************************
 * @Geolocation
 ******************************************************/
navigator.geolocation.getCurrentPosition(function(position){

    position.coords //位置坐标
    position.coords.longitude //经度
    position.coords.latitude //纬度
    position.coords.accuracy //精度
    position.coords.altitudeAccuracy //高度的精度
    position.coords.heading //朝向
    position.coords.speed //速度
    position.timestamp //获取坐标的时间戳
});

/******************************************************
 * @Audio + Video
 ******************************************************/
//获得video对象,audio对象也可以通过此方法,需要在html中放置video或audio标签
Media = document.getElementById("vvv");

//audio对象可以通过这个方法快速创建,video不可以。
Media = new Audio("http://directguo.com/html5/src/france.ogg")

//方法和属性。video和audio方法和属性基本相同
Media.src = value; //返回或设置当前资源的URL
Media.currentTime = value; //当前播放的位置,赋值可改变位置
Media.startTime; //一般为0,如果为流媒体或者不从0开始的资源,则不为0
Media.duration; //当前资源长度 流返回无限
Media.paused; //是否暂停
Media.ended; //是否结束
Media.autoPlay = value; //是否自动播放 true/false
Media.loop = value; //是否循环播放 true/false
Media.play(); //播放
Media.pause(); //暂停
Media.controls = value; //是否有默认控制条 true/false
Media.volume = value; //音量
Media.muted = value; //静音 true/false
//TimeRanges(区域)对象 :该对象描述的是一个或多个区域,例如已经加载的区域为两个部分:1-5.8秒 6-10秒
TimeRanges.length; //区域段数,例如上述例子,应该返回2
TimeRanges.start(i) //第i段区域的开始位置,单位秒
TimeRanges.end(i) //第i段区域的结束位置,单位秒

//事件
eventTester = function(e){//着里定义了一个简单的事件检测函数来检测如下的事件
    Media.addEventListener(e, function(){
        console.log((new Date()).getTime(), e);
    });
}

eventTester("abort"); //客户端主动终止下载(不是因为错误引起),
eventTester("error"); //请求数据时遇到错误
eventTester("play"); //play()和autoplay开始播放时触发
eventTester("pause"); //pause()触发
eventTester("playing"); //开始回放
eventTester("timeupdate"); //播放时间改变
eventTester("ended"); //播放结束
eventTester("ratechange"); //播放速率改变
eventTester("volumechange"); //音量改变

//详细API请看:http://directguo.com/blog/index.php/2010/07/html5-audio-video-tag/

/******************************************************
 * @Canvas2D
 ******************************************************/
var elem = document.getElementById('myCanvas');
var ctx = elem.getContext('2d');

//画矩形
ctx.fillRect(x,y,width,height);  //画一个填充的矩形
ctx.strokeRect(x,y,width,height);  //为一个矩形描边
ctx.clearRect(x,y,width,height);  //清楚一个矩形的一部分并且设为透明
ctx.rect(x, y, width, height); //画矩形

//画路径
ctx.beginPath();//创建路径的第一步是调用beginPath方法,返回一个存储路径的信息
ctx.closePath();//从当前的点到起始点闭合路径
ctx.stroke();//描边路径
ctx.fill();//填充路径
ctx.lineTo(x, y);//从上一个起点到(x,y)的点画线,上一个起点可以通过moveTo来指定,默认为原先路径的终点

//画圆弧
arc(x, y, r, sa, ea, cw);//x,y圆心坐标,r-半径, sa和ea是圆弧的开始和结束弧度cw为true是逆时针,false为顺时针

//画贝塞尔曲线
quadraticCurveTo(cp1x, cp1y, x, y);//二次贝塞尔曲线

//使用图像
drawImage(image, x, y); //image-图像对象

//更多内容请看:http://adamlu.com/?p=157

转自:http://directguo.com/blog/index.php/2010/08/%e9%83%a8%e5%88%86html5%e5%8a%9f%e8%83%bd%e7%9a%84%e6%95%99%e5%ad%a6%e4%bb%a3%e7%a0%81/

  • Share/Save/Bookmark

[转]关于DOM事件的Bubbling和Capturing

March 19th, 2011

Bubbling
在浏览器解析事件的时候,有两种触发方式,一种叫做Bubbling(冒泡),另外一种叫做Capturing(捕获)。由上图可以看出来,冒泡的方式效果就是当一个DOM元素的某事件例如click事件被fire时,依次它的父元素的click事件也被fire(触发),一直传递到最顶层的body元素为止。而捕获的触发方式正好相反,当某个元素的click事件被触发时,先从最顶层的body元素click事件被触发开始,一直传递到真正被触发的元素为止。
****************************************************************************
这次我将讨论W3C的标准DOM事件模型和IE独立门户的DOM事件模型到底有多少区别,首先我们可以回想一下目前大多数Js程序员习惯如何绑定事件到 DOM元素上,最常见的就是obj.onclick=handler这种方式(更恶劣的是在Html代码的元素标签中直接加上onclick属性,完全没达到视图和动作分开的原则)。我们暂时称这种方式的事件添加为Traditional(传统方式)吧,IE有自己的IE Event Module,而火狐等浏览器则遵循的W3C方式的Event Module,下面看看这三者各自的优缺点在哪里——
1、Traditional Module

传统方式的事件模型即直接在DOM元素上绑定事件处理器,例如—
window.onload=function(){…}
obj.onmouseover=function(e){…}
obj.onclick=function(){…}
首先这种方式是无论在IE还是Firefox等其他浏览器上都可以成功运行的通用方式。这便是它最大的优势了,而且在Event处理函数内部的this变量无一例外的都只想被绑定的DOM元素,这使得Js程序员可以大大利用this关键字做很多事情。
至于它的缺点也很明显,就是传统方式只支持Bubbling,而不支持Capturing,并且一次只能绑定一个事件处理器在DOM元素上,无法实现多 Handler绑定。最后就是function参数中的event参数只对非IE浏览器有效果(因为IE浏览器有特制的window.event)。
2、W3C (Firefox.e.g) Event Module

Firefox等浏览器很坚决的遵循W3C标准来制定浏览器事件模型,使用addEventListener和removeEventListener两个函数,看几个例子—
window.addEventListener(‘load’,function(){…},false);
document.body.addEventListener(‘keypress’,function{…},false);
obj.addEventListener(‘mouseover’,MV,true);
function MV(){…}
addEventListener带有三个参数,第一个参数是事件类型,就是我们熟知的那些事件名字去掉前面的’on’,第二个参数是处理函数,可以直接给函数字面量或者函数名,第三个参数是boolean值,表示事件是否支持Capturing。
W3C的事件模型优点是Bubbling和Capturing都支持,并且可以在一个DOM元素上绑定多个事件处理器,各自并不会冲突。并且在处理函数内部,this关键字仍然可以使用只想被绑定的DOM元素。另外function参数列表的第一个位置(不管是否显示调用),都永远是event对象的引用。
至于它的缺点,很不幸的就只有在市场份额最大的IE浏览器下不可使用这一点。
3、IE Event Module

IE自己的事件模型跟W3C的类似,但主要是通过attachEvent和detachEvent两个函数来实现的。依旧看几个例子吧—
window.attachEvent(‘onload’,function(){…});
document.body.attachEvent(‘onkeypress’,myKeyHandler);
可以发现它跟W3C的区别是没有第三个参数,而且第一个表示事件类型的参数也必须把’on’给加上。这种方式的优点就是能绑定多个事件处理函数在同一个DOM元素上。
至于它的缺点,为什么如今在实际开发中很少见呢?首先IE浏览器本身只支持Bubbling不支持Capturing;而且在事件处理的function 内部this关键字也无法使用,因为this永远都只想window object这个全局对象。要想得到event对象必须通过window.event方式,最后一点,在别的浏览器中,它显然是无法工作的。
最后我在推荐两个必须知道的IE和W3C标准的区别用法吧—
1、当我们需要阻止浏览器某DOM元素的默认行为的时候在W3C下调用e.preventDefault(),而在IE下则通过window.event.returnValue=false来实现。
2、当我们要阻止事件冒泡的时候,在W3C标准里调用e.stopPropagation(),而在IE下通过设置window.event.cancelBubble=true来实现。

转自:http://hi.baidu.com/dcyhldcyhl/blog/item/70e94d235e4fffac4723e86a.html

另外还有一篇介绍了详细的事件触发顺序(Capturing >target >Bubbling):http://blog.sina.com.cn/s/blog_66d6c8870100nl76.html

  • Share/Save/Bookmark

document.ready不代表图片加载完毕

July 6th, 2010

document.ready不代表图片加载完毕,所以在document.ready里调用$(”img”).height()或者width()时,在强制刷新页面时很容易就获得错误的值。
解决办法1:
$(document).ready(function() {

// regular jQuery code

$(window).load(function() {
// use height() and width() on images here
});

});
来源于
http://forum.jquery.com/topic/jquery-height-and-width-returning-incorrect-values-in-opera

解决办法2:
$(document).ready(function() {

// regular jQuery code

$(”img”).load(function() {
// use height() and width() on images here
});

});
基于1的修改,有可能会出现如果img本地有缓存的话,貌似不会触发load事件,待确认。

  • Share/Save/Bookmark

jquery的mouseover与slideDown效果搭配存在的问题

December 30th, 2009

html结构如下:

<ul id="topNav">
 <li class="popular">
  <a href="javascript:void(0);">Popular</a>
  <div class="dropMenuList">
   <a href="popular/message">Popular message</a>
   <a href="popular/people">Popular people</a>
  </div>
 </li>
<!--li loops-->
</ul>

实现效果如下:

$("#topNav > li").mouseover(function(){
 $("div", $(this)).slideDown();
}).mouseout(function(){
 $("div", $(this)).slideUp();
});

这样写会发现当移动到dropMenuList上时整个div会一直做slideDown和slideUp的死循环,也无法点击dropMenuList上的项目,将slideDown换成hide效果则无此问题,但是效果就没了不是,于是去官网查文档,发现关于mouseover的说明有这么一句话:

Show texts when mouseover and mouseout event triggering. Mouseover fires when the pointer moves into or out from child element, while mouseenter does’t.

意思就是,mouseover方法当鼠标移动到元素本身以及其子元素时都会被触发,而mouseenter则只在元素本身会被触发,移动到其子元素不会再次触发。

于是:

$("#topNav > li").bind("mouseenter", function(){
 $("div", $(this)).slideDown();
}).bind("mouseleave",function(){
 $("div", $(this)).slideUp();
});

O了。

今天在其他项目使用又发现了个问题,因#topNav > li与div之间有间隔,也会导致这样的死循环,要注意li与div之间无缝衔接XD

  • Share/Save/Bookmark