blog | 业余项目 | 关于Karry | RSS订阅 | 我在阅读 | 管理

Objective-C学习笔记

七月 21st, 2010

objective-c 是C语言的超集,本质和C语言一样,但语法风格迥异。这篇文章主要是介绍objctive-c的语法规则。
定义一个方法:

头文件中:
-(void) test: (NSString *) firstName : (NSString *) lastName;

其中 test 是方法名,firstName和lastName是两个参数,NSString声明参数的类型为字符串类型。最前面的“-”说明该方法为普通方法(即需要实例化这个类之后才可调用)。若为“+”则声明为静态方法,即为用类名直接可调用。

方法的实现:

- (void)test : (NSString *) firstName :  (NSString *) lastName {

NSLog(@”your first Name is:%@,your last Name is %@”,firstName,lastName);

}

方法的调用:

[self test:(NSString *) @"karry" :  (NSString *) @"zhang"];

调用方法用[],在objective-c里面意为发送一个消息(message).传入参数时需要写清楚参数的类型。

定义一个类Rectangle

头文件:Rectangle.h

#import <Foundation/Foundation.h>
@interface Rectangle : NSObject {
NSString *name;
NSString *color;
int size;
}
//构造函数,返回值是id类型,名称可自定义
-(id) init : (NSString	*) names : (NSString *) colors: (int) sizes;
-(void) setName:(NSString *) names;
-(void) setColor:(NSString *) colors;
-(void) setSize:(int) sizes;
-(void) getArea;
@end


第一句“@interface Rectangle : NSObject ”声明Rectangle 类继承自NSObject类。在Objective-C中,继承用“:”,并且不能多继承
用init 方法作为构造函数应该是约定俗成的习惯。理论上可以是任意名称。

实现 Rectangle.m

#import "Rectangle.h"
@implementation Rectangle
//构造函数的实现
- (id)init:(NSString *)names : (NSString *)colors : (int)sizes {
	if(self = [super init]){
		name = names;
		color = colors;
		size = sizes;
	}
	return self;
}
-(void) setName:(NSString *) names {
name = names;
}
-(void) setColor:(NSString *) colors{
color = colors;
}
-(void) setSize:(int) sizes{
size= sizes;
}
-(void) getArea{
NSLog(@"%@的颜色是%@,面积是%d",name,color,size);
}
@end


注意init方法中的这一句:if(self = [super init]){,我并没有少写一个等号,这里就是把super 的init返回结果赋值给self.这样做是为了防止超类在初始化的过程中返回的对象不同于原先创建的对象。

使用这个类:
首先要引入头文件:

#import "Rectangle.h"
//实例化一个类,直接调init函数
Rectangle *rect =
[[Rectangle alloc] init : (NSString *) @"正方形" : (NSString *) @"红色" : (int) 50];
[rect getArea];//调用方法

[收藏]好程序员和坏程序员

七月 16th, 2010

今天看到两篇文章,整理在一起收藏起来,有空多看看。
==============================================================================
五个方法成为更好的程序员

对我来说,一个好的程序员的定义应该是渴望更少错误的代码。 一些人也许认为好的程序员是那些懂得多门编程语言,懂得很牛技术的程序员,是的,这在某些情况下是对的。但归根到底,无论你用什么样的技术,什么样的语言,所有的程序被写出来,其功能都要尽可能地没有错误。 如果一个能力普通的程序员有足够多的时间来做测试和发布程序,那么,其所有的代码都会是没有错误的。

但是,很明显,所有的已经开发出来项目都是在不完美的条件下开发出来的,一般来说,几乎所有的项目都是在压榨程序员去尽可能地达到最大化软件产品成果。而且,软件工业界对于深度测试和压力测试并不关心,所以,我们总是期望那些赶工出来的代码可以正常工作。 下面是是五个程序员可以在这种不完美的情况下做得更好的观点(它们都和语言和技术没什么关系,只不过是一种你的工作行为,能够和所有的行业相通)

  1. 寻找不同观点:程序员好像并不喜欢技术上有异见的人,他们特别喜欢争论各自的技术观点。但是,他们忽略了不同观点的价值。任何事情都有好有坏,我们应该学会在不同观点中学习和平衡。这样才会更多的了解编程和技术。要经常在做事之前问自己和别人,这么做对不对?做完事后问自己,还可不可以改进?努力去寻找别一个观点。程序员应该经常上网,经常和同事讨论不同的实现方法,不同的技术观点,这样才能取长补短。然而,在实际工作中,我发现程序员们并不喜欢互相请教,因为请教的人怕别人看不起他,而被请教的人总是先贬低对方的能力,哎……(参看《十个让你变成糟糕的程序员的行为》),如果有这样的文化氛围的话,那也没有关系。上网吧,网上的人谁也不认识谁,可以尽情地问一些愚蠢的问题。呵呵。总之,一定要明白,如果某些事情只有一个观点,那么你一定要怀疑一下了,没有观点和技术方案的比较,没有百花齐放的情况,你就无法知道是否还有更好的东西。真正的和谐不是只有一种声音,真正的和谐而是在不同的观点声音下取长补短,百家争鸣(参看《十条不错的编程观点》)。否则,你永远都不会接受到新的观点,也就无法进步和成长了。
  2. 千万别信自己的代码: 在任何时候,一定要高度怀疑自己的代码。很多时候,错误总是自己造成的。所以,当出现问题的时候,要学会review代码中所有的可疑点,千万别觉得某段代码很简单,可以略过。事实证明,很多疏忽大意都是在阴沟里翻的船,都是那些很低级的错误。在查错的过程中,切忌过早下结论,切忌四处乱改(参看《各种流行的编程风格》),停下来,想一想,会是哪儿的代码有重大嫌疑,然后查看一下代码,捋一捋程序的逻辑,调试并验证一下程序的逻辑和变量在运行时是否是正确的。很多时候,对于那些难缠的问题,最后解决了总是因为我们开始认真回头审视所有的代码。只有对自己的代码保持着高度的怀疑,这样我们才会想着如何让其运行得更好更稳定,也会让我们在单元测试中下更多的功夫,这样才能更能在那忙碌的环境中节省时间。相信我,在集成测试中fix bug的成本要比在单元测试Fix bug的成本大得多的多。一个简单的例子就是memory leak。程序员对自己的程序需要有忧患意识,这样才会越来越成熟,而自己的能力也会越来越强。
  3. 思考和放松: 做事前多想一想,这样做事的时候就不会不顾此失彼,手忙脚乱,一旦事情一乱,你的心情也会更乱,于是,事情也就会更乱。最后,你只得重写,这种事情太多了。而且,在工作中要学会享受,要学会放松心情,我并不是让你工作的时候聊QQ,我只是说,有时候,心态过于紧张,压力过大,你的工作成果反而更不好,从而又反过来造成新一轮的焦虑和紧张。我个人认为,思考和放松是可以完美统一的,思考其实就是一种放松,停下来,休息一下,回头看看走过的路,喝口水,登个高,看看过去走的对不对?总体是个什么样?总结一下,然后看看前路怎么样好走,这会你才会越走越好,越走越快。好的程序员都不是那种埋头苦干的人,好的程序员总是那些善于总结成败得失,善于思考,善于调整,善于放松的人(参看《优秀程序员的十个习惯》)。不然,我能看到的情形是,你很快地把事干完,回到家刚坐下来,老板或是客户就打电话来告诉你你的程序出问题了。总之,深思熟虑,动作会很慢,但是你可以保证你工作成果的质量,反而能让你更多的节约时间。
  4. 学习历史,跟上时代: 如果你是从十年前开始编程的,那么,今天的这门语言或是技术会有很多很多的改进和改善。你以前开发一个功能或函数,今天早已被集成时了语言中,而且做得比你的版本要好得多。以前你需要100行代码完成的事情,今天只需要1行代码。这样的事情在未来还会发生,所以,今天的你一定要学会如何跟上时代。但是,你也不要放弃历史,我现在看到很多程序员对一些现代的语言和技术使用的非常好,他们可以很容易地跟上时代。但不要忘了,计算机世界的技术更新和技术淘汰也是非常猛的。所以,你一定要学习历史,这些历史不是产商的历史,而是整个计算机文化的历史(参见《Unix传奇》)。只有通过历史,你才能明白历史上出现的问题,新技术出来的原因,这样才能够对今天的这些新的技术更了解,也才能明白明天的方向在哪里。学习历史和跟上时代都是相当重要的。使用新型的技术,停下来接受培训,可以让你工作得更快,更高效(参看《未来五年程序员需要掌握的10项技能》)。而学习和总结历史,才会让你在纷乱的世界中找到方向。
  5. 积极推动测试活动: 只有测试才能保证软件可以正常工作,只有测试才能保证软件的质量。无论什么产品,都需要经过或多或少的测试。测试地充分的产品,你会发现其质理总是那么好,测试的不充的产品,质量总是那么次。德系汽车,日系汽车质量怎么样,关键还是在于怎么去测试的,测试的是否充分。所以,在你开发软件的过程中,如果你说你的程序写地好,质量高,那么请你拿出实实在在的测试报告。在整个软件开发过程中,做为一个好的程序员,你应该积极地在各个环节推动项目组进行测试活动。不要以为技术需求阶段和设计阶段不需要测试,一样的,只要你要release什么,release的这个东西都需要进行测试。技术需求怎么做测试?用户案例就是测试案例。在软件开发的整个过程中,保证产品质量有时候比实现需求更重要,尤其是那些非常重要甚至人命关天的产品。

十个让你变成糟糕的程序员的行为

1) 情绪化的思维

如果你开始使用不同颜色的眼光来看待这个世界的话,那么你可能会成为一个很糟糕的程序员。情绪化的思维或态度很有可能会把自己变成一个怪物。相信你经常可以看到很多很糟糕的程序会使用下面的这些语句:

  • 我的程序不可能有这种问题。
  • Java就是shit。
  • 我最恨的就是使用UML做设计。
  • 需求怎么老在变,没办干了。
  • 受不了这些人,他们到底懂不懂啊。
  • …… ……

这些带着情绪化的思维和态度,不但可以让你成为一个很糟糕的程序员,甚至可以影响你的前途。因为,情绪化通常都是魔鬼,会让你做出错误的判断和决定,错误码率的判断和决定直接决定了你的人生。

2) 怀疑别人

糟糕的程序总是说:“我的代码一定是正确的,我怀疑编译器有问题”,“我这应该没有问题吧,STL库怎么这么难用啊”。我曾经见过有程序员这样使用STL类:map<char*, char*>,当他发现这样放入字符串后却取不出来,觉得那是STL库的BUG,然后自己写了一个map!我的天啊!

某些时候,过早的下结论是一个很不好的习惯,任何事情都有其原因,只有知道了原因,你才能知道是谁的问题。一般来说,总是自己出的问题。

3) 过多关注实现,陷入问题细节

有些时候,当我们面对一个问题或是一个需求的时候,糟糕的程序员总是会马上去找一个解决方案或是实现,这是一个很不好的习惯。设计模式告诉我们,“喜欢接口,而不是实现”就是告诉我们,认清问题的本质和特性要比如何实现更重要。

  • 对于一个客户的问题来说,首先应该想到的是如何先让用户正常工作,如何恢复正在“流血”的系统,而不是把用户放在一边而去分析问题的原因和解决方案。
  • 对于解决一个bug来说,重现bug,了解原来程序的意图是首先重要的事,而不是马上去修改代码,否则必然会引入更多的BUG。
  • 对于一个需求来说,我们需要了解的需求后面的商业背景,use case和真实意图,而不是去讨论如何实现。只有了解了用户的真实意图,实际使用的方式和案例,你才能真正如果去做设计。

糟糕的程序总是容易陷入细节,争论于如何实现和实现难题,以及问题的根本原因,而忽略了比这些更重要的东西。只有看懂了整个地图,我们才知道要怎么去走。

4) 使用并不熟悉的代码

糟糕的程序员最好的朋友是 Ctrl-C 和 Ctrl-V ,有些时候,他们并不知道代码的确切含义,就开始使用它,有证据表明,由拷贝粘贴引发的bug占了绝大多数。因为,代码总是只能在特定的环境下才能正常地工作,如果代码的上下文改变了,很有可能使得代码产生很多你不知道的行为,当你连代码都控制不住了,你还能编出什么好的程序呢?

5) 拼命工作而不是聪明的工作

对于糟糕的程序员,我们总是能看到他们拼命地修正他们的bug,总是花非常多时间并重复地完成某一工作。而好的程序可能会花双倍的时间来准备一个有效的开发环境,工具,以及在开发的时候花双倍甚至10倍的时间来避免一些错误。好的程序员总是会利用一切工具或手段来让自己的工作变得更有效率,总是为在开发的时候尽可能得不出错。后期出错的成本将会是巨大的,而且那时改正错误的压力也是巨大的。所以,糟糕的程序通常会让自己进入一种恶性循环,他们看上去总是疲惫的,总是很辛苦的,所以更没有时间来改善,越没有时间来改善,就有越多的问题。所以,拼命工作有些时候可能表明你不是一个好的程序员。

6) 总是在等待、找借口以及抱怨

当需求不明确的时候,当环境不是很满意的时候,他们总是在等待别人的改善。出现问题的时候,总是在找借口,或是抱怨这也不好,那也不好,所以自己当然就没有做好。糟糕的程序员总是希望自己的所处的环境是最好的,有明确的需求,有非常不错的开发环境,有足够的时间,有不错的QA,还有很强的team leader,以及体贴自己的经理,有足够的培训,有良好的讨论,有别人强有力的支持……,这是一种“饭来张口,衣来伸手”的态度,这个世界本来就不完美,一个团队需要所有人去奋斗,况且,如果什么都变得完美了,那么,你的价值何在吗?driving instead of waiting, leading instead of following.

7) 滋生办公室政治

有句话叫“丑女多作怪”,意思是说如果一个自己没有真实的能力的话,那么他一定会在其它方面作文章。糟糕的程序员也是这样,如果他们程序编不好的话,比不过别人的话,他们通常会去靠指责别人,推脱责任,或是排挤有能力的人,等等不正常的手段来保全自己。所以,糟糕的程序通常伴随着办公室政治。

8 ) 说得多做得少

糟糕的程序员总是觉得自己什么都懂,他们并不会觉得自己的认识和知识都是有限的。这就是所谓的夸夸其谈,是的,什么都做不好的程序员能靠什么混日子呢?就是吹啊吹啊。

另一个表现方式是他们在评论起别人的程序或是设计,总是能挑出一堆毛病,但自己的程序写得也很烂。总是批评抱怨,而没有任何有建设性的意见,或是提出可行的解决方案。

这些糟糕的程序员,总是喜欢以批评别人的程序而达到显示自己的优秀。

9) 顽固

当你给出一打证据说明那里有一个更好的方案,那里有一个更好的方向的时候,他们总是会倔强的认为他们自己的做法才是最好的。一个我亲身经历的事例就是,当我看到一个新来的程序员在解决一个问题的时候走到了错误的方向上时,我提醒他,你可能走错了,应该是另外那边,并且我证明了给他看还有一个更为简单的方法,有。然而,这位程序员却告诉我,“那是我的方法,我一定要把之走下去,不然我会非常难受”,于是,在三天后的代码评审中,在经过顽固地解释以及一片质疑声中,他不得不采用了我最先告诉他的那个方法。

这些程序员,从来不会去想,也不会去找人讨论还有没有更好的方法,而是坚持自己的想法,那怕是条死路都一往直前,不撞南墙永不回头。

10) 写“聪明”的代码

他们写出来的代码需要别的同事查看程序语言参考手册,或是其程序的逻辑或是风格看上去相当时髦,但却非常难读。代码本应该简洁和易读,而他们喜欢在代码中表现自己,并尝试另类的东西,以显示自己的才气。是的,只有能力有问题的程序员才需要借助这样的显示。

记得以前的一个经历,一位英语很不错的程序员加入公司,本来对我们这些英语二把刀来说,我们喜欢看到的是简单和易读的英文文档,然后,那位老兄为了展示他的英语如何牛,使用了很多GRE中比较生僻的短语和词汇。让大家阅读得很艰苦。最有讽刺意味的是,有一位native的美国人后来在其邮件中询问他某个单词的意思。呵呵。

你是一个糟糕的程序员吗?欢迎你分享你的经历。

javascript设定文本框中的指定文字为选中状态

六月 5th, 2010

前段时间写了一个获取网页中鼠标选中的文字,这个是逆向操作,通过javascript设置文本框中的指定文字为选定状态。

var PG={
    isIE:!-[1,],  //判断浏览器是否为IE,为IE时返回true
    /*
    * 设置文本框中的文字为选中状态,包括开始索引,不包括结束索引
    * param domObj 文本框的dom对象,start为开始索引,不填则从0开始, end为结束索引,不填则选中到文本结束
    * 若domObj参数不填,则直接返回为false.
    */
    setSelectText:function(domObj,start,end){
        if(typeof domObj !=="object"){
            return false;
        }
        start = start ||0;
        end = end || domObj.value.length
        domObj.focus();
        if(this.isIE){
            var range = domObj.createTextRange();
            range.move("character",start);
            range.moveEnd("character",end-start);
            range.select();
        }else{
            domObj.setSelectionRange(start,end)
        }
    }
}

【测试页面】

Dict–我的chrome词典插件

五月 22nd, 2010

DICT前段时间Kevin做了一个很不错的翻译工具–尚译,使用的是google language api,用起来感觉很方便。由于是油猴脚本(Grease Monkey),每次使用都要在导航栏点击一次。 另外,这个脚本主要侧重于翻译,对于我自己并不是很适用,决定做一个适合自己使用的chrome词典小插件,关注单词的发音和用法,顺便也学习一下Google Chrome Extensions 的开发。

我将这个插件命名为”Dict”,基于google language api 、 dict.cn和有道词典,中文翻译为英文,单词和词组有音标和例句和发音,其他语言翻译成中文。现在工作中偶尔也要用到日文,所以也附带做了简单的日文翻译功能。

一开始就为了满足自己的需求而开发,所以这个插件不一定适合你,如果你恰好和我有相似的需求,也欢迎你使用。

用google chrome 浏览器打开: chrome词典小插件

点击安装之后你会在浏览器右上角看到一个红色的小图标。点击红色小图标:

输入你要查询的单词,回车:

鼠标放在黄色的喇叭按钮上,会有单词的读音。你也可以输入中文:

Dictionary-chrome 小插件

如果你觉得单词的解释和例句不够完整,可以点击右下角的”google dictionary” 在google提供的词典中查看更加完整的信息。

你也可以输入整句获得翻译,当然,句子是没有发音和音标的:

正在考虑是否加上屏幕取词的功能,可能下一个版本加上该功能,对这个插件有任何建议也欢迎和我交流。

获取网页中鼠标选中的文字

五月 16th, 2010

最近在做一个chrome插件,需要用到捕获鼠标选中的文字,发现各浏览器兼容性解决起来挺麻烦,总结了一下,方便以后使用。

直接看代码:

 var PG={
            isIE:!-[1,],  //判断浏览器是否为IE,为IE时返回true
            getText:function(){
                 if(this.isIE){
                     return this._getText();
                }else{
                    var element = document.activeElement;
                    if (element && (element.tagName.toLowerCase() == 'input' || element.tagName.toLowerCase() == 'textarea')) {
                        return this._getTextInput()
                    } else {
                        return this._getText()
                    }
                }
            },
            _getText:function(){
                if (window.getSelection) {
                    return window.getSelection().toString();
                } else if (document.selection && document.selection.createRange) {
                    return document.selection.createRange().text;
                }
                return "";
            },
            //获取非IE浏览器中input框和textarea框中的文字
            _getTextInput:function(){
                var element = document.activeElement;
                if (element.selectionStart != undefined && element.selectionEnd != undefined) {
                    return element.value.substring(element.selectionStart, element.selectionEnd);
                }
                return "";
            }
        }

使用方法:

 document.onmouseup = function(){
            alert("您选中的文字是:"+PG.getText());
        }

点击查看:[测试示例]

参考:
PPK :Introduction to Range
getSelection method (window)
document.selection.createRange方法

WAP开发相关资源收集

五月 11th, 2010

交互原则

  1. Strive for consistency.力求一致
  2. Enable frequent users to use shortcuts.允许频繁的使用快捷键
  3. Offer informative feedback.提供明确的反馈
  4. Design dialog to yield closure.设计对话,告诉用户任务已完成
  5. Offer simple error handling.提供错误预防和简单的纠错能力
  6. Permit easy reversal of actions.应该方便用户取消某个操作
  7. Support internal locus of control.用户应掌握控制权
  8. Reduce short-term memory load.减轻用户的记忆负担
  1. 尽量减少操作的步骤
  2. 尽量利用点击来代替输入
  3. 时刻让用户知道自己所处的位置
  4. 与web保持一致且数据同步
  5. 为输入法让出空间
  6. 摘要形式展现信息
  7. 导航和提示处于明显的位置
  8. 减少滚动

界面简洁的途径:

  • 减少控件的数目,使程序的主功能显然易见,引导用户操作。
  • 当内容过多时,要突出重要信息,便于用户快速浏览。
  • 显示出错信息时,不要只告知用户程序出现错误,要提供有用的信息引导用户完成操作。
  • 手机上网的速度慢,一般在6k/s,这就要求页面的内容尽量精简,避免过多的图片。
  • 页面的内容控制在两屏以内,也不能空白。比如当用户支付电影票之后,不能只显示“支付成功”,可以引导用户使用其他功能。

操作方式

手机操作有物理按键和触摸等多种操作方式,当同样的程序要在多种操作方式下使用,需顾及手指点击时可点区域的大小。使用物理按键时,按钮可以只是两个字,选中控件即可操作,而iPhone的可点击区域最好不低于44×44像素。

分辨率种类(不完全统计):

  • 128*128  128*160 130*130  176*144  176*220 208*208 208*320  240*160 240*240 240*260
  • 240*320 240*400 240*432 240*480 320*240 320*320 320*400 320*480 345*800 352*416
  • 360*480 360*640 400*800 480*320 480*360
  • 480*640 480*800 480*854 480*864 640*480  800*480

手机浏览器兼容性测试结果概要

注意:以下所说的“大多数”是指在我们测试过的机型中,发生此类状况的手机占比达50%及以上,“部分”为20%到50%;“少数”为20%及以下。而这个概率也仅仅只限于我们所测试过的机型,虽然我们采集的样本尽量覆盖各种特征的手机,但并不代表所有手机的情况。

XHTML部分

大多数手机不支持的:

  • 表单元素的“disable”属性

部分手机不支持的:

  • “button”标签
  • “input[type=file]“标签
  • “iframe”标签。

虽然只有部分手机不支持这几个标签,但因为这些标签在页面中往往具有非常重要的功能,所以属于高危标签,要谨慎使用。

少数手机不支持的:

  • “select”标签:该标签如果被赋予比较复杂的CSS属性,可能会导致显示不正常,比如”vertical-align:middle”。

CSS部分

大部分手机不支持的:

  • “font-family”属性:因为手机基本上只安装了宋体这一种中文字体;
  • “font-family:bold;”:对中文字符无效,但一般对英文字符是有效的;
  • “font-style: italic;”:同上;
  • “font-size”属性:比如12px的中文和14px的中文看起来一样大,当字符大小为18px的时候你也许能看出来一些区别;
  • “white-space/word-wrap”属性:无法设置强制换行,所以当你网页有很多中文的时候,需要特别关注不要让过多连写的英文字符撑开页面;
  • “background-position”属性:但背景图片的其他属性设定是支持的;
  • “position”属性;
  • “overflow”属性;
  • “display”属性;
  • “min-height”和”min-weidth”属性;

部分手机不支持的:

  • “height”属性:对”height”的支持不太好,奇怪的是在我们的测试当中,仅仅只有很少部分手机不支持”width”属性;
  • “pading”属性
  • “margin”属性:更高比例的手机不支持”margin”的负值。

少数手机不支持的:

  • 少数手机对CSS完全不支持;

JavaScript部分

这部分测试相对不那么让人抓狂,要么干脆不支持,如果支持的话,对基本的dom操作、事件等支持度都还不错。但我们没有测试过很复杂的脚本。

在我们测试过的手机当中,支持(包括不完全支持)JavaScript的手机比例大约在一半左右,当然,对于我们来说,最重要的不是这个比例,而是要如何做好JavaScript的优雅降级。

其他

  • 部分手机不支持png8和png24,所以尽量使用jpg和gif的图片
  • 另外对于平滑的渐变等精细的图片细节,部分手机的色彩支持度并不能达到要求,所以慎用有平滑渐变的bar设计
  • 部分手机对于超大图片,既不进行缩放,也不显示横下滚动条
  • 少数手机在打开超过20k的测试页面时,会显示内存不足

开发中你需要注意的问题

  1. 手机网页编码需要遵循什么规范?
    遵循XHTML Mobile Profile规范(WAP-277-XHTMLMP-20011029-a.pdf),简称为XHTML MP,也就是通常说的WAP2.0规范。 XHTMLMP是为不支持XHTML的全部特性且资源有限的客户端所设计的。它以XHTML Basic为基础,加入了一些来自XHTML 1.0的元素和属性。这些内容包括一些其他元素和对内部样式表的支持。和XHTML Basic相同,XHTML MP是严格的XHTML 1.0子集。
  2. 网页文档推荐使用扩展名?
    推荐命名为xhtml,按WAP2.0的规范标准写成html/htm等也是可以的。但少数手机对html支持的不好。
  3. 为什么现今大多数的网站一行字数上限为14个中文字符?
    由于手持设备的特殊性,其页面中实际文字大小未必是我们在CSS中设定的文字大小,尤其是在第三方浏览器中。例如Nokia5310,其内置浏览器 页面内文字大小与CSS设定相符,但是第三方浏览器OperaMini与UCWEB页面内文字大小却大于CSS设定。经测试,其文本大概在16px左右。 假如屏幕分辨率宽度为240px,去除外边距,那么其一行显示14个字以内,是比较保险(避免文本换行)的做法。
  4. 使用WCSS还是CSS?
    WCSS (WAP Cascading Style Sheet 或称 WAP CSS)是移动版本的CSS样式表。它是CSS2的一个子集,去掉了一些不适于移动互联网特性的属性,并加入一些具有WAP特性的扩展(如-wap-input-format/-wap-input-required/display:-wap-marquee等)。 需要留意的是,这些特殊的属性扩展并不是很实用,所以在实际的项目开发当中,不推荐使用WCSS特有的属性。
  5. 避免空值属性
    如果属性值为空,在web页面中是完全没有问题的,但是在大部分手机网页上会报错。
  6. 网页大小限制
    建议低版本页面不超过15k,高版本页面不超过60k。
  7. 用手机模拟器和第三方手机浏览器的在线模拟器来测试页面是不是靠谱?
    有条件的话,我们当然建议在手机实体上进行测试,因为目标客户群的手机设备总是在不断变化的,这些手机模拟器通常不能完全正确的模拟页面在手机上的显示情况,比如图片色彩,页面大小限制等就很难再模拟器上测试出来。当然,一些第三方手机浏览器的在线模拟器还是可以进行测试的,第三方浏览器相对来说受手机设备的影响较小。

参考网站

交互

开发

招聘广告一枚

五月 6th, 2010

上海五分钟诚聘前端开发工程师

职位名称:前端开发工程师

你有两个方向可供选择:

平台方向
职位描述
1. 负责公司各游戏产品的web页面输出及优化;
2. 能快速处理主流浏览器的兼容性问题(FF/IE6/IE7/IE8/Chrome/Opera);
3. 使用Facebook/人人网/opensocial等Javascript API完成相关功能;
4. 负责公司各管理系统后台界面的输出和Javascript开发;
游戏WAP版方向
职位描述
1.负责游戏wap版的前端开发工作;
2.保证在各种不同的移动设备中有良好的可用性;

职位要求
1. 本科或以上学历,一年以上前端开发相关工作经验,有WAP相关开发经验者优先考虑;
2. 精通各种Web前端技术,包括XHTML/XML/CSS/Javascript等;
3. 能熟练使用一门服务器端语言者优先考虑(如Java/PHP/C#/Ruby);
4. 有良好的沟通能力,善于和各种背景的人合作;
5. 理解Web标准,对可用性、可访问性等相关知识有实际的了解。
6. 关注前端技术发展方向,对HTML5和CSS3有所了解;
注:简历请附上作品链接,若有技术BLOG,请附上BLOG地址。

简历请投递:jobs[at]fminutes.com 或   kai.zhang[at]fminutes.com

加入我们,一起创造快乐!

上海五分钟是世界上成长最快、创造性最强的社交游戏公司之一。在这里,你的每一份努力,都会成为全世界玩家的一份快乐!我们可以给你:

  • 一个开放快乐的环境;
  • 一个有挑战性的岗位;
  • 一把潜力巨大的股票;
  • 一份有竞争力的薪水;
  • 一段共同奋斗的回忆!

DOMContentLoaded事件在IE中的实现机制

五月 3rd, 2010

在所有非IE浏览器中都有DOMContentLoaded事件,也就是DOM结构加载完毕之后执行的事件,有别于onload事件必须页面上的所有元素(比如图片和flash)加载完毕才执行,通常该事件用于绑定dom事件,操作dom等。而IE中缺乏对该事件的支持,几乎所有的javascript框架都为IE实现了该事件,但实现方式各不相同。comojs有Como.onloadHandler,jQuery里有$(document).ready,YUI里有onDOMReady。

加载script标签

comojs当前采用的这种方式,Dojo和比较老的jQuery版本也采用的这种方式。


var src = 'javascript: void(0)';
if(window.location.protocol == 'https:'){
    src = '//:';
}
document.write('<script onreadystatechange="if
(this.readyState==\'complete\') {this.parentNode.removeChild(this);
Como.Hook._onloadHook();}" defer="defer" ' + 'src="' + src + '">
<\/script\>');

这个原理比较简单,在页面中插入一个script标签。利用IE支持defer属性的特点,使插入的这个script标签在文档加载完毕之后才执行,然后利用script标签的onreadystatechange函数实现ready事件。

利用doScroll()

这是目前最主流的解决方案jQuery、Ext、YUI、Mootool都用这种方式处理。原理是利用IE浏览器支持的doScroll,当DOM未加载完毕时,执行doScroll时会抛出异常。利用这个特定定时执行doScroll,直到不抛异常,说明DOM加载完成。

// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" )
(function(){
	if ( jQuery.isReady ) return;
	try {
		// If IE is used, use the trick by Diego Perini
		// http://javascript.nwbox.com/IEContentLoaded/
		document.documentElement.doScroll("left");
	} catch( error ) {
		setTimeout( arguments.callee, 0 );
		return;
	}
	// and execute any waiting functions
	jQuery.ready();
})();

监测document, document.getElementByTagName及document.body

设置定时器不断监测document的相关属性和方法是否已存在,如果存在,说明dom加载完毕。

domReady.timer = setInterval(isDomReady, 13);
function isDomReady() {
    if (domReady.done) return false;
    if (document && document.getElementsByTagName && document.getElementById && document.body) {
        clearInterval(domReady,timer);
        domReady.timer = null;
        //执行ready函数。
    }
}
好消息一则:IE9支持DOMContentLoaded事件。

参考文档

http://developer.yahoo.com/yui/docs/YAHOO.util.Event.html#onContentReady

http://peter.michaux.ca/articles/the-window-onload-problem-still

javascript单元测试工具QUnit介绍

四月 24th, 2010

[点击查看示例]

QUnit 介绍:

QUnit是jQuery团队开发的JavaScript单元测试工,使用起来非常方便。有漂亮的外观和完整的测试功能(包括异步测试)。

由于存在浏览器解析环境、用户操作习惯等差异,前端程序的许多问题是无法捕捉或重现的,现在前端程序的测试多是黑盒测试,靠模仿用户不停的点击来寻找程序bug。这种方式既费时费力,又无法保证测试的覆盖面。

随着前端逻辑和交互越来越复杂,和其他编程语言一样,一个函数,一个模块,在修改bug或添加新功能的过程中,很容易就产生新的bug,或使老的bug复活。这种情况下,反复进行黑盒测试效率很低,如果测试工作交给QA去做,更是怨声载道。此外,浏览器兼容性测试是前端程序测试的重要一环,在多个浏览器之间测试前端程序,黑盒测试的工作量就会成倍增加。这时候单元测试就体现出了优势,你只需要写一份单元测试代码,到各给浏览器跑一遍,就可以轻松看到不同的浏览器导致的BUG。有新功能的增加或修改时,只需要跑一下单元测试,问题就一目了然。同时,单元测试本身就是一份良好的说明文档,而且总是能跟着程序保持同步。

使用方法:

QUnit虽然是jQuery团队开发,但是并不依赖jQuery,使用QUnit也很方便,只需要引入一个css和一个js文件即可。

<link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js"></script>

你当然可以把这两个文件下载到本地直接使用。

测试方法介绍:

module(string,lifecycle)声明一个测试模块。第一个个参数为必填,第二参数可选。如:

module("doAdd方法测试模块");

test( name, expected, testfuction )开始一个测试。第一个参数为必填,测试名字,字符串。第二个参数为选填,预期的测试个数,数字。第三个参数为测试的方法。如:

test('doAdd(a,b)方法测试',function() {
    expect(1);
    equals(doAdd(2,5), 7, '2+5等于7');
});

ok( state, message ) 布尔断言,第一个参数是true时,表示测试通过,第二个参数选填,附加信息。

equals( actual, expected, message )等价判断,第一个参数为实际的执行结果,必填。第二个参数为预期结果,必填。当两个结果相等时,测试通过,否则测试不通过。第三个参数为附加信息。但要注意的是,equals适用于判断字符串、数字等是否相等。对于数组、object、或自定义类别的对比,应该使用same()函数测试。
same( actual, expected, message ) 与equal用法一样,适合判断数组、object等的等价。
expect( number ) 测试个数预期,与test函数的第二个参数等价。如果实际测试次数和预期值不符合,则测试不通过。

asyncTest( name, expected, test ) 异步测试。该测试模块并不立即执行,等到start()函数出现时才开始执行,适合事件、ajax等异步函数的测试。
start()开始执行这个测试模块。
stop()暂停执行这个测试模块,直到start()函数重新开启。如:

module("异步测试模块");
asyncTest("事件测试", function() {
    expect(1);
    document.body.onclick = function(event){
        start();
        equals(event,"[object MouseEvent]","event值");
    }
});
相关文档:http://docs.jquery.com/QUnit

关于“跨域”问题的总结

四月 19th, 2010

什么是同源策略?

同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。这个浏览器策略很旧,从 Netscape Navigator 2.0 版本开始就存在。

URL 说明 是否允许通信
http://www.playgoogle.com/lab/a.js

http://www.playgoogle.com/script/b.js

同一域名下不同文件夹 允许
http://www.playgoogle.com/a.js

http://www.playgoogle.com/b.js

同一域名下 允许
http://www.playgoogle.com:8000/a.js

http://www.playgoogle.com/b.js

同一域名,不同端口 不允许
http://www.playgoogle.com/a.js

https://www.playgoogle.com/b.js

同一域名,不同协议 不允许
http://www.playgoogle.com/a.js

http://61.129.251.35/b.js

域名和域名对应ip 不允许
http://www.playgoogle.com/a.js

http://script.playgoogle.com/b.js

主域相同,子域不同 不允许
http://www.test.com/a.js

http://www.playgoogle.com/b.js

不同域名 不允许

常用的跨域解决方案

jsonp(JSON with Padding): 简单点说,异步请求跨域的服务器端时,不是直接返回数据,而是返回一个js方法,把数据作为参数传过来。这需要服务器端稍作修改,如果只是跨域传递数据(而不是DOM操作),个人认为这种方式是最好的。参考内容:使用 JSONP 实现跨域通信

服务器端代理: 由js请求同源的服务器端,再由服务器端做代理来实现跨域的请求。参考内容:ajax跨域之服务端代理

动态创建script:虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function,根据这一点,可以方便地通 过创建script节点的方法来实现完全跨域的通信有点XSS跨站脚本攻击的意思,所以安全性方面需要仔细评估。这也是所有GreaseMonkey的实现方式,比如sogou的云输入法

document.domain:仅适用于不同的二级域名之间的跨域访问。

window.name:name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面时,name 的属性值依旧保持不变。通过在 iframe 中加载一个资源,该目标页面将设置 frame 的 name 属性。此 name 属性值可被获取到,以访问 Web 服务发送的信息。参考使用 window.name 解决跨域问题

window.location.hash:hash可以实现跨域传值从而达到跨域通讯的目标。为了及时捕获Hash值的修改,需要轮询实现。如果是iframe和主页面不在同一个域下而要进行通讯,这是不错的方式。不过会导致一个问题,在chrome和firefox这类浏览器中,hash值的修改会在浏览器中保存记录,扰乱正常的前进和后退功能。

iframe 代理:iframe和主页面不在同一个域,但iframe 需要操作主页面的DOM结构,这个时候用iframe代理可实现,比如iframe高度自适应,只要在iframe中再插入一个与主页面同域的iframe,把参数传递过去即可。