<?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>Here comes the Sun &#187; web</title>
	<atom:link href="http://sunng.info/blog/tag/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://sunng.info/blog</link>
	<description>47% users on this site use *nix</description>
	<lastBuildDate>Sat, 04 Feb 2012 13:08:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Clojure on CloudFoundry</title>
		<link>http://sunng.info/blog/2012/01/clojure-on-cloudfoundry/</link>
		<comments>http://sunng.info/blog/2012/01/clojure-on-cloudfoundry/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 13:31:55 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[cloudfoundry]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1139</guid>
		<description><![CDATA[In this article, I will show you how to develop and deploy clojure web application on CloudFoundry. As you may know, CloudFoundry is an opensource PaaS backed by VMWare. Java, Ruby and Nodejs are officially supported. As a JVM language, &#8230; <a href="http://sunng.info/blog/2012/01/clojure-on-cloudfoundry/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In this article, I will show you how to develop and deploy clojure web application on CloudFoundry. As you may know, CloudFoundry is an opensource PaaS backed by VMWare. Java, Ruby and Nodejs are officially supported. As a JVM language, clojure is born to be also available on this platform, although it&#8217;s not listed. </p>
<p>CloudFoundry accepts a .war file for Java web application deployment. So you don&#8217;t need the ring-jetty-adaptor and a procfile as heroku requires. To help your development and deployment, I strongly recommend the lein-ring plugin:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; :<span style="color: #555;">dev</span><span style="color: #66cc66;">-</span>dependencies <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>lein<span style="color: #66cc66;">-</span>ring <span style="color: #ff0000;">&quot;0.5.4&quot;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span></div></div>
<p>CloudFoundry provides backend services like mysql, redis, mongodb and more. The connection information are stored as environment variables. <a href="http://env.cloudfoundry.com/env" target="_blank">Here</a> you can find a subset of them. </p>
<p>Take mongodb as example, connection information (host, port, username and password) are encoded as JSON, stored in environment variables. You can get them with this function:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defn</span> mongo<span style="color: #66cc66;">-</span>config <span style="color: #66cc66;">&#91;</span>key<span style="color: #66cc66;">&#93;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if-let</span> <span style="color: #66cc66;">&#91;</span>services <span style="color: #66cc66;">&#40;</span>System<span style="color: #66cc66;">/</span>getenv <span style="color: #ff0000;">&quot;VCAP_SERVICES&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>services<span style="color: #66cc66;">-</span>dict <span style="color: #66cc66;">&#40;</span>json<span style="color: #66cc66;">/</span>read<span style="color: #66cc66;">-</span>json services false<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">-&gt;</span> services<span style="color: #66cc66;">-</span>dict<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>get <span style="color: #ff0000;">&quot;mongodb-1.8&quot;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">first</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>get <span style="color: #ff0000;">&quot;credentials&quot;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>get key<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>In the server bootstrap function, create the mongodb connection:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defn</span> app<span style="color: #66cc66;">-</span>init <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">def</span> db<span style="color: #66cc66;">-</span>conn <span style="color: #66cc66;">&#40;</span>make<span style="color: #66cc66;">-</span>connection<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">or</span> <span style="color: #66cc66;">&#40;</span>mongo<span style="color: #66cc66;">-</span>config <span style="color: #ff0000;">&quot;db&quot;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #ff0000;">&quot;lazypress&quot;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:<span style="color: #555;">host</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">or</span> <span style="color: #66cc66;">&#40;</span>mongo<span style="color: #66cc66;">-</span>config <span style="color: #ff0000;">&quot;hostname&quot;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #ff0000;">&quot;localhost&quot;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:<span style="color: #555;">port</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">or</span> <span style="color: #66cc66;">&#40;</span>mongo<span style="color: #66cc66;">-</span>config <span style="color: #ff0000;">&quot;port&quot;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">27017</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when-not</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">nil?</span> <span style="color: #66cc66;">&#40;</span>mongo<span style="color: #66cc66;">-</span>config <span style="color: #ff0000;">&quot;username&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>authenticate db<span style="color: #66cc66;">-</span>conn<br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>mongo<span style="color: #66cc66;">-</span>config <span style="color: #ff0000;">&quot;username&quot;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>mongo<span style="color: #66cc66;">-</span>config <span style="color: #ff0000;">&quot;password&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>By adding check for nil, local databased is also supported. This is pretty convenience for local development. These environment variables are consistent on all cloudfoundry application, so it&#8217;s possible to deploy the application on multiple accounts without any changes.</p>
<p>Then you can add your web stuff just like standard clojure web development. (If you are using compojure, place your static files under resource/public.)</p>
<p>Finally, package it. (Suppose your application is named as &#8220;lazypress&#8221;)</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">lein ring uberwar lazypress.war</div></div>
<p>Use the vmc tool to deploy it:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">vmc update lazypress</div></div>
<p>For more usage about the vmc tool, you can read <a href="http://blog.cloudfoundry.com/post/13481010498/simplified-application-deployment-with-cloud-foundry-manifest" target="_blank">this article</a>.</p>
<p>So you have finished deploying your clojure web application to cloudfoundry.</p>
<p>Backed by spring and vmware, cloudfoundry is more Java-friendly than other PaaS like heroku. You don&#8217;t have to start a Java process by yourself (&#8220;lein run&#8221; isn&#8217;t a graceful way to start your app in product environment). And you don&#8217;t have to worry about your web container settings (configure jetty with limited options via ring-jetty-adaptor). All you have to do is package the application as a portable war file, which you can deploy to tomcat, glassfish, and also cloudfoundry. The vmc tool could detect you war file and handle it correctly.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/01/clojure-on-cloudfoundry/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Weekend Project: LazyPress</title>
		<link>http://sunng.info/blog/2012/01/weekend-project-lazypress/</link>
		<comments>http://sunng.info/blog/2012/01/weekend-project-lazypress/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 07:40:01 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[cloudfoundry]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1134</guid>
		<description><![CDATA[发布一个典型的weekend project, 名字叫做LazyPress.顾名思义,这是一个在线的写作系统. 取名Lazy, 除了因为它用Clojure写成,更因为他的简单: 没有繁琐的注册,没有繁琐的分类tag,没有繁琐的格式化,无论是使用还是开发都力求做到最简单. LazyPress采用Mozilla刚刚发布的BrowserID. 技术作为账号系统, 用户只需要在首次登录后提供一个ID即可(原本这一步也可以省略, 但是为了保护您的邮箱隐私, 现在需要一个LazyPress专用的ID). 这样LazyPress本身不存储用户的密码,也简化了用户账号管理的代价. BrowserID的登录流程非常简单, 速度也比传统的OpenID和OAuth要快, 用户体验要比多次跳转好很多. LazyPress使用Markdown进行文本格式化, 简单的编辑器可以支持绝大多数格式的要求. 另外,在浏览器后台LazyPress使用HTML5 LocalStorage技术自动保存用户的文本草稿, 如果用户没有成功发布, 可以在下次浏览器打开时进行恢复. LazyPress后台存储采用mongodb. 正是mongodb的schema free特性降低了项目功能重构的成本, 促进了人们更快更频繁地优化产品的模型. 这应该是文档型数据库之于传统关系型数据库最大的优势. (犹如git之于svn, 开分支的成本要低得多, 看似是一个普通的功能改进, 实则鼓励促进了开发人员通过开分支实现自己的修改) LazyPress运行在最近发布的compojure 1.0.0和ring 1.0.0上, 打包为标准的Java web应用直接部署在cloudfoundry上. 前端继续使用的是我偏爱的Mootools库, 因为使用了很多新的浏览器技术, 所以目前只能保证在最新的Firefox和Chromium/Chrome上正常使用. Fork me &#8230; <a href="http://sunng.info/blog/2012/01/weekend-project-lazypress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>发布一个典型的weekend project, 名字叫做<a href="http://lazypress.cloundfoundry.com">LazyPress</a>.顾名思义,这是一个在线的写作系统. 取名Lazy, 除了因为它用Clojure写成,更因为他的简单: 没有繁琐的注册,没有繁琐的分类tag,没有繁琐的格式化,无论是使用还是开发都力求做到最简单.<br />
LazyPress采用Mozilla刚刚发布的<a href="http://browserid.org/">BrowserID</a>. 技术作为账号系统, 用户只需要在首次登录后提供一个ID即可(原本这一步也可以省略, 但是为了保护您的邮箱隐私, 现在需要一个LazyPress专用的ID). 这样LazyPress本身不存储用户的密码,也简化了用户账号管理的代价. BrowserID的登录流程非常简单, 速度也比传统的OpenID和OAuth要快, 用户体验要比多次跳转好很多.<br />
LazyPress使用Markdown进行文本格式化, 简单的编辑器可以支持绝大多数格式的要求. 另外,在浏览器后台LazyPress使用HTML5 LocalStorage技术自动保存用户的文本草稿, 如果用户没有成功发布, 可以在下次浏览器打开时进行恢复.</p>
<p>LazyPress后台存储采用mongodb. 正是mongodb的schema free特性降低了项目功能重构的成本, 促进了人们更快更频繁地优化产品的模型. 这应该是文档型数据库之于传统关系型数据库最大的优势. (犹如git之于svn, 开分支的成本要低得多, 看似是一个普通的功能改进, 实则鼓励促进了开发人员通过开分支实现自己的修改)<br />
LazyPress运行在最近发布的compojure 1.0.0和ring 1.0.0上, 打包为标准的Java web应用直接部署在cloudfoundry上. 前端继续使用的是我偏爱的Mootools库, 因为使用了很多新的浏览器技术, 所以目前只能保证在最新的Firefox和Chromium/Chrome上正常使用.</p>
<p>Fork me on github: <a href="http://github.com/sunng87/lazypress">http://github.com/sunng87/lazypress</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/01/weekend-project-lazypress/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>使用Enlive作为模板引擎</title>
		<link>http://sunng.info/blog/2011/12/%e4%bd%bf%e7%94%a8enlive%e4%bd%9c%e4%b8%ba%e6%a8%a1%e6%9d%bf%e5%bc%95%e6%93%8e/</link>
		<comments>http://sunng.info/blog/2011/12/%e4%bd%bf%e7%94%a8enlive%e4%bd%9c%e4%b8%ba%e6%a8%a1%e6%9d%bf%e5%bc%95%e6%93%8e/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 13:13:19 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1125</guid>
		<description><![CDATA[在所有的clojure web开发例子里，对模板的介绍都很少。很多的简单例子都是以hiccup作为页面生成的手段。hiccup是个clojure的html DSL，例子里用这样的DSL生成页面确实很酷，可是他是real world吗，当然不是。 好在clojure世界里早就有了enlive，它不仅是一个通过css selector解析html的库，本身也可以作为模板引擎应用在web开发中。我不知道这种通过css selector的方式是否是enlive首创，不过他实在是非常新颖独特，而且平滑了页面设计和程序的集成。 例如这样一个模板 index.html： &#60;div id=&#34;cc&#34;&#62;Sample Text&#60;/div&#62; 在clojure程序中，使用enlive的deftemplate &#40;deftemplate index &#34;index.html&#34; &#160; &#91;ctx&#93; &#160; &#91;:div#cc&#93; &#40;content &#40;:data ctx&#41;&#41;&#41; 在控制器里，可以很MVC地渲染页面 &#40;index &#123;:data &#34;rendered text&#34;&#125;&#41; 除了content用于渲染文本，还有html-content可以渲染含html标签的内容，以及set-attr用来修改页面元素的属性。 和传统的模板引擎相比，最大的不同是enlive里没有嵌入模板的直观的控制流，没有循环和条件判断，但是并非不可实现。 循环输出一组list 页面 list.html &#60;ul id=&#34;the-list&#34;&#62; &#60;li class=&#34;list-item&#34;&#62;&#60;/li&#62; &#60;/ul&#62; 定义一个enlive的snippet &#40;defsnippet &#8230; <a href="http://sunng.info/blog/2011/12/%e4%bd%bf%e7%94%a8enlive%e4%bd%9c%e4%b8%ba%e6%a8%a1%e6%9d%bf%e5%bc%95%e6%93%8e/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>在所有的clojure web开发例子里，对模板的介绍都很少。很多的简单例子都是以hiccup作为页面生成的手段。hiccup是个clojure的html DSL，例子里用这样的DSL生成页面确实很酷，可是他是real world吗，当然不是。</p>
<p>好在clojure世界里早就有了enlive，它不仅是一个通过css selector解析html的库，本身也可以作为模板引擎应用在web开发中。我不知道这种通过css selector的方式是否是enlive首创，不过他实在是非常新颖独特，而且平滑了页面设计和程序的集成。</p>
<p>例如这样一个模板 index.html：</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;cc&quot;</span>&gt;</span>Sample Text<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div>
<p>在clojure程序中，使用enlive的deftemplate</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>deftemplate index <span style="color: #ff0000;">&quot;index.html&quot;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>ctx<span style="color: #66cc66;">&#93;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>:<span style="color: #555;">div</span>#cc<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>content <span style="color: #66cc66;">&#40;</span>:<span style="color: #555;">data</span> ctx<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>在控制器里，可以很MVC地渲染页面</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>index <span style="color: #66cc66;">&#123;</span>:<span style="color: #555;">data</span> <span style="color: #ff0000;">&quot;rendered text&quot;</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>除了content用于渲染文本，还有html-content可以渲染含html标签的内容，以及set-attr用来修改页面元素的属性。</p>
<p>和传统的模板引擎相比，最大的不同是enlive里没有嵌入模板的直观的控制流，没有循环和条件判断，但是并非不可实现。</p>
<p>循环输出一组list</p>
<p>页面 list.html</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;the-list&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;list-item&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span></div></div>
<p>定义一个enlive的snippet</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>defsnippet item<span style="color: #66cc66;">-</span>model <span style="color: #ff0000;">&quot;page.html&quot;</span> <span style="color: #66cc66;">&#91;</span>:<span style="color: #66cc66;">.</span>list<span style="color: #66cc66;">-</span>item<span style="color: #66cc66;">&#93;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>ctx<span style="color: #66cc66;">&#93;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>:<span style="color: #66cc66;">.</span>list<span style="color: #66cc66;">-</span>item<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>content <span style="color: #66cc66;">&#40;</span>:<span style="color: #555;">data</span> ctx<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>在页面模板里</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>deftemplate list<span style="color: #66cc66;">-</span>page <span style="color: #ff0000;">&quot;list.html&quot;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>ctx<span style="color: #66cc66;">&#93;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>:<span style="color: #555;">ul</span>#the<span style="color: #66cc66;">-</span>list<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>content <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">map</span> item<span style="color: #66cc66;">-</span>model <span style="color: #66cc66;">&#40;</span>:<span style="color: #555;">some</span><span style="color: #66cc66;">-</span>list ctx<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>这样在页面里列表项会被循环输出，而在页面设计时这里可以放任意个li，并且直接交给后台作为模板。</p>
<p>条件判断</p>
<p>页面，设计时显示所有的内容 msg.html</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;msg&quot;</span>&gt;</span>只在一定条件下显示<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span></div></div>
<p>在模板中通过clojure的if进行判断</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>deftemplate msg <span style="color: #ff0000;">&quot;msg.html&quot;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>ctx<span style="color: #66cc66;">&#93;</span><br />
&nbsp; <span style="color: #66cc66;">&#91;</span>:<span style="color: #555;">span</span>#msg<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>:<span style="color: #555;">show</span> ctx<span style="color: #66cc66;">&#41;</span> identity <span style="color: #66cc66;">&#40;</span>html<span style="color: #66cc66;">-</span>content <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>解决了这两个问题，基本上用enlive作为模板引擎就没有障碍了。不过enlive也有一点小问题，其一可能是性能的问题，方便的selector显然要比传统的模板语言消耗更多的CPU。另外，在开发过程里，页面文件在服务器启动后不能热加载，修改页面必须重启ring才能看到。也许有时间的话，可以给它加一个reload选项。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/12/%e4%bd%bf%e7%94%a8enlive%e4%bd%9c%e4%b8%ba%e6%a8%a1%e6%9d%bf%e5%bc%95%e6%93%8e/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HeatCanvas hits 1.0, and public available</title>
		<link>http://sunng.info/blog/2011/06/heatcanvas-hits-1-0-and-public-available/</link>
		<comments>http://sunng.info/blog/2011/06/heatcanvas-hits-1-0-and-public-available/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 13:55:08 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[heatcanvas]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/06/heatcanvas-hits-1-0-and-public-available/</guid>
		<description><![CDATA[As described in Wikipedia, a heat map is a graphical representation of data in a two-dimensional table. HeatCanvas enables heat map on HTML5 canvas. With HeatCanvas, you can visualize your data on modern web browser without server-side support. HeatCanvas is &#8230; <a href="http://sunng.info/blog/2011/06/heatcanvas-hits-1-0-and-public-available/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As described in Wikipedia, a heat map is a graphical representation of data in a two-dimensional table. HeatCanvas enables heat map on HTML5 canvas. With HeatCanvas, you can visualize your data on modern web browser without server-side support.</p>
<p>HeatCanvas is based on <a href="http://sunng.info/blog/2010/02/sunngs-canvas-based-heatmap-api/">the prototype</a> I wrote 15 months ago. I just rewrite the whole with WebWorker API to keep user away from UI frozen and annoying slow-script warning. HeatCanvas is implemented as pixel based, so the image quality is great.</p>
<p><img src="http://i.imgur.com/gNHOw.png" alt="" title="Hosted by imgur.com" /></p>
<p>The API is rather simple. There are only three steps to create a basic heat map.</p>
<p>1. Create the heat map object:</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> heatmap <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> HeatCanvas<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'canvasId'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>2. Add some data to heat map:</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">heatmap.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">223</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">98</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// x,y and value for this point</span></div></div>
<p>3. Render it:</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">heatmap.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>In contrast to the base API, HeatCanvas also supports flexible options to customize the rendering. Even custom colour scheme is allowed. You can <a href="https://github.com/sunng87/heatcanvas/blob/master/README.md">refer to the doc</a> for detail.</p>
<p>And for your convenience, we have a GoogleMap plugin, <b>HeatCanvasOverlayView</b>, that wraps HeatCanvas. You can use it in your GoogleMap application.</p>
<p>For live demos, you can find at:<br />
<a href="http://sunng87.github.com/heatcanvas/">http://sunng87.github.com/heatcanvas/</a></p>
<p>As always, the project is hosted on github:<br />
<a href="https://github.com/sunng87/heatcanvas">https://github.com/sunng87/heatcanvas</a> .</p>
<p>The three javascript files are only necessary in your application, thus, please ignore the htmls in your deployment. Any feedback is welcomed and also please kindly let me know your application using this API.</p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=9343259e-039c-8fdf-8721-dbd6277de695" /></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/06/heatcanvas-hits-1-0-and-public-available/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>网站五月访问量的可视化</title>
		<link>http://sunng.info/blog/2011/06/%e7%bd%91%e7%ab%99%e4%ba%94%e6%9c%88%e8%ae%bf%e9%97%ae%e9%87%8f%e7%9a%84%e5%8f%af%e8%a7%86%e5%8c%96/</link>
		<comments>http://sunng.info/blog/2011/06/%e7%bd%91%e7%ab%99%e4%ba%94%e6%9c%88%e8%ae%bf%e9%97%ae%e9%87%8f%e7%9a%84%e5%8f%af%e8%a7%86%e5%8c%96/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 14:17:46 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[visualization]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/06/%e7%bd%91%e7%ab%99%e4%ba%94%e6%9c%88%e8%ae%bf%e9%97%ae%e9%87%8f%e7%9a%84%e5%8f%af%e8%a7%86%e5%8c%96/</guid>
		<description><![CDATA[今天用正在调试中的heatmap做了一个网站访问量的可视化。数据从google analytics得到，再通过我本地的geonames数据库做了geocoding（用google的就太慢了）。这里有一个live版本。 关于这个heatmap目前还在开发中，很快会介绍给大家的。]]></description>
			<content:encoded><![CDATA[<p><img src="http://i.imgur.com/cc0wj.png" alt="" title="Hosted by imgur.com" /></p>
<p>今天用正在调试中的heatmap做了一个网站访问量的可视化。数据从google analytics得到，再通过我本地的geonames数据库做了geocoding（用google的就太慢了）。<a href="http://sunng.info/heatmap/googlemap.html">这里</a>有一个live版本。</p>
<p>关于这个heatmap目前还在开发中，很快会介绍给大家的。</p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=a1aebb1c-f22a-8723-aff4-16528e75dae4" /></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/06/%e7%bd%91%e7%ab%99%e4%ba%94%e6%9c%88%e8%ae%bf%e9%97%ae%e9%87%8f%e7%9a%84%e5%8f%af%e8%a7%86%e5%8c%96/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>用coffeescript重写了首页</title>
		<link>http://sunng.info/blog/2011/05/%e7%94%a8coffeescript%e9%87%8d%e5%86%99%e4%ba%86%e9%a6%96%e9%a1%b5/</link>
		<comments>http://sunng.info/blog/2011/05/%e7%94%a8coffeescript%e9%87%8d%e5%86%99%e4%ba%86%e9%a6%96%e9%a1%b5/#comments</comments>
		<pubDate>Fri, 13 May 2011 14:48:20 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[coffeescript]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/05/%e7%94%a8coffeescript%e9%87%8d%e5%86%99%e4%ba%86%e9%a6%96%e9%a1%b5/</guid>
		<description><![CDATA[下午有时间看了一下coffeescript，发现非常优雅。过去对JavaScript的工作，从dojo到jquery主要是在库的层面，这次coffeescript的出现是在语言层面对javascript做了一次加强。现在对语言的加强不再需要mozilla/microsoft/google/apple几家坐下来慢慢聊了，民间的力量就可以实现。 coffeescript的几个特点也属于博采众长： 类似python的，以缩进取代代码块 类似ruby/perl，方法调用括号可选 类似ruby，无须return 正常的类声明语法 在nodejs的环境里可以通过npm安装coffer-script，利用它的命令行程序，可以把coffeescript编译成javascript。不过最给力的是可以在网页里通过引入coffee-script.js来直接执行（其实也是编译一下）coffeescript。 于是我顺手重写了一下首页的js，改写成coffeescript。因为少打很多() {}，手可以控制在键盘中心的，敲字的效率大大提高。用空你也可以尝试一下。]]></description>
			<content:encoded><![CDATA[<p>下午有时间看了一下<a href="http://jashkenas.github.com/coffee-script/">coffeescript</a>，发现非常优雅。过去对JavaScript的工作，从dojo到jquery主要是在库的层面，这次coffeescript的出现是在语言层面对javascript做了一次加强。现在对语言的加强不再需要mozilla/microsoft/google/apple几家坐下来慢慢聊了，民间的力量就可以实现。</p>
<p>coffeescript的几个特点也属于博采众长：</p>
<ul>
<li>类似python的，以缩进取代代码块</li>
<li>类似ruby/perl，方法调用括号可选</li>
<li>类似ruby，无须return</li>
<li>正常的类声明语法</li>
</ul>
<p>在nodejs的环境里可以通过npm安装coffer-script，利用它的命令行程序，可以把coffeescript编译成javascript。不过最给力的是可以在网页里通过<a href="http://jashkenas.github.com/coffee-script/#scripts">引入coffee-script.js</a>来直接执行（其实也是编译一下）coffeescript。</p>
<p>于是我顺手重写了一下首页的js，改写成coffeescript。因为少打很多() {}，手可以控制在键盘中心的，敲字的效率大大提高。用空你也可以尝试一下。</p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=c7456ff3-1bf5-8c54-b037-86800bd4f910" /></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/05/%e7%94%a8coffeescript%e9%87%8d%e5%86%99%e4%ba%86%e9%a6%96%e9%a1%b5/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tiny LifeStream widget available on sunng.info</title>
		<link>http://sunng.info/blog/2011/03/tiny-lifestream-widget-available-on-sunng-info/</link>
		<comments>http://sunng.info/blog/2011/03/tiny-lifestream-widget-available-on-sunng-info/#comments</comments>
		<pubDate>Fri, 11 Mar 2011 14:48:50 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[daf]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/03/tiny-lifestream-widget-available-on-sunng-info/</guid>
		<description><![CDATA[首先推荐samson的stdout，这是一个LifeStream Web应用（针对Loser的LifeStream称为LoserStream）。你可以从github上获得代码，参考samson的deployment和customization文档，在一二三四五六七八九十十一十二……分钟内搭建一个自己stdout，至于是不是LoserStream你自己看着办。 本来打算在自己的主机上搭一个实例的，怎奈怎奈我那CentOS5的主机。所以我说我们这些CentOS用户最伤不起了！！！源里有Ruby有个毛用！！1.8.4，泥玛gem都装不上！！还要去找1.8.6的代码来编译，有没有！！！好不容易装上gem了，gem 1.6.1说找不到Win32API！！！干掉重装1.4.5！再装ruby-sqlite3，源里的sqlite3版本又不行，装不上，有没有！！！有没有！！！ 最后我无奈了，还是用老朋友Yahoo Pipes吧。拖一拖拉一拉神马都有了，页面上整点咱最擅长的document.getElementById就成了。你可以在http://sunng.info找到这个东西，现在这个源里收录了： blog 豆瓣 github osm editing twitter reddit like 这些也是我主要混迹的地方了，遗憾就是bitbucket居然没有个人的RSS输出。倒是可以通过他们的API获得，不过在Pipes里要多拖点东西，所以我先琢磨一下再说吧。网易八方我说过了，不愧是互联网产品经理驱动的东西，连个RSS输出都木有。饭否嘛现在作为扯淡专用场所就不收录了。 说实在的把这些东西都聚合在一起还是挺吓人的，所以我把他稍微藏了一下。 还有，今天日本地震，祝daf同学平平安安平平安安。]]></description>
			<content:encoded><![CDATA[<p>首先推荐samson的<a href="http://stdout.samsonw.info/">stdout</a>，这是一个LifeStream Web应用（针对Loser的LifeStream称为LoserStream）。你可以从<a href="https://github.com/samsonw/stdout">github</a>上获得代码，参考samson的<a href="http://blog.samsonis.me/2011/03/stdout-deployment/">deployment</a>和<a href="http://blog.samsonis.me/2011/03/stdout-customization/">customization</a>文档，在一二三四五六七八九十十一十二……分钟内搭建一个自己stdout，至于是不是LoserStream你自己看着办。</p>
<p>本来打算在自己的主机上搭一个实例的，怎奈怎奈我那CentOS5的主机。所以我说我们这些CentOS用户最伤不起了！！！源里有Ruby有个毛用！！1.8.4，泥玛gem都装不上！！还要去找1.8.6的代码来编译，有没有！！！好不容易装上gem了，gem 1.6.1说找不到Win32API！！！干掉重装1.4.5！再装ruby-sqlite3，源里的sqlite3版本又不行，装不上，有没有！！！有没有！！！</p>
<p>最后我无奈了，还是用老朋友Yahoo Pipes吧。拖一拖拉一拉神马都有了，页面上整点咱最擅长的document.getElementById就成了。你可以在<a href="http://sunng.info">http://sunng.info</a>找到这个东西，现在这个源里收录了：</p>
<ul>
<li>blog</li>
<li>豆瓣</li>
<li>github</li>
<li>osm editing</li>
<li>twitter</li>
<li>reddit like</li>
</ul>
<p>这些也是我主要混迹的地方了，遗憾就是bitbucket居然没有个人的RSS输出。倒是可以通过他们的API获得，不过在Pipes里要多拖点东西，所以我先琢磨一下再说吧。网易八方我说过了，不愧是互联网产品经理驱动的东西，连个RSS输出都木有。饭否嘛现在作为扯淡专用场所就不收录了。</p>
<p>说实在的把这些东西都聚合在一起还是挺吓人的，所以我把他稍微藏了一下。</p>
<p>还有，今天日本地震，祝daf同学平平安安平平安安。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/03/tiny-lifestream-widget-available-on-sunng-info/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>When nodejs meets mapnik</title>
		<link>http://sunng.info/blog/2011/03/when-nodejs-meets-mapnik/</link>
		<comments>http://sunng.info/blog/2011/03/when-nodejs-meets-mapnik/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 08:04:17 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mapnik]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/03/when-nodejs-meets-mapnik/</guid>
		<description><![CDATA[tilelive.js是一个基于nodejs的web地图工具，帮助用户快速查看他们创建的地图样式。tilelive.js是Mapbox众多产品中的一个，你可以通过tilemill了解更多。 要运行tilelive.js，你需要安装一系列软件。 安装mapnik 首先需要安装mapnik2，注意并非是目前的稳定版本0.7.1，而是开发版本。 签出SVN代码： svn co http://svn.mapnik.org/trunk mapnik-trunk 按照Mapnik的文档描述进行安装。 安装node依赖 推荐你安装最新的node 0.4.2和npm 0.3.1。 安装npm后执行 npm config set unsafe-perm true 去除超级用户运行npm时的警告。 接下来就可以安装一系列node modules了： sudo npm install mapnik sudo npm install carto sudo npm install generic-pool sudo npm install underscore sudo &#8230; <a href="http://sunng.info/blog/2011/03/when-nodejs-meets-mapnik/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>tilelive.js是一个基于nodejs的web地图工具，帮助用户快速查看他们创建的地图样式。tilelive.js是Mapbox众多产品中的一个，你可以通过<a href="http://mapbox.github.com/tilemill/">tilemill</a>了解更多。</p>
<p>要运行tilelive.js，你需要安装一系列软件。</p>
<h3>安装mapnik</h3>
<p>首先需要安装mapnik2，注意并非是目前的稳定版本0.7.1，而是开发版本。<br />
签出SVN代码：</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">svn co http://svn.mapnik.org/trunk mapnik-trunk</div></div>
<p>按照Mapnik的<a href="http://trac.mapnik.org/browser/trunk/INSTALL">文档</a>描述进行安装。</p>
<h3>安装node依赖</h3>
<p>推荐你安装最新的node 0.4.2和npm 0.3.1。</p>
<p>安装npm后执行</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">npm config set unsafe-perm true</div></div>
<p>去除超级用户运行npm时的警告。</p>
<p>接下来就可以安装一系列node modules了：</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install mapnik</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install carto</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install generic-pool</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install underscore</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install node-get</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install step</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install express</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install sqlite3</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo npm install compress</div></div>
<h3>签出 tilelive.js</h3>
<p>tilelive.js并不兼容最新的node 0.4.x和express 2.0.0，所以你可以签出我fork的版本：</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">git clone git://github.com/sunng87/tilelive.js.git</div></div>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">git checkout new-fork</div></div>
<p>运行：</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">./bin/tilelive_server.js examples/stysheet.xml</div></div>
<p>打开浏览器，访问 http://localhost:8888/ 即可<br />
<a href="http://www.flickr.com/photos/40741608@N08/5498409697/" title="screenshot_001 by 贝小塔, on Flickr"><img src="http://farm6.static.flickr.com/5177/5498409697_6bf280e8fb.jpg" width="500" height="405" alt="screenshot_001" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/03/when-nodejs-meets-mapnik/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python3 script to query free TOEFL seats</title>
		<link>http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/</link>
		<comments>http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 14:46:19 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/</guid>
		<description><![CDATA[应同学要求，写了一个爬托福考试空闲考位的脚本。这是第一次真正用Python3写。 通过调用get_seat_status，传入省名（如&#8217;Jiangsu&#8217;），时间（如&#8217;201104&#8242;），您可以得到这样的数据结构： &#91; &#91;datetime.datetime&#40;2011, 4, 23, 10, 0&#41;, &#160;'STN80085B', &#160;'南通市教育装备与勤工俭学管理中心', &#160;'1415', &#160;True&#93;, &#160;&#91;datetime.datetime&#40;2011, 4, 23, 10, 0&#41;, 'STN80086A', '扬州大学', '1415', True&#93;&#93; 下面是一个多线程调用的例子： #! /usr/bin/python3 import threading import pprint from toeflgraber import get_seat_status # 查询江浙沪 2011年3月和4月的考位 locations = &#91;'Jiangsu', 'Shanghai', 'Zhejiang'&#93; &#8230; <a href="http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>应同学要求，写了一个爬托福考试空闲考位的脚本。这是第一次真正用Python3写。</p>
<p><script src="https://gist.github.com/846150.js?file=gistfile1.py"></script></p>
<p>通过调用get_seat_status，传入省名（如&#8217;Jiangsu&#8217;），时间（如&#8217;201104&#8242;），您可以得到这样的数据结构：</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: black;">&#91;</span> <span style="color: black;">&#91;</span><span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">23</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #483d8b;">'STN80085B'</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #483d8b;">'南通市教育装备与勤工俭学管理中心'</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #483d8b;">'1415'</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #008000;">True</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp;<span style="color: black;">&#91;</span><span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">23</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'STN80086A'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'扬州大学'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'1415'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></div></div>
<p>下面是一个多线程调用的例子：</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">#! /usr/bin/python3</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">threading</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pprint</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> toeflgraber <span style="color: #ff7700;font-weight:bold;">import</span> get_seat_status<br />
<br />
<span style="color: #808080; font-style: italic;"># 查询江浙沪 2011年3月和4月的考位</span><br />
locations <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'Jiangsu'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Shanghai'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Zhejiang'</span><span style="color: black;">&#93;</span><br />
months <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'201103'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'201104'</span><span style="color: black;">&#93;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> descartes<span style="color: black;">&#40;</span>x<span style="color: #66cc66;">,</span> y<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> x:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> j <span style="color: #ff7700;font-weight:bold;">in</span> y:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: black;">&#40;</span>i<span style="color: #66cc66;">,</span> j<span style="color: black;">&#41;</span><br />
<br />
lock <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">RLock</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
tasks <span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>locations<span style="color: black;">&#41;</span> * <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>months<span style="color: black;">&#41;</span><br />
e <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">Event</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
results <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> task<span style="color: black;">&#40;</span>location<span style="color: #66cc66;">,</span> month<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">global</span> results<span style="color: #66cc66;">,</span> tasks<br />
&nbsp; &nbsp; all_seats <span style="color: #66cc66;">=</span> get_seat_status<span style="color: black;">&#40;</span>location<span style="color: #66cc66;">,</span> month<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; available_seats <span style="color: #66cc66;">=</span> <span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x<span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> all_seats<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">with</span> lock:<br />
&nbsp; &nbsp; &nbsp; &nbsp; results.<span style="color: black;">extend</span><span style="color: black;">&#40;</span>available_seats<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tasks -<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> tasks <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">for</span> t <span style="color: #ff7700;font-weight:bold;">in</span> descartes<span style="color: black;">&#40;</span>locations<span style="color: #66cc66;">,</span> months<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; t <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span><span style="color: black;">&#40;</span>target<span style="color: #66cc66;">=</span>task<span style="color: #66cc66;">,</span> args<span style="color: #66cc66;">=</span>t<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; t.<span style="color: black;">daemon</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span><br />
&nbsp; &nbsp; t.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
e.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: #dc143c;">pprint</span>.<span style="color: #dc143c;">pprint</span><span style="color: black;">&#40;</span>results<span style="color: black;">&#41;</span></div></div>
<p>Enjoy it.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using dojo on Chrome/Chromium from local file system</title>
		<link>http://sunng.info/blog/2011/02/using-dojo-on-chromechromium-from-local-file-system/</link>
		<comments>http://sunng.info/blog/2011/02/using-dojo-on-chromechromium-from-local-file-system/#comments</comments>
		<pubDate>Mon, 21 Feb 2011 12:59:10 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/02/using-dojo-on-chromechromium-from-local-file-system/</guid>
		<description><![CDATA[dojo.require uses XMLHttpRequest to load additional components. On default Chrome settings, XMLHttpRequest on local file system is not allowed. This will break whole dojo system. To change the default policy, you can start Chrome with a command line option &#8211;allow-file-access-from-files. &#8230; <a href="http://sunng.info/blog/2011/02/using-dojo-on-chromechromium-from-local-file-system/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>dojo.require uses XMLHttpRequest to load additional components. On default Chrome settings, XMLHttpRequest on local file system is not allowed. This will break whole dojo system.</p>
<p>To change the default policy, you can start Chrome with a command line option <i>&#8211;allow-file-access-from-files</i>.</p>
<p>This issue is a well known one for Chromium project and still under active discussion:<br />
<a href="http://code.google.com/p/chromium/issues/detail?id=40787">http://code.google.com/p/chromium/issues/detail?id=40787</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/02/using-dojo-on-chromechromium-from-local-file-system/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

