二分之一

Just Jason's Blog

javascript

JetBrains WebStorm 7.0.3汉化语言包及汉化方法

语言包来自前人的不断积累,本人也做了很多错误修改和补全。

语言包核心文件:ActionsBundle.properties。

语言包位置: D:\Program Files\JetBrains\WebStorm 7.0.3\lib\resources_en.jar这个压缩包内部resources_en\messages\ActionsBundle.properties(请找到自己的安装目录)。

语言包下载:ActionsBundle.zip。http://pan.baidu.com/s/1eQwxAWa

必备工具:360压缩,请自行下载安装。(虽然是数字公司的,但是没办法~~)

汉化步聚:

1、备份,将resources_en.jar拷到其它盘,注意千万不能在安装目录下,即使改名,WebStorm也能优先读取到原文件。

2、用360压缩打开安装目录下的:resources_en.jar(不用解压),进入目录messages下,使用压缩软件的添加功能,将下载的ActionsBundle.properties添加覆盖。

Read more »

Node.js ES6(harmony模式)支持情况一览

本文地址:http://www.2fz1.com,转载请注明来源。

ES6指:ECMAScript 6草案 (2012.4) 规定。

Node.js需要0.11.*版本来开启ES6实验阶段的支持,官网最新版本下载链接。

安装 0.11.* 以后的版本后,通过node --harmony来启动应用程序。本文只例出Node.js支持的新特性,暂未支持的特性,不在本文介绍范围。以下特性均通过Node.js v0.11.9测试!

const

声明一个只读的命名常量,一个常量不可以被重新赋值,并且不能被重复声明。

const例子

const a = 'a';
console.log(a); //a
a = 'b';
console.log(a); //a

//以下重复定义,会报错
//Error:Variable 'a' has already been declared
var a = 'c';
const a = 'd';
console.log(a);

Read more »

支持Node.js和浏览器端使用的全功能农历和公历日历类库:LunarCalendar

过年长假期间,写了一个农历类库:LunarCalendar

开源在github:https://github.com/zzyss86/LunarCalendar 文档地址:http://www.tuijs.com/lib/52fcc5f51fc3c6de6a9e4552

农历(阴历)万年历,是一款支持Node.js和浏览器端使用的全功能农历和公历日历类库。支持农历与公历之间相互转换,含有二十四节气,天干地支纪年纪月纪日,生肖属相,公历节假日及农历传统节假日信息等功能。自带2013-2014节假日安排数据,并可自行配置。带有黄历数据,可自行选择配置。支持1891-2100年。使用LunarCalendar可快速开发一款属于自己的万年历产品,行动起来吧!

/assets/upload/banner200.png

Read more »

用Node.js写了一个小站:推JS

好久没更新博客了,说说最近除了工作之外的业余时间在忙什么吧,年前用Node.js写了一个小站:推JS; 托管在BAE3.0上,不是很稳定,各种问题,但是百度总是这样,有好产品但没有好的用户服务,忍了,因为国内就此一家。

推JS,传送门:http://www.tuijs.com/

推JS(又名“推即时”),是一个优质开源WEB前端类库及框架推荐的网站,接受用户推荐,收藏自己喜爱的类库等。

推JS所有类库框架尽量做到精挑细选,如有质量低的类库框架,请大家举报,站长会审核下架。

推JS采用:Node.js + MongoDB架构,前端仅支持IE8+及标准浏览器。推JS是Jason利用工作之余,学习研究Nodejs开发之作,前后台开发时长总共约4个周末。没有经过严格测试,如有问题请邮件给站长,万分感谢!

Read more »

javascript设计模式之Observer(观察者)模式

没空讲原理了,写了一个DEMO供大家学习,先上一段核心代码,然后附上DEMO。

请查看DEMO,更详细的理解Observer(观察者)模式

DEMO:test.html

/**************订阅者/观察者/subscribe************/
function ObserverList(){
    this.observerList = [];
};

//添加
ObserverList.prototype.Add = function(obj){
    if(this.IndexOf(obj,0)==-1){
        return this.observerList.push(obj);
    }else{
        this.observerList;
    }
};

//清空
ObserverList.prototype.Empty = function(){
    this.observerList = [];
};

//统计
ObserverList.prototype.Count = function(){
    return this.observerList.length;
};

//获取
ObserverList.prototype.Get = function(index){
    if(index>-1 && index<this.observerList.length){
        return this.observerList[index];
    }
};

//插入
ObserverList.prototype.Insert = function(obj,index){
    var pointer = -1;
    if(index===0){
        this.observerList.unshift(obj);
        pointer = index;
    }else if(index === this.observerList.length){
        this.observerList.push(obj);
        pointer = index;
    }
    return pointer;
};

//查询位置
ObserverList.prototype.IndexOf = function(obj,startIndex){
    var i = startIndex,pointer = -1;
    while(i<this.observerList.length){
        if(this.observerList[i]===obj){
            pointer = i;
        }
        i++;
    }
    return pointer;
};

ObserverList.prototype.RemoveIndexAt = function(index){
    if(index===0){
        this.observerList.shift();
    }else if(index===this.observerList.length-1){
        this.observerList.pop();
    }else{
        this.observerList.splice(index,1);
    }
}

//扩展对象
function extend(obj,extension){
    for(var key in obj){
        extension[key] = obj[key];
    }
}

/**************发布者/目标/publish****************/
function Subject(){
    this.observers = new ObserverList();
}

Subject.prototype.AddObserver = function(observer){
    this.observers.Add(observer);
};

Subject.prototype.RemoveObserver = function(observer){
    this.observers.RemoveIndexAt(this.observers.IndexOf(observer,0));
    console.log(this.observers);
};

Subject.prototype.Notify = function(context){
    var observerCount = this.observers.Count();
    for(var i=0;i<observerCount;i++){
        this.observers.Get(i).Update(context);
    }
};

Read more »

使用 SourceMap 来进行压缩后的代码调试,以underscore为例

JS发布后通常会经过压缩和混淆,所有代码被压缩成一行代码,如果发生错误,无法定位错误,SourceMap因此而生。

说起SourceMap,不得不说说uglifyjs,uglifyjs是nodejs下一款优秀的JS压缩优化工具,支持SourceMap的生成。

一、uglifyjs的使用及SourceMap文件的生成方法

1、安装nodejs:http://nodejs.org,windows下直接安装即可,安装好后自带npm.
2、打开CMD,输入node -v查看,nodejs是否安装成功,如果成功会返回一个版本号。
3、安装uglifyjs:执行命令:npm install uglify-js -g
4、uglifyjs使用方法及API:https://github.com/mishoo/UglifyJS2
5、压缩JS并生成SourceMap文件

uglifyjs underscore.js --source-map underscore.js.map
--source-map-root ./ -m -c -o underscore-mini.js

会生成两个文件:

二、用 SourceMap 调试

有了SourceMap文件,放置underscore-mini.js同一目录,引用underscore-mini.js时,就可以调试,看到未压缩的代码

调试方法: 打开chrome – F12(打开调试工具)- 调试工具右下角有一个设置,打开设置 – General – Enable source maps

这样就打开了SourceMap调试功能。

在Sources面板下,左侧展开,就能看到SourceMap解出来的未压缩文件,多个压缩文件都可以看到。

三、SourceMap的原理解析

单说,Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码。这无疑给开发者带来了很大方便。

1、SourceMap基本结构如下:

/assets/upload/20130723160149.png

2、重点在于mappings的解码

第一层是行对应,以分号(;)表示,每个分号对应一行代码;
第二层是位置对应,以逗号(,)表示,每个逗号对应转换后源码的一个位置。
第三层是位置转换,以VLQ编码表示,代表该位置对应的转换前的源码位置。

VLQ编码相关,请查询更多资料~~

Read more »

jQuery源码解读一:部份jQuery工具方法实现

jQuery作为前端最流行的类库,没有之一,源码必须得读一读。本博将不定期更新源码解读内容,如果解读不正确的地方,还请同学们在评论中指正。

本系列文章基于最新的jquery-1.9.1.js。

一、$.type() 判断js数据类型

用法:$.type(new Array()); //array

部份源码(截取关键部份,请忽略源码语法):

//生成typelist的map
class2type = {}
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

//每个对象实例都有toString方法
core_toString = class2type.toString

//主方法
type: function( obj ) {
    if ( obj == null ) {
        return String( obj );
    }
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ core_toString.call(obj) ] || "object" :
        typeof obj;
}

解读:

1、class2type生成后的内容为

var class2type = {
    "[object Boolean]":"boolean",
    "[object Number]":"number",
    "[object String]":"string",
    "[object Function]":"function",
    "[object Array]":"array",
    "[object Date]":"date",
    "[object RegExp]":"regexp",
    "[object Object]":"object",
    "[object Error]":"error"
}

2、core_toString使用的是对象实例的toString

所有继随自Object的对象都有toString方法,为什么一定要使用object.toString,因为array,function虽然有toString方法,但该方法进行了重写,array调用toString打印的数组成员用逗号隔开的字符串。这里使用的是{}.toString.call(obj);改变toString的this指向为object实例。jquery为什么使用的是class2type.toString.call,这样就可以少声明一个object。

var func = function(){};
var arr = [];
console.log({}.toString.call(func)); //[object Function]
console.log({}.toString.call(arr)); //[object Array]

这样就得到class2type的键名,以此判断数据类型。

Read more »

让IE6完美实现position:fixed并发布自己写的一个小插件jquery.fixed.js

在工作中,常碰到模态窗口、固定header、固定广告、固定go to top等等,都需要一个很重要的特性position:fixed,该特性在大多数浏览器下支持的还不错,只有IE6这个老大难,又调皮了。

遇到问题就解决问题,解决了问题就记录下,趁假期得空,把一些遇到的坑填平记录一下,同时分享给各位同学,好了,不多废话。

一、IE6下使用position:absolute代替position:fixed

使用绝对定位,很好理解,但是浏览器在调整时(滚动、缩放),left和top如何动态的计算其值呢?在IE6下CSS表达式(expression)可以帮我们解决难题,虽然IE8取消了该API,由于其它效率低,不建议使用。浏览器在调整时,会重新计算css expression,所以我们的问题就解决了。

CSS解决办法:

* html .header{
    position:absolute;
    left:expression(eval(document.documentElement.scrollLeft+10)+"px");
    top:expression(eval(document.documentElement.scrollTop+10)+"px");
}

JS解决办法:

expression对应在JS中的方法是style的setExpression方法,第一个参数是CSS属性名,第二个参数计算表达式字符串。

domThis.style.setExpression('left',
'eval((document.documentElement).scrollLeft + ' + 10 + ') + "px"');

二、修正IE6抖动bug

IE有一个多步的渲染进程。当你滚动或调整你的浏览器大小的时候,它将重置所有内容并重画页面,这个时候它就会重新处理css表达式。

因此虽然CSS进行了重新计算,需要fixed的元素位置也进行了正确的调整,但是会有一跳一跳的抖动感觉,这种体验很不好,如果浏览器调整的频繁,很伤眼。

好在,这个问题不是无解的,是“有药可医”的。

Read more »

记录一下IE6下的两个小坑(form post target iframe、void)及解决办法

一、IE6下使用form post target iframe进行POST跨域请求,如果设置了document.domain,POST请求发送不出去。

另外iframe的name属性要一次性写入,不能通过dom的方式修改,修改无效。

www.2fz1.com/a.html

<script type="text/javascript">
document.domain = "2fz1.com"
</script>
<iframe name="commentpost" id="commentpost"></iframe>
<form action="http://data.2fz1.com/data.php" method="post" target="commentpost">
    <textarea name="detail"></textarea>
    <input type="submit" class="publish_btn" value="提交">
</form>

原因分析:

1、IE6下,因为在父页面或在iframe页面中,只要设置了document.domain,无论是和当前域名相同还是根域名,均视为跨域。而我们使用form post到iframe时,IE6当作跨域给“拒绝访问”了。有人可能会说,可以给子页面设置document.domain,但是我们的子页面是变动的服务器程序,iframe的src如果是定死的就可以解决。

2、大概定位一下:IE6升级到IE7后默认禁用了“跨域浏览子框架”,但是IE7下不会禁用这种,但是把IE7卸载后回到ie6这个设置没改回原来默认的启用,导致ie6不允许form.target指向一个空的iframe。IETester下的IE6,也有同样的原因。

解决办法:

<iframe src="javascript:document.domain='xxx.ooo';void 0;"></iframe>

Read more »

Javascript异步编程几种方式及Ajax串行执行探讨

由于JS是单线程语言,程序在同步执行时,如果耗时较长就会阻塞下面的进程,而异步编程则可以避免这个问题。异步编程在耗时长的操作中非常重要,比如连接网络文件,读取本地文件等。

Ajax就是经典的异步程序,但是多个ajax需要串行执行时,怎样才能优雅有序的执行呢?本文将探讨大规模异步ajax串行执行时的编程问题。

常用的几种异步编程方式有:【本文代码范例基于jquery】

一、回调函数

function a(callback){
    $.get("a.php",function(data){
        callback(data);
    });
}
function b(data){
    console.log(data);
}
a(b);

a执行完后,b再执行。这是典型的回调函数用法,但是回调函数代码高度耦合,代码可读性不高,而且比较混乱,如果回调流程比较长,需要从中减掉一个回调流程时,不易修改。

Read more »