今天支付宝UED团队给大家分享一个好玩的东东,那就是由我们的鸽子同学做的点亮网页的firefox插件.

———————————————下面是说明——————————————————

*安装前,请确认您已安装Firebug插件,获取Firebug请访问:http://getfirebug.com/

目前功能:

  1. 开启网页编辑模式,随意编辑任意网页;与Fiddler一起使用,快速调试线上网页;HTML代码快速生成;
  2. 刷新CSS,DOM不刷新;禁用CSS样式;
  3. CSS Sprites位置快速设定;
  4. 保持登录状态,Session不过期。
  5. 导出任意节点为PNG图片;

下载:

本地下载(Firefox直接安装) 1.7版new
Mozilla官方介绍页面 1.6版

目的:

  1. 以任意网页为模板,快速制作DEMO——浏览器就是网页编辑器;
  2. 与Fiddler配合,快速调试线上网页;
  3. 保持网站Session,减少登录操作次数;
  4. 快速设置CSS Sprites的位置,鼠标拖移即可得到位置;
  5. 修改了CSS,无需刷新整页,刷新CSS即可;
  6. 此扩展完全使用JS开发,并使用了CSS3、HTML5等技术,方便移植到Chrome或Safari下;

图示:


Gmail 作为一个经典的 Web 2.0 应用,在带来革命性的邮件管理体验的同时,以其完整、快速的 AJAX 操作方式,深受用户的推崇和技术人员的追捧。

技术上,Gmail 通过将用户的操作以 #op1/op2 这样的形式(即 hash 或 fragment, 这里称之为 hash)反映在浏览器地址栏,最后得到一个类似这样的 URL: https://mail.google.com/mail/#inbox. 它还允许用户直接粘贴这样的地址到达相同的操作界面,并可以通过浏览器的前进/后退按钮在操作步骤之间跳转。

也想尝试一下?先分析一下,通过获取 hash 的值,执行一些操作,即可恢复到该值表示的场景——非常简单。但是,要处理浏览器前进/后退按钮,跳转到相应场景,则有一定困难。因为浏览器不会告诉你 hash 发生变化了。因此,需要实现一个 JavaScript 浏览器导航按钮处理模块。

网上有些代码实现了类似功能,大多感觉冗长复杂。这里,我们介绍支付宝实际应用中开发的一段代码,它的功能简单实用——允许用户指定 hash 发生变化时要做的事情(回调),也可以随时停止它。简单地说,这个代码的原理是,每隔一段时间检查 hash 有没有发生变化,如果有,就运行用户指定的回调方法。代码如下:
More »

最近一直在“深山老林”中修炼“支付宝新版收银台”,经历了白板设计,视觉设计,前端开发,前后端联调各个阶段。点点滴滴……

重点谈谈对交互设计的感受吧:个人觉得设计师应该好好的思考一下收银台的设计粒度,在我们不能确定用户是否会遇到某类问题时,不妨放开怀抱,将粒度切的大一些,如果一味的把自己当作用户,患得患失,其结果只会把自己的产品绑成个大粽子,这样很可能导致在不明确具体问题的情况下,设计粒度过细。到后期再想优化,就举步为艰了。

个人非常反对,设计师总是以“我觉得用户可能”,“我觉得用户一定”的论调在设计讨论中去说服需求方,“觉得”只是一种推测,既然不能确定用户会遇到你假设的问题,那为什么不能先把设计粒度切大一些,等产品上线,观察分析用户使用的情况后,再对症下药呢?究其原因,是因为设计师太怕用户受挫,关心则乱下失去了一些设计原则。我想,在不影响用户正常操作的情况下,对于一些假设的受挫场景,不妨放手一试,用户不犯错,你又怎么知道自己的产品问题在哪里呢。知错而改之,总比一辈子都活在自己“觉得”的世界里强。更何况未必错!

说了这么多,其实只是想引出一个话题,作为一个优秀的设计师,必须学会“如何均衡用户体验和系统实现”,要知道你设计的是一款产品,你必须对他的未来有一个规划,而这个规划,用户体验和系统实现之间的关系是非常微妙的。常常听到很多设计师再抱怨“我想到个很好的体验改进点子,但是开发告诉我系统实现不了,郁闷!”有没有想过为什么?我想很大一个原因就是因为前期设计粒度过细,到后面瓜就不好切了~~呜呼哀哉!总之一句话:“该有的体验一个也不能少,该有的原则同样不能少!”粒度要怎么切,很有学问,需要在不断的实践中去体会。

说到如何均衡体验和系统实现,不妨拿新老收银台做个比较,个人觉得非常有说服力,我们从老收银台现有问题着手分析一下:


More »

目录:

  1. 分析和设计组件
  2. 编码实现和算法
  3. 用 Ant 构建组件
  4. 测试 JavaScript 组件

smart-queue-test
本期,我们要讨论的话题是 JavaScript 的测试,以检查组件的状态和工作方式是否符合预期,还会介绍一个可以方便编写测试用例的测试方法。这里说的测试当然是使用自动化的测试手段,这是软件质量保证(QA)的重要环节。就本系列文章介绍的 Smart Queue 来说,我们的测试目标包括:

  • Task 对象的创建第二期的代码提供了多种创建方式,需要测试对象创建后的状态。
  • Queue 内的任务运行次序:我们提供了两种改变运行次序的方式:优先级和依赖配置,同样也要测试各种配置对次序的影响。

对于第一个目标,只需检查对象创建后的属性是否符合预期即可。我们已经多次提到“符合预期”,断言(Assert)正是为此而设计的。简单的说,断言就是确保所测试的表达式结果为“真”,否则,以某种方式通知测试人员,并帮助其定位断言失败的测试用例。
第二个目标稍稍有点复杂。由于我们在组件编码实现的时候,将排序后的队列( [/cci]_sorted [/cci])隐藏在了闭包中,所以外部是无法访问的。有两种方法可以考虑:(1)重构代码,增加代码的可测试性,又有两种重构方法:(a)设置 debug 开关,打开时将 _sorted 暴露给外部;(b)增加独立文件,以构建的方式拼接代码最终生成一个测试版本。(2)测试行为的结果而不是过程,前一种方法实质上是深入到组件的运行时状态,而这个方法只是检查组件的运行结果。本期选用后一种种测试方式,第一种测试方式留给有兴趣的读者练习:)

需要说明的是,我个人不赞成第一种的方法a. 为什么呢?我先说一下这个任务队列的设计理念:
More »

最近重新温习了一次《javascript设计模式》,确实是一本好书,每次看都有不同的领悟,每次领悟到的都受益匪浅,无怪古圣人都说学无止镜了,仅以“加油,好吗?”共勉!

记得早前就说过要和大家分享“javascript设计模式”,迟迟没写不是因为我懒,最近确实太忙,忙工作,忙旅游(啊哦?),好不容易这几天空闲了,接下来是兑现之前空口白话的时间了。

在讨论设计模式之前,请确认您已经有一定的脚本编程基础,如果不甚了解,建议可以先查阅本人很久之前写的这篇《浅谈javascript面向对象编程》

讲到设计模式,不得不先重点着墨于“接口设计”,因为接口设计在设计模式中的意义太大了,大于模式本身。直观起见,先介绍一下接口定义的形式:

1
  var interface = new Interface("interface",[["getName",1],["getAge",1]]);

可以看出接口函数必须包含两个参数,接口方法定义在一个二维数组中。上例中定义了两个接口方法:getName,getAge,这两个方法都带一个参数,下面我们详细看一下Interface函数的实现代码,从而加深大家对接口的理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  function Interface(name,methods){
    if(arguments.length !=2){
      console.log("参数必须为二个");
    }
    this.name = name;
    this.methods = [];
    if(methods.length<1){
     console.log("第二个参数不能为空数组");
    }
    for(var i=0;len=methods.length,i<len ;i++){
      if(typeof methods[i][0] !== 'string'){
          console.log("第一个参数数据类型必须为字符串");
      }
      if(methods[i][1] && typeof methods[i][1] !== 'number'){
         console.log("第二个参数数据类型必须为整数型");
      }
      if(methods[i].length == 1){
          methods[i][1] = 0;
      }
      this.methods.push(methods[i]);
    }
  }

从代码中不难看出,接口函数的定义规则:[1]Interface函数只能包含两个参数,第一个参数为接口名称,第二个参数是一个二维数组[2]第二个参数不允许为空数组[3]methods参数中的第一个参数必须为字符串类型,用以定义方法名,第二个参数必须为整数类型,用以定义方法的参数个数[4]当methods中方法的参数个数为0时,可以省略不写。

接下来要建一个类,让该类继承前面定义的interface接口,那该怎么做呢,别急,我们需要新增一个方法,见如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  var ioldfish = function(name,age){
    this.name = name;
    this.age = age;
    Interface.regImplement(this,interface);
  }
  ioldfish.prototype.getName = function(){
      alert(this.name);
  };
  ioldfish.prototype.getAge = function(){
      alert(this.age);  
  };
 
  var fishwl = new ioldfish("老鱼",27);
  fishwl.getName();


More »

Page12345...6