Skip navigation.

极湖

无不用其“极”

Posts tagged with "JavaScript"

JavaScript 查错小帮手: JavaScript Lint

JavaScript 的调试,一般情况下,FireBug 足可应付。可有时候 FireBug 所报的错误太笼统,比如一个括号没有匹配,它不能给出具体的位置,js 文件比较大的时候,查找这样的错误很费功夫。

于是找到了这个 JavaScript Lint ,我用下来的结果,不能说很好,可也是个帮手,有时候实在查不出错误在哪儿,就用它分析一下 js 文件,根据输出的列表(有行号),再去查找错误,有时也可行,能够提高一些效率。

JavaScript Lint 的安装比较简单,看看帮助文件很快就能搞定。安装之后建议把 jsl 的路径追加到用户的 PATH 变量中。

用法:
jsl -conf jsl.conf -process javascript文件名
jsl -process javascript文件名

利用 jQuery 克隆 Object

, ,

在网上搜索关键字 “javascript object clone”,可以找到很多实现克隆 Object 的代码,可是据我测试,让人满意的几乎没有。

今天发现 jQuery 的作者 John Resig 给别人的答复,尝试了一下确实很好用。

方法如下:
// 浅层复制(只复制顶层的非 object 元素)
var newObject = jQuery.extend({}, oldObject);

// 深层复制(一层一层往下复制直到最底层)
var newObject = jQuery.extend(true, {}, oldObject);

测试如下:
var obj1 = {
  'a': 's1',
  'b': [1,2,3,{'a':'s2'}],
  'c': {'a':'s3', 'b': [4,5,6]}
}

var obj2 = $.extend(true, {}, obj1);
obj2.a='s1s1';
obj2.b[0]=100;
obj2.c.b[0]=400;

console.log(obj1);
console.log(obj2);

obj2 内部元素的值改变之后,如果 obj1 的相应值保持不变,就说明复制成功。

ExtJS 也有类似的方法 Ext.apply,因此单独用 ExtJS 应该也能实现同样的功能。

ExtJS 控件扩展: 带清空功能的 ComboBox

,

在 ExtJS 官方网的论坛上找到的代码,稍稍改动之后如下:
/*
 * 带清空功能的 ComboBox
*/
Ext.form.ClearableComboBox = Ext.extend(Ext.form.ComboBox, {
    initComponent: function(){
        Ext.form.ClearableComboBox.superclass.initComponent.call(this);
        this.addEvents('clear');
        
        this.triggerConfig = {
            tag:'span',
            cls:'x-form-twin-triggers',
            style:'padding-right:2px',
            cn:[
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger"},
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger x-form-clear-trigger"}
            ]
        };
    },

    getTrigger: function(index){
        return this.triggers[index];
    },

    initTrigger: function(){
        var ts = this.trigger.select('.x-form-trigger', true);
        this.wrap.setStyle('overflow', 'hidden');
        var triggerField = this;
        ts.each(function(t, all, index){
            t.hide = function(){
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = 'none';
                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
            };
            t.show = function(){
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = '';
                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
            };
            var triggerIndex = 'Trigger'+(index+1);

            if(this['hide'+triggerIndex]){
                t.dom.style.display = 'none';
            }
            t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});
            t.addClassOnOver('x-form-trigger-over');
            t.addClassOnClick('x-form-trigger-click');
        }, this);
        this.triggers = ts.elements;
    },

    onTrigger1Click: function() {this.onTriggerClick()},
    onTrigger2Click: function() {this.clearValue(); this.fireEvent('clear', this)}
});

给 javascript 的 String 增加 replaceAll 方法

通常情况下,javascript 下批量替换字符串都用正则表达式,如:
sText = sText.replace(/str1/g, 'str2');

或者
sText = sText.replace(new RegExp('str1', 'g'), 'str2');

问题是,如果要替换的字符串是变量,以上方法反倒不好用。

其实,给String增加一个简单的方法即可实现字符串的批量替换:
String.prototype.replaceAll = function(sSearch, sReplace){
    return this.split(sSearch).join(sReplace);
};

测试:
alert("s1 and s1".replaceAll('s1', 's2'));

escape(), encodeURI(), encodeURIComponent() 的区别

,

javascript 的函数 escape(), encodeURI(), encodeURIComponent(),功能都是对 HTML 的一部分字符进行加密。至于哪些字符被加密那些字符不被加密,容易搞混,因此做一个简单的测试和总结。

测试对象范围: %20(半角空格) 〜 %7E (波浪字符~)

元数据
 !"#$%&'()*+,-./
0123456789
:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ
[\]^_`
abcdefghijklmnopqrstuvwxyz
{|}~


escape()
%20%21%22%23%24%25%26%27%28%29*+%2C-./
0123456789
%3A%3B%3C%3D%3E%3F@
ABCDEFGHIJKLMNOPQRSTUVWXYZ
%5B%5C%5D%5E_%60
abcdefghijklmnopqrstuvwxyz
%7B%7C%7D%7E%7F


encodeURI()
%20!%22#$%25&'()*+,-./
0123456789
:;%3C=%3E?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ
%5B%5C%5D%5E_%60
abcdefghijklmnopqrstuvwxyz
%7B%7C%7D~%7F


encodeURIComponent()
%20!%22%23%24%25%26'()*%2B%2C-.%2F
0123456789
%3A%3B%3C%3D%3E%3F%40
ABCDEFGHIJKLMNOPQRSTUVWXYZ
%5B%5C%5D%5E_%60
abcdefghijklmnopqrstuvwxyz
%7B%7C%7D~%7F


总结
  • 以上函数对 [0-9A-Za-z] 都不作变换。
  • escape() 不变换的字符是 *+-./@_
  • encodeURI() 不变换的字符是 !#$'()*+,-./:;=?@_~
  • encodeURIComponent() 不变换的字符只有 !'()*-._~
  • 对于多字节代码,比如 UTF-8 编码的「」,escape() 变换的结果是 %u554A,encodeURL() 以及 encodeURIComponent() 的变换结果是 %E5%95%8A


以上三个函数的逆变换函数分别是 unescape(), decodeURI(), decodeURIComponent()

※以上资料翻译整理自 groundwalker.com

jQuery 1.3 正式登场

,

闲来无事,打开 jQuery 的主页看了一下,发现,下载链接下面的当前版本已经变成 1.3。仔细一看,新版本的 jQuery 已经于 1月 14 日发布。

和前一版本 1.2.6 相比,jQuery 1.3 的主要改进如下:

1. 集成 Sizzle 引擎
Sizzle 是一个独立的 CSS 查询引擎,同样出自 jQuery 的作者 John Resig

2. 增加 .live() 和 .die() 方法。
这两个方法用来实现网页上新追加元素的事件自动绑定和解除。

3. 彻底检修事件处理的代码
完全重新布置,简化了事件处理。

4. 重写了动态插入 HTML 的代码
比如 append, prepend, before 和 after 等方法,重写之后速度快了很多。

5. 重写了偏移计算的代码
元素定位的偏移计算方法超级快速。

6. 不再增加新浏览器的探测
增加 jQuery.support 属性,jQuery.browser 保留但不推荐使用。

发布一个 jQuery 插件 —— ColorPicker

, ,

效果图(ScreenShot):


用法:
一.绑定到单个text输入框
$('#txt_color').colorPicker();


二.绑定到多个text输入框)
$('.color_fields').colorPicker();


三. 所选颜色值传递给回调函数(callback)
$.colorInput.toggleMenu($('#test_box'), function(sColor){
    alert(sColor);
});


下载(Download):
jquery.colorPicker.js

jQuery 判断 checkbox 是否被选中的几种方法

,

方法一:
if ($("#checkbox-id")get(0).checked) {
    // do something
}

方法二:
if($('#checkbox-id').is(':checked')) {
    // do something
}

方法三:
if ($('#checkbox-id').attr('checked')) {
    // do something
}

用土办法记忆可编辑 div 内的光标位置

, ,

可编辑 div 内光标位置的记忆和恢复实在是太难,情急之下想了个很土的办法:做一个不可见的 span 紧跟光标,在光标位置插入内容的时候只需找到这个 span 即可。

程序如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>(jQuery) Cursor Position Test </title>
<script type="text/javascript" src="jquery.pack.js"></script>
<style type="text/css" media="all">
#editor {
        width:500;
        height:100;
        margin:10px;
        padding:2px;
        border:1px solid #0000FF;
        overflow:auto;
}
#info {
        width:500;
        height:200;
        margin:10px;
        padding:2px;
        border:1px solid #00FF00;
        background-color:#F8F8F8;
        overflow:auto;
}
#caret_pos {
        display:none;
        cursor:default;
}
</style>
<script type="text/javascript">
    function trace(obj) {
        if(typeof(obj) == 'object') {
            for(var x in obj) {
                $('#info').append(x + '<br/>');
            }
        } else {
            $('#info').append(obj + '<br/>');
        }
    }
        
    $(document).ready(function(){
        var caretRange;
        //update Caret Pos
        function updateCaretPos(e) {
                caretRange = document.selection.createRange();
                if(caretRange.text != '') {
                        return;
                }
                var caretHtml = '<span id="caret_pos"></span>';
                if($('#caret_pos').length > 0) {
                        $('#caret_pos').remove();
                }
                caretRange = document.selection.createRange();
                caretRange.pasteHTML(caretHtml);
                caretRange.collapse(true);
        }

        //insert HTML at Caret Pos
        function insertAtCaret(sHtml) {
                $('#caret_pos').before(sHtml);
                var caret = document.getElementById('caret_pos');
                var txtRange = document.body.createTextRange();
                txtRange.moveToElementText(caret);
                txtRange.select();
        }
        $('#editor').keyup(function(e){
                updateCaretPos(e);
        }).click(function(e){
                updateCaretPos(e);
        }).focus(function(e){
                updateCaretPos(e);
        });
            
        $('#insert').click(function(e){
                insertAtCaret($('#instext').val());
        });
        $('#editor_html').click(function(e){
                $('#info').text($('#editor').html());
        });
        $('#clear_info').click(function(e){
                $('#info').html('');
        });
    });
</script>
</head>
<body>
        <div><h2>Caret Position Test</h2></div>
    <div id="editor" contentEditable="true">
        <span>start</span>
    </div>
    &nbsp;&nbsp;
    <input type="button" id="editor_html" value="Html in Editor" />
    &nbsp;&nbsp;
    <input type="text" id="instext" value="" />
    &nbsp;
    <input type="button" id="insert" value="Insert" />
    &nbsp;&nbsp;
    <div id="info">
    </div>
    &nbsp;&nbsp;
    <input type="button" id="clear_info" value="Clear Info" />
</body>
</html>

注:以上程序仅适用于IE。Mozilla系浏览器只需修改pasteHTML部分的代码

CodeMirror:浏览器内的高亮文本编辑器

, ,

因为要做编辑器,所以找了很多 OpenSource 的 WYSIWYG 编辑器代码,当然都是 JavaScript。无意间发现一个好东西——CodeMirror,看了这个东西,我吃惊不少,因为它几乎已经达到了桌面程序的水平,写程序代码能够高亮彩显(目前支持 HTML 和 Javascript),还有自动缩进、括号匹配提示等功能,而且比较流畅。

看了一下 CodeMirror 的代码,觉得很不一般,称得上短小精悍,一看就知道作者的 JavaScript 功底相当深厚,称得上是大师级的水平。作者在他网站上还发布了一本 JavaScript 的教程——Eloquent JavaScript,我看也是个难得的东西,初学者或者是有经验的开发人员都可以参考。

用 JavaScript 写的类似编辑器还有


以上列表也是 CodeMirror 的作者介绍的,看看这些东西,也许您会和我一样惊叹:JavaScript 实在是神奇!
December 2009
S M T W T F S
November 2009January 2010
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