如何实现一个ECMAScript 6 的promise补丁

Promise最先是CommonJS工作组提出的一种规范之一,目的是为了解决js异步编程过程中,回调嵌套过深的问题。ECMAScript 6 规范化了Promise对象的语言接口,使其成了js的原生对象之一。

如果你还不了解ECMAScript 6 中的Promise对象,建议阅读http://es6.ruanyifeng.com/#docs/promise。ECMAScript 6 中的Promise对象与一些常用的promise库(如jquery,when.js)中的实现略有不同,本文讨论的实现,以ECMAScript 6 为准。
下面,我们来一起学习,如何在不支持ES6的浏览器上简单实现Promise,如有不对的地方,还请多多指正。

首先,我们来看看Promise构造函数。

var Promise = function (fun) {
        var me = this,
            resolve = function (val) {
                me.resolve(val);
            },
            reject = function (val) {
                me.reject(val);
            }
        me._st = 'pending';
        me._rsq = null;
        me._rjq = null;
        (typeof fun === 'function') && fun(resolve, reject);
    },
    fn = Promise.prototype;

构造函数接受一个异步的回调函数,并调用,回调函数的2个参数,分别为异步操作成功和失败时候要调用的改变Promise实例状态的方法。
_st用于存放当前实例的状态,初始值为”pending”,异步操作成功为”resolve”,失败为”reject”。_rsq用于存放异步操作成功的回调,_rjq用于存放异步操作失败的回调。
同时,把Promise.prototype挂在变量fn上,接下我们只要给fn添加方法就可以了。

Read More

Blog迁移到Github

由于Wordpress主机到期,而且wp的markdown插件非常坑爹,经常把本来些的好好的md格式转得乱七八糟。于是花了一天时间,把Blog搬到github来了。使用了Jekyll Bootstrap框架,下面是折腾过程中的一些体会:

  • 文章迁移: wp后台把数据导出为xml文件,再用exitwp转成md。
  • 评论迁移: Jekyll自带的disqus不太符合国情, 于是选择了国产的多说
  • 代码高亮: 使用Pygments
  • 文章摘要: Jekyll自带的显示摘要功能对HTML支持非常不好,我只好全文输出到一个script标签,再通过JS来截取并显示。
  • 搜索文章: 尝试了google站内搜索,但是发现好多冗余的页面也被搜出来了,最后决定自己用JS来实现一个简单的,只针对文章标题进行匹配的搜索功能。

迁移到Jekyll以后, 终于可以愉快地用md写blog了。

发布grunt-cptpl插件

view on Github:https://github.com/hanan198501/grunt-cptpl

grunt-cptpl插件可以将您的文本模板文件编译成javascript文件。在前端开发的时候,模板文本我们一般存放在一个隐藏dom节点,再通过javascript去获取这个节点的内容,将其编译。或者在写javascript的时候,我们手动通过拼接字符串的方式储存模板文本。grunt-cptpl使前端开发也可以像后端一样,把模板文本存放在单独的文件中,使我们的开发工作从繁琐的dom操作和拼串中解放出来,提高我们的开发效率。最主要的,模板文件作为单独文件存放,可以使我们的项目代码逻辑更加清晰,更具可维护性。

grunt-cptpl都做了啥?

grunt-cptpl会读取每个模板文件的文本内容,用指定模板引擎的预编译方法将其包裹起来,生成一个新的javascript文件。这个javascript文件文件里面的内容,其实就是模板引擎的预编译方法调用,传入的参数为模板文件的文本内容。这样我们就有了一个编译好的模板函数,要渲染的时候把数据传给它就好了。

Read More

popup组件中mask层的IE6 bug和兼容办法

我们在写一个popup组件时候,通常会加上一个元素作为mask层,用于遮盖住popup元素以外的页面内容。 而IE6下有个著名的bug就是select元素无法被遮盖,通常的做法,在IE6我们会在mask和和popup里面添加一个iframe来解决,一般的,iframe的css会是这样:

#iframe {
    display: block;
    width: 100%;
    height: 100%;
    _filter: Alpha(opacity=0);
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: -1;
}

如果popup组件需要一个功能是:点击mask的时候,隐藏popup。 所以,我们会给mask加上click事件来完成这件事。但是,这个办法在IE6下却行不通,不管吧click添加在mask元素,还是添加到mask的iframe里面的document对象,都无法出发click事件。

由于mask只有一个iframe,而iframe里面又没有然后内容,在IE下其实我们点击mask的时候是相当于点击了mask的iframe的window里。解决的办法是在mask里面再添加一个可以被“点击”到的元素,这个元素撑满mask。这样鼠标点击这个元素时候,事件自然会冒泡的mask上,保证了在IE6下mask的click也能正常被触发。

<div id="mask">
    <div style="height: 100%"></div>
    <iframe id="iframe"></iframe>
</div>

重温CSS 3D

最近开始折腾一些CSS3的东西,发现以前走马观花看过的CSS 3D相关的属性几乎忘记的差不多了,今天就来通过一个小立方体的效果来温习下:

首先,我们来实现HTML布局,用一个div#arana作为“展台元素”,存放整个立方体容器div#box,div#box里面有6个子节点div.face,代表这个立方体的6个面。

<div id="arena">
    <div id="box">
        <div class="face">1</div>
        <div class="face">2</div>
        <div class="face">3</div>
        <div class="face">4</div>
        <div class="face">5</div>
        <div class="face">6</div>
    </div>
</div>

最外层的div#arena的作用类似于一个“展台”,我们可以想象,在“展台”上,我们需要拜访一台摄像机,来拍摄这个立方体。那么,这个摄像机,我们称之为“视点”,视点和立方体的距离,就是div#arana的-webkit-perspective属性值, 它和我们在画画的时候“透视点”的概念有点像,只不过,“透视点”在屏幕的后方,而“视点”在屏幕的前方。在立方体旋转,偏移的时候,我们还需要知道一个“基点”,3D变换的元素, 都会基于这个点来变化,“基点”通过-webkit-perspective-origin属性来定义,的默认值是50% 50%,分别代表“基点”距离元素本身左边和顶部的距离。

#arena {
    -webkit-perspective: 400;
    -webkit-perspective-origin: 50% 50%;
}

第二个容器div#box实际上就是我们的立方体,通过-webkit–transition属性,定义了立方体在变化时候的过度动画效果。-webkit-transform-style属性用于定义3d元素的透视效果,它有2个值:其两个参数,flat|preserve-3d. 前者flat为默认值,表示平面的;后者preserve-3d表示3D透视。这个属性应该用在作为立方体的容器元素上,而不是它里面的6个作为6个面的子元素。

#box {
    position: relative;
    margin: 100px auto;
    height: 200px;
    width: 200px;
    -webkit-transition: -webkit-transform 2s linear;
    -webkit-transform-style: preserve-3d;
}

定义6个“面”元素共同的普通css属性,注意,这里通过position: absolute使6面的“基点”位置保持一致。

.face {
    color: #FFF;
    font-size: 30px;
    font-weight: bold;
    position: absolute;
    background: rgba(50, 50, 50, 0.7);
    width: 160px;
    height: 160px;
    padding: 20px;
    border: 1px solid #333;
}

通过-webkit-transform属性分别设置六个面的偏移和旋转位置,使其刚好围成一个立方体。-webkit-transform属性有多种方法(函数),rotateX()、rotateY()、rotateZ()分别用于设置元素基于XYZ轴的旋转角度。translateX()、translateY()、translateZ()则分别用于设置元素偏离XYZ轴的距离。

.face:nth-child(1) {-webkit-transform: translateZ(100px);}
.face:nth-child(2) {-webkit-transform: rotateY(90deg) translateZ(100px);}
.face:nth-child(3) {-webkit-transform: rotateY(180deg) translateZ(100px);}
.face:nth-child(4) {-webkit-transform: rotateY(270deg) translateZ(100px);}
.face:nth-child(5) {-webkit-transform: rotateX(90deg) translateZ(100px);}
.face:nth-child(6) {-webkit-transform: rotateX(270deg) translateZ(100px);}

最后,我们通过js绑定keyup事件,来改变div#box的-webkit-transform值来达到旋转的目的。

var xAngle = 0, yAngle = 0;
document.addEventListener('keydown', function(e){
    switch (e.keyCode) {
        case 65: // left
            yAngle -= 90;
            break;
        case 87: // up
            xAngle += 90;
            break;
        case 68: // right
            yAngle += 90;
            break;
        case 83: // down
            xAngle -= 90;
            break;
    };
    var box = document.getElementById('box');
    box.style.webkitTransform = "rotateX("+xAngle+"deg) rotateY("+yAngle+"deg)";
}, false);

ubuntu下创建启动器程序的方法。

python的开发工具pycharm每次打开都要在终端下执行sh文件,非常蛋疼,于是我想把它锁定到启动器。但是,在终端下打开的pycharm锁定到启动器以后,如果关闭了,下次点击启动器里的图标,还是无法打开。

Google了一下,原来需要创建一个启动器图标程序才行,ubuntu的启动器程序都是放在/usr/share/applications文件夹下的文件, 那我们就在这个文件夹下面创建一个pycharm.desktop,内容如下:

[Desktop Entry]
Version=1.0
Type=Application
Name=pycharm
Icon=/usr/local/pycharm/pycharm-3.1.1/bin/pycharm.png
Exec="/usr/local/pycharm/pycharm-3.1.1/bin/pycharm.sh" %f
Comment=Develop with pleasure!
Categories=Development;IDE;
Terminal=false
StartupWMClass=jetbrains-pycharm

然后双击打开,再锁定到启动器就好了。

通过ReRes让chrome拥有路径映射的autoResponse功能。

前端开发过程中,经常会有需要对远程环境调试的需求。比如,修改线上bug,开发环境不在本地等等。我们需要把远程css文件或者js映射到本地的文件上,通过修改本地文件进行调试和开发。通常我们可以通过以下方法来实现映射:

1.修改host文件——只能把域名映射到IP

2.使用Apache或者nginx搭建反向代理——需要装环境,配置相对繁琐

3.使用Fiddler中的AutoRespnose功能——不支持目录映射,mac、linux无法使用

以上方式,或者功能缺失,或者需要额外安装软件,或者配置繁琐、或者不支持多平台。我理想中的请求映射工具应该是这样的:简单,打开浏览器就能用、支持目录映射和文件映射、跨平台。 ReRes就是居于这个目标写出来的,您可以把请求映射到其他的url,也可以映射到你本机的文件或者目录。ReRes支持单个url映射,也支持目录映射。

现在就开始使用ReRes

Read More

通过Visual Event查看页面元素的绑定事件

WEB标准提倡结构、表现和行为相 分离,现在越来越多采用这种表现和行为的方式,但它也为我们开发调试带来一些问题,网页载入一堆javascript,,我们很难搞清楚最后在哪些元素的哪个动作绑定了事件,尤其是javascript加载事件的方式五花八门,可以透过jQuery、element.click = function() { }、element.addEventListener()…,很难由单一处找出所有事件。而理不清事件来龙去脉,要追踪某个点击动作背后的行为就变得有些困难,直到我们遇到以下两种利器。

chrome开发者工具有查看HTML元素绑定事件的功能,如下图所示:
chrome event view

但这种方式查看事件的方法还是有点困难,直到遇到它chrome的插件 Chrome Web Store - Visual Event
Visual Event的运作原理,在于其熟知主要javascript库(例如: jQuery、YUI、ExtJS)事件机制,可深入其中撷取事件,并将其标注在对象元素上。目前支持的JS库包括:

DOM 0 events
jQuery 1.2+
YUI 2
MooTools 1.2+
Prototype 1.6+
Glow

在启用Visual Event后,有绑定事件元素将被标上蓝色区块,滑鼠停留时会显示事件的细节。如下图所示:
Visual Event

Read More