Jade's fantastic Blog

Make a difference.Where amazing happens!

驾照记

泰华驾校

学驾照是一场华丽的冒险!

学习过程

  • 科目一

    科目一应该是纯体力活,1000多道题目全部做好了,然后错题巩固几遍,考试拿个100分还是很简单的。

  • 科目二 (小路考)

    科目二包括:直角转弯,S弯,坡道起步,侧方停车,倒库出库。学习的过程还是停揪心的,就整个学习的过程来说,被教练说了不少,主要还是因为对车的感觉不好,不够灵活。教练一把年纪了,不能指望能手把手的教的特别仔细,所以在学习的过程中,不能只听教练师傅提到的技巧,还要结合自身实际情况。例如:对于直角转弯教练在右前窗处做了个记号,让大家看着这个记号转,但是我每次看这个几号转弯总是容易压到另一边的路牙边线,这时候就结合自己的情况想一想,后来我向前调整了我的点位,于是就很少牙线了。在我看来,在学习科目二之前应该先学习方向盘的转动,转动越灵活,后面的项目越容易练;其次,对于座椅的调整也很重要,坐的不舒服的座椅会导致踩离合器的时候非常别扭。第三,要学会看后视镜,通过后视镜可以对于后轮和车身整体情况有所了解,这样可以减少压线的可能性。

  • 科目三 (大路考)

    很多人说大路考是最简单的,但是我个人看来大路考是心里战。为什么呢?因为大路上地形多样,情况复杂,需要你胆大心细,同时不能忘记细节。比如说起步五要素:踏挂开鸣放,通过路口和人行横道注意行人,并且要记得打转向灯。只要有好的心理素质,不要忘记细节,通过大路考还是不难的。

  • 科目四 (道路文明)

    正在练习,个人感觉还是体力活,通过考试应该不难。对于即将开车上路的新手,了解一些道路上的常识还是很不错的,例如:遇到紧急状况怎么样处理最安全?车声着火可以直接用水浇吗?等等。

学车吐槽

吐槽

  • 做理论测试题的时候,有时会很想骂人,这是哪个脑残出的题目?含糊其次,没有逻辑性
  • 每次练的不好的时候,师傅总是会冒出一句:诶呦,你学的慢得来,你学的不快吧
  • 最不想听师傅说的的一句话就是:怎么还没学会啊,考不过的吧,你这样肯定考不过的哇
  • 大路考的时候,感觉考官心理阴暗,不知道是不是大姨夫来了?态度凶的一塌糊涂,我真想说,MD,我要不是为了考试,真想揍你一顿
  • 小路和大路都是需要打理的,不同的驾校真的是不一样
  • 驾校师傅竟然没有基本工资?我也是醉了,教练是真心不容易啊,我们每个人身上的油钱加奖金才能是教练的收入,并且一个周期内休息不了几天,几乎每天都要带学员练车,让我们一起喊个口号吧:尊重教练!

总结

Anyway, 开车不是儿戏,练车被骂,被呵斥都是小事,真正学会,并且熟练运用到未来自己的开车的实践中最重要。祝愿所有正在学车的同仁顺利通过!

杭JS 小记

hang js

提要

今年已经是第三届China JS峰会了, 前两次分别在北京和上海举办,今年移步到杭州举办,票价也是一年接一年的飙升,哥今年花了500大洋参加,不过总体来说还是值得的, 有学到新的方法, 技术, 认识新的朋友, 扩大了知识面。主要可以分为以下几部分:

  • Library & Framework
  • 流程改善
  • 工具
  • 大数据
  • 性能优化
  • 架构设计
  • 嵌入式NodeJS: EdgeJS –> CLR+V8
  • 移动设备传感器
  • Hybird API
  • 离奇的idea: Node OS
  • 开源社区
  • 程序员软实力: 时间管理
  • JS 编译器 (不知道应用场景)

Library & Framework

Then.JS

这部分最精彩的莫过于then.js的分享,then.js是一个用来处理移步请求的库,据作者所说本来打算直接用AsyncJS, 但由于AsyncJS不支持链式调用,于是就整了这么一个库。从bench mark来看then.js确实有很大优势,主要有以下特点:

  • 体积小
  • 速度快
  • 使用thunk函数而不是用promise实现,不会出现栈溢出错误

TroopJS

其次, 我不得不提TroopJS,这是一个非常好用的framework。目前已经到3.0版本,主要特点有:

  • 推崇异步编程方式
  • 使用声明式事件绑定
  • 使用Mixin的方式继承
  • 完善的组件生命周期管理机制
  • 3.0 会支持Web Component

Rabbit.js

Rabbit.JS 是一个非常早期的Node MVC框架,主要目标是简化配置,实现快速开发。

Edge.js

Edge.JS 是由微软开发的一个用来填平CLR和NodeJS之间的沟壑的库。个人不太喜欢, 不解释。

流程

淘宝的前后端分离

流程一直是小公司不太注意的问题, 尤其是创业公司,追求速度而忽略了流程的构建, 造成资源浪费,效率低下。淘宝的前后端有严重的耦合,经常是前段开发好HTML分发给后端,后端还要进行处理,甚至也要写前段代码。于是淘宝加了一个中间层NodeJS来进行解藕,主要做了以下改变:

  • 使用NodeJS产生静态页面到CDN
  • 前后端路由共享
  • 接口服务化
  • 模块化Everything
  • 组件化 (多环境)
  • 框架化

点对点的协作 (Peer to peer collaborate)

点对点的协作是由NodeJS社区大神SubStack提出的,主要用于开源社区中和成千上万的npm package开发者协作,核心思想是:

  • 功能最小化模块
  • 不重复造轮子

工具

Atom 编辑器

Atom编辑器是由Github引领的一款转为Web Developer打造的开源编辑器,深度定制Chromium底层和NodeJS结合,程序员可以通过NodeJS来对编辑器进行自定制,相信未来应该是前段开发利器。

NodeJS 命令行工具

随着NodeJS越来越普及,可以用NodeJS做的事情也越来越多了,比如各种小工具。做一个小工具是如此的easy。下面的作品是来自new relic的大神 Jacob@newrelic.com的作品:

  • jscurl 一个建议的类curl工具
  • node-nsh一个类bash shell命令行
  • node-wssh 一个类ssh的实现, 可同时用于服务器和客户端
  • node-os 一个使用nodejs编写的操作系统,http://node-os.com

实现一个npm package是非常的easy:

  • Run npm init
  • Add a new file with node env put on the top
  • Write your function
  • Add bin config point to the file. e.g.: {package name: “target js file”}
  • Run npm link and test with package name

大数据

大数据是近两年流行起来的一个词, 各种大数据技术层出不穷,其中以Google (Big Table), Facebook (Hadoop)牵头, twitter (Storm)随后跟上。

Google Big Query

BigQuery是一个海量数据管理工具, 可以用来查询海量数据, 目前查询免费, 操作新表会收费。目前已经有NodeJS BigQuery模块。有兴趣的朋友可以搜索BigQuery了解。

Twitter Storm

来自twitter的一位后端女工程师带来了storm的分享,看起来很牛叉,原理类似map –> reduce, 现在也已经有NodeJS模块可以使用, 有兴趣的可以查询了解。

性能优化

性能优化似乎是永久不变的话题, 这也是更好的用户体验使然。Angular近年来非常的火, 但众所周知, angular使用的dirty check非常的吃性能, 这就不得不对大型的angular进行优化。

Angular JS 优化

以下是一位讲师的经验所得:

  • 代码组织
    • angular seed
    • 数据共享 (Event / Service)
    • 共享template (directive)
  • 性能监测
    • bindonce
    • limitTo
    • Batarang
    • 分页
  • 缓存HTTP请求
  • 实时数据绑定 (feed / Firebase / cloda)
  • SEO
    • #!/url/path => /?escape_fragment=/url/path
    • HTML5 meta fragment

架构设计

架构设计还是属EF Lab‘s Mikael带来的演讲非常精彩。随着前端越来越可以胜任大规模的复杂的业务逻辑, 架构设计也变得越来越重要。

Mikael的架构哲学:

  • 模块化 (Code , template, styles , data)

  • 开发小的模块 (easy to read, maintain , use) –> 分离注点

  • 部署 bigish

    • 合并可重用的代码,函数和小的应用程序

    • 移动设备上有一个文件

  • 解藕

    • 向后端开发者学习

      • 事件总线: EIP, ESB, micro services
  • 前端 ?

    • 连接components
  • 集成

    • 订阅改变而不影响整个应用程序
    • 使用假的component进行快速开发
  • 程序异步化? why?

    • 连接速度
    • 连接的可用性
  • 变得事件驱动化

    • Nodejs emitter
    • Dom event
    • web sockets
    • akka http://akka.io/
    • erlang – event driven languages
  • 使程序自表达,自解释, 并且保持不重复

    • 自表达 – 方法名,链式操作, URL的结构
    • 自声明 – what do we want to do instead of how do we want to do
    • DRY – not repeat yourself
    • congnitive load (直觉加载, 一种方法学) ??
  • AKA – one application to rule them all ? [一个java后台框架]

移动设备传感器

传感器绝对使整个大会的一个亮点, 我们每天都在用HTML5,每天都在用Mobile,但是我看没有多少人真正在意各种奇妙的传感器。未来这个技术一定会越来越火, 建议每个前端开发人员都要了解传感器的概念。

Hybrid API 传感器

  • 动作

    • 陀螺仪

      • 水平仪
    • 加速计 -> acceleration or accelerationWithGravity

      • 小猫快跑
    • 距离传感

      • 锁屏
  • 环境

    • 指南针
    • GPS + 磁力计
    • 智能感光

      • Css light-level : normal …
    • 其他

      • 气压 - 海拔
      • 温度, 湿度
      • 音频

        • 呐喊
        • 支付宝 修修修
        • 语音识别 SIRI
      • 视频

        • 试衣间 ?
        • 试戴
        • 肤色识别
        • 虚拟现实 VR? 沉浸式技术联盟 (ITA)
        • 增强现实 AR
  • 目标

    • 功能封装
    • 跨平台使用
  • W3C device API

Web Component – web开发的未来

Web Component的概念已经提出来有段时间了, 但是还没有完全兼容,它主要用来组件化各个功能Dom模块,使开发效率变高,维护成本变低。目前IE全员不支持,Ya的, 不解释。

  • 新增的template元素
    • 内容被解析, 但是不显示
    • 图片不会下载
    • 脚本不会下载
  • document.registerElement(‘element name’, {prototype: “prototype object”})
  • shadow dom
  • import 引用 <link rel=“import” href=“target.html”>

  • polyfill

程序员的软实力

程序员可能天天与新技术和代码打交道,实际上我们做这一切都是未来生活, 如何平衡好生活和工作的关系对于程序员的身心健康也是非常的重要。我推荐大家多了解:

  • 时间管理
  • 人际关系拓展
  • 关于生活的书: 《生存之道》《高效程序员习惯》
  • TED: 《幸福的定义》

开源社区

我对开源一直持有开放的态度, 希望极可能加入到开源项目中,我觉得这会是程序员的附加价值,不仅丰富生活,还可以和全世界各地的开发者一起共事,想想就很amazing。所以我觉得每个程序员都应该选择一个自己感兴趣的领域多做共享,实现自己更高的价值。

来自开源社区贡献者turingou的分享:

  • 垂直领域 Express-scaffold, Theme, Mails
  • 有趣的 Douban.fm, candy, o3o
  • 有成长的 NodeJS & NPM, Koa, Smart Hardware
  • 爆发性的 swift bitcoin

结论

前端开发变得原来越庞大,复杂,每天都会有新技术涌现出来,我们必须时刻准备好迎接新的挑战,多关注开源项目,平衡好工作和生活。总之一句话, 未来属于前端Full Stack Developer的!

Thinking in D3

d3

前记

最近在使用D3做数据可视化开发,学到一些东西,因此写篇文章记录一下。

D3 是什么?

D3.js is a JavaScript library for manipulating documents based on data. D3.js 是一个基于数据,用于操纵文档的javascript库。

D3中含有3个D:Data, Driven, Documents。 通俗的讲,D3可以用来做一下事务:

  • 数据可视化
  • 数据交互
  • 数据实时更新

如果说大数据是一堆凌乱,毫无秩序的碎片, 那么D3就是可以让这些凌乱不堪的数据变得井然有序的指挥手。

为什么选择D3?

  • 开源,并且在github中获得star前10位 (BSD licensed (BSD-new))
  • jQuery相似的API
  • 背后有商业公司支持(New York Times)
  • 社区活跃, 问题可以得到及时的解答, 以下是D3在Github中的实时状态
    D3-status
  • 方便扩展和调试,可以对Dom直接操作
  • 简单,快速,高效
  • 完美的动画支持

在对比了无数可视化library,发现D3能够满足目前项目的需求,于是果断使用。当然,如果你的银子不在乎, 可以考虑使用highchart, 目前被很多大公司使用, 非常稳定。

使用起来方便吗?

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 定义边距值
var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;
    
var parseDate = d3.time.format("%d-%b-%y").parse;

// 定义x坐标的值类型和范围
var x = d3.time.scale()
    .range([0, width]);
    
// 定义y坐标的类型和使用范围
var y = d3.scale.linear()
    .range([height, 0]);

// 定义x轴的样式以及数据源
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");
    
// 定义y轴的样式和数据源
var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

// 定义线段的取值范围
var line = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.close); });

// 向Dom body元素中加入一个svg元素并指定svg的大小
var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// 加载数据源
d3.tsv("data.tsv", function(error, data) {
  
  // 数据预处理
  data.forEach(function(d) {
    d.date = parseDate(d.date);
    d.close = +d.close;
  });
  
  //定义x,y坐标领域值范围
  x.domain(d3.extent(data, function(d) { return d.date; }));
  y.domain(d3.extent(data, function(d) { return d.close; }));
  
  //添加g元素用于组合x,y轴(svg中部分元素必须置于g中才能正常显示)
  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
  
  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Price ($)");
  
  // 创建线段
  svg.append("path")
      .datum(data)
      .attr("class", "line")
      .attr("d", line);
});

上面的代码是不是很容易懂? 如果你对SVG概念有个大概的了解, 并且会使用jQuery, 那么你会很容易上手。

如何开始学习使用?

  • 首先,你需要对SVG有足够的了解和认识
  • 然后,学习D3基本语法规则
  • 查看example, 实践
  • 优化, 实践…

简单解析D3源码

为什么要看源码?我的想法是,知其然还不够,知其所以然可以让我们更快更好的发现问题并解决。同时可以让我们学习到不同的方法来创建,管理一个framework。

  • 文件结构
    • bin 基础性的配置工具,bower, uglyfy等
    • lib 第三方的库以及版权信息
    • src 所有D3领域编程源码,在所有的源码中,每个目录都会有一个index.js文件,用来定义所有在当前目录中的模块以及以来顺序
    • test 所有的单元测试文件
  • 开发流程(根据文件结构及构建脚本推断)
    1. 首先定义好所有领域原子模块,如: svg, xhr, event, color, geo等
    2. 对于每个原子模块在进行细分,如: svg中的线段,圆弧等基本图标属性
    3. 定义index.js来包含原子模块,并定义依赖关系
    4. 使用Make脚本测试,打包生成生产环境可以使用的代码
    5. 部署到travis CI server进行集成测试
  • 工具使用
    • smash 根据index.js中定义的规则合并原子模块
    • Uglyfy 用于minify JS
    • vows 用于单元测试
    • jsdom在node环境中模拟Dom tree 在看了一些D3的源码之后,我的感觉是非常的简洁,模块化,非常值得借鉴,如果你有想法要构建一个XXX library的时候,不妨参考一些D3的源码。欣赏一下D3的构建脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
GENERATED_FILES = \
  d3.js \
  d3.min.js \
  bower.json \
  component.json

all: $(GENERATED_FILES)

.PHONY: clean all test

test:
  @npm test

src/start.js: package.json bin/start
  bin/start > $@

d3.js: $(shell node_modules/.bin/smash --ignore-missing --list src/d3.js) package.json
  @rm -f $@
  node_modules/.bin/smash src/d3.js | node_modules/.bin/uglifyjs - -b indent-level=2 -o $@
  @chmod a-w $@

d3.min.js: d3.js bin/uglify
  @rm -f $@
  bin/uglify $< > $@

%.json: bin/% package.json
  @rm -f $@
  bin/$* > $@
  @chmod a-w $@

clean:
  rm -f -- $(GENERATED_FILES)

虽然目前前端开发有比较成熟的Grunt, 但是在某些场景下有点过于繁琐和笨重, 这时候使用Make file会是比较好的选择。

学习资料

结论

D3的使用是非常优雅, 但是学习曲线非常陡峭,有很多领域知识需要学习,如果不想学习D3, 但又想快速使用D3来构建分析图表,那么可以考虑使用 NVD3 或者 D4。同时,众所周知SVG不支持<=IE8, 那么在IE8中可以使用:

  • aight 让D3可以在IE8中工作
  • R2D3 同时使用Raphael和D3
  • 通过特性检测选择使用不同的library document.implementation.hasFeature ("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1");

对于性能方面,如果页面节点过多,还是考虑使用canvas。另外,为了更好的使用D3,可以试用D3的领域知识加上AngularJS创建custom的component, 这样在未来的开发中可以加快开发进度, 并且拥抱web component。

Use OpenTag Management System

Qubit OpenTags

什么是Tag管理?


这里的Tag指的是第三方的JavaScript tags,这些tag你可以用来增强网站功能,比如说Google Analytics。国内的某些大型网站可能会使用成千上万的tag,这样就需要一个中心化的Tag管理系统来统一管理一个或多个网站的tags。

为什么需要管理tags?

  1. 统一跟踪管理
  2. 随时更新版本
  3. 全局性的添加,删除
  4. 高可用性

使用Qubit tag管理系统

Qubit Opentag is available as a self-service or managed tag manager, tailored to your business needs.

  • 完全免费
  • 允许百万PV每月
  • 友好的UI配置管理
  • 使用简单
  • 服务背后使用AWS,高可用性

Qubit允许你使用一系列加载规则加载不同的tag应用于不同的网站, 并且你只需要在你的网站中引用一个可以从CDN加载的JavaScript文件就可以了。

使用步骤:

  1. 首先你需要注册一个免费的账户
  2. 创建一个tag容器, 一个容器可以管理多个tag Qubit容器
  3. 设置tag加载规则,Qubit有许多默认的模版供你使用,同时你也可以自定制加载脚本。
    • AB & Muti-Variate Tesing A/B Testing
    • Custom Script Custom Script
  4. 配置加载规则 Filters
  5. 删除你当前使用的Tag脚本
  6. 添加Qubic生成的脚本到head标签中 Qubit Track
  7. 重新测试网站,确保一切都可以正常工作
  8. Done!

更多细节,可以访问:Qubit Opentag DashBoard

How to Build Glyph Icons Fonts

Glyph ICON Fonts

什么是Glyph?

A glyph /ˈɡlɪf/ is an element of writing: An individual mark on a written medium that contributes to the meaning of what is written. 字形-一个可以辨认的抽象的图形符号,它不依赖于任何特定的设计

为什么要用Glyph ICON?

  • 扁平化设计
  • 响应性设计
  • 更灵活的调整元素的各种属性但不失真(大小,颜色)

简言之, Glyph ICon font就是一种用font的方式来设计web元素的背景。

有什么神器可以用?

  • Iconmoon 一款非常实用的在线工具,但前提是你要准备好SVG
  • Glyphsapp一款非常强大的编辑器,项目化整个ICON制作流程, 但不是免费的
  • GlyphStudio 一个免费的基于HTML5的字体编辑器

Glyph Studio

Glyph Studio

  • 可以在线或者离线方式访问
  • 可以创建或者导入项目, 基于文件存贮
  • 自由定制

使用Glyph Studio制作字体的完整流程

  • 访问Glyphr_Studio_Beta_3.2后者直接将页面存贮到本地
  • 拖拽项目文件到页面,或者点击“Start a new font from scratch”创建一个新的项目
  • 设计,修改字符集(拉丁字符)
  • 完成后,选择“export font”->“Generate TTX XML File”,之后会生成一个以项目名命名TTX的文件
  • 访问TTX安装相应软件(Windows和Mac平台均支持)
  • TTX 是一个可以从XML转换OpenType或TrueType字体,或者将字体转换成XML文件 ttx [options] inputfile1 [... inputfileN]
  • 运行ttx [project-name].ttx会生成ttf字体文件
  • 访问font-to-web导出所有格式的字体文件(.ttf, .otf, .eot, .woff and .svg)

Notes

  • Mac上安装TTX时候需要提升权限 sudo
  • 为了方便只用TTX, 最好在你的命令行中配置: alias ttx=/Library/Frameworks/Python.framework/Versions/2.7/bin/ttx,这样你就可以直接使用ttx来操作了

Emoji in Web

Emoji

什么是Emoji?


emoji就是表情符号,在外国的手机短信里面已经是很流行使用的一种表情。这些符号可以让您的消息变得更有趣味并为您的生活增添亮点,在您添加Emoji键盘之后,点击空格键左边的“Globe”按钮来转换键盘,在短消息、电子邮件、注释、联系人和日程表中使用独特的Emoji图标——在使用键盘的iPhone或iPod touch的任何应用中都可以使用。

Web Emoji

Web Emoji指的是在web网页中实现和手机Message相同功能的emoji功能。

Web友好的Emoji编辑器

Gmail Emoji Editor

单纯的emoji的显示还是听简单的,但是如果放到编辑器中还是有很多挑战的:

  1. 编辑器中显示emoji
  2. emoji和文本同时显示
  3. emoji插入到光标的位置
  4. 删除光标位置的emoji
  5. 各个系统的emoji准确的显示

我的思路

  1. 使用contenteditable实现简易的web编辑器
  2. 动态检测鼠标位置并进行记录, 在需要插入emoji的时候,插入到保存的鼠标位置。
  3. 将各个系统发送的emoji进行unicode转义,然后映射到指定的图片

看起来很美,但是其中有些部分很难实现:

  1. 获取emoji在编辑器中的位置和文本可以用相同的方法吗?
  2. emoji unicode图片都一一进行单独制作吗?
  3. 插入emoji到指定的光标位置可以正确的工作吗?

经过多种方法尝试,发现浏览器在获取emoji和文本光标位置的时候,用业界流行的方法无法正确获取, 这样就导致插入或者删除emoji并不是我们所期望位置的。例如连续插入多个emoji,会发现后插入的emoji竟然显示到了之前插入的emoji之前。大概看了一下gmail的源码,也找不错特别的端倪,于是只好采用比较ugly的方式:

  • 在每个emoji之后默认加入一个空格符(如: &nbsp;), 这样浏览器就可以正确到emoji的位置,但是问题是加入本来内容就是空格的情况将不适用
  • 每次插入emoji的时候,记录所插入的emoji dom元素的位置,这样在连续插入emoji的时候可以使用原生的dom api插入新的节点到后面,这样做的好处是没有多余的空格的元素
  • 对于转义各个系统的emoji到unicode的问题,参考了字符编码 unicode 及其在javascript 中的使用Emoji Unicode Tables。解决方法是:首先遍历editor内容,找出所有超出正常字符(中英文,标点符号等)显示范围的特殊字符,然后统转义到unicode 16,然后从emoji unicode table中引用对应的图片,完美解决,具体实现是:Implement Code

结论

对于如何正确找出emoji所在editor的位置,始终没有找到好的办法,目前只是处于能用的程度,未来计划有时间深入研究一下Dom Mutation Observer看看能不能有新的突破,欢迎大家留言讨论。对于性能问题也有过对比新浪和QQ的策略,最终觉得使用Emoji Sprite比较合适,这个也是需要改进的一个地方。

Git Tips

  • Git basic
    
      man git-
      
  • When remote system password, but you stored it in local credential, you should earse local cache first.
    
      git credential-osxkeychain erase
      
  • You can not create a branch with a relationship of contains
    
      # disable
      git checkout -b branchA
      git checkout -b branchA/branchB
      # enable
      # git checkout -b branchA
      git checkout -b branchA/branchB
      
  • Stage changes in Hunks
    
      git add -p 
      
  • Checkout Your Last Branch
    
      git checkout –
      
  • Show Which Branches are Merged
    
      git branch —merged
      git branch —no-merged
      git branch —merged | xargs git branch -d
      
  • Auto-Completion
    • Base dir : contrib/completion
    • How:
      
        # in .bashrc
        source ~/.git-completion.bash
        # or copy to specific dir
        cp ~/.git-completion.bash /opt/local/etc/bash_completion.d
        cp ~/.git-completion.bash /etc/bash_completion.d/
        
  • Grab a File from Another Branch without Switching Branches
    
      git checkout  — path/to/file.rb
      
  • Git Branches Sorted by Last Commit
    
      git for-each-ref —sort=-committerdate —format=‘%(committerdate:short) %(refname:short) [%(committername)]’
      # add a alias
      git config —global alias.latest “for-each-ref —sort=-committerdate —format=‘%(committerdate:short) %(refname:short) [%(committername)]’”
      
  • Git Aliases
    
      git config —global alias.co checkout
      git config —global alias.ds ‘diff —staged’
      git config —global alias.st ‘status -sb’
      git config —global alias.amend ‘commit —amend -C HEAD’
      git config —global alias.undo ‘reset —soft HEAD^’
      git config —global alias.br branch
      git config —global alias.ci commit
      git config —global alias.st status
      git config —global alias.ls ‘log —pretty=format:“%C(yellow)%h %C(blue)%ad%C(red)%d %C(reset)%s%C(green) [%cn]” —decorate —date=short’
      git config —global alias.unstage ‘reset HEAD —’
      git config —global alias.visual ‘!gitk’
      git config —global alias.standup ‘log —since '1 day ago’ —oneline —author ‘
      git config —global alias.graph 'log —graph —pretty=format’:%C(yellow)%h%Cblue%d%Creset %s %C(white) %an, %ar%Creset'‘
      
  • Git blame

    
      git blame -w  # ignores white space
      git blame -M  # ignores moving text
      git blame -C  # ignores moving text into other files
      

  • Git Attribute file to avoid in-consistent EOL

    
      # These files are text and should be normalized (convert crlf => lf)
      .cs      text diff=csharp
      .xaml    text
      .csproj  text
      .sln     text
      .tt      text
      .ps1     text
      .cmd     text
      .msbuild text
      *.md      text

    # Images should be treated as binary # (binary is a macro for -text -diff) .png binary .jepg binary

    *.sdf binary

  • Good Resource:

Troopjs Code Analysis of Factory

The factory method pattern is an object-oriented creational design pattern to implement the concept of factories and deals with the problem of creating objects (products) without specifying the exact class of object that will be created.

The factory of troopjs actually is a basic widget composer, it is a decorator at the same time. It’s based on ECMA Script 5 Object which enable you todo following staff:

  • Object.Create Creates a new object with the specified prototype object and properties.
  • Object.defineProperty Defines a new property directly on an object, or modifies an existing property on an object, and returns the object.
    • configurable
    • enumerable
    • value
    • writable
    • get
    • set
  • Object.defineProperties Defines new or modifies existing properties directly on an object, returning the object.
  • propertyIsEnumerable
  • Object.keys Returns an array of a given object’s own enumerable properties, in the same order as that provided by a for-in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
  • Object.getOwnPropertyNames Returns an array of all properties (enumerable or not) found directly upon a given object.
  • Object.getOwnPropertyDescriptor
  • Object.freeze Freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed. In essence the object is made effectively immutable. The method returns the object being frozen.
  • Object.getPrototypeOf Returns the prototype (i.e. the internal [[Prototype]]) of the specified object.
  • Object.preventExtensions Prevents new properties from ever being added to an object (i.e. prevents future extensions to the object).

  • But how to does Object-base Inheritance works? See example.

Decouple Factory

  • Decorate
    • Before is excuted before origin function
    • After is excuted after origin function
    • Around is mixed with origin function
  • Inheritance
    • create is used to create a component
    • extend is used to extend a component
    • constructors are from function arguments passed to factory
  • Detail explain
    • special is used to handle event like: “dom/[data-action=‘test’]/click.dbclick” from property /^(\w+)(?::(.+?))?\/([-_./\d\w\s]+)$/
    • factory descriptors

      • create
      • before
      • after
      • around
    • constructor descriptors

      • protype
      • constructors
        • default is
          • “enumerable” : true,
          • “configurable” : true,
          • “writable” : true
      • specials
      • tostring
      • extend
      • create

It’s a good pattern to create Mix-in component. Use case:


    // component/base.js
    return Factory(
    /**
     * Creates a new component
     * @constructor
     */
    function Component() {
        var me = this;

        // Update instance count
        me[INSTANCE_COUNT] = ++INSTANCE_COUNTER;

        // Set configuration
        me[CONFIGURATION] = {};
    }, {
        "instanceCount" : INSTANCE_COUNTER,

        "displayName" : "core/component/base",

        /**
         * Configures component
         * @returns {Object} Updated configuration
         */
        "configure" : function configure() {
            return merge.apply(this[CONFIGURATION], arguments);
        },

        /**
         * Signals the component
         * @param _signal {String} Signal
         * @return {*}
         */
        "signal" : function onSignal(_signal) {
            ...
        },

        /**
         * Start the component
         * @return {*}
         */
        "start" : function start() {
            ...
        },

        /**
         * Stops the component
         * @return {*}
         */
        "stop" : function stop() {
            ...
        },

        /**
         * Creates new task
         * @param {Function} resolver
         * @param {String} [name]
         * @returns {Promise}
         */
        "task" : function task(resolver, name) {
            ...
        },

        /**
         * Generates string representation of this object
         * @returns {string} displayName and instanceCount
         */
        "toString" : function _toString() {
            ...
        }
    });

My Dot Files

What’s the dotfiles?

  • A dot-file is generally any file whose name begins with a full stop.

Why we should use dot file?

  • Keep environment consistensy
  • Own settings, configurations, or themes

Which dotfiles we need?

  • Git
    • .gitconfig

      
            [user]
                name = jade.zhangjin
                email = jade.zhangjin@ef.com
            [gui]
                recentrepo = E:/Program Files/SmartGit 2/bin/blitz
                recentrepo = E:/EF_Work/cheetah
            [core]
                excludesfile = .gitignore
            [alias]
                st = status
                sts = status —short
                ci = commit -m
                cia = commit -am
                cie = commit —amend
                co = checkout
                br = branch
                sb = show-branch
                cp = cherry-pick
                rb = rebase
                rbc = rebase —continue
                rbs = rebase —skip
                rl = reflog
                rs = remote show
                rt = remote
                ru = remote update
                rp = remote prune
                sm = submodule
                add = add -v
                staged = diff —staged
                unstage = reset HEAD
                diff-all = diff HEAD
                diff-stat = diff -b —stat
                log-graph = log —all —graph —decorate
                log-refs = log —all —graph —decorate —simplify-by-decoration —no-merges
                log-timeline = log —oneline —format=‘%h %an %ar – %s’
                log-local = log —oneline origin..HEAD
                log-fetched = log —oneline HEAD..origin/master
                hist = log —pretty=format:\“%h %ad | %s%d [%an]\” —graph —date=short
                type = cat-file -t
                dump = cat-file -p
                codev = checkout team/school-pc/develop
      codra = checkout team/school-dragon/develop pulldra= pull —rebase origin team/school-dragon/develop pushdra= push origin team/school-dragon/develop corefac = checkout feature/school/ux/refactor
      cosdev = checkout feature/school/develop
      pulldev = pull —rebase origin team/school-pc/develop
      pushdev = push origin team/school-pc/develop pullsdev = pull —rebase origin feature/school/develop
      pushsdev = push origin feature/school/develop
      pullrefac = pull —rebase origin feature/school/ux/refactor pushrefac = push origin feature/school/ux/refactor udsub = submodule update —recursive udinitsub = submodule update —recursive —init ls = log —pretty=format:“%C(yellow)%h%Cred%d\ %Creset%s%C(yellow)\ [%cn]” —decorate ll = log —pretty=format:“%C(yellow)%h%Cred%d\ %Creset%s%C(yellow)\ [%cn]” —decorate —numstat lnc = log —pretty=format:“%h\ %s\ [%cn]” [core] autocrlf = true [color] branch = auto status = auto [format] pretty = %h %an %ad – %s # default log —pretty format [log] date = iso # log use iso format for date decorate = short # decorate log with branch name abbrevCommit = true # show short SHA1 hash [merge] tool = p4merge [mergetool “p4merge”] path = C:\Program Files\Perforce\p4merge.exe cmd = p4merge “$BASE” “$LOCAL” “$REMOTE” “$MERGED” keepTemporaries = false keepBackup = false trustExitCode = false [diff] tool = p4merge [difftool “p4merge”] path = C:\Program Files\Perforce\p4merge.exe cmd = p4merge “$LOCAL” “$REMOTE” keepBackup = false trustExitCode = false [credential] helper = !‘C:\Users\jade.zhangjin\AppData\Roaming\GitCredStore\git-credential-winstore.exe’ [push] default = upstream

    • .gitignore

      
          .min.js
          node_modules
          .min.css
        

  • Shell (bash/zsh/csh)
    • .bashrc
      
            # Common Alias
            alias cls=‘clear’
            alias g=‘git’
            alias open=‘explorer .’
            alias stash=‘cd $work’
            alias ui=‘cd $work/school-ui’
            alias act=‘cd $work/school-ui-activity’
            alias cont=‘cd $work/school-ui-activity-container’
            alias school=‘cd $work/school’
            alias shared=‘cd $work/school-ui-shared’
            alias study=‘cd $work/school-ui-study’
            alias blitz=‘cd /e/Project/blitz’
            alias dist=‘cd $shared_work/ui-shared-dist’
            alias st=‘git st’
            alias co=‘git co’
            alias diff=‘git difftool’
            alias merge=‘git mergetool’
            alias codcr=‘git $codra’
            alias pulldcr=‘git $pulldra’
            alias pushdcr=‘git $pushdra’
            alias gpp=‘git pull origin; git push origin’
        
  • System Env config (Ruby/Python/NodeJS…)
    • .editorconfig

      
        ; EditorConfig is awesome: http://EditorConfig.org

      ; top-most EditorConfig file root = true

      ; 4 space indentation [*.py] indent_style = space indent_size = 4

      ; Tab indentation (no size specified) [*.js] indent_style = space indent_size = 4 trim_trailing_whitespace = true

    • .jshintrc
      
        {
          “undef”: true,
          “unused”: true,
          “globals”: {
            “jQuery”: false,
            “define”: false,
            “browser”: false
          }
        }
        

      Bootstrap.sh

  • Auto install develop software
  • Auto config environment (hostFile/auto startup)
  • Intial all repos project source
  • Auto run local web server

    #!/bin/bash
    # init-Xnix-env.sh
    # A tool used to config front-end developer's environment.

    # Notes:
    # 1. Please use "WorkSpace" as develop directory
    # 2. If you got error 'Error: listen EADDRINUSE', then you need check apps runs at net port 80
    # 3. This command automatically setes host file
    # 4. Please use cns-etuat-[9,18,19,21].localnet.englishtown.com to access website
    # 5. 'school-ui' repo need checkout "team/school-pc/dev-server-template" branch for dev develop
    root="Stash"
    config="config.json"

    # Util Functions
    function detectEnv() {
        if [ command -v $1 >/dev/null 2>&1 ]
        then 
            return 1
        else 
            return 0
        fi
    }

    function installNodeJS() {
        git clone git://github.com/ry/node.git
        cd node
        ./configure
        make
        sudo make install
        cd ..

        git clone http://github.com/isaacs/npm.git
        cd npm
        sudo make install
        
        cd ..
        export NODE_PATH="/usr/local/lib/node"
    }

    function installGit {
        version=1.8.2.1
        curl -O https://git-core.googlecode.com/files/git-$version.tar.gz
        tar xzvf git-$version.tar.gz cd git-$version
        
        tar xzvf git-1.7.7.tar.gz cd git-1.7.7
        ./configure --prefix=/usr/local
        make 
        sudo make install
        cd ..
    }

    function setEnv {
        export PATH="/usr/local/bin:/usr/local/sbin:usr/local/lib;/usr/local/mysql/bin:$PATH"
        source ~/.bashrc
    }

    function createDir() {
        for i in $@
        do echo $i && mkdir $i
        done
    }

    function ensureDir() {
        for i in $@
        do
            if [ -d "$i" ]
            then
                echo $i exists.
            else
                echo Ensure Dir $i
                createDir "$i"
            fi
        done
    }

    function clone() {
        shared_repo=ui-shared-dist
        framework=ef-troopjs
        # Note: must put school-ui at last, cause we have special logic for this 
        school="school-ui-shared school-ui-activity school-ui-activity-container school-ui-study school-ui"
        blue="et-ui-headerfooter tooltips-ui"
        repo_server="https://stash.englishtown.com/scm"
        branch="team/school-pc/develop"
        must_have="school-ui school-ui-activity school-ui-study school-ui-shared"
        # $1 is type, $2 is repo name

        if [ $1 = COMM ]
            then repo_type=$blue && branch=develop
        elif [ $1 = FRAM ] 
            then repo_type=$framework && branch=develop
        elif [ $1 = TSCHOOL ] 
            then repo_type=$school
        elif [ $1 = SHARE ] 
            then repo_type=$shared_repo
        fi

        for i in $repo_type
        do 
            echo Start to clone $i now...  
            if [ ! -d $i ]; then git clone -b $branch $repo_server/$1/$i.git; fi;
            cd $i && git submodule update --init --recursive && cd ..
        done

        if [ $1 = SHARE ] 
            then cd ui-shared-dist && ensureDir $must_have && cd ..
        fi  
    }

    function mkSoftLink() {
      for i in $@;
      do 
        ln -s ~/$root/Workspace/labs-school/$i/src ~/$root/Server/root/localnet.englishtown.com/_shared/$i/snapshot 
      done
    }

    cd ~
    # Steps to setup dev environment in Xnix:
    # 1. Detect NodeJS/Git is installed or not
     detectEnv node || installNodeJS
     detectEnv git || installGit 
     setEnv
    # 2. Check node-devserver is installed or not, if not, auto install it
     detectEnv npm && sudo -- sh -c "npm install -g devserver"
    # 3. Create structure dir of Project Server and work space
    ensureDir $root && cd ~/$root
    path="Server Server/root Server/root/localnet.englishtown.com Workspace"
    createDir $path
    # 4. Generate Dev Server config file

    cd ~/$root/Server 

    echo [{                                                                   > $config
    echo         \"module\" : \"devserver.frontend\",                             >> $config
    echo         \"arguments\" : [ \"root\" ]                                     >> $config
    echo }, {                                                                 >> $config
    echo         \"module\" : \"devserver.backend\",                              >> $config
    echo         \"arguments\" : [{                                             >> $config
    echo                 "\"regexp\" : \"^(?(cns-etuat|cnshhq|cns)-\\\\d+)\\\\.(?.+)\"", >> $config
    echo                 \"proxy\" : {                                          >> $config
    echo                         \"host\" : \"\$\{uat\}.ef.com\",                    >> $config
    echo                         \"port\" : 80                                 >> $config
    echo                 }                                                    >> $config
    echo         }]                                                           >> $config
    echo }]                                                                   >> $config
    # 5. Make system start up service for startup dev server
    # 6. Indicate whether is the first time to use Git, if it is, then remind to config git
    git config --list --global | grep user.name || git config --global user.name 
    git config --list --global | grep user.email || git config --global user.email 
    # 7. Get school related code from stash, checkout 'team/school-pc/develop' branch , init and update submodule
    cd ~/$root/Workspace
    repo_ctg="Frameworks labs-blue labs-school labs-shared"
    createDir $repo_ctg

    cd ~/$root/Workspace/labs-shared && clone SHARE
    cd ~/$root/Workspace/labs-blue && clone COMM
    cd ~/$root/Workspace/Frameworks && clone FRAM 
    cd ~/$root/Workspace/labs-school && clone TSCHOOL

    # 8. Make snapshot soft link 
    ln -s ~/$root/Workspace/labs-shared/ui-shared-dist/ ~/$root/Server/root/localnet.englishtown.com/_shared
    ln -s ~/$root/Workspace/Frameworks/ef-troopjs/src ~/$root/Server/root/localnet.englishtown.com/_shared/troopjs-ef/snapshot
    ln -s ~/$root/Workspace/labs-blue/et-ui-headerfooter/src ~/$root/Server/root/localnet.englishtown.com/_shared/headerfooter/snapshot

    repos="school-ui school-ui-study school-ui-shared school-ui-activity school-ui-activity-container"
    mkSoftLink $repos
    # 9. Config Host File (cns-etuat-9,cns-etuat-18,cns-etuat-19,cns-etuat-21)
    host_file="/etc/hosts"
    host="cns-etuat-9 cns-etuat-18 cns-etuat-19 cns-etuat-21"
    sudo  -- sh -c "echo >> /etc/hosts"
    echo Start to config host file now...
    for i in $host 
    do 
       cat $host_file | grep $i.localnet.englishtown.com || sudo -- sh -c "echo 127.0.0.1 $i.localnet.englishtown.com >> /etc/hosts"
    done   
    # 10.Start server at 88 port 
    cd ~/$root/Server && node-devserver -c $config

Todo: continue integration dotfiles to this blog

Troopjs Architecture Analysis

Troopjs framework is seperated by 6 different parts:

  • troopjs-core is the basic frastrate modules
    • component
      • factory is the most basic widget factory based on poly.js
      • base is the most common widget which used to manage life-cycle and task.
      • gadget is a observable base widget
      • service is most common service lift-cycle mamager
    • event
      • emitter is a NodeJS style event manager, the event will be excuted by sequence
    • logger
      • console is a system Console wrapper
      • pubsub is a hub wapper for logger topic
      • service is a log service which used to wrapper message and output data to different appender
    • pubsub
      • hub is a wrapper of event emitter
      • proxy
        • to1x is troop 1.0 hub proxy
        • to2x is troop 2.0 hub proxy
    • resistry
      • service is a action service manager

  • troopjs-jquery
    • destory is a jquery plugin used to handle dom destroy special event
    • dimensions is a jquery plugin used to handle widget resize when parent resized
    • hashchange is a jquery plugin used to handle has changed event and support mutiple browsers
    • loom is weave function wrapper and weave css expression extender
    • noconflict is jQuery noconflict wrapper
    • resize is a window resize event wrapper

  • troopjs-requirejs
    • multiversion is used to support require multiple context widget
    • shadow is used to load different version of widget at the same time
    • template is troop template engine which use function context

  • troopjs-utils
    • getargs ?????(todo: find use case)
    • merge is a deep merge util method
    • unique is used to filter duplicted data and consist comparator

  • troopjs-browser
    • ajax
      • service is a ajax request handler
    • application
      • widget is a base browser application life-cycle manager
    • component
      • widget is a base dom component widget life-cycle manager
    • dimensions
      • widget is a dom demensions life-cycle manager
    • loom
      • config is used to config indicator for weave related stuff
      • unweave is unweave promise manager
      • weave is weave promise manager
      • woven is woven promise manager
    • route
      • uri is base url factory widget
      • widget is listened to “hashchange” event, and manage route life-cycle
    • store
      • base is a common storage wrapper
      • local is a localStorage wrapper
      • session is a seesionStorage wrapper

  • troopjs-data
    • cache
      • component is cache life-cycle manager
    • component
      • widget is a common query widget wrapper
    • query
      • component is a cache manager to support mutiple cache process stuff
      • service is a batch query service life-cycle manager
    • store
      • component is storage util wrapper used to process different storage stuff