无法删除Cookie的烦恼。。
2010-10-29

    今天遇到一个cookie的问题: 名叫username的,域为www.umiwi.com的cookie无法删除,导致用户登录以后无法退出。搞了半天终于发现问题所在:原来是我关于cookie的基础知识没搞清楚null 。。。。

    Cookie不仅仅有名字和值两个属性,还有域(domain),过期时间(expires),路径(path)等属性。 其中,不同的域、不同的路径下可以存在同样名字的cookie。 比如这个页面:  用鼠标戳我

    一般我们删除cookie的方法是用一个同样名字、过期时间为过去某个时候的Cookie覆盖之。 这时就一定要搞清楚你要删除的cookie的域和路径,Cookie域和路径要一样才能被覆盖。 否则产生的效果就是那个想要被删除的Cookie具有神奇的生命力,无法被清除~~~

    另外,我发现在设置Cookie的时候,如果没有指定域名,那么设置的这个cookie的域默认为当前域,比如www.umiwi.com。 如果设置的时候指定了某个域,那么浏览器存的时候会自动在前面加.。比如PHP代码: setcookie('test','a',0,'www.umiwi.com');  那么 浏览器里面存的Cookie的域为.www.umiwi.com。 所以,最好的方式是设置Cookie的时候怎么写的,删除的时候就怎么写。  要不就会出现我遇到的情况: 明明浏览器里看有 username=longbill,域为www.umiwi.com的Cookie,但是在php里写 setcookie('username','',time()-1000,'www.umiwi.com','/'); 无法删除那个Cookie。 原因就是我删Cookie的操作其实上是发了一个新的名叫username、值为空、过期时间为过去1000秒、域为.www.umiwi.com、路径为/的Cookie。这个Cookie发到浏览器马上就过期了,什么也看不到。而我要删除的在www.umiwi.com上的cookie还活的好好的。。。

    补充一下HTTP的知识: php里面的header函数发送的header信息默认是不重复的,后面发的会自动覆盖前面的内容。一般说来HTTP请求的header部分也是没有重复信息的,除了Set-Cookie头!  所以,如果我们使用header函数来发送cookie,请注意加第二个参数true。 详见header函数

完。

39888 read 6 comment(s)
精确到省市级的ip地址库
2010-10-19

    由于工作需要,自己整理了一个精确到市级的IP地址库(国外的精确到国家)。 需要的同学可以点击这里下载。文件是utf-8编码。

完。

17376 read 9 comment(s)
Google JavaScript Style Guide 中文翻译
2010-10-19

    昨天不小心看到了Google Javascript Style Guide,Google在里面约定了一些名字的书写规则,也给出一些更好的建议。 下面我翻译一段个人认为很有价值的东西:

布尔表达式

以下代码在布尔表达式里都等于false:

  • null
  • undefined
  • '' 空字符串
  • 0 数字

但是请注意,以下这些等于true:

  • '0' 字符串
  • [] 空的数组
  • {} 空的对象

这就意味着本来这样的代码:

while (x != null) {

你可以这样来写(当你不希望x为0、空字符串、false时):

while (x) {

当你希望检查一个字符串是否为空的时候你可以这样:

if (y != null && y != '') {

但是这样会更简洁更高效:

if (y) {

注意: 有很多容易搞错的布尔表达式(以下表达式的值都为true):

  • Boolean('0') == true
    '0' != true 
    /* Longbill注释:
     * if ('0') alert('yes');
     * if ('0' != true) alert('yes');
     * if ('0' == false) alert('yes');
     * 以上三个都会弹出yes!!
     */
  • 0 != null
    0 == []
    0 == false
  • Boolean(null) == false
    null != true
    null != false
  • Boolean(undefined) == false
    undefined != true
    undefined != false
  • Boolean([]) == true
    [] != true
    [] == false
  • Boolean({}) == true
    {} != true
    {} != false
  • Longbill 补充下:
    NaN != true
    NaN != false
    Boolean(NaN) == false

三目运算符

这样的代码:

if (val != 0) {
  return foo();
} else {
  return bar();
}

可以被简化成这样:

return val ? foo() : bar();

三目运算符在生成html字符串的时候也很有用:

var html = '<input type="checkbox"' +
    (isChecked ? ' checked' : '') +
    (isEnabled ? '' : ' disabled') +
    ' name="foo">';

&& 和 ||

由这两个逻辑运算符连接的表达式会从左到右依次执行,直到遇到满足条件为止。

所以"||" 又被称作 '缺省值' 操作符,因为如下代码:

/** @param {*=} opt_win */
function foo(opt_win) {
  var win;
  if (opt_win) {
    win = opt_win;
  } else {
    win = window;
  }
  // ...
}

可以被简写成:

/** @param {*=} opt_win */
function foo(opt_win) {
  var win = opt_win || window; 
  // ...
}

"&&" 同样很有用。比如,如下代码:

if (node) {
  if (node.kids) {
    if (node.kids[index]) {
      foo(node.kids[index]);
    }
  }
}

可以被简写成:

if (node && node.kids && node.kids[index]) {
  foo(node.kids[index]);
}

或者这样:

var kid = node && node.kids && node.kids[index];
if (kid) {
  foo(kid);
}

甚至可以这样:

node && node.kids && node.kids[index] && foo(node.kids[index]);


使用 join() 来创建字符串

一般来说,累加字符串是很常见的:

function listHtml(items) {
  var html = '<div class="foo">';
  for (var i = 0; i < items.length; ++i) {
    if (i > 0) {
      html += ', ';
    }
    html += itemHtml(items[i]);
  }
  html += '</div>';
  return html;
}

但是这种方式在万恶的IE浏览器下会很慢,通常以下代码会更快:

function listHtml(items) {
  var html = [];
  for (var i = 0; i < items.length; ++i) {
    html[i] = itemHtml(items[i]);
  }
  return '<div class="foo">' + html.join(', ') + '</div>';
}

注意:指定数组的下标来赋值会比直接用数组的push()方法更高效。


遍历Node List

在遍历Node list 的时候,常常会用到length属性来当循环的边界条件。因为循环的时间复杂度是O(n),而每循环一次,都要检查一下边界条件(length属性),这样时间复杂度变为O(n^2):

var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i < paragraphs.length; i++) {
  doSomething(paragraphs[i]);
}

这样做会更高效(时间复杂度应该是O(n) ):

var paragraphs = document.getElementsByTagName('p');
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
  doSomething(paragraph);
}

以上这个方法同样适用于对象和数组(当数组不含有会被当成是false的值的时候)。

/* 原文出自:Google,翻译: Longbill (http://php.js.cn) 2010-10-19 */

另外,当你遍历一个Node的所有子Node的时候,可以用firstNode和nextSibling属性,就像这样:

var parentNode = document.getElementById('foo');
for (var child = parentNode.firstChild; child; child = child.nextSibling) {
  doSomething(child);
}

完。

8221 read 6 comment(s)
TextMate 开发AS3应用
2010-10-18

    记得08年flashplayer10刚出来的时候,我看到过一个视频 ,Adobe的人就是用Textmate开发的Flash。 他是用Flex SDK里面的mxmlc命令编译的。当年我还用Mac OS的Automation功能做了一个应用程序,功能是把AS文件拖动到上面就自动给你编译成swf文件。 今年再回头看的时候,发现其实有更简单的方法。那就是用TextMate的Actionscript3 Bundle。然后我就尝试去配置这个环境,结果发现还很不容易。 下面把我的过程跟大家分享一下:

  1. 当然你要有一台Mac
  2. 你得先安装 TextMate。
  3. 安装上面提到过的actionscript 3 bundle。
  4. 到http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk 下载flex sdk
  5. 将sdk解压,放到一个方便找到的位置
  6. 然后打开Textmate->prefrences->advanced->shell variables,添加一个PATH变量,值是你的flex sdk里bin的位置,比如:/Developer/SDK/flex_sdk_3.5/bin。 如果已经存在PATH变量,那么请不要改动原来的数据,在原来数据的后面加冒号(:),然后再加上bin目录的位置。
  7. 同样是在Shell Variables里面,添加一个LC_ALL变量,值是en_US.UTF-8。因为我发现flex会根据系统语言来显示错误信息,但是显示出来的是乱码,所以还是统一用英文的错误信息算了
  8. 打开flex sdk的目录,进入frameworks,编辑flex-config.xml,把<target-player>9xxx</target-player>替换成<target-player>10.0.0</target-player>

然后就爽把,新建一个as文件,写一些东西,然后按苹果键+B,就会自动调用mxmlc编译你的as文件,生成swf。 当然actionscript3 bundle的功能还有很多,自己去发觉吧~

2010年10月18日更新

    今天搞了一下flash player的debug版本。可以把as3程序trace出来的信息记录到一个文件。步骤大概是这样的:

  1. 新建一个文件  ~/mm.cfg ,写上TraceOutputFileEnable=1
  2. 打开textmate的 Bundles >> Bundle Editor >> Edit Commands
  3. 打开左边的ActionScript 3 这个Bundle,然后点击左下角的+按钮,选择New Command
  4. 然后在右边的详细信息区域做如下选择:Save:Nothing,   Input: None, Output: Show as HTML, Activation: Key Equivalent (然后点击右边区域,再按Apple键+D),Scope Selector: source.actionscript.3
  5. 在Command(s)区域,写:
    echo "<pre>"
    cat ~/Library/Preferences/Macromedia/Flash\ Player/Logs/flashlog.txt
    echo "</pre>"
    

    好了,现在在as3的代码界面按Apple+D就可以看到刚刚运行的flash的trace信息了。 上图:

    运行效果如下:

完。

9966 read 23 comment(s)
Actionscript 3 中实现类似JQuery的mouseleave和mouseenter事件
2010-10-15

    最近在搞flash的东西。遇到一个事件冒泡带来的问题。类似Javascript,flash里面的元素也有事件冒泡机制。经常会遇到给一个外层的元素绑定一个mouse_over事件,本意是想实现进入这个外层的元素的时候触发。但是实现的时候却有很奇怪的表现:鼠标在这个元素内部移动的时候,遇到这个元素北部的元素的时候,内部元素触发mouse_over,这个事件会冒泡到外层这个元素,同样触发外层元素的mouse_over事件! 然后你就会发现,鼠标在这个外层元素内部移动的时候,绑定的事件会被触发很多次。

    为了解决这个问题,JQuery自己实现了mouseenter和mouseleave事件,实现鼠标移入这个元素内部和离开这个元素的时候触发,鼠标在元素内部移动不会触发。原理我就不详细说了,大概是判断触发的对象与绑定事件的对象之间的关系吧。  

    在flash里面我自己实现了一个类似的东西,实现了mouseenter和mouseleave的响应。 大概原理是利用mouseover和mouseout的关系(在元素内部移动鼠标到内部的其他元素上的时候,会先触发mouseout,然后触发mouseover事件),把mouseout事件延后处理,然后看如果mouseover到了内部元素上,那就取消mouseout执行,否则触发mouseleave。呃。。。貌似很混乱。。。。核心思想就是利用setTimeout(function(){ },0); 把函数延后执行。

as代码:

function mouseEnterLeave(red,enterCall,leaveCall)
{
	red.mouseOvering = false; //标记鼠标是否处在元素内部
	red.addEventListener(MouseEvent.MOUSE_OVER,function(e:MouseEvent)
	{
		var ct = e.currentTarget;
		try{ clearTimeout(ct.outTimer); }catch(e:Error){ }
		if (!ct.mouseOvering) //如果从外面到里面,那么触发mouseEnter
		{
			enterCall.call(red);
		}
		ct.mouseOvering = true;
	});
	
	red.addEventListener(MouseEvent.MOUSE_OUT,function(e:MouseEvent)
	{	
		var ct = e.currentTarget;
		ct.outTimer = setTimeout(function()
		{ //把mouseout响应延后执行,如果能执行,那么表示鼠标移出
			ct.mouseOvering = false;
			leaveCall.call(red);
		},0);
	});
}

 

    当然,这个函数也可以在Javascript中实现。就像这样:(非IE)

function mouseEnterLeave(o,enterCallback,leaveCallback)
{
	o.addEventListener('mouseover',function(e)
	{
		try{ clearTimeout(o.outTimer); } catch(e) { }
		if (!o.overing)
		{
			if (typeof enterCallback == 'function') enterCallback.call(o);
		}
		o.overing = true;
	},false);
	o.addEventListener('mouseout',function(e)
	{
		o.outTimer = setTimeout(function()
		{
			o.overing = false;
			if (typeof leaveCallback == 'function') leaveCallback.call(o);
		},0);
	},false);
}

    Javascript的例子见这里(非IE浏览器)。

完。

6216 read 3 comment(s)
上一页 1... 5 6 7 [8] 9 10 11 ...35 下一页
Copyright © Longbill 2008-2024 , Designed by EndTo , Powered by EndCMS