<?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>小强ORG</title>
	<atom:link href="http://www.xiaoqiang.org/feed" rel="self" type="application/rss+xml" />
	<link>http://www.xiaoqiang.org</link>
	<description>关注web前端开发&#124;web性能&#124;NodeJs&#124;用户体验&#124;交互设计</description>
	<lastBuildDate>Thu, 26 Apr 2012 01:23:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>android用phonegap实现websocket</title>
		<link>http://www.xiaoqiang.org/mobile-web/android-websocket-phonegap.html</link>
		<comments>http://www.xiaoqiang.org/mobile-web/android-websocket-phonegap.html#comments</comments>
		<pubDate>Tue, 24 Apr 2012 08:34:21 +0000</pubDate>
		<dc:creator>小强</dc:creator>
				<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[phonegap]]></category>
		<category><![CDATA[websocket]]></category>

		<guid isPermaLink="false">http://www.xiaoqiang.org/?p=653</guid>
		<description><![CDATA[由于android浏览器是不支持websocket的，想到了phonegap，包一层外壳使用android的socketChannel进行socket通信。当然，别人已经写好一个插件https://github.com/anismiles/websocket-android-phonegap 支持草案76和75,标准兼容性暂未测试 服务端用的小胖写的GT-WebSocketServer ====分隔线====== X10i/android2.3.3系统模拟器会关掉程序，真机会抛出一个socket连接错误。 miui android2.3.7,android2.1和4.0模拟器测试通过 =====分隔线===== 1，隔一段时间自动断开，服务器端的close事件也是异常的，并没有关闭phonegap连接的session。 待续]]></description>
			<content:encoded><![CDATA[<p>由于android浏览器是不支持websocket的，想到了phonegap，包一层外壳使用android的socketChannel进行socket通信。当然，别人已经写好一个插件<a title="websocket-android-phonegap" href="https://github.com/anismiles/websocket-android-phonegap" target="_blank">https://github.com/anismiles/websocket-android-phonegap</a> 支持草案76和75,标准兼容性暂未测试<br />
服务端用的小胖写的<a title="GT-WebSocketServer" href="https://github.com/finscn/GT-WebSocketServer" target="_blank">GT-WebSocketServer</a><br />
====分隔线======<br />
X10i/android2.3.3系统模拟器会关掉程序，真机会抛出一个socket连接错误。<br />
miui android2.3.7,android2.1和4.0模拟器测试通过<br />
=====分隔线=====<br />
1，隔一段时间自动断开，服务器端的close事件也是异常的，并没有关闭phonegap连接的session。</p>
<p>待续</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xiaoqiang.org/mobile-web/android-websocket-phonegap.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>backbone.js实例Todo阅读笔记</title>
		<link>http://www.xiaoqiang.org/javascript/backbone-js-todo.html</link>
		<comments>http://www.xiaoqiang.org/javascript/backbone-js-todo.html#comments</comments>
		<pubDate>Fri, 13 Apr 2012 06:50:36 +0000</pubDate>
		<dc:creator>小强</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[backbone]]></category>
		<category><![CDATA[todo]]></category>

		<guid isPermaLink="false">http://www.xiaoqiang.org/?p=648</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<pre class="brush: jscript; title: ; notranslate">
// 一个backbone的实例，作者：
// [Jérôme Gravel-Niquet](http://jgn.me/). 这个demo使用了
// [LocalStorage adapter](backbone-localstorage.js)
// 你可以在浏览器中演示它.

//当DOM载入完之后加载应用:
$(function() {

    // Todo Model
    // 基础 **Todo** model 拥有 `title`, `order`, 和 `done` 属性.
    var Todo = Backbone.Model.extend({

        // todo的默认属性.
        defaults : {
            title : &quot;empty todo...&quot;,
            done : false
        },

        // 保证每个model创建的时候都有`title`.
        initialize : function() {
            if(!this.get(&quot;title&quot;)) {
                this.set({
                    &quot;title&quot; : this.defaults.title
                });
            }
        },
        // 切换`done`状态.
        toggle : function() {
            this.save({
                done : !this.get(&quot;done&quot;)
            });
        },
        // 将Todo从*localStorage*和视图中删除.
        clear : function() {
            this.destroy();
        }
    });

    // Todo 列表
    // ---------------

    // 列表存储在*localStorage*中，代替存储在服务器中
    var TodoList = Backbone.Collection.extend({

        // 关联列表的 model.
        model : Todo,

        // 以`&quot;todos&quot;`名字空间保存所有Todo.
        localStorage : new Store(&quot;todos-backbone&quot;),

        // 过滤已完成的Todo.
        done : function() {
            return this.filter(function(todo) {
                return todo.get('done');
            });
        },
        // 过滤列表，保留未完成的Todo.
        remaining : function() {
            return this.without.apply(this, this.done());
        },
        // 尽管我们在localStorage中是无序存储的，但是我们还是按顺序读取和保存的
        nextOrder : function() {
            if(!this.length)
                return 1;
            return this.last().get('order') + 1;
        },
        // 按照原来的顺序保存.
        comparator : function(todo) {
            return todo.get('order');
        }
    });

    // 创建一个全局列表 **Todos**.
    var Todos = new TodoList;

    // Todo Item View
    // --------------

    // todo item的DOM元素
    var TodoView = Backbone.View.extend({

        //列表标签.
        tagName : &quot;li&quot;,

        // 为单个元素缓存模板.
        template : _.template($('#item-template').html()),

        // 单个元素的DOM事件.
        events : {
            &quot;click .toggle&quot; : &quot;toggleDone&quot;,
            &quot;dblclick .view&quot; : &quot;edit&quot;,
            &quot;click a.destroy&quot; : &quot;clear&quot;,
            &quot;keypress .edit&quot; : &quot;updateOnEnter&quot;,
            &quot;blur .edit&quot; : &quot;close&quot;
        },

        // TodoView视图监听 model的事件变化,重新渲染, **Todo** 和 **TodoView** 成一一对应的关系.
        initialize : function() {
            this.model.bind('change', this.render, this);
            this.model.bind('destroy', this.remove, this);
        },
        // 重新渲染单条todo的title.
        render : function() {
            var $el = $(this.el);
            $el.html(this.template(this.model.toJSON()));
            $el.toggleClass('done', this.model.get('done'));

            this.input = this.$('.edit');
            return this;
        },
        // 切换model的`&quot;done&quot;`状态.
        toggleDone : function() {
            this.model.toggle();
        },
        // 切换视图为`&quot;editing&quot;`,显示输入框.
        edit : function() {
            $(this.el).addClass(&quot;editing&quot;);
            this.input.focus();
        },
        // 关闭`&quot;editing&quot;`视图, 保存改变数据到Todo.
        close : function() {
            var value = this.input.val().trim();

            if(!value)
                this.clear();

            this.model.save({
                title : value
            });
            $(this.el).removeClass(&quot;editing&quot;);
        },
        // 如果输入 `enter`回车键, 保存编辑项目.
        updateOnEnter : function(e) {
            if(e.keyCode == 13)
                this.close();
        },
        // 移除单条Todo，销毁model.
        clear : function() {
            this.model.clear();
        }
    });

    // The Application
    // ---------------

    // **AppView**是最外层层UI.
    var AppView = Backbone.View.extend({

        // 使用页面上已有的HTML结构.
        el : $(&quot;#todoapp&quot;),

        // app底部统计的模板.
        statsTemplate : _.template($('#stats-template').html()),

        // 为新建Todo和清除已完成Todo创建事件代理.
        events : {
            &quot;keypress #new-todo&quot; : &quot;createOnEnter&quot;,
            &quot;click #clear-completed&quot; : &quot;clearCompleted&quot;,
            &quot;click #toggle-all&quot; : &quot;toggleAllComplete&quot;
        },

        // 初始化的时候绑定 `Todos`列表的事件，add事件会添加到 *localStorage*.
        initialize : function() {

            this.input = this.$(&quot;#new-todo&quot;);
            this.allCheckbox = this.$(&quot;#toggle-all&quot;)[0];

            Todos.bind('add', this.addOne, this);
            Todos.bind('reset', this.addAll, this);
            Todos.bind('all', this.render, this);

            this.$footer = this.$('footer');
            this.$main = $('#main');

            Todos.fetch();
        },
        // 重新渲染只是刷新统计，其他不变.
        render : function() {
            var done = Todos.done().length;
            var remaining = Todos.remaining().length;

            if(Todos.length) {
                this.$main.show();
                this.$footer.show();

                this.$footer.html(this.statsTemplate({
                    done : done,
                    remaining : remaining
                }));
            } else {
                this.$main.hide();
                this.$footer.hide();
            }

            this.allCheckbox.checked = !remaining;
        },
        // 添加一个Todo项，并插入到`&lt;ul&gt;`中.
        addOne : function(todo) {
            var view = new TodoView({
                model : todo
            });
            this.$(&quot;#todo-list&quot;).append(view.render().el);
        },
        // 一次把所有的Todo添加到 **Todos** 列表中.
        addAll : function() {
            Todos.each(this.addOne);
        },
        // 新建一个Todo赋予属性.
        newAttributes : function() {
            return {
                title : this.input.val().trim(),
                order : Todos.nextOrder(),
                done : false
            };
        },
        // 在input中按回车键会新建一个**Todo** model并且保存到*localStorage*.
        createOnEnter : function(e) {
            if(e.keyCode != 13)
                return;
            if(!this.input.val().trim())
                return;

            Todos.create(this.newAttributes());
            this.input.val('');
        },
        // 清除所有已完成Todo models.
        clearCompleted : function() {
            _.each(Todos.done(), function(todo) {
                todo.clear();
            });
            return false;
        },
        toggleAllComplete : function() {
            var done = this.allCheckbox.checked;
            Todos.each(function(todo) {
                todo.save({
                    'done' : done
                });
            });
        }
    });

    // 创建一个 **App**.
    var App = new AppView;
});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xiaoqiang.org/javascript/backbone-js-todo.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>nodejs资源打包下载优化</title>
		<link>http://www.xiaoqiang.org/nodejs/nodejs-zip.html</link>
		<comments>http://www.xiaoqiang.org/nodejs/nodejs-zip.html#comments</comments>
		<pubDate>Wed, 11 Apr 2012 09:32:45 +0000</pubDate>
		<dc:creator>小强</dc:creator>
				<category><![CDATA[Nodejs]]></category>
		<category><![CDATA[zip]]></category>

		<guid isPermaLink="false">http://www.xiaoqiang.org/?p=637</guid>
		<description><![CDATA[幸得点睛老辜笔，打包请求双变单！ 之前做webslide在线设计的小工具就有一个打包下载的功能。使用了node-native-zip模块，原本实现的思路是分两步： 发起一次请求在服务端把资源打包成name.zip的文件（打包）； 再发起一个普通的get请求获取name.zip的文件（下载）； 代码片断如下： 然后用普通的http请求name.zip文件下载到本地。 然后来看看第二种方式，设置contentType为application/zip先输出请求头，并且识别为zip文件。然后打包文件一遍读buffer一边输出请求正文，使用了zipstream模块，通过管道输出。 代码片断如下： 第二种方式的好处是： 请求立即下载，不需要二次请求； 数据只在内存中操作，不进行硬盘的IO操作； 下载是实时的，不需要缓存数据，更不需要维护硬盘的缓存区； 管道会自动限速，以速度慢的那一头为准； 可以并发成千上万的下载量，每个时间点只有少来资源被占用。 参考文献：Why node.js streams are awesome]]></description>
			<content:encoded><![CDATA[<p>幸得点睛老辜笔，打包请求双变单！</p>
<p>之前做<a title="webslide在线设计" href="http://webslide.cnodejs.net/" target="_blank">webslide在线设计</a>的小工具就有一个打包下载的功能。使用了<a title="node-native-zip" href="https://github.com/janjongboom/node-native-zip" target="_blank">node-native-zip</a>模块，原本实现的思路是分两步：</p>
<ol>
<li>发起一次请求在服务端把资源打包成name.zip的文件（打包）；</li>
<li>再发起一个普通的get请求获取name.zip的文件（下载）；</li>
</ol>
<p>代码片断如下：</p>
<pre class="brush: jscript; title: ; notranslate">
app.get('/zip/:sid', function(req, res) {
    var archive = new zip();
    archive.addFiles([{
        name : '...',
        path : '...'
    }], function(err) {
        if(err) {
            res.write('0');
            throw err;
        } else {
            var buff = archive.toBuffer();
            fs.writeFile('public/zip/name.zip', buff, function(err) {
                if(err) {
                    res.write('0');
                    throw err;
                } else {
                    console.log('name.zip Finished');
                    res.write('1');

                }
            });
        }
        res.end();
    });
});
</pre>
<p>然后用普通的http请求name.zip文件下载到本地。</p>
<p>然后来看看第二种方式，设置contentType为application/zip先输出请求头，并且识别为zip文件。然后打包文件一遍读buffer一边输出请求正文，使用了<a title="zipstream" href="https://github.com/wellawaretech/node-zipstream" target="_blank">zipstream</a>模块，通过管道输出。<br />
代码片断如下：</p>
<pre class="brush: jscript; title: ; notranslate">
app.get('/zip/:sid', function(req, res) {
    var zip = zipstream.createZip({ level: 1 });
    zip.addFile(fs.createReadStream('...'), { name: '...' }, function() {
        zip.finalize(function(written) { console.log(written + ' total bytes written'); });
    });
    res.header('Content-Disposition', 'attachment;filename=' + sid + '.zip');
    res.contentType('application/zip');
    zip.pipe(res);
});
</pre>
<p>第二种方式的好处是：</p>
<ol>
<li>请求立即下载，不需要二次请求；</li>
<li>数据只在内存中操作，不进行硬盘的IO操作；</li>
<li>下载是实时的，不需要缓存数据，更不需要维护硬盘的缓存区；</li>
<li>管道会自动限速，以速度慢的那一头为准；</li>
<li>可以并发成千上万的下载量，每个时间点只有少来资源被占用。</li>
</ol>
<p>参考文献：<a title="Why node.js streams are awesome" href="http://blog.dump.ly/post/19819897856/why-node-js-streams-are-awesome" target="_blank">Why node.js streams are awesome</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.xiaoqiang.org/nodejs/nodejs-zip.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于box-flex的一些讨论结果</title>
		<link>http://www.xiaoqiang.org/css/box-flex.html</link>
		<comments>http://www.xiaoqiang.org/css/box-flex.html#comments</comments>
		<pubDate>Fri, 10 Feb 2012 03:36:30 +0000</pubDate>
		<dc:creator>小强</dc:creator>
				<category><![CDATA[Css]]></category>
		<category><![CDATA[box-flex]]></category>
		<category><![CDATA[css3]]></category>

		<guid isPermaLink="false">http://www.xiaoqiang.org/?p=609</guid>
		<description><![CDATA[今天在群里和@6key同学还有@qbaty同学一起讨论了一下关于box-flex的宽度设置问题。 @6key同学提出的最原始的代码如下： demo地址：http://debug.cnodejs.net/html/1328843547100.html 问题是当.box &#62; div的内容宽度不一样的时候，三个div并不是均分。 解决方式在.box &#62; div中加上宽度即可，任何有效数值都行。只需保证.box下的子div宽度相等即可 但是问题又来了1动画没有了，2鼠标移上去div的宽度很怪异； 讨论得出的解决方案是： .box &#62; div的宽度单位要和.box &#62; div:hover的宽度单位一致，要么都是%要么都是px，否则没有动画； .box &#62; div的宽度值相等，可以随意设置，每列就可以等宽； 根据实践得出，当3个div的宽度不一致（例如hover的时候）只有当3个div的总宽=box的宽度才回正确显示。如果3个div大于或者小于box宽度，三个div都会按照一定规则缩放，具体规则还有待研究。动手试试：http://debug.cnodejs.net/1328861122371]]></description>
			<content:encoded><![CDATA[<p>今天在群里和@6key同学还有<a href="http://weibo.com/qbaty" target="_blank">@qbaty</a>同学一起讨论了一下关于box-flex的宽度设置问题。</p>
<p>@6key同学提出的最原始的代码如下：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;box&lt;/title&gt;
    &lt;style type=&quot;text/css&quot;&gt;
        .box {
            /* basic styling */
            width: 300px;
            height: 95px;
            border: 1px solid #555;
            font: 14px Arial;

            /* flexbox setup */
            display: -webkit-box;
            -webkit-box-orient: horizontal;

            display: -moz-box;
            -moz-box-orient: horizontal;

            display: box;
            box-orient: horizontal;
        }

        .box &gt; div {
            -webkit-box-flex: 1;
            -moz-box-flex: 1;
            box-flex: 1;
            /*width:100px;*/
            -moz-transition: width 0.7s ease-out;
            -o-transition: width 0.7s ease-out;
            -webkit-transition: width 0.7s ease-out;
            transition: width 0.7s ease-out;
        }

            /* our colors */
        .box &gt; div:nth-child(1){ background : #FCC; }
        .box &gt; div:nth-child(2){ background : #CFC; }
        .box &gt; div:nth-child(3){ background : #CCF; }

        .box &gt; div:hover {
            width:200px;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class=&quot;box&quot;&gt;
    &lt;div&gt;deuxssssss&lt;/div&gt;
    &lt;div&gt;deux&lt;/div&gt;
    &lt;div&gt;deux&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>demo地址：<a href="http://debug.cnodejs.net/html/1328843547100.html" target="_blank">http://debug.cnodejs.net/html/1328843547100.html</a></p>
<p>问题是当.box &gt; div的内容宽度不一样的时候，三个div并不是均分。</p>
<p><strong>解决方式在.box &gt; div中加上宽度即可，任何有效数值都行。只需保证.box下的子div宽度相等即可</strong></p>
<p>但是问题又来了1动画没有了，2鼠标移上去div的宽度很怪异；</p>
<p>讨论得出的解决方案是：</p>
<ol>
<li>.box &gt; div的宽度单位要和.box &gt; div:hover的宽度单位一致，要么都是%要么都是px，否则没有动画；</li>
<li>.box &gt; div的宽度值相等，可以随意设置，每列就可以等宽；</li>
<li>根据实践得出，当3个div的宽度不一致（例如hover的时候）只有当3个div的总宽=box的宽度才回正确显示。如果3个div大于或者小于box宽度，三个div都会按照一定规则缩放，具体规则还有待研究。动手试试：<a href="http://debug.cnodejs.net/1328861122371" target="_blank">http://debug.cnodejs.net/1328861122371</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.xiaoqiang.org/css/box-flex.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>debug&#8211;在线代码调试工具</title>
		<link>http://www.xiaoqiang.org/mobile-web/debug-online.html</link>
		<comments>http://www.xiaoqiang.org/mobile-web/debug-online.html#comments</comments>
		<pubDate>Fri, 23 Dec 2011 03:07:05 +0000</pubDate>
		<dc:creator>小强</dc:creator>
				<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[codebox]]></category>
		<category><![CDATA[debug]]></category>

		<guid isPermaLink="false">http://www.xiaoqiang.org/?p=589</guid>
		<description><![CDATA[工具地址:http://debug.cnodejs.net 这个工具主要是为群里面同学们的提问发代码用的，webapp开发可以方便js调试。 主要功能点： 分享代码，仅支持html,javascript,css； 代码高亮 生成可运行的html文件 支持手机访问运行页面，生成二维码文件地址； 支持手机访问的console信息打印在pc的控制台,需要添加一段js，并且调用wa.log() 项目地址：https://github.com/xiaoqiang/debug]]></description>
			<content:encoded><![CDATA[<p>工具地址:<a href="http://debug.cnodejs.net/" title="在线debug工具" target="_blank">http://debug.cnodejs.net</a><br />
这个工具主要是为群里面同学们的提问发代码用的，webapp开发可以方便js调试。<br />
<strong>主要功能点</strong>：</p>
<ul>
<li>分享代码，仅支持html,javascript,css；</li>
<li>代码高亮</li>
<li>
生成可运行的html文件</li>
<li>支持手机访问运行页面，生成二维码文件地址；</li>
<li>支持手机访问的console信息打印在pc的控制台,需要添加一段js，并且调用wa.log()</li>
</ul>
<p>项目地址：<a href="https://github.com/xiaoqiang/debug" title="https://github.com/xiaoqiang/debug" target="_blank">https://github.com/xiaoqiang/debug</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.xiaoqiang.org/mobile-web/debug-online.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

