LevenshTeinDistance是俄罗斯科学家Vladimir Levenshtein在1965年提出的根据编辑距离(Edit Distance)计算字符串相似度的一种算法。
/*
* @name:LevenshteinDistance.js
* @description:
* @author:wondger@gmail.com
* @date:2012-04-17
* @param:
* @todo:
* @changelog:
*/
var LevenshteinDistance = {
_str1:null,
_str3:null,
_matrix:null,
_isString:function(s){
return Object.prototype.toString.call(s) === '[object String]';
},
_isNumber:function(s){
return Object.prototype.toString.call(s) === '[object Number]';
},
init:function(str1,str2){
if(!this._isString(str1) || !this._isString(str2)) return;
this._str1 = str1;
this._str2 = str2;
str1.length && str2.length && this._createMatrix(str1.length+1,str2.length+1);
this._matrix && this._initMatrix();
return this;
},
get:function(){
return 1 - this._getDistance()/Math.max(this._str1.length,this._str2.length);
},
//计算编辑距离
_getDistance:function(){
var len1 = this._str1.length,
len2 = this._str2.length;
if(!len1 || !len2) return Math.max(len1,len2);
var str1 = this._str1.split(''),
str2 = this._str2.split('');
var i = 0,j = 0,temp = 0;
while(i++ < len1){
j = 0;
while(j++ < len2){
temp = str1[i-1] === str2[j-1] ? 0 : 1;
this._matrix[i][j] = Math.min(this._matrix[i-1][j]+1,this._matrix[i][j-1]+1,this._matrix[i-1][j-1]+temp);
}
}
return this._matrix[i-1][j-1];
},
/*
* 初始化矩阵
* 为第一行、第一列赋值
*/
_initMatrix:function(){
var cols = this._matrix[0].length,
rows = this._matrix.length;
var l = Math.max(cols,rows);
while(l--){
cols-1 >= l && (this._matrix[0][l] = l);
rows-1 >= l && (this._matrix[l][0] = l);
}
},
/*
* 创建矩阵
* n:行
* m:列
*/
_createMatrix:function(n,m){
if(!this._isNumber(n) || !this._isNumber(m) || n<1 || m<1) return;
this._matrix = new Array(n),i = 0;
while(i<n) this._matrix[i++] = new Array(m);
}
}
示例:
alert(LevenshteinDistance.init('omiga.org','omiga').get()); // 0.5555555555555556
alert(LevenshteinDistance.init('omiga','omiga').get()); // 1 完全相同
alert(LevenshteinDistance.init('god','superman').get()); // 0 完全不同
对于一个事件通常我们主要关注两件事情:
- 怎么注册/注销
- 何时触发
DOM Level 2 Events和DOM Level 3 Events中已经提供了接口用于对自定义事件的支持,addEventListener/removeEventListener完成对任意事件函数的注册/注销(标准事件、自定义事件),createEvent-initEvent-dispatchEvent完成事件的触发。
注册/注销方式和普通标准事件没有区别,而事件的触发需要自行再包装实现一下,这个方法我们也暂命名为dispatchEvent。
var Event = {
dispatchEvent:function(el,type,evtType){
//create Event
var evtType = evtType || 'CustomEvent',
evt = document.createEvent(evtType);
//init Event
evt.initEvent(type,true,true);
//dispatch Event
el.dispatchEvent(evt);
}
}
createEvent支持多种事件类型丰富,比如"UIEvents"、"MouseEvents"、"MutationEvents"、"HTMLEvents",具体类型可参考前面的两个文档。不同类型事件具有不同的初始化方法,比如"initUIEvent"、"initMouseEvent"、"initMutationEvent"、"initHTMLEvent"…使用专有初始化方法具有更多大灵活性,具有更多的参数接口。而"initEvent"是一个基础方法,使用起来更简单,但有时候无法满足更多的需求。
IE9及以后版本开始支持dispatchEvent,而IE8及以前版本并不支持。但好在IE提供了另外一个方法fireEvent用于触发事件函数,而且标准事件模型中的createEvent-initEvent-dispatchEvent过程在IE中只需要createEventObject-fireEvent两个步骤即可完成,当然其实是将initEvent中的初始化工作合并到了createEventObject中。所以我们也有了IE8及以下版本的fireEvent方法实现。
var Event = {
fireEvent:function(el,type,cfg){
//create Event
var evt = document.createEventObject(cfg);
//fire Event
el.fireEvent('on'+type,evt);
}
}
但遗憾的是fireEvent仅能触发通过attachEvent注册的标准事件,对于我们的自定义事件该方法其实形同虚设。
另外:即使对于标准事件,fireEvent还有一个很大的不同:不会触发默认行为。比如有一个form,
Event.dispatchEvent(form,'submit'); //会触发submit行为提交表单
Event.fireEvent(form,'submit'); //不会触发submit行为
对于不支持自定义事件注册/注销、触发的浏览器,可是有如下方案:
- 注册/注销
将DOM与自定义事件对应关系保存,这其中涉及到保存的自定义事件与DOM对象的对应关系数据的结构如何设计;以及如何避免重复注册
- 触发
对于关系保存下来了,其实触发就很简单,直接调用事件方法即可,唯一需要注意的是一个模拟的Event对象传递个事件函数
代码不贴了~···^-^
参考:
github使用SSH与客户端连接。如果是单用户(first),生成密钥对后,将公钥保存至github,每次连接时SSH客户端发送本地私钥(默认~/.ssh/id_rsa)到服务端验证。单用户情况下,连接的服务器上保存的公钥和发送的私钥自然是配对的。但是如果是多用户(first,second),我们在连接到second的帐号时,second保存的是自己的公钥,但是SSH客户端依然发送默认私钥,即first的私钥,那么这个验证自然无法通过。不过,要实现多帐号下的SSH key切换在客户端做一些配置即可。
首先cd到~/.ssh 使用 ssh-keygen -t -rsa -C ‘second@mail.com’ 生成新的SSH key:id_rsa_second,生成完后将新的SSH public key添加到github。
ssh-keygen -t rsa -C 'second@mail.com'
默认SSH只会读取id_rsa,所以为了让SSH识别新的私钥,需要将其添加到SSH agent
ssh-add ~/.ssh/id_rsa_second
该命令如果报错:Could not open a connection to your authentication agent.无法连接到ssh agent,可执行ssh-agent bash命令后再执行ssh-add命令。
完成以上步骤后在~/.ssh目录创建config文件,该文件用于配置私钥对应的服务器。内容如下:
# Default github user(first@mail.com)
Host github.com
HostName github.com
User git
IdentityFile C:/Users/username/.ssh/id_rsa
# second user(second@mail.com)
Host github-second
HostName github.com
User git
IdentityFile C:/Users/username/.ssh/id_rsa_second
阅读全文»
首先看看这两个单词的英文释义(来自有道词典)。先是property:
property ['prɔpəti]
n. 性质,性能;财产;所有权
英英释义:
- any area set aside for a particular purpose “the president was concerned about the property across from the White House”
同义词:place
- something owned; any tangible or intangible possession that is owned by someone “that hat is my property”; ” he is a man of property”
同义词:belongings | holding | material possession
- a basic or essential attribute shared by all members of a class
- a construct whereby objects or individuals can be distinguished “self-confidence is not an endearing property”
同义词:attribute | dimension
- any movable articles or objects used on the set of a play or movie
同义词:prop
重点看2、3、4条。
再看attribute:
attribute [ə'tribju:t, 'ætribju:t]
n. 属性;特质
vt. 归属;把…归于
英英释义:
n.
- a construct whereby objects or individuals can be distinguished
同义词:property | dimension
- an abstraction belonging to or characteristic of an entity
v.
- attribute or credit to ”We attributed this quotation to Shakespeare”
同义词:impute | ascribe | assign
- decide as to where something belongs in a scheme
同义词:assign
property,attribute都作“属性”解,但是attribute更强调区别于其他事物的特质/特性,而在这篇文章中也提交到attribute是property的子集。
而在JavaScript中,property和attribute更是有明显的区别。众所周知,setAttribute是为DOM节点设置/添加属性的标准方法:
var ele = document.getElementById("my_ele");
ele.setAttribute("title","it's my element");
但很多时候我们也这样写:
ele.title = "it's my element";
如果不出什么意外,他们都运行的很好,它们似乎毫无区别?而且通常情况下我们还想获取到我们设置的“属性”,我们也很爱这样写:
alert(ele.title);
这时候,你便会遇到问题,如果你所设置的属性属于DOM元素本身所具有的标准属性,不管是通过ele.setAttribute还是ele.title的方式设置,都能正常获取。但是如果设置的属性不是标准属性,而是自定义属性呢?
阅读全文»
SSI(Server Side Include)使用在HTML中,用于在请求内容返回到客户端前执行页面中的SSI命令,生成动态内容。通常用于多个页面引用公共的内容模块,将此模块分离出来,使用SSI引入即可。
<!--#include virtual="/inc/header.html"-->
以上代码便能在服务端完成header.html的动态引入,非常简单。
服务端配置
使用SSI之前需要服务端进行简单的配置,开启SSI功能。SSI是针对HTML增加动态内容的技术,所以只对HTML类型文件(.html,.shtml),使用SSI功能的文件建议使用.shtml后缀,便于维护。如果使用.shtml后缀需在服务端作一些配置:
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
第一行命名配置将.shtml作为html文件返回
第二行命令用于在返回请求内容前执行页面中的SSI命令,如果你在.html文件中使用SSI,那么将.shtml改为.html即可。
SSI命令
SSI的语法有点像HTML注释,所以如果SSI不能识别,那么将被视作HTML注释处理。SSI的语法功能主要包括:变量的设置/获取,文件的引用,可执行命令,条件表达式等。
SSI基本语法
<!--#command param="value"-->
SSI的语法非常简单,但使用中需注意以下几点:
- <!–与#之间无空格
- SSI大小写敏感
- 所有value需写在引号中
config命令
config命令主要用于修改SSI的默认设置,诸如时间格式,默认错误信息,文件大小单位。
设置默认错误信息:errmsg
<!--#config errmsg="Error,please contact webmaster@mail.com"-->
定义日期和时间格式:timefmt
<!--#config timefmt="%A, %B %d, %Y"-->
定义文件大小单位
<!--#config sizefmt="bytes"-->
config命令只对其后使用的命令生效。同时,后定义的设置具有更高的优先级,会覆盖之前的设置。
阅读全文»