<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Der&#039;s Blog</title>
	<atom:link href="http://www.ueder.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ueder.net</link>
	<description>学无止境－专注于html、css、js等前端技术</description>
	<lastBuildDate>Tue, 08 May 2012 03:22:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>碎碎念 = =&#124;&#124;</title>
		<link>http://www.ueder.net/2012/05/08/%e7%a2%8e%e7%a2%8e%e5%bf%b5/</link>
		<comments>http://www.ueder.net/2012/05/08/%e7%a2%8e%e7%a2%8e%e5%bf%b5/#comments</comments>
		<pubDate>Tue, 08 May 2012 03:19:00 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[碎碎念]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=848</guid>
		<description><![CDATA[刚开了个碎碎念的频道，发现0文章是不会显示导航的 好吧，承认这篇是凑数的。。。 留待以后更新，放放照片，记录下生活什么的~]]></description>
			<content:encoded><![CDATA[<p>刚开了个碎碎念的频道，发现0文章是不会显示导航的<br />
好吧，承认这篇是凑数的。。。<br />
留待以后更新，放放照片，记录下生活什么的~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2012/05/08/%e7%a2%8e%e7%a2%8e%e5%bf%b5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>简洁的html5 Slides Show(类ppt)</title>
		<link>http://www.ueder.net/2012/04/02/%e7%ae%80%e6%b4%81%e7%9a%84html5-slides-show%e7%b1%bbppt/</link>
		<comments>http://www.ueder.net/2012/04/02/%e7%ae%80%e6%b4%81%e7%9a%84html5-slides-show%e7%b1%bbppt/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 05:06:08 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[ppt]]></category>
		<category><![CDATA[Slides]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=839</guid>
		<description><![CDATA[由于最近准备分享chrome Dev Tools ，就简单弄了个基于html5 的 Slides Show，方便在讲工具时直接调试当前页面。 主要实现思路是利用transform: translate() ; 进行横向移位，有点类似absolute之后的left 值与top值，但这里的left值与top值已经用来居中了，所以这里用translate是最佳选择，然后配合css3的transition进行属性改变时动画，在翻页时根据页值，改变所有article的class值，来进行切换，每一页用hash标示，使用了hashchange为主要驱动事件，翻页按钮只改变hash，然后由hashchange事件来驱动翻页。 demo演示点这里 完整源代码点这里 (github上面的) 以下是完整的js代码： /** * Author : Der (http://www.ueder.net) * Date : 2012/04/02 */ //window 以参数方式传进来，沙箱模式， //undefined定为局部变量，提高性能, 以及防止被恶意修改 ;(function(window, undefined) { //使document指向参数window里的document var document = window.document, location &#8230; <a href="http://www.ueder.net/2012/04/02/%e7%ae%80%e6%b4%81%e7%9a%84html5-slides-show%e7%b1%bbppt/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>由于最近准备分享chrome Dev Tools ，就简单弄了个基于html5 的 Slides Show，方便在讲工具时直接调试当前页面。</p>
<p>主要实现思路是利用transform: translate() ; 进行横向移位，有点类似absolute之后的left 值与top值，但这里的left值与top值已经用来居中了，所以这里用translate是最佳选择，然后配合css3的transition进行属性改变时动画，在翻页时根据页值，改变所有article的class值，来进行切换，每一页用hash标示，使用了hashchange为主要驱动事件，翻页按钮只改变hash，然后由hashchange事件来驱动翻页。</p>
<p><a href="http://www.ueder.net/html5-Slides/slides.html" target="_blank">demo演示点这里</a></p>
<p><a href="https://github.com/chongzhi/html5-Slides" target="_blank">完整源代码点这里</a> (github上面的)</p>
<p>以下是完整的js代码：</p>
<pre class="prettyprint">
/**
 * Author : Der (http://www.ueder.net)
 * Date : 2012/04/02
 */

//window 以参数方式传进来，沙箱模式，
//undefined定为局部变量，提高性能, 以及防止被恶意修改
;(function(window, undefined) { 

    //使document指向参数window里的document
    var document = window.document,
        location = document.location;

    /**
     * //扩展对象(默认值替换)
     * @param  {object} target 默认值对象
     * @param  {object} obj    待扩展的对象
     * @return {object}        返回扩展后的对象
     */
    var extend = function (target, obj) {
        if (obj) {
            for (var i in target) {
                if ((typeof obj[i]) === "undefined") {
                    obj[i] = target[i];
                }
            }
            return obj;
        } else {
            return target;
        }
    }

    /**
     * Slides 构造函数
     */
    var Slides = function(config) {

        //支持 Slides()直接调用
        if (!(this instanceof Slides)) {
            return new Slides(config);
        }

        //默认配置
        config = extend({
            container: '#slides', //slides的容器选择器
            pages: '.page', //所有slide页选择器
            hashPrefix: 'slide-', //hash里的前缀，后面为页值
            prev: '#prev', //前一页按钮
            next: '#next', //后一页按钮
            changeBtn: '#changeType', //切换风格的按钮
            changeTypes: ['slides', 'slides2'], //切换风格的class
            typeArr: ['p-current', 'p-past', 'p-past-far', 'p-next', 'p-next-far'],
            typeCount: 0 //默认的切换风格，对应changeTypes里的数组
        }, config);

        //挂载内部参数
        this.container = document.querySelector(config.container); //slides的容器
        this.pages = this.container.querySelectorAll(config.pages); //所有slide页
        this.prevBtn = document.querySelector(config.prev); //上一页按钮
        this.nextBtn = document.querySelector(config.next); //下一页按钮
        this.hashPrefix = config.hashPrefix; //hash前缀
        this.currentPage = null; // 当前页
        this.totalPages = this.pages.length; //ppt总页数
        this.changeBtn = document.querySelector(config.changeBtn); //
        this.changeTypes = config.changeTypes; //切换type数组
        this.typeCount = config.typeCount; //
        this.curType = this.changeTypes[this.typeCount]; //默认切换type为第一个
        this.typeArr = config.typeArr;

        this.init();

    };

    /**
     * 扩展构造函数
     * @type {Object}
     */
    Slides.prototype = {

        /**
         * 还原contructor
         * @type {Function}
         */
        constructor: Slides, 

        /**
         * 初始化
         * @return {undefined}
         */
        init: function() {
            var self = this;

            self.bindUI(); //用户事件绑定
            self.container.className = self.curType; //
            self.currentPage = self._getPageFromHash(); //从hash获取在第几页
            self._emptyClass();//先清空设置过的class
            self.gotoPage(self.currentPage); //跳转到第几页
            self._setPageToHash(self.currentPage); //设置hash状态

        },

        /**
         * 事件绑定
         * @return {undefined}
         */
        bindUI: function() {
            var self = this;

            //前一页
            this.prevBtn.addEventListener('click', function(e) {
                e.preventDefault();
                self.prev();
            }, false);

            //后一页
            this.nextBtn.addEventListener('click', function(e) {
                e.preventDefault();
                self.next();
            }, false);

            // onhashchange handle 哈希驱动事件
            // 所有的上一页下一页跳转到几页都只改变hash值，然后由hashchange事件驱动页面跳转
            window.addEventListener('hashchange', function(e) {
                var cp = self._getPageFromHash();
                self.currentPage = cp;
                self._emptyClass(); //先清空设置过的class
                self.gotoPage(cp);
            }, false);

            //切换风格
            this.changeBtn.addEventListener('click', function(e) {
                e.preventDefault();

                self._changeType();
                self.container.className = self.curType;
            }, false);

            //添加键盘事件
            window.addEventListener('keydown', function(e) {

                switch (e.keyCode) {
                    case 39: // right arrow
                    case 40: // down arrow
                    case 13: // Enter
                    case 32: // space
                    case 34: // PgDn
                        self.next();
                        break;

                    case 37: // left arrow
                    case 38: // top arrow
                    // case 8: // Backspace
                    case 33: // PgUp
                    case 27: //Esc
                        self.prev();
                        break;
                }

            }, false)

        },

        /**
         * 转换切换风格
         * @return {undefined}
         */
        _changeType: function() {
            var self = this;

            self.typeCount = (self.typeCount === self.changeTypes.length - 1)
                ? 0 : self.typeCount + 1;

            self.curType = self.changeTypes[self.typeCount];
        },

        /**
         * 从hash获取当前到第几页
         * @return {number} 返回第几页的数字
         */
        _getPageFromHash: function() {
            var self = this,
                hashPrefix = self.hashPrefix,
                tp = self.totalPages, //总slides数
                hash = location.hash.slice(1), //获取hash去掉#之后的字符串
                page = hashPrefix === '' ? hash : hash.split(hashPrefix)[1], //前缀为空直接取hash，否则取前缀之后的值
                pageN = parseInt(page, 10); //转为number

            //page为不合法或为0时，统一返回1
            if (isNaN(pageN) || pageN &lt; 1) {
                pageN = 1;
            }
            //page大于总slides数，统一返回最大slides数
            else if (pageN &gt; tp) {
                pageN = tp;
            }

            return pageN;
        },

        /**
         * 设置hash
         * @param {number} n 设置hash到第n页
         */
        _setPageToHash: function(n) {
            var self = this,
                hashPrefix = self.hashPrefix;

            location.hash = '#' + hashPrefix + n;
        },

        /**
         * 清空class
         * @return {undefined}
         */
        _emptyClass: function() {
            var classNameList = this.typeArr,
                i = 0,
                len = this.totalPages,
                l = classNameList.length,
                pages = this.pages;

            for (; i &lt; len; i++){
                var el = pages[i];

                for (var j = 0; j &lt; l; j++) {
                    el.classList.remove(classNameList[j]);
                }
            }
        },

        /**
         * 跳转到第n页
         * @param  {number} n 跳转到的页数
         * @return {undefined}
         */
        gotoPage: function(n) {
            var self = this,
                pages = self.pages,
                cur = n - 1, //当前页, 转为0起始
                past = n - 2, //上一页
                pastFar = n - 3, //上上一页
                next = n, //下一页
                nextFar = n + 1, //下下一页
                i = 0, len = self.totalPages,
                classNameList = this.typeArr;

            //改变当前slide以及前后各两个slide的className，
            //再利用css3 的translate偏离位置 + transition动画
            for (; i &lt; len; i++) {
                var page = pages[i];

                switch (i) {
                    case cur:
                        page.classList.add(classNameList[0]);
                        break;

                    case past:
                        page.classList.add(classNameList[1]);
                        break;

                    case pastFar:
                        page.classList.add(classNameList[2]);
                        break;

                    case next:
                        page.classList.add(classNameList[3]);
                        break;

                    case nextFar:
                        page.classList.add(classNameList[4]);
                        break;
                }
            }
        },

        /**
         * 前一页
         * @return {undefined}
         */
        prev: function() {
            var cp = this.currentPage;

            if (cp === 1) return; //边界

            this.currentPage--;
            this._setPageToHash(this.currentPage);
        },

        /**
         * 后一页
         * @return {undefined}
         */
        next: function() {
            var tp = this.totalPages,
                cp = this.currentPage;

            if (cp === tp) return; //边界

            this.currentPage++;
            this._setPageToHash(this.currentPage);
        }
    };

    //将Slides暴露到全局
    window.Slides = Slides;

})(window);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2012/04/02/%e7%ae%80%e6%b4%81%e7%9a%84html5-slides-show%e7%b1%bbppt/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>从notepad++ 到 sublime text2</title>
		<link>http://www.ueder.net/2012/03/08/%e4%bb%8enotepad-%e5%88%b0-sublime-text2/</link>
		<comments>http://www.ueder.net/2012/03/08/%e4%bb%8enotepad-%e5%88%b0-sublime-text2/#comments</comments>
		<pubDate>Thu, 08 Mar 2012 10:50:04 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[编辑器]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=779</guid>
		<description><![CDATA[之前一直在用notepad++ coding，最近接触了sublime text2 ，感受匪浅，这里暂且做下记录，记录下我所深度试用过的两款编辑器的优劣，有一款得心应手的编辑器，coding起来真是享受。先说np++，这货是一个台湾人做的开源的编辑器，已经许久不更新，界面也像win98时期的软件，不过软件本身够小，打开够快，这也是它的优点，列一下我常用的它的功能点吧（普通编辑器都具备的功能就不列举了）： 1. 括号或标签高亮匹配 (sublime也实现了，不过高亮得太不明显了，不过可以有插件辅助) 2. 代码折叠（效果有点坑爹，折叠后没有结束，无法整块删除，折叠在文件关闭再打开后也不能保存） 3. 上下文中与选择内容一致的高亮显示 （这特性极有用，在看上下文时） 4. 在任意行打标记，F2切换标记点（标记在关闭后再打开也不能保存） 5. 自动完成（NP++的自动完成算是比较坑爹的，系统自带两种方式，一种函数自动完成，用于一些js关键字等，另一个是词法自动完成，就是你上文输过的文字自动完成，这两种还不能共存！） 6. np++提供块级或单行注释的快捷键，不过如果在HTML文件里有JS代码，那么注释就不会智能转换了。 7. NP++对GBK的支持还是很好的，自带编码转换功能 8. zencoding，这是一个插件，在很多编辑器里都有，方便输入html css等 9. NP++本身不带explore，装了插件后可以实现 10. NP++有FTP插件，这工具对于有自己空间需要管理的人来说，很是方便 11. 还有JSHINT，Compare等插件，但插件质量总不是太完美 以上大概就是我常用到的NP++功能，功能不多，算是比较纯粹的编辑器。 - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; &#8230; <a href="http://www.ueder.net/2012/03/08/%e4%bb%8enotepad-%e5%88%b0-sublime-text2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>之前一直在用notepad++ coding，最近接触了sublime text2 ，感受匪浅，这里暂且做下记录，记录下我所深度试用过的两款编辑器的优劣，有一款得心应手的编辑器，coding起来真是享受。先说np++，这货是一个台湾人做的开源的编辑器，已经许久不更新，界面也像win98时期的软件，不过软件本身够小，打开够快，这也是它的优点，列一下我常用的它的功能点吧（普通编辑器都具备的功能就不列举了）：</p>
<p><strong>1. 括号或标签高亮匹配 </strong>(sublime也实现了，不过高亮得太不明显了，不过可以有插件辅助)<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/1.png"><img class="alignnone size-full wp-image-782" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/1.png" alt="" width="416" height="213" /></a><br />
<strong>2. 代码折叠</strong>（效果有点坑爹，折叠后没有结束，无法整块删除，折叠在文件关闭再打开后也不能保存）<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/2.png"><img class="alignnone size-full wp-image-784" title="2" src="http://www.ueder.net/wp-content/uploads/2012/03/2.png" alt="" width="335" height="153" /></a><br />
<strong>3. 上下文中与选择内容一致的高亮显示</strong> （这特性极有用，在看上下文时）<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/3.png"><img class="alignnone size-full wp-image-789" title="3" src="http://www.ueder.net/wp-content/uploads/2012/03/3.png" alt="" width="360" height="207" /></a><br />
<strong>4. 在任意行打标记</strong>，F2切换标记点（标记在关闭后再打开也不能保存）<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/4.png"><img class="alignnone size-full wp-image-791" title="4" src="http://www.ueder.net/wp-content/uploads/2012/03/4.png" alt="" width="358" height="198" /></a></p>
<p>5. 自动完成（NP++的自动完成算是比较坑爹的，系统自带两种方式，一种函数自动完成，用于一些js关键字等，另一个是词法自动完成，就是你上文输过的文字自动完成，这两种还不能共存！）</p>
<p>6. np++提供块级或单行注释的快捷键，不过如果在HTML文件里有JS代码，那么注释就不会智能转换了。</p>
<p>7. NP++对GBK的支持还是很好的，自带编码转换功能</p>
<p>8. zencoding，这是一个插件，在很多编辑器里都有，方便输入html css等</p>
<p>9. NP++本身不带explore，装了插件后可以实现</p>
<p>10. NP++有FTP插件，这工具对于有自己空间需要管理的人来说，很是方便</p>
<p>11. 还有JSHINT，Compare等插件，但插件质量总不是太完美</p>
<p>以上大概就是我常用到的NP++功能，功能不多，算是比较纯粹的编辑器。</p>
<p>- &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; - &#8211; -</p>
<p>下面介绍下<a href="http://sublimetext.com/" target="_blank">sublime text2(点这官网下载)</a> ，这几天深度试用中，对各种编辑辅助功能，语法高亮，快捷键，snippet，插件都有大致的了解，列下各个细节功能点吧：</p>
<p><strong>1. 项目文件夹浏览：</strong> sublime不同于np++，它是基于项目管理，侧边栏可以导入正在开发的项目文件夹，(ctrl+k,ctrl+b)快捷键可以开关侧栏(ps: 这里逗号分隔的两个快捷键代表按下ctrl的同时先按K再按B，这种方式大大增加了快捷键的使用有效率),同时右键菜单里可以remove folder移除文件夹<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/11.png"><img class="alignnone size-full wp-image-797" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/11.png" alt="" width="259" height="232" /></a></p>
<p><strong>2. 文件快速导航：</strong> 这是sublime上面很好用的功能之一，ctrl+p可以调出窗口，菜单上的解释是goto anythings ，确实如其所言，调出窗口后，直接输入关键字，可以在已打开的项目文件夹中进行快速文件名导航，而且支持模糊搜索 ，对于不想一直鼠标点开文件夹的同学来说极为方便，并且在该窗口里加上:前缀即为行跳转(ctrl+G)，加上@(ctrl+R)前缀在html里是id关键字导航，css里是每条规则导航，js里则是每个function导航。<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/21.png"><img class="alignnone size-full wp-image-799" title="2" src="http://www.ueder.net/wp-content/uploads/2012/03/21.png" alt="" width="497" height="277" /></a></p>
<p><strong>3. 命令行模式</strong> ctrl+` 可以调出命令行模式，主要支持python语法等，没试用过只知 quit()可以退出 。。不过sublime的插件平台package controller可以用命令行安装，<a href="http://wbond.net/sublime_packages/package_control/installation" target="_blank">详见这里</a><br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/31.png"><img class="alignnone size-full wp-image-800" title="3" src="http://www.ueder.net/wp-content/uploads/2012/03/31.png" alt="" width="338" height="173" /></a></p>
<p>4. ctrl+up, ctrl+down可以一行一行的滚动屏幕，pageUp pageDown一页一页翻动</p>
<p>5. ctrl+j是拼合两行，ctrl+shift+d是直接复制当前行，</p>
<p>6. ctrl+/ 单行注释， ctrl+shift+/块注释，sublime会自动根据语言选择注释方式</p>
<p>7. ctrl+L 选择当前行，ctrl+d 选择当前文字块，ctrl+shift+a 可以HTML标签内容，每按一次逐级往上， ctrl+shift+space可以选择js等语言里的块{内容}, ctrl+shift+F 是文件夹里查找，与普通编辑不同的地方是sublime允许添加多个文件夹进行查找(add directory)<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/12.png"><img class="alignnone size-full wp-image-802" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/12.png" alt="" width="448" height="118" /></a></p>
<p>8. 在 菜单View-syntax下可以将当前面面以指定的语言进行语法高亮，通常情况下sublime会自动进行判断选择</p>
<p>9. ctrl+F2可以进行标记，然后F2在标记之间切换，这里不爽的是无法进行鼠标添加标记</p>
<p>10. snippets 代码片段插件 ，在tools-snippets菜单下可以查看当前页面支持的snippets，可以在缩略词后加tab自动补全snippets， snippets也可以从安装插件进行扩展</p>
<p>11. Build编译，可以进行ruby等代码的编译，我安装了一个yui compressor后，就可以在css js页面里进行压缩，快捷键是ctrl+B, 会自动在当前目录下生成xx.min.js, xx.min.css等压缩文件</p>
<p>12. 在菜单Preferences 下面是各种配置文件，sublime与其他编辑器不同的是，他不提供可视化配置，软件的配置及快捷键配置全都是存在.xml文件里手动配置，Settings-default 是系统默认配置，最好不要改，要改动的东西存放 在Settings-User里，比如font-size等， Key-bindings是快捷键配置, color scheme是代码配色方案选择，sublime本身提供了很多很不错的配色方案<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/13.png"><img class="alignnone size-full wp-image-804" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/13.png" alt="" width="500" height="278" /></a></p>
<p>13. 在页面右下角，有快速设置tab转为spaces的菜单，可以指定页面的tab宽度，也可以将页面所有tab转为指定的spaces格数<br />
<a class="noeffect"  href="http://www.ueder.net/wp-content/uploads/2012/04/1.png"><img src="http://www.ueder.net/wp-content/uploads/2012/04/1.png" alt="" title="1" width="212" height="38" class="alignnone size-full wp-image-836" /></a><br />
<a class="noeffect"  href="http://www.ueder.net/wp-content/uploads/2012/04/2.png"><img src="http://www.ueder.net/wp-content/uploads/2012/04/2.png" alt="" title="2" width="275" height="310" class="alignnone size-full wp-image-837" /></a></p>
<p><span style="color: red;">接下来介绍一下sublime的亮点，插件机制：</span><br />
sublime插件可以通过两种方式进行插件安装，一种直接下载所有源码放置到C:\Users\yourName\AppData\Roaming\Sublime Text 2\Packages下面，另一种则可以通过在线安装 package control的方式进行在线安装，<br />
package control安装见其<a href="http://wbond.net/sublime_packages/package_control/installation">官网</a>，就是在控制台里运行如下一段代码，再重启即可：</p>
<pre class="prettyprint">import urllib2,os; pf='Package Control.sublime-package'; ipp=sublime.installed_packages_path(); os.makedirs(ipp) if not os.path.exists(ipp) else None; urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler())); open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read()); print 'Please restart Sublime Text to finish installation'</pre>
<p>安装完即可在菜单preferences-package control下打开（这里有个快捷键ctrl+shift+p是编辑器操作的命令集合，可以直接根据关键字索引，省却菜单栏寻找的过程），在package control下 Install Package是安装插件，选择后会连网获取插件列表，disabled package 是禁用某插件，enabled package 启用插件，remove package 移除插件，list package列出插件列表。<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/14.png"><img class="alignnone size-full wp-image-806" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/14.png" alt="" width="422" height="418" /></a></p>
<p>下面介绍几个我觉得比较有用的插件，及它的功用吧（安装方法直接package control install 在线搜索安装）：<br />
<strong>1. BracketHighlighter</strong> ：该插件提供配对标签，或大括号或字符引号的配对高亮显示，算是对系统高亮的加强吧。<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/15.png"><img class="alignnone size-full wp-image-808" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/15.png" alt="" width="396" height="318" /></a><br />
<strong>2. ClipboardHistory</strong>： 该插件提供多剪贴板支持，你就可以同时保存多个剪贴板里的内容了，ctrl+alt+v快捷键调出<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/16.png"><img class="alignnone size-full wp-image-809" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/16.png" alt="" width="413" height="180" /></a><br />
<strong>3. DocBlockr</strong> ：该插件提供文件注释，方便后期根据注释生成API文档，输入 &#8220;/**&#8221; + enter调出 (在function的上面一行才有效果)<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2012/03/17.png"><img class="alignnone size-full wp-image-810" title="1" src="http://www.ueder.net/wp-content/uploads/2012/03/17.png" alt="" width="425" height="168" /></a><br />
<strong>4. GBK Encoding Support</strong>: sublime本身不支持GBK，根据国情，装下这个插件就可以支持GBK了，同时也提供GBK与UTF之间转换</p>
<p><strong>5. jquery</strong> 提供jquery的一些snippets片段 ，方便直接调用</p>
<p><strong>6. JS Minifer</strong> 提供js压缩功能，基于GG的closure complier，快捷键：ctrl+alt+M</p>
<p><strong>7. js Format</strong> 提供JS格式化功能，快捷键 ctrl+alt+F，会根据</p>
<p><strong>8. prefixr</strong> 提供CSS3属性的浏览器前缀自动填充像-webkit- -moz- -o- -m-, 快捷键：ctrl+alt+x</p>
<p><strong>9. yui compressor </strong>这个大家都知道yui的压缩工具，可以压缩CSS JS，直接CTRL+B，即可（需要安装配置了jdk之后才可用）</p>
<p><strong>10. sublime v8</strong> 该插件提供jshint 及 v8引擎的js解析器console，jshint是JS语法校验器，较严格， v8则跟chrome里控制台一样。</p>
<p><strong>11. zenCoding</strong> 大名鼎鼎的zencoding就不用多解释， 调用方式两种，一种是ctrl+alt+enter, 一种是输入完标签直接tab。</p>
<p><strong>12. html5 </strong> 该插件提供许多 html5相关的标签等snippets，也非常实用。</p>
<p><strong>13. SFTP</strong> 该插件提供ftp服务器管理，用来管理自己的空间很不错，通过配置来操作</p>
<p>暂时就以上这些体验，日后再有新的东西再更新。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2012/03/08/%e4%bb%8enotepad-%e5%88%b0-sublime-text2/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>javascript模版引擎-tmpl 的精简及bug修正</title>
		<link>http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/</link>
		<comments>http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 11:50:29 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=760</guid>
		<description><![CDATA[在基于MVC框架开发的web app中，js模板引擎显得特别重要，只需一个模板文本加一段json数据，mix一下，内容就出来了，以往都是用mustache.js， 这里记录一下项目同事介绍一个超精简的模板引擎-tmpl ，对对于mustache.js的单独的模板语法，这个引擎亲切许多，因为可以直接使用js原生的语法，像for switch if，之类。原作为jquery的作者John Resig 开发，详细博客地址, 另有国内某牛人性能改进版，详细见 博文 ，但使用之后，发现还是有点问题，先贴下完整代码： /** * 微型模板引擎 tmpl 0.2 * 0.2 更新: * 1. 修复转义字符与id判断的BUG * 2. 放弃低效的 with 语句从而最高提升3.5倍的执行效率 * 3. 使用随机内部变量防止与模板变量产生冲突 * @example * 方式一：在页面嵌入模板 * &#60;scriptt type="text/tmpl" id="tmpl-demo"&#62; * &#60;ol &#8230; <a href="http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>在基于MVC框架开发的web app中，js模板引擎显得特别重要，只需一个模板文本加一段json数据，mix一下，内容就出来了，以往都是用mustache.js， 这里记录一下项目同事介绍一个超精简的模板引擎-tmpl ，对对于mustache.js的单独的模板语法，这个引擎亲切许多，因为可以直接使用js原生的语法，像for switch if，之类。原作为jquery的作者John Resig  开发，<a href="http://ejohn.org/blog/javascript-micro-templating/"  target="_blank">详细博客地址</a>, 另有国内某牛人性能改进版，详细见<a href="http://www.planeart.cn/?p=1594" target="_blank"> 博文 </a>，但使用之后，发现还是有点问题，先贴下完整代码：</p>
<pre class="prettyprint">
/**
 * 微型模板引擎 tmpl 0.2
 * 0.2 更新:
 * 1. 修复转义字符与id判断的BUG
 * 2. 放弃低效的 with 语句从而最高提升3.5倍的执行效率
 * 3. 使用随机内部变量防止与模板变量产生冲突
 * @example
 * 方式一：在页面嵌入模板
 * &lt;scriptt type="text/tmpl" id="tmpl-demo"&gt;
 * &lt;ol title="&lt;%=name%&gt;"&gt;
 *  &lt;% for (var i = 0, l = list.length; i &lt; l; i ++) { %&gt;
 *      &lt;li&gt;&lt;%=list[i]%&gt;&lt;/li&gt;
 *  &lt;% } %&gt;
 * &lt;/ol&gt;
 * &lt;/scriptt&gt;
 * tmpl('tmpl-demo', {name: 'demo data', list: [202, 96, 133, 134]})
 *
 * 方式二：直接传入模板：
 * var demoTmpl =
 * '&lt;ol title="&lt;%=name%&gt;"&gt;'
 * + '&lt;% for (var i = 0, l = list.length; i &lt; l; i ++) { %&gt;'
 * +    '&lt;li&gt;&lt;%=list[i]%&gt;&lt;/li&gt;'
 * + '&lt;% } %&gt;'
 * +'&lt;/ol&gt;';
 * var render = tmpl(demoTmpl);
 * render({name: 'demo data', list: [202, 96, 133, 134]});
 *
 * 这两种方式区别在于第一个会自动缓存编译好的模板，
 * 而第二种缓存交给外部对象控制，如例二中的 render 变量。
 * @blog http://www.planeart.cn/?p=1594
 * @see		http://ejohn.org/blog/javascript-micro-templating/
 * @param	{String}	模板内容或者装有模板内容的元素ID
 * @param	{Object}	附加的数据
 * @return	{String}	解析好的模板
 */
var tmpl = (function (cache, $) {
return function (str, data) {
	var fn = !/\W/.test(str)
	? cache[str] = cache[str]
		|| tmpl(document.getElementById(str).innerHTML)

	: function (data) {
		var i, variable = [$], value = [[]];
		for (i in data) {
			variable.push(i);
			value.push(data[i]);
		};
		return (new Function(variable, fn.$))
		.apply(data, value).join("");
	};

	fn.$ = fn.$ || $ + ".push('"
	+ str.replace(/\\/g, "\\\\")
		 .replace(/[\r\t\n]/g, " ")
		 .split("&lt;%").join("\t")
		 .replace(/((^|%&gt;)[^\t]*)'/g, "$1\r")
		 .replace(/\t=(.*?)%&gt;/g, "',$1,'")
		 .split("\t").join("');")
		 .split("%&gt;").join($ + ".push('")
		 .split("\r").join("\\'")
	+ "');return " + $;

	return data ? fn(data) : fn;
}})({}, '$' + (+ new Date));
</pre>
<p><span id="more-760"></span><br />
此代码预设了两种模板使用环境，一种是用script标签，另一种直接传入string，是由代码的这个部分：</p>
<pre class="prettyprint">
var fn = !/W/.test(str)
</pre>
<p>来判断是script标签还是直接string的，\W是代表非单词字符，这种判断预设了用户的script 的 id 一定为单词字符，如果是连字符&#8221;-&#8221;即会被当成string，出现错误，不是特别完美，<br />
暂时也没找到什么好的判断方式，况且通常应用场都是用string, 索性直接去掉script的判断，只支持string的模板，如果硬要script，可以自行获取 script的innerHTML然后再以string的方式传给tmpl函数，另外模板里的语法是通过<%%>包裹的，容易与其他后端语言的模板冲突，故改成<##>.<br />
以下是修正后的完整代码：</p>
<pre class="prettyprint">
/**
 * 微型模板引擎 tmpl
 * 方式：直接传入模板：(可以随心所欲的使用js原生语法)
 * var demoTmpl =
 * '&lt;ol title="&lt;#= name#&gt;"&gt;'
 * + '&lt;# for (var i = 0, l = list.length; i &lt; l; i ++) { #&gt;'
 * +    '&lt;li&gt;&lt;#= list[i] #&gt;&lt;/li&gt;'
 * + '&lt;# } #&gt;'
 * +'&lt;/ol&gt;';
 * var render = tmpl(demoTmpl);
 * render({name: 'demo data', list: [202, 96, 133, 134]});
 *
 * 缓存交给外部对象控制，如例二中的 render 变量。
 * @blog http://www.planeart.cn/?p=1594
 * @see		http://ejohn.org/blog/javascript-micro-templating/
 * @param	{String}	模板内容或者装有模板内容的元素ID
 * @param	{Object}	附加的数据
 * @return	{String}	解析好的模板
 */
var tmpl = (function (cache, $) {
return function (str, data) {
	var fn = function (data) {
		var i, variable = [$], value = [[]];
		for (i in data) {
			variable.push(i);
			value.push(data[i]);
		};
		return (new Function(variable, fn.$))
		.apply(data, value).join("");
	};

	fn.$ = fn.$ || $ + ".push('"
	+ str.replace(/\\/g, "\\\\")
		 .replace(/[\r\t\n]/g, " ")
		 .split("&lt;#").join("\t")
		 .replace(/((^|#&gt;)[^\t]*)'/g, "$1\r")
		 .replace(/\t=(.*?)#&gt;/g, "',$1,'")
		 .split("\t").join("');")
		 .split("#&gt;").join($ + ".push('")
		 .split("\r").join("\\'")
	+ "');return " + $;

	return data ? fn(data) : fn;
}})({}, '$' + (+ new Date));
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>一个简单的中文字符转unicode的chrome插件</title>
		<link>http://www.ueder.net/2011/11/10/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e8%bd%acunicode%e7%9a%84chrome%e6%8f%92%e4%bb%b6/</link>
		<comments>http://www.ueder.net/2011/11/10/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e8%bd%acunicode%e7%9a%84chrome%e6%8f%92%e4%bb%b6/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 10:58:53 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[chrome插件]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=744</guid>
		<description><![CDATA[插件安装地址(请用chrome打开)： charCodeTranslate.crx 12-7-2011 更新增加了从unicode转字符，以及encode，decode等方便的功能 3-5-2012 更新增加了转义成HTML实体字符，例如&#8217;]]></description>
			<content:encoded><![CDATA[<p>插件安装地址(请用chrome打开)： <a href="http://www.ueder.net/chrome_expansion/charCodeTranslate.crx">charCodeTranslate.crx</a><br />
<span style="color:red">12-7-2011 更新增加了从unicode转字符，以及encode，decode等方便的功能</span><br />
<span style="color:red">3-5-2012 更新增加了转义成HTML实体字符，例如&#8217;<' 转成'&#38&#35&#54&#48' 方便页面使用</span></p>
<p>在通常的JS或CSS文件里，汉字等字符是以unicode的16进制形式存在的， 如果直接输入汉字，在英文或其他语种的系统上，容易造成乱码无法识别的状况，如果把所有汉字转成unicode形式就没有问题了，所以就想到做一个chrome小插件，随时查看汉字的unicode编码，<br />
直接看下主转换代码：</p>
<pre class="prettyprint">
/**
 * 中文转unicode字符工具
 */
function toUnicode(str, cssType) {
    var i = 0,
        l = str.length,
        result = [], //转换后的结果数组
        unicodePrefix, //unicode前缀 (example:&#x5C;1234||&#x5C;u1234)
        unicode16; //转换成16进制后的unicode

    //如果是css中使用格式为&#x5C;1234之类
    unicodePrefix = (cssType &#038;&#038; cssType.toLowerCase() === 'css') ? '&#x5C;&#x5C;' : '&#x5C;&#x5C;u';

    for (; i &lt; l; i++) {
        //转为16进制的unicode, js及css里须转成16进制
        unicode16 = str.charCodeAt(i).toString(16);
        result.push( unicodePrefix + unicode16 );
    }

    return result.join(' ');
}
</pre>
<p><span id="more-744"></span><br />
字符串的charCodeAt方法返回的是10进制的unicode，所以我们需要用toString(16)将其转为16进制的，才能在JS及CSS中使用，而CSS中跟JS不同的是少了个U。</p>
<p>再来看下页面上的调用 ：</p>
<pre class="prettyprint">
/**
 * excute
 */
var input = document.getElementById('input'),
    convert = document.getElementById('convert'),
    CSSResult = document.getElementById('resultCSSType'),
    JSResult = document.getElementById('resultJSType'),
    msg = document.getElementById('msg');

//事件处理
function convertStr(e) {
    var v = input.value;

    //管理事件
    switch (e.type) {
        case 'click':
            if (checkInput(v)) {
                renderResult(v);
            }
            break;

        case 'keydown':
            if (e.keyCode === 13 &#038;&#038; checkInput(v)) {
                renderResult(v);
            }
            break;
    }

    //检测英文等字符排除
    function checkInput(str) {
        var charReg = /[^u0391-uFFE5]/g; //匹配英文等无需转换的字符

        if (charReg.test(str)) {
            msg.innerHTML = '输入字符格式有误，请输入中文等字符';
            input.select();
            input.focus();
            renderResult('');
            return false;
        } else {
            msg.innerHTML = '';
            return true;
        }

    }

    //渲染结果
    function renderResult(str) {
        JSResult.innerHTML = toUnicode(str);
        CSSResult.innerHTML = toUnicode(str, 'css');
    }

} 

//bind事件
convert.addEventListener('click', convertStr, false);
input.addEventListener('keydown', convertStr, false);
input.addEventListener('blur', convertStr, false);
</pre>
<p>正则/[\u0391-\uFFE5]/是用来匹配中文字符，包括标点，繁体什么的。</p>
<p>再来就是生成chrome插件，chrome插件制作很简单，只需在chrome的扩展程序里导入你的项目文件 ，通常就是html+css+js文件即可，然后就可打包生成crx文件，可以在chrome上安装的插件了，（PS:具体的插件制作GG搜索下就有了）</p>
<p>本来想发布至chrome的webstore里，结果发布竟然还要收费 ，所以还是作罢，直接贴一下插件安装地址吧，请用chrome打开 <a href="http://www.ueder.net/chrome_expansion/charCodeTranslate.crx">charCodeTranslate.crx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/11/10/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e8%bd%acunicode%e7%9a%84chrome%e6%8f%92%e4%bb%b6/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>关于递归在项目中的几种常用应用</title>
		<link>http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/</link>
		<comments>http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 04:04:35 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[递归]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=732</guid>
		<description><![CDATA[项目中常常会对开发返回的json数据进行遍历，然后更新页面，如果数据只是简单的一层结构，只需一个for循环即可搞定，但如果数据存在较深且不确定的层次，此时就需要使用递归配合循环来搞定，先看下模拟的数据格式： //json数据 var json = { status: 'success', data: [ { status: 0, title: '文件夹1', data: [ { status: 0, title: '文件夹2', data: [ { status: 0, title: '文件夹3', data: [ { status: 0, title: '文件夹4', data: [] }, { &#8230; <a href="http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>项目中常常会对开发返回的json数据进行遍历，然后更新页面，如果数据只是简单的一层结构，只需一个for循环即可搞定，但如果数据存在较深且不确定的层次，此时就需要使用递归配合循环来搞定，先看下模拟的数据格式：</p>
<pre class="prettyprint">
//json数据
var json = {
    status: 'success',
    data: [
        {
            status: 0,
            title: '文件夹1',
            data: [
                {
                    status: 0,
                    title: '文件夹2',
                    data: [
                        {
                            status: 0,
                            title: '文件夹3',
                            data: [
                                {
                                    status: 0,
                                    title: '文件夹4',
                                    data: []
                                },
                                {
                                    status: 0,
                                    title: '文件夹4',
                                    data: []
                                }
                            ]
                        },
                        {
                            status: 0,
                            title: '文件夹3',
                            data: []
                        }
                    ]
                },
                {
                    status: 0,
                    title: '文件夹2',
                    data: []
                }
            ]
        },
        {
            status: 1,
            title: '文件1',
        }
    ]
};
</pre>
<p>对于上面这种深层次的数据结构，普通的循环是无法搞定的，此时可以提取重复处理的代码片段，然后使用递归 即可搞定，直接看代码：</p>
<pre class="prettyprint">
/**
 * 递归遍历数据
 */
function recursion(data) {
    var i = 0,
        len = data.length,
        j, item, current, flag;

    for (; i &lt; len; i++) {
        item = data[i];

        for (j in item) {
            current = item[j];
            //是否数组判断
            flag = (Object.prototype.toString.call(current) === '[object Array]') ? true : false;

            if (flag) {
                recursion(current);
            } else {
                //这里执行对数据的相应操作
                console.log(current);
            }
        }
    }
}

//调用
recursion(json.data);
</pre>
<p><span id="more-732"></span><br />
一个类似的应用是DOM节点的游走，可以遍历整个文档所有节点，包括子节点，看如下代码：</p>
<pre class="prettyprint">
/**
 * 节点遍历
 */
function nodeWalk(node, fn) {
    var re = arguments.callee; //引用函数本身

    if (node.nodeType === 1) {
        //处理节点
        fn.call(node, node);
    }

    node = node.firstChild;

    while (node) {
        re(node, fn);
        node = node.nextSibling;
    }

}

//调用
nodeWalk(document.body, function(n){
    console.log(this.nodeName);
});
</pre>
<p>还有一种典型用例是，对于多行的input需要往后端ajax实时验证输入内容的时候，普通的for循环已不能解决问题，需要在ajax请求成功的回调函数里进行递归调用，直接看示例代码：</p>
<pre class="prettyprint">
//初始化
var nodeList = $('#test input:text'),
    n = 0;

/**
 * 递归验证
 */
(function recursionCheck(node) {

    var v = node.value,
        nextNode = nodeList[++n];

    //ajax请求服务端验证
    $.ajax({
        'url': 'xxxxx.do',
        'data': 'xxxxxx',
        'dataType': 'json',
        'success': function(data){

            //验证成功，递归调用代码验证下一个node
            if (data.value === v) {

                //判断节点是否存在
                if (nextNode) {
                    recursionCheck(nextNode);
                } else {
                    alert('验证通过');
                }
            } 

            //验证不成功，结束执行，给出错误提示
            else {
                alert('数据验证不正确');
            }
        }
    });

})(nodeList[n]);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>模拟AJAX无刷新的文件上传功能</title>
		<link>http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/</link>
		<comments>http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 07:42:59 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[upload]]></category>
		<category><![CDATA[无刷新上传]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=720</guid>
		<description><![CDATA[传统的文件上传功能一般是用form包一个input:file直接提交到后端进行处理，form须指定enctype=&#8221;multipart/form-data&#8221;，代码如下： &#60;form action="test.php" target="" method="post" enctype="multipart/form-data"&#62; &#60;input type="file" name="file" id="file" /&#62; &#60;input type="submit" id="J_submit" value="submit" /&#62; &#60;/form&#62; 在ajax盛行的现时，提交form再刷新整个页面，显得用户体验不佳，然而ajax与后端通信 只能传送字符串，是无法传递实体文件的，所以用ajax是无法实现直接文件上传的，这里提供一个解决方案就是用一个实时创建的隐藏iframe来完成上传功能， 具体的原理是，在点击提交按钮时，动态的生成一个隐藏iframe加入到页面上，并且 将form 的 target指向该隐藏iframe，服务端就接收到上传的file文件，并进行相应的操作，然后将返回结果返回到隐藏的iframe里面，这时我们可以与后端开发约定返回结果的格式，可以是json格式，便于我们前端操作，然后前端部分就可以用iframe.contentWindow.document.body.innerHTML来获取后端返回的结果，进行相应的parseJSON处理，即可像处理ajax返回的json一样，处理数据。。。直接贴源代码了(ps:代码是基于jQuery库的)： /** * 模拟ajax无刷新文件上传 */ var fileUpLoad = function(config) { var ifr = null, fm = null, defConfig &#8230; <a href="http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>传统的文件上传功能一般是用form包一个input:file直接提交到后端进行处理，form须指定enctype=&#8221;multipart/form-data&#8221;，代码如下：</p>
<pre class="prettyprint">
&lt;form action="test.php" target="" method="post" enctype="multipart/form-data"&gt;
    &lt;input type="file" name="file" id="file" /&gt;
    &lt;input type="submit" id="J_submit"  value="submit" /&gt;
&lt;/form&gt;
</pre>
<p>在ajax盛行的现时，提交form再刷新整个页面，显得用户体验不佳，然而ajax与后端通信 只能传送字符串，是无法传递实体文件的，所以用ajax是无法实现直接文件上传的，这里提供一个解决方案就是用一个实时创建的隐藏iframe来完成上传功能， 具体的原理是，在点击提交按钮时，动态的生成一个隐藏iframe加入到页面上，并且 将form 的 target指向该隐藏iframe，服务端就接收到上传的file文件，并进行相应的操作，然后将返回结果返回到隐藏的iframe里面，这时我们可以与后端开发约定返回结果的格式，可以是json格式，便于我们前端操作，然后前端部分就可以用iframe.contentWindow.document.body.innerHTML来获取后端返回的结果，进行相应的parseJSON处理，即可像处理ajax返回的json一样，处理数据。。。直接贴源代码了(ps:代码是基于jQuery库的)：</p>
<pre class="prettyprint">
/**
 * 模拟ajax无刷新文件上传
 */
var fileUpLoad = function(config) {

    var ifr = null,
        fm = null,
        defConfig = {
            submitBtn: $('#J_submit'), //提交按钮
            complete: function(response) {}, //上传成功后回调
            beforeUpLoad: function() {}, //点击提交未上传时回调
            afterUpLoad: function() {} //点击提交上传后回调
        };

    //静态变量
    var IFRAME_NAME = 'fileUpLoadIframe';

    //配置
    config = $.extend(defConfig, config);

    //绑定submit事件
    config.submitBtn.bind('click', function(e){
        e.preventDefault();

        //点击提交前触发事件, 函数返回false可阻止提交表单，用于file为空判断
        if (config.beforeUpLoad.call(this) === false) {
            return;
        }

        //生成一个隐藏iframe，并设置form的target为该iframe，模拟ajax效果
        ifr = $('&lt;iframe name="'+ IFRAME_NAME +'" id="'+ IFRAME_NAME +'" style="display:none;"&gt;&lt;/iframe&gt;');
        fm = this.form;

        ifr.appendTo($('body'));
        fm.target = IFRAME_NAME; //target目标设为ifr

        //上传完毕iframe onload事件
        ifr.load(function(){
            var response = this.contentWindow.document.body.innerHTML;

            config.complete.call(this, response);
            ifr.remove();
            ifr = null; //清除引用
        });

        fm.submit(); //提交表单

        //点击提交后触发事件
        config.afterUpLoad.call(this);

    });

};
</pre>
<p><span id="more-720"></span><br />
页面调用是：</p>
<pre class="prettyprint">
fileUpLoad({
    submitBtn: $('#J_submit'),
    complete: function(response){ //上传成功后处理回调
        var d = $.parseJSON(response);

        alert('返回成功')
        console.log(d);
    },
    beforeUpLoad: function() {
        alert('上传前');
    },
    afterUpLoad: function() {
        alert('上传后');
    }
});
</pre>
<p>而对于需要实时显示上传进度条的应用，则可以考虑form提交后用ajax实时轮询的方式向后端取文件上传的进度，来进行前端页面进度渲染，另一种方式则是基于flash上传，这里就不详细展开了。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>正则表达式的技巧总结</title>
		<link>http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/</link>
		<comments>http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/#comments</comments>
		<pubDate>Thu, 07 Jul 2011 07:02:19 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=688</guid>
		<description><![CDATA[正则表达式在现在web的应用当中，如表单验证，url解析等，应用非常方便，比起普通的字符串解析性能上也高出不少。 这里就做一些关于正则表达式通用技巧的个人小总结，正则的入门可以参考以下网址内容 http://www.regexlab.com/zh/regref.htm http://w3school.com.cn/js/jsref_obj_regexp.asp 1. 一些常用的元字符. \w : 查找单词字符，包含字母数字及下划线，相当于[A-Za-z0-9_]; \d : 查找数字，相当于[0-9] \s : 查找空白字符 \n : 查找换行符 . : 点号代表除换行符及行结束符外所有字符 2. 验证完整字符串，这在表单验证中常用到，例子如下: var str = '18636200607'; var str2 = '10010'; var reg = /^\d{11}$/; console.log(reg.test(str)); // return true; console.log(reg.test(str2)); &#8230; <a href="http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>正则表达式在现在web的应用当中，如表单验证，url解析等，应用非常方便，比起普通的字符串解析性能上也高出不少。<br />
这里就做一些关于正则表达式通用技巧的个人小总结，正则的入门可以参考以下网址内容<br />
<a target="_blank" href="http://www.regexlab.com/zh/regref.htm">http://www.regexlab.com/zh/regref.htm</a><br />
<a target="_blank"  href="http://w3school.com.cn/js/jsref_obj_regexp.asp">http://w3school.com.cn/js/jsref_obj_regexp.asp</a></p>
<p><strong>1. 一些常用的元字符.</strong><br />
\w : 查找单词字符，包含字母数字及下划线，相当于<span class="code">[A-Za-z0-9_]</span>;<br />
\d : 查找数字，相当于<span class="code">[0-9]</span><br />
\s : 查找空白字符<br />
\n : 查找换行符<br />
.  : 点号代表除换行符及行结束符外所有字符</p>
<p><strong>2. 验证完整字符串，这在表单验证中常用到，例子如下:</strong></p>
<pre class="prettyprint">
var str = '18636200607';
var str2 = '10010';
var reg = /^\d{11}$/;
console.log(reg.test(str)); // return true;
console.log(reg.test(str2)); // return false;
</pre>
<p>这里的头尾的^$即是限定匹配的必须是整个字符串，而不是其中一部分，这对于表单验证里验证完整的合法输入很有用。<br />
<span id="more-688"></span><br />
<strong>3. 验证一个完整的单词，可以用到\b，例子如下：</strong></p>
<pre class="prettyprint">
var str = 'hello world!';
var str2 = 'helloworld!';
var reg = /\bhello\b/;
console.log(reg.test(str)); //return true
console.log(reg.test(str2)); //return false
</pre>
<p>这里\b作为单词的边界条件进行判断，与^$夹着字符串相似，但\b夹的是单个单词</p>
<p><strong>4. 捕获型分组与非捕获型分组</strong><br />
捕获型分组是小括号包围起来的一个分组表达式，里面匹配到的内容可以在之后调用，例子如下:</p>
<pre class="prettyprint">
var str = '1234haha';
var reg = /(\d+)\w+/;
var result = reg.exec(str);
console.log(result[0]); //return '1234haha'
console.log(result[1]); //return '1234'
</pre>
<p>正则对象的exec方法与test不同，它如果匹配不成功返回null,成功则返回一个数组对象，[0]包含匹配到的完整字符串，[1][2]&#8230;等等则保存着各个子表达式里所捕获的内容（即小括号里获取的字符串）;<br />
小括号在正则里还有一个用处则是起到分组的作用<br />
如： <span class="code">(abcd){4}</span><br />
此表达式表示abcd整个字符串重复4次才能匹配成功<br />
但小括号同时也影响了exec方法返回的捕获数组内容，<br />
此时如果不希望捕获内容影响，可以使用非捕获分组，非捕获分组格式是(?:&#8230;..);<br />
如： <span class="code">(?:abcd){4}</span><br />
此时小括号里的内容只会起到分组的作用，并不会捕获内容。</p>
<p><strong>5. 方括号与分组表达式的或结构</strong><br />
方括号里的内容只会匹配单个字符，<br />
例如 <span class="code">[1234]</span> 只会匹配1234里的一个字符，如果希望匹配的是一个字符串可以使用非捕获型分组来达成目的<br />
而或结构的分组表达式 <span class="code">(?:12|34)</span> 会匹配12 或 34这两个字符里的其中一组。<br />
示例代码：</p>
<pre class="prettyprint">
var str = '1234';
var reg = /[1234]/;
var reg2 = /(?:12|34)/;
console.log(reg.exec(str)[0]); //retrun '1'
console.log(reg2.exec(str)[0]); //return '12'
</pre>
<p><strong>6. 贪婪模式与非贪婪模式</strong><br />
<span class="code">\w+</span> 在匹配字符串 &#8216;hello&#8217; 时会匹配整个字符串，此时为贪婪模式<br />
但 <span class="code">\w+?</span> 在匹配时 则只匹配 &#8216;h&#8217;单个字符串，此时为非贪婪模式<br />
也就是说在量词(*, +, ?, {5, })后面加个?即形成非贪婪模式，会尽可能在不影响匹配成功的情况下，少匹配字符<br />
示例代码：</p>
<pre class="prettyprint">
var str = 'hello';
var reg = /\w+/;
var reg2 = /\w+?/;
console.log(reg.exec(str)[0]); //retrun 'hello'
console.log(reg2.exec(str)[0]); //return 'h'
</pre>
<p><strong>7. 反向引用</strong><br />
捕获型分组里捕获的内容在三种情况下可以被引用<br />
第一是exec方法回复的数组里，从[1]开始<br />
第二是test或exec方法执行后，RegExp.$1开始之后存储捕获内容<br />
第三则是在正则表达式里的反向引用，如\1 \2这种形式<br />
看下例子：</p>
<pre class="prettyprint">
var str = '&lt;td&gt;这里是td&lt;/td&gt;';
var reg = /&lt;(\w+)&gt;.*&lt;\/\1&gt;/;
console.log(reg.test(str)); // return true
</pre>
<p>此处正则表达式里\1则是引用了前面的捕获型分级(\w+)的内容</p>
<p><strong>8. 正向预搜索及不匹配</strong><br />
预搜索与^$\b一样本身不匹配内容，只是提供一个判断<br />
看下例子：</p>
<pre class="prettyprint">
var str = 'HelloWorld';
var reg = /Hello(?=World)/;
var reg2 = /Hello(?!World)/;
console.log(reg.test(str)); // return true
console.log(reg2.test(str)); //return false
</pre>
<p><span class="code">(?=&#8230;)</span>代表前面要匹配的字符后面必须带有指定的字符才能匹配成功<br />
<span class="code">(?!&#8230;)</span>则相反，代表不包含指定的字符<br />
javascript不支持反向预搜索，这里就不介绍了</p>
<p><strong>9. 正则对象的方法</strong><br />
RegExpObject.test 方法：<br />
这是表单验证中常用到的方法，如果匹配成功返回true,反之false</p>
<p>RegExpObject.exec 方法：<br />
exec方法很强大，它基本提供了所有所需要的信息<br />
返回的是一个数组，数组的[0]存放的是匹配到的完整字符串，[1][2]开始存放的是捕获型分组（也就是正则里的小括号包围的内容）捕获到的字符串,<br />
该数组还包含额外两个属性index及input; index标识的是匹配结果的字符串位置，input标识的是正则表达式<br />
其实exec最强大的地方是在于，对于带g全局标识的正则表达式(如<span class="code">/\w+/g</span>)，在每次执行exec的时候，都会将正则对象的lastIndex设置为前一个匹配到的字符串的最后一个位置<br />
换句话说，你就可以利用这个特性进行整个字符串的遍历，并配合捕获型分组，就可以得到你想要的字串内容<br />
看如下例子</p>
<pre class="prettyprint">
//解析url
var url = 'http://www.taobao.com/?ver=1.0&#038;q=search';
var reg = /(\w+)=([^&#038;]*)/g;
var obj = {};
var result;
while(result = reg.exec(url)){
    obj[result[1]] = result[2];
}
console.log(obj); //return {ver:'1.0', q:'search'}
</pre>
<p>以上就可以遍历正则匹配整个字符串，配合捕获分组就可以得到你想要的字串了</p>
<p>String.match 方法 ：<br />
如果正则表达式不带g全局标识，字符串的match方法与正则对象的exec对象相似，只进行一次匹配，返回一个数组，[0]存放的是完整匹配字串，[1]以后存放捕获分组的内容<br />
如果正则表达式带g全局标识，则match方法回返的内容大不一样，也是一个数组，但是是从[0]开始各个存放匹配到的完整匹配字串，就不会再存放捕获分组的内容了<br />
有时这在简单匹配整个字串的时候比起exec简便些<br />
看下例子：</p>
<pre class="prettyprint">
var str = '1: 哈哈，2: 呵呵， 3: 嘿嘿';
var reg = /\d:/g;
console.log(str.match(reg)); //return ['1:', '2:', '3:']
</pre>
<p>以上直接回返匹配到的结果数组</p>
<p>String.replace 方法：<br />
字符串的replace方法带两个参数，第一个参数是查找匹配的字符串，第二个参数是要替换成的内容，也可以是个function匿名函数<br />
如果是正则替换方式，则第二个参数里的$有特殊的含义，$1 $1&#8230;代表的是之前正则表达式里的捕获分组得到的字串，$&#038;代表的是匹配得到的完整字串，$`代表匹配字串左侧的文本，$&#8217;代表匹配字串右侧的文本</p>
<p>看下面个例子：</p>
<pre class="prettyprint">
var str = 'hello world!';
var reg = /(\w+)\s(\w+)/;
str = str.replace(reg, '$2 $1');
console.log(str); //return 'world hello!'
</pre>
<p>这里利用到$1 $2的捕获分组的内容。</p>
<p>再看个例子：</p>
<pre class="prettyprint">
var str = 'background-color';
var reg = /-(\w)/g;
str = str.replace(reg, function(w, s){
    return s.toUpperCase();
});
console.log(str); // return 'backgroundColor'
</pre>
<p>对于加g的正则表达式，replace方法会循环执行替换操作，replace方法里的第二个参数如果是function，则function的第一个参数是完整的正则匹配字串，第二个参数开始则是捕获分组得到的字串。</p>
<p>String.split方法及String.search方法较为简单，可参考相关资料</p>
<p>参考资料：<br />
<a href="http://www.regexlab.com/zh/regref.htm">http://www.regexlab.com/zh/regref.htm</a><br />
<a href="http://w3school.com.cn/js/jsref_obj_regexp.asp">http://w3school.com.cn/js/jsref_obj_regexp.asp</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>浮动元素的水平居中</title>
		<link>http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/</link>
		<comments>http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 06:07:33 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[html/css]]></category>
		<category><![CDATA[浮动元素水平居中]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=680</guid>
		<description><![CDATA[对于页面上的块级元素，只须定宽及设置margin:0 auto;即可在水平上居中，但对于浮动的元素水平居中是无效的，一个典型的应用就是页面的分页效果了，看如下图： 这种分页效果，在以往可能会采取设置inline-block，然后父容器设置text-align:center方式来实现内容居中，像如下代码： &#60;!DOCTYPE html&#62; &#60;html xmlns=&#34;http://www.w3.org/1999/xhtml&#34;&#62; &#60;head&#62; &#60;meta http-equiv=&#34;Content-Type&#34; content=&#34;text/html; charset=utf-8&#34; /&#62; &#60;title&#62;页面元素的水平居中&#60;/title&#62; &#60;style type=&#34;text/css&#34;&#62; * { margin:0; padding:0; list-style:none; font-size:14px; font-family:Tahoma, Geneva, sans-serif; } .clearfix:after { content:&#34;&#34;; height:0; visibility:hidden; display:block; clear:both; } .clearfix { zoom:1; } a{ text-decoration:none;} &#8230; <a href="http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>对于页面上的块级元素，只须定宽及设置margin:0 auto;即可在水平上居中，但对于浮动的元素水平居中是无效的，一个典型的应用就是页面的分页效果了，看如下图：<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2011/03/1.jpg"><img src="http://www.ueder.net/wp-content/uploads/2011/03/1.jpg" alt="" title="1" width="643" height="85" class="alignnone size-full wp-image-681" /></a><br />
这种分页效果，在以往可能会采取设置inline-block，然后父容器设置text-align:center方式来实现内容居中，像如下代码：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_hlTAPd">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;页面元素的水平居中&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
* { margin:0; padding:0; list-style:none; font-size:14px; font-family:Tahoma, Geneva, sans-serif; }
.clearfix:after { content:&quot;&quot;; height:0; visibility:hidden; display:block; clear:both; }
.clearfix { zoom:1; }
a{ text-decoration:none;}
h1{ text-align:center; padding:10px; font-size:20px; margin:30px 0;}
.wrap { margin:20px auto; padding:10px 0; background:orange; overflow:hidden; position:relative; }
.page2{ text-align:center;}
.page2 a{ display:inline-block;padding:2px 9px; background:white; border:1px solid red; vertical-align:middle;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;页面元素的水平居中&lt;/h1&gt;
&lt;h2&gt;inline-block方式：&lt;/h2&gt;
&lt;div class=&quot;wrap page2&quot;&gt;
	&lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_hlTAPd").style.height = document.getElementById("runcode_hlTAPd").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_hlTAPd');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_hlTAPd');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_hlTAPd','runcode_hlTAPd');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p><span id="more-680"></span><br />
这种设置inline-block的缺点是，元素需要设置vertical-align:middle，并且ie下不能完美对齐，以及元素间有空白符等。。<br />
所以可以考虑用float方式代替inline-block，优点是float的元素盒模型好控制 ，无空白符等等。<br />
代码如下：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_TbUH9P">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;页面元素的水平居中&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
* { margin:0; padding:0; list-style:none; font-size:14px; font-family:Tahoma, Geneva, sans-serif; }
.clearfix:after { content:&quot;&quot;; height:0; visibility:hidden; display:block; clear:both; }
.clearfix { zoom:1; }
a{ text-decoration:none;}
h1{ text-align:center; padding:10px; font-size:20px; margin:30px 0;}
.wrap { margin:20px auto; padding:10px 0; background:orange; overflow:hidden; position:relative; }
.page { float:left; position:relative; left:50%; }
.page li { float:left; position:relative; right:50%; overflow:hidden; margin:0 5px; }
.page li a { display:block; padding:2px 9px; background:white; border:1px solid red; }
.page2{ text-align:center;}
.page2 a{ display:inline-block;padding:2px 9px; background:white; border:1px solid red; vertical-align:middle;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;页面元素的水平居中&lt;/h1&gt;
&lt;h2&gt;浮动方式：&lt;/h2&gt;
&lt;div class=&quot;wrap clearfix&quot;&gt;
	&lt;ul class=&quot;page&quot;&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;1&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;5&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;6&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt; &lt;/li&gt;
	&lt;/ul&gt;
&lt;/div&gt;
&lt;h2&gt;inline-block方式：&lt;/h2&gt;
&lt;div class=&quot;wrap page2&quot;&gt;
	&lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_TbUH9P").style.height = document.getElementById("runcode_TbUH9P").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_TbUH9P');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_TbUH9P');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_TbUH9P','runcode_TbUH9P');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p>这里主要用到position:relative配合left:50%的技巧，兼容各浏览器，需要注意的是IE7下需要设置overflow:hidden;来解决无法设置子元素宽度的BUG。</p>
<p>这里也可以多套一层的方式设置left:-50%，更合理，也可以避免一些不必要的IE BUG，如下代码：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_tNJsZ8">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;页面元素的水平居中&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
* { margin:0; padding:0; list-style:none; font-size:14px; }
.clearfix:after { content:&quot;&quot;; height:0; visibility:hidden; display:block; clear:both; }
.clearfix { zoom:1; }
a{ text-decoration:none;}
h1{ text-align:center; padding:10px; font-size:20px; margin:30px 0;}
.wrap { margin:20px auto; padding:10px 0; background:orange; overflow:hidden; position:relative; }
.inwrap{ float:left; position:relative; left:50%;}
.page { float:left; position:relative; left:-50%; }
.page li { float:left;margin:0 5px;  }
.page li a { display:block; padding:2px 9px; background:white; border:1px solid red; float:left;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;页面元素的水平居中&lt;/h1&gt;
&lt;h2&gt;浮动方式：&lt;/h2&gt;
&lt;div class=&quot;wrap clearfix&quot;&gt;
	&lt;div class=&quot;inwrap&quot;&gt;
		&lt;ul class=&quot;page&quot;&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;1&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;5&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;6&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt; &lt;/li&gt;
		&lt;/ul&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_tNJsZ8").style.height = document.getElementById("runcode_tNJsZ8").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_tNJsZ8');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_tNJsZ8');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_tNJsZ8','runcode_tNJsZ8');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p>举一反三，这种float元素居中的方式其实可以延展应用到很多需要浮动元素又居中的情况。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>HTML5的本地存储 LocalStorage</title>
		<link>http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/</link>
		<comments>http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 03:51:59 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[本地存储]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=666</guid>
		<description><![CDATA[localStorage顾名思义，就是本地存储的意思，在以前很长一段时间，要想在客户端存储一些配置及登录信息等数据都只能通过COOKIE或flash的方式，如今html5来临，也带来了更强大的本地存储，最多可存储大小5M的字符串，足可以满足大部分的web应用，比cookie的4K要大出不少，还有一个sessionStorage，功能基本与localStorage相同，看名字便知与sesstion一样，关闭浏览器即失效。 以前有用过cookie的都了解cookie的存储读取方式都不太优雅，需要自己封装set get方法，而localStorage则方便许多，localStorage 是作為window的一个属性存在的，拥有setItem,getItem,removeItem,clear等方法，相当方便。 浏览器的支持除了IE７及以下不支持外，其他标准浏览器都完全支持(ie及FF需在web服务器里运行)，支持情况如下图： 如下代码即可判断浏览器是否支持 if(window.localStorage){ alert("浏览支持localStorage") }else{ alert("浏览暂不支持localStorage") } localStorage不但可以用自身的setItem,getItem等方便存取，也可以像普通对象一样用点操作符，及[]的方式进行数据存储，像如下的例子 var storage = window.localStorage; storage.a = "haha"; storage["b"] = "hehe"; var a = storage.a; var b = storage["b"]; 另外，localStorage还提供了一个key()方法，配合localStorage的length属性，可以在不知道有哪些键值的时候使用，如下： var storage = window.localStorage; function showStorage(){ for(var i=0;i&#60;storage.length;i++){ //key(i)获得相应的键，再用getItem()方法获得对应的值 &#8230; <a href="http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>localStorage顾名思义，就是本地存储的意思，在以前很长一段时间，要想在客户端存储一些配置及登录信息等数据都只能通过COOKIE或flash的方式，如今html5来临，也带来了更强大的本地存储，最多可存储大小5M的字符串，足可以满足大部分的web应用，比cookie的4K要大出不少，还有一个sessionStorage，功能基本与localStorage相同，看名字便知与sesstion一样，关闭浏览器即失效。</p>
<p>以前有用过cookie的都了解cookie的存储读取方式都不太优雅，需要自己封装set get方法，而localStorage则方便许多，localStorage 是作為window的一个属性存在的，拥有setItem,getItem,removeItem,clear等方法，相当方便。</p>
<p>浏览器的支持除了IE７及以下不支持外，其他标准浏览器都完全支持(ie及FF需在web服务器里运行)，支持情况如下图：<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2011/03/1375849686163397167.jpg"><img src="http://www.ueder.net/wp-content/uploads/2011/03/1375849686163397167.jpg" alt="" title="1375849686163397167" width="637" height="152" class="alignnone size-full wp-image-667" /></a></p>
<p>如下代码即可判断浏览器是否支持</p>
<pre class="prettyprint">
if(window.localStorage){
    alert("浏览支持localStorage")
}else{
   alert("浏览暂不支持localStorage")
}
</pre>
<p><span id="more-666"></span><br />
localStorage不但可以用自身的setItem,getItem等方便存取，也可以像普通对象一样用点操作符，及[]的方式进行数据存储，像如下的例子</p>
<pre class="prettyprint">
var storage = window.localStorage;
storage.a = "haha";
storage["b"] = "hehe";
var a = storage.a;
var b = storage["b"];
</pre>
<p>另外，localStorage还提供了一个key()方法，配合localStorage的length属性，可以在不知道有哪些键值的时候使用，如下：</p>
<pre class="prettyprint">
var storage = window.localStorage;
function showStorage(){
 for(var i=0;i&lt;storage.length;i++){
  //key(i)获得相应的键，再用getItem()方法获得对应的值
  document.write(storage.key(i)+ " : " + storage.getItem(storage.key(i)) + "&lt;br&gt;");
 }
}
</pre>
<p>FF里storage.key(i) == storage[i], 算个BUG吧</p>
<p>HTML5的本地存储，还提供了一个storage事件，可以对键值对的改变进行监听，使用方法如下：</p>
<pre class="prettyprint">
if(window.addEventListener){
 window.addEventListener("storage",handle_storage,false);
}else if(window.attachEvent){
 window.attachEvent("onstorage",handle_storage);
}
function handle_storage(e){
 if(!e){e=window.event;}
 //showStorage();
}
</pre>
<p>对于事件变量e，是一个StorageEvent对象，提供了一些实用的属性，可以很好的观察键值对的变化，如下表：</p>
<table width="100%" border="1">
<tr>
<td> Property
  </td>
<td> Type
  </td>
<td> Description
  </td>
</tr>
<tr>
<td>key
  </td>
<td>String
  </td>
<td> The named key that was added, removed, or moddified
  </td>
</tr>
<tr>
<td>oldValue
  </td>
<td>	 Any
  </td>
<td> The previous value(now overwritten), or null if a new item was added
  </td>
</tr>
<tr>
<td>newValue
  </td>
<td>	 Any
  </td>
<td>	 The new value, or null if an item was added
  </td>
</tr>
<tr>
<td> url/uri
  </td>
<td>String
  </td>
<td>The page that called the method that triggered this change
  </td>
</tr>
</table>
<p>写一个最简单的，利用本地存储的计数器，有一个需要注意的地方是不管setItem里传什么类型，最终都会被转成string，所以getItem的时候需要转类型：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_OCpxE8">
&lt;!doctype HTML&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body &gt;
&lt;div id=&quot;c&quot;&gt;&lt;/div&gt;
 &lt;script&gt;
var storage = window.localStorage;
if(!storage.getItem(&quot;num&quot;)){
	storage.setItem(&quot;num&quot;,0);
}
var n = parseInt(storage.getItem(&quot;num&quot;))+1;
storage.setItem(&quot;num&quot;,n);
document.getElementById(&quot;c&quot;).innerHTML = &quot;这里显示的是计数结果：&quot; + n;
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_OCpxE8").style.height = document.getElementById("runcode_OCpxE8").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_OCpxE8');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_OCpxE8');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_OCpxE8','runcode_OCpxE8');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

