<?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>幼学笔记 &#187; JavaScript</title>
	<atom:link href="http://www.oncoding.cn/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.oncoding.cn</link>
	<description>追寻简单生活</description>
	<lastBuildDate>Sun, 29 May 2011 14:03:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>“最被误解的语言”正焕发全新活力</title>
		<link>http://www.oncoding.cn/2010/javascript-new-journey/</link>
		<comments>http://www.oncoding.cn/2010/javascript-new-journey/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 15:10:00 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[扯淡]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=820</guid>
		<description><![CDATA[这些内容最早出自6月份的一次团队内分享，后来圆心推荐发表在了8月的《程序员》杂志上。遗憾的是编辑自行作了很多删改，原文发在这里。 Douglas Crockford曾称JavaScript是“世界上最被误解的语言”。确实，很长一段时间里，JavaScript都曾是泛滥的网页特效和弹窗广告的代名词。近些年来，随着Ajax应用的流行和前端框架的发展，JavaScript已经越来越严格和标准化。同时，在前端领域之外，JavaScript 也正被越来越广泛的使用。下面我们通过几个简单的JavaScript语句，一起来了解这些领域的应用。 这几句代码大体可以看出，它们的作用为：在本地的8080端口监听请求，返回浏览器响应──没错，这是基于JavaScript的服务器程序 node.js（ http://nodejs.org/）的一段控制语句。 node.js基于V8引擎（Chrome浏览器使用的JS解析器），它继承了 JavaScript的诸多特性，具备比Apache等传统服务端程序更好的性能和特性：I/O读写都经由V8引擎来处理，避免不良代码造成的死锁；更节省内存开支；处理并发请求效率更高；等等…… 这是一句简单的JavaScript专用数据格式——JSON语句，但确切的说，它一种基于JSON的数据库存储格式——BSON，是最近流行的NOSQL(非关系型数据库)的一种存储形式，非关系数据库多采用kay-value形式，具备比关系型数据库更强的扩展性和可操作性，并且在海量存储、高并发读写方面有绝佳的表现。 这句JavaScript语句的作用为：在以BSON存储的数据库中取得一条记录。它是著名的非关系数据库——MongoDB的一条查询语句。MongoDB基于C++开发，使用二进制格式存储BSON数据，可以对BSON中每个字段进行索引，具备极高的处理海量数据的能力。让人惊讶的是，它分别提供了基于十几种语言的查询语句和服务端、客户端，其中就包含对JavaScript的完美支持——MongoDB提供了基于Node.js的数据库服务器、基于SpiderMonkey的数据库客户端，以及JavaScript查询语句，并且提供了全功能的Web Shell。 JavaScript在这些领域的应用，已经不单单是停留在实验和玩票的性质，它们在国内外已经开始了大规模的使用。可以预见，在不久的将来，会出现这样的网站：它的前端使用JavaScript实现网页特效和交互，服务端运行的是基于JavaScript的Web服务器和数据库服务器，数据库使用JSON/BSON存储数据。 作为前端工作者，看到我们最熟悉的语言正在被这么多人、在这么多领域研究和使用，兴奋之余也倍感压力——越来越多的研究和关注，必然会促进这门语言更快的发展，同时也会变得更严格和严谨。这对前端工作者提出了更高的要求和挑战——与时俱进，不断超越！]]></description>
			<content:encoded><![CDATA[<blockquote><p>这些内容最早出自6月份的一次团队内分享，后来<a title="怿飞" href="http://www.planabc.net/" target="_blank">圆心</a>推荐发表在了8月的《程序员》杂志上。遗憾的是编辑自行作了很多删改，原文发在这里。</p></blockquote>
<p>Douglas Crockford曾称JavaScript是“世界上最被误解的语言”。确实，很长一段时间里，JavaScript都曾是泛滥的网页特效和弹窗广告的代名词。近些年来，随着Ajax应用的流行和前端框架的发展，JavaScript已经越来越严格和标准化。同时，在前端领域之外，JavaScript 也正被越来越广泛的使用。下面我们通过几个简单的JavaScript语句，一起来了解这些领域的应用。</p>
<pre class="brush: jscript; title: ; notranslate">
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(8080, &quot;127.0.0.1&quot;);
</pre>
<p>这几句代码大体可以看出，它们的作用为：在本地的8080端口监听请求，返回浏览器响应──没错，这是基于JavaScript的服务器程序 node.js（ http://nodejs.org/）的一段控制语句。<br />
node.js基于V8引擎（Chrome浏览器使用的JS解析器），它继承了 JavaScript的诸多特性，具备比Apache等传统服务端程序更好的性能和特性：I/O读写都经由V8引擎来处理，避免不良代码造成的死锁；更节省内存开支；处理并发请求效率更高；等等……</p>
<pre class="brush: jscript; title: ; notranslate">
{&quot;id&quot;: &quot;036378&quot;,  &quot;name&quot;: &quot;etai&quot;, &quot;job&quot;: &quot;F2E&quot; }
</pre>
<p>这是一句简单的JavaScript专用数据格式——JSON语句，但确切的说，它一种基于JSON的数据库存储格式——BSON，是最近流行的NOSQL(非关系型数据库)的一种存储形式，非关系数据库多采用kay-value形式，具备比关系型数据库更强的扩展性和可操作性，并且在海量存储、高并发读写方面有绝佳的表现。</p>
<pre class="brush: jscript; title: ; notranslate">
var t = db.things.findOne( { name : “etai” } );
</pre>
<p>这句JavaScript语句的作用为：在以BSON存储的数据库中取得一条记录。它是著名的非关系数据库——MongoDB的一条查询语句。MongoDB基于C++开发，使用二进制格式存储BSON数据，可以对BSON中每个字段进行索引，具备极高的处理海量数据的能力。让人惊讶的是，它分别提供了基于十几种语言的查询语句和服务端、客户端，其中就包含对JavaScript的完美支持——MongoDB提供了基于Node.js的数据库服务器、基于SpiderMonkey的数据库客户端，以及JavaScript查询语句，并且提供了全功能的Web Shell。</p>
<p>JavaScript在这些领域的应用，已经不单单是停留在实验和玩票的性质，它们在国内外已经开始了大规模的使用。可以预见，在不久的将来，会出现这样的网站：它的前端使用JavaScript实现网页特效和交互，服务端运行的是基于JavaScript的Web服务器和数据库服务器，数据库使用JSON/BSON存储数据。</p>
<p>作为前端工作者，看到我们最熟悉的语言正在被这么多人、在这么多领域研究和使用，兴奋之余也倍感压力——越来越多的研究和关注，必然会促进这门语言更快的发展，同时也会变得更严格和严谨。这对前端工作者提出了更高的要求和挑战——与时俱进，不断超越！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2010/javascript-new-journey/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>可以在前端实现的几个地理位置小功能</title>
		<link>http://www.oncoding.cn/2010/geo-location-frontend/</link>
		<comments>http://www.oncoding.cn/2010/geo-location-frontend/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 16:09:55 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[地图]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=690</guid>
		<description><![CDATA[在Smashing Magazine上看到这篇Entering The Wonderful World of Geo Location，介绍了获取并处理用户地理位置的应用和方法，很有意思。结合原文的内容，加上之前的一些应用，整理了几个可以完全在前端实现的地理位置相关小功能。 1.通过IP获取用户位置 很多时候需要通过IP判断用户的位置，通常的办法是通过自己的后台程序查询数据库得到。如果用户位置只是应用在前端，或者有其他的特殊原因(比如，懒:)，也有一些其他办法来快速的获取用户位置。 maxmind.com提供了一个服务，通过引入一个js文件(http://j.maxmind.com/app/geoip.js)，可以把他判断到的用户的国家、城市、经纬度等信息加入到页面中来。下面是从青岛访问这个js文件返回的内容： 我们就可以利用这些信息做很多东西了：DEMO 另外，腾讯也有一个类似的接口，地址为 http://fw.qq.com/ipaddress，可以得到访问者的省、市信息，返回的格式如下： 具体的应用可以看这里： 断桥残雪WordPress天气插件 2.W3C共享位置接口 HTML5加入了的贡献地理位置的浏览器API接口，目前firefox3.5等浏览器已经支持这一功能。 用法： 看 DEMO 3. Google Gears 的 Geolocation API Google Gears是主要提供本地存储功能的浏览器扩展，新版本的Gears中，加入了判断用户地理位置的API，通过IP、WIFI热点等判断位置。不过Gears的使用似乎并不太广泛(Chrome内置了Gears，其他浏览器需要安装)，国内的地理位置信息也不够丰富，所以这个应用目前只可作为参考。 使用Gears的基本方法看这里，引入gears_init.js，使用Geolocation API的程序为： 更多内容参考这篇文章：使用Gears获取当前地理位置，以及DEMO。 4.逆经纬度解析 通过浏览器API等方式得到经纬度后，有时需要得到对应的城市名，这就是逆经纬度解析。 google maps api提供了一些经纬度解析方法，如果我们不想引入庞大的api，可以直接使用他的请求地址，通过jsonp方式得到google的经纬度解析数据。jsonp请求地址形式为： http://ditu.google.cn/maps/geo? output=json&#038;oe=utf-8&#038;q=纬度%2C经度 &#038;key=你申请到的key &#038;mapclient=jsapi&#038;hl=zh-CN&#038;callback=myfunction 参数q为经纬度，参数callback为回调函数名。 可以看下这个地址的返回结果，数据非常丰富，并且还是中文的： Yahoo提供的接口 雅虎提供了一些经纬度查询接口，可以使用YQL查询。 查询语句为： 用法： 使用YQL进行更多地理信息查询，可以看这个PPT：YQL Geo Library and Introduction to Geo Hacking [...]]]></description>
			<content:encoded><![CDATA[<p>在Smashing Magazine上看到这篇<a target="_blank" href="http://www.smashingmagazine.com/2010/03/08/entering-the-wonderful-world-of-geo-location/">Entering  The Wonderful World of Geo Location</a>，介绍了获取并处理用户地理位置的应用和方法，很有意思。结合原文的内容，加上之前的一些应用，整理了几个可以完全在前端实现的地理位置相关小功能。</p>
<h3>1.通过IP获取用户位置</h3>
<p>很多时候需要通过IP判断用户的位置，通常的办法是通过自己的后台程序查询数据库得到。如果用户位置只是应用在前端，或者有其他的特殊原因(比如，懒:)，也有一些其他办法来快速的获取用户位置。</p>
<p><a target="_blank" href="http://www.maxmind.com" >maxmind.com</a>提供了一个服务，通过引入一个js文件(<a target="_blank" href="http://j.maxmind.com/app/geoip.js">http://j.maxmind.com/app/geoip.js</a>)，可以把他判断到的用户的国家、城市、经纬度等信息加入到页面中来。下面是从青岛访问这个js文件返回的内容：<br />
<span id="more-690"></span></p>
<pre class="brush: jscript; title: ; notranslate">
function geoip_country_code() { return 'CN'; }
function geoip_country_name() { return 'China'; }
function geoip_city() { return 'Qingdao'; }
function geoip_region() { return '25'; }
function geoip_region_name() { return 'Shandong'; }
function geoip_latitude() { return '36.0986'; }
function geoip_longitude() { return '120.3719'; }
function geoip_postal_code() { return ''; }
</pre>
<p>我们就可以利用这些信息做很多东西了：<a href="http://isithackday.com/hacks/geo/js-location.html" target="_blank">DEMO</a></p>
<p>另外，腾讯也有一个类似的接口，地址为 http://fw.qq.com/ipaddress，可以得到访问者的省、市信息，返回的格式如下：</p>
<pre class="brush: jscript; title: ; notranslate">
var IPData = new Array(&quot;123.235.153.126&quot;,&quot;&quot;,&quot;山东省&quot;,&quot;青岛市&quot;);
</pre>
<p>具体的应用可以看这里：<a target="_blank" href="http://www.js8.in/wordpress-weather"> 断桥残雪WordPress天气插件</a></p>
<h3>2.W3C共享位置接口</h3>
<p>HTML5加入了的贡献地理位置的浏览器API接口，目前firefox3.5等浏览器已经支持这一功能。</p>
<p><a target="_blank" href="http://www.oncoding.cn/wp-content/uploads/2010/03/w3c-geo.jpg"><img src="http://www.oncoding.cn/wp-content/uploads/2010/03/w3c-geo-300x76.jpg" alt="" title="w3c-geo-api" width="300" height="76" class="aligncenter size-medium wp-image-693" /></a></p>
<p>用法：</p>
<pre class="brush: jscript; title: ; notranslate">
// if the browser supports the w3c geo api
if(navigator.geolocation){
  // get the current position
  navigator.geolocation.getCurrentPosition(

  // if this was successful, get the latitude and longitude
  function(position){
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
  },
  // if there was an error
  function(error){
    alert('ouch');
  });
}
</pre>
<p>看 <a target="_blank" href="http://isithackday.com/hacks/geo/distance.php">DEMO</a> </p>
<h3>3. Google Gears 的 Geolocation API</h3>
<p><a target="_blank" href="http://gears.google.com/">Google Gears</a>是主要提供本地存储功能的浏览器扩展，新版本的Gears中，加入了判断用户地理位置的API，通过IP、WIFI热点等判断位置。不过Gears的使用似乎并不太广泛(Chrome内置了Gears，其他浏览器需要安装)，国内的地理位置信息也不够丰富，所以这个应用目前只可作为参考。</p>
<p>使用Gears的基本方法看<a target="_blank" href="http://code.google.com/intl/zh-CN/apis/gears/design.html">这里</a>，引入<a href="http://code.google.com/intl/zh-CN/apis/gears/gears_init.js" target="_blank">gears_init.js</a>，使用Geolocation API的程序为：</p>
<pre class="brush: jscript; title: ; notranslate">
var geo = factory.create('beta.geolocation'); //创建geolocation对象
var okCallback = function(d){
  alert('当前位置(纬度，经度): ' + d.latitude + ',' + d.longitude);
};
var errorCallback = function(err){
  alert(err.message);
};
geo.getCurrentPosition(okCallback , errorCallback);
</pre>
<p>更多内容参考这篇文章：<a href="http://www.qgy18.com/2009/09/%E4%BD%BF%E7%94%A8google-gears%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E5%9C%B0%E7%90%86%E4%BD%8D%E7%BD%AE/" target="_blank">使用Gears获取当前地理位置</a>，以及<a target="_blank" href="http://www.qgy18.com/lab/gears/">DEMO</a>。</p>
<h3>4.逆经纬度解析</h3>
<p>通过浏览器API等方式得到经纬度后，有时需要得到对应的城市名，这就是逆经纬度解析。</p>
<p>google maps api提供了一些经纬度解析方法，如果我们不想引入庞大的api，可以直接使用他的请求地址，通过<strong>jsonp方式得到google的经纬度解析数据</strong>。jsonp请求地址形式为：</p>
<blockquote><p>http://ditu.google.cn/maps/geo?<br />
output=json&#038;oe=utf-8&#038;q=纬度%2C经度<br />
&#038;key=<em>你申请到的key</em><br />
&#038;mapclient=jsapi&#038;hl=zh-CN&#038;callback=myfunction</p></blockquote>
<p>参数q为经纬度，参数callback为回调函数名。</p>
<p>可以看下<a target="_blank" href="http://ditu.google.cn/maps/geo?output=json&#038;oe=utf-8&#038;q=36.06023%2C120.3024&#038;key=ABQIAAAAira30FR5tVprWCJ-8_WcqxSrc1zAT9YCtP2kOyoD7kBAJfliJBROJEdu9hUE13rp9a4OHneyOoW5gg&#038;mapclient=jsapi&#038;hl=zh-CN&#038;callback=myfunction">这个地址</a>的返回结果，数据非常丰富，并且还是中文的：</p>
<pre class="brush: jscript; collapse: true; light: false; title: ; toolbar: true; notranslate">
myfunction &amp;&amp; myfunction( {
  &quot;name&quot;: &quot;36.06023, 120.3024&quot;,
  &quot;Status&quot;: {
    &quot;code&quot;: 200,
    &quot;request&quot;: &quot;geocode&quot;
  },
  &quot;Placemark&quot;: [ {
    &quot;id&quot;: &quot;p1&quot;,
    &quot;address&quot;: &quot;中国山东省青岛市市南区台西三路6号-10号&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 8,
   &quot;Country&quot; : {
      &quot;AdministrativeArea&quot; : {
         &quot;AdministrativeAreaName&quot; : &quot;山东省&quot;,
         &quot;Locality&quot; : {
            &quot;DependentLocality&quot; : {
               &quot;DependentLocalityName&quot; : &quot;市南区&quot;,
               &quot;Thoroughfare&quot; : {
                  &quot;ThoroughfareName&quot; : &quot;台西三路6号-10号&quot;
               }
            },
            &quot;LocalityName&quot; : &quot;青岛市&quot;
         }
      },
      &quot;CountryName&quot; : &quot;中国&quot;,
      &quot;CountryNameCode&quot; : &quot;CN&quot;
   }
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0633254,
        &quot;south&quot;: 36.0570301,
        &quot;east&quot;: 120.3054361,
        &quot;west&quot;: 120.2991409
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3024027, 36.0602271, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p2&quot;,
    &quot;address&quot;: &quot;中国山东省青岛市市南区台西三路8号阿双美容美发厅&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 9,
   &quot;Country&quot; : {
      &quot;AdministrativeArea&quot; : {
         &quot;AdministrativeAreaName&quot; : &quot;山东省&quot;,
         &quot;Locality&quot; : {
            &quot;DependentLocality&quot; : {
               &quot;AddressLine&quot; : [ &quot;阿双美容美发厅&quot; ],
               &quot;DependentLocalityName&quot; : &quot;市南区&quot;,
               &quot;Thoroughfare&quot; : {
                  &quot;ThoroughfareName&quot; : &quot;台西三路8号&quot;
               }
            },
            &quot;LocalityName&quot; : &quot;青岛市&quot;
         }
      },
      &quot;CountryName&quot; : &quot;中国&quot;,
      &quot;CountryNameCode&quot; : &quot;CN&quot;
   }
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0632366,
        &quot;south&quot;: 36.0569414,
        &quot;east&quot;: 120.3055696,
        &quot;west&quot;: 120.2992744
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3024220, 36.0600890, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p3&quot;,
    &quot;address&quot;: &quot;中国青岛市市南区台西四路站&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 9,
   &quot;AddressLine&quot; : [ &quot;台西四路站&quot; ]
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0630636,
        &quot;south&quot;: 36.0567684,
        &quot;east&quot;: 120.3063986,
        &quot;west&quot;: 120.3001034
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3032510, 36.0599160, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p4&quot;,
    &quot;address&quot;: &quot;中国青岛市市南区云南路(台西四路口)站&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 9,
   &quot;AddressLine&quot; : [ &quot;云南路(台西四路口)站&quot; ]
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0643586,
        &quot;south&quot;: 36.0580634,
        &quot;east&quot;: 120.3073456,
        &quot;west&quot;: 120.3010504
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3041980, 36.0612110, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p5&quot;,
    &quot;address&quot;: &quot;中国青岛市市南区贵州路站&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 9,
   &quot;AddressLine&quot; : [ &quot;贵州路站&quot; ]
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0614856,
        &quot;south&quot;: 36.0551904,
        &quot;east&quot;: 120.3036956,
        &quot;west&quot;: 120.2974004
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3005480, 36.0583380, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p6&quot;,
    &quot;address&quot;: &quot;中国青岛市市南区团岛站&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 9,
   &quot;AddressLine&quot; : [ &quot;团岛站&quot; ]
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0629146,
        &quot;south&quot;: 36.0566194,
        &quot;east&quot;: 120.3022496,
        &quot;west&quot;: 120.2959544
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.2991020, 36.0597670, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p7&quot;,
    &quot;address&quot;: &quot;中国山东省青岛市市南区团岛四路海湾花园&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 9,
   &quot;Country&quot; : {
      &quot;AdministrativeArea&quot; : {
         &quot;AdministrativeAreaName&quot; : &quot;山东省&quot;,
         &quot;Locality&quot; : {
            &quot;DependentLocality&quot; : {
               &quot;AddressLine&quot; : [ &quot;海湾花园&quot; ],
               &quot;DependentLocalityName&quot; : &quot;市南区&quot;,
               &quot;Thoroughfare&quot; : {
                  &quot;ThoroughfareName&quot; : &quot;团岛四路&quot;
               }
            },
            &quot;LocalityName&quot; : &quot;青岛市&quot;
         }
      },
      &quot;CountryName&quot; : &quot;中国&quot;,
      &quot;CountryNameCode&quot; : &quot;CN&quot;
   }
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0642706,
        &quot;south&quot;: 36.0579754,
        &quot;east&quot;: 120.3006386,
        &quot;west&quot;: 120.2943434
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.2974910, 36.0611230, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p8&quot;,
    &quot;address&quot;: &quot;中国山东省青岛市市南区&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 4,
   &quot;Country&quot; : {
      &quot;AdministrativeArea&quot; : {
         &quot;AdministrativeAreaName&quot; : &quot;山东省&quot;,
         &quot;Locality&quot; : {
            &quot;DependentLocality&quot; : {
               &quot;DependentLocalityName&quot; : &quot;市南区&quot;
            },
            &quot;LocalityName&quot; : &quot;青岛市&quot;
         }
      },
      &quot;CountryName&quot; : &quot;中国&quot;,
      &quot;CountryNameCode&quot; : &quot;CN&quot;
   }
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0954205,
        &quot;south&quot;: 36.0413849,
        &quot;east&quot;: 120.4266629,
        &quot;west&quot;: 120.2858189
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3877350, 36.0667110, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p9&quot;,
    &quot;address&quot;: &quot;中国山东省青岛市&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 4,
   &quot;Country&quot; : {
      &quot;AdministrativeArea&quot; : {
         &quot;AdministrativeAreaName&quot; : &quot;山东省&quot;,
         &quot;Locality&quot; : {
            &quot;LocalityName&quot; : &quot;青岛市&quot;
         }
      },
      &quot;CountryName&quot; : &quot;中国&quot;,
      &quot;CountryNameCode&quot; : &quot;CN&quot;
   }
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.3313685,
        &quot;south&quot;: 35.9407727,
        &quot;east&quot;: 120.6326294,
        &quot;west&quot;: 120.0970459
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3827710, 36.0663480, 0 ]
    }
  }, {
    &quot;id&quot;: &quot;p10&quot;,
    &quot;address&quot;: &quot;中国山东省&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 2,
   &quot;Country&quot; : {
      &quot;AdministrativeArea&quot; : {
         &quot;AdministrativeAreaName&quot; : &quot;山东省&quot;
      },
      &quot;CountryName&quot; : &quot;中国&quot;,
      &quot;CountryNameCode&quot; : &quot;CN&quot;
   }
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 38.4055838,
        &quot;south&quot;: 34.3851760,
        &quot;east&quot;: 122.7159599,
        &quot;west&quot;: 114.8033683
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 117.0198960, 36.6692270, 0 ]
    }
  } ]
}
 )
</pre>
<p><strong>Yahoo提供的接口</strong></p>
<p>雅虎提供了一些经纬度查询接口，可以使用<a target="_blank" href="http://developer.yahoo.com/yql">YQL</a>查询。</p>
<p>查询语句为：</p>
<pre class="brush: sql; title: ; notranslate">select * from flickr.places where lat=36.06023 and lon=120.3024</pre>
<p>用法：</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;
 function getPlaceFromFlickr(lat,lon,callback){
   // the YQL statement
   var yql = 'select * from flickr.places where lat='+lat+' and lon='+lon;

   // assembling the YQL webservice API
   var url = 'http://query.yahooapis.com/v1/public/yql?q='+
              encodeURIComponent(yql)+'&amp;format=json&amp;diagnostics='+
              'false&amp;callback='+callback;

   // create a new script node and add it to the document
   var s = document.createElement('script');
   s.setAttribute('src',url);
   document.getElementsByTagName('head')[0].appendChild(s);
 };

 // callback in case there is a place found
 function output(o){
   if(typeof(o.query.results.places.place) != 'undefined'){
     alert(o.query.results.places.place.name);
   }
 }

 // call the function with my current lat/lon
 getPlaceFromFlickr(36.6692270,117.0198960,'output');
&lt;/script&gt;
</pre>
<p>使用YQL进行更多地理信息查询，可以看这个PPT：<a target="_blank" href="http://www.wait-till-i.com/2010/03/11/yql-geo-library-and-introduction-to-geo-hacking-talk/">YQL Geo Library and Introduction to Geo Hacking talk</a></p>
<h3>5.经纬度解析</h3>
<p>经纬度解析就是通过地名取得经纬度数据，同样利用google那个请求地址，可以实现这一功能，请求地址格式为：</p>
<blockquote><p>http://ditu.google.cn/maps/geo?output=json&#038;oe=utf-8<br />
&#038;q=<em>地名的url encode编码</em><br />
&#038;key=<em>你申请到的key</em><br />
&#038;mapclient=jsapi&#038;hl=zh-CN&#038;callback=myfunction</p></blockquote>
<p>参数q为encodeURI(“中国山东省青岛市市北区”)，callback是jsonp回调函数名。</p>
<p><a target="_blank" href="http://ditu.google.cn/maps/geo?output=json&#038;oe=utf-8&#038;q=%E4%B8%AD%E5%9B%BD%E5%B1%B1%E4%B8%9C%E7%9C%81%E9%9D%92%E5%B2%9B%E5%B8%82%E5%B8%82%E5%8C%97%E5%8C%BA&#038;key=ABQIAAAAira30FR5tVprWCJ-8_WcqxSrc1zAT9YCtP2kOyoD7kBAJfliJBROJEdu9hUE13rp9a4OHneyOoW5gg&#038;mapclient=jsapi&#038;hl=zh-CN&#038;callback=myfunction">举个例子</a>，返回结果：</p>
<pre class="brush: jscript; collapse: true; light: false; title: ; toolbar: true; notranslate">
myfunction &amp;&amp; myfunction( {
  &quot;name&quot;: &quot;中国山东省青岛市市北区&quot;,
  &quot;Status&quot;: {
    &quot;code&quot;: 200,
    &quot;request&quot;: &quot;geocode&quot;
  },
  &quot;Placemark&quot;: [ {
    &quot;id&quot;: &quot;p1&quot;,
    &quot;address&quot;: &quot;中国山东省青岛市市北区&quot;,
    &quot;AddressDetails&quot;: {
   &quot;Accuracy&quot; : 4,
   &quot;Country&quot; : {
      &quot;AdministrativeArea&quot; : {
         &quot;AdministrativeAreaName&quot; : &quot;山东省&quot;,
         &quot;Locality&quot; : {
            &quot;DependentLocality&quot; : {
               &quot;DependentLocalityName&quot; : &quot;市北区&quot;
            },
            &quot;LocalityName&quot; : &quot;青岛市&quot;
         }
      },
      &quot;CountryName&quot; : &quot;中国&quot;,
      &quot;CountryNameCode&quot; : &quot;CN&quot;
   }
},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.1237216,
        &quot;south&quot;: 36.0515859,
        &quot;east&quot;: 120.4388307,
        &quot;west&quot;: 120.3107713
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3748010, 36.0876620, 0 ]
    }
  } ]
}
 )
</pre>
<h3>6.google maps 图片接口</h3>
<p>有时候我们只想展示简单的地图，不需要交互和拖动，可以通过google maps提供的<a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/staticmaps/" target="_blank">静态地图API</a>引入动态生成的地图图片，不过需要为你的域名申请一个key。</p>
<p>引入图片的url格式为：</p>
<pre class="brush: jscript; title: ; notranslate">

http://maps.google.com/maps/api/staticmap?

sensor=false
&amp;size=200x200
&amp;maptype=roadmap
&amp;key=&lt;em&gt;你申请到的KEY&lt;/em&gt;
&amp;markers=color:blue|label:1|37.4447,-122.161
&amp;markers=color:red|label:2|37.3385,-121.886
&amp;markers=color:green|label:3|37.3716,-122.038
&amp;markers=color:yellow|label:4|37.7792,-122.42
</pre>
<p>得到图片：</p>
<p><img src="http://maps.google.com/maps/api/staticmap?sensor=false&#038;size=400x250&#038;maptype=roadmap&#038;key=ABQIAAAANYuHabJr5Z8J0b86Q2gfvhR1W14e20gxBFMhpdYy_DdVp1kFtxTi-_5WaVDeQjdfRBmrQT3Diu153g&#038;markers=color:blue|label:1|37.4447,-122.161&#038;markers=color:red|label:2|37.3385,-121.886&#038;markers=color:green|label:3|37.3716,-122.038&#038;markers=color:yellow|label:4|37.7792,-122.42" alt="null" /></p>
<h3>后记</h3>
<p>关于地图的更多操作，可以参见以前的这篇文章：<a target="_blank" href="http://www.oncoding.cn/2009/google-maps-api/">Google Maps Api介绍与基础操作</a>。</p>
<p>随着互联网的发展，越来越多的功能可以在前端实现，出现了越来越多的强大的第三方服务，我们可以很方便的在我们的网站上加入一些实用的功能。这也许就是web2.0的魅力吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2010/geo-location-frontend/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>JavaScript单元测试工具 — QUnit</title>
		<link>http://www.oncoding.cn/2010/javascript-unit-testing-qunit/</link>
		<comments>http://www.oncoding.cn/2010/javascript-unit-testing-qunit/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 04:32:47 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[QUnit]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=629</guid>
		<description><![CDATA[QUnit是jQuery团队开发的JavaScript单元测试工具，使用方便，界面美观。近期试用了一下并进一步了解了JavaScript单元测试，记录一下所思所得。 什么是单元测试 单元测试又称为模块测试，是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。单元测试主要是用来检验程式的内部逻辑，也称为个体测试、结构测试或逻辑驱动测试。通常由撰写程式码的程式设计师负责进行。 通常来说，程式設計師每修改一次程式就會進行最少一次單元測試，在編寫程式的過程中前後很可能要進行多次單元測試，以證實程式達到軟件規格書(en:Specification)要求的工作目標，沒有臭蟲；雖然单元测试不是什么必须的，但也不坏，這牽涉到專案管理的政策決定。 —— 维基百科 (中文，英文) 为什么JavaScript需要单元测试 由于存在浏览器解析环境、用户操作习惯等差异，前端程序的许多问题是无法捕捉或重现的，现在前端程序的测试多是黑盒测试，即靠点击点击点击来寻找程序bug。这种方式既费时费力，又无法保证测试的覆盖面。 同时，前端逻辑和交互越来越复杂，和其他编程语言一样，一个函数，一个模块，在修改bug或添加新功能的过程中，很容易就产生新的bug，或使老的bug复活。这种情况下，反复进行黑盒测试，其工作量和测试质量是可想而知的。 此外，浏览器兼容性测试是前端程序测试的重要一环，在多个浏览器之间测试前端程序，上面说的工作量就会成n倍的增加。 为什么我们的前端程序如此脆弱？就是因为没用单元测试。。 假如使用了单元测试，上边的问题就变得很容易了，当然前提是你要花时间去研究和编写测试用例。 根据函数或模块的源代码，编写出包含各种情况的测试用例，每次解决bug或添加新功能，都随时更新这个用例然后进行测试，很容易就找出新bug和“复活”的老bug。 测试兼容性，只需要在不同的浏览器中分别运行这个测试，问题就一目了然了。 也许白盒比黑盒要多费几倍的脑子，但想想我们那脆弱的程序，想想那些随时冒出来的烦人的老bug，费点脑子，值了！ 使用QUnit 注：下面的内容主要参考了 QUnit文档 和 NetTuts+的这篇文章。 建立一个测试页面，引入 qunit.js 和 qunit.css 这两个必需的文件，这两个文件是存放在github上的，鉴于目前操蛋的互联网环境，最好下载到本地调用。 注：body中的元素id命名必须依照如下形式，否则无法正常显示。 测试示例 下面是一个最简单的函数测试用例，解释请见程序注释。 module( name, [lifecycle] ) 函数指定测试模块和周期。 ok( state, [message] ) 是QUnit中最常用的一个判断函数，只能判断true和false。 DEMO在这里，看一下测试结果： 结果都是绿的，说明两条测试语句都符合设定的规则。可以尝试修改下规则 就可以看到爆红了。。 更多测试判断 除了ok()之外，QUnit还有如下几个判断函数： 相等判断equals( actual, expected, [message] ) 示例： 相同判断(包含数组、对象等)same( actual, expected, [message] ) [...]]]></description>
			<content:encoded><![CDATA[<p>QUnit是jQuery团队开发的JavaScript单元测试工具，使用方便，界面美观。近期试用了一下并进一步了解了JavaScript单元测试，记录一下所思所得。</p>
<h3>什么是单元测试</h3>
<blockquote><p>单元测试又称为模块测试，是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。单元测试主要是用来检验程式的内部逻辑，也称为个体测试、结构测试或逻辑驱动测试。通常由撰写程式码的程式设计师负责进行。</p>
<p>通常来说，程式設計師每修改一次程式就會進行最少一次單元測試，在編寫程式的過程中前後很可能要進行多次單元測試，以證實程式達到軟件規格書(en:Specification)要求的工作目標，沒有臭蟲；雖然单元测试不是什么必须的，但也不坏，這牽涉到專案管理的政策決定。</p>
<p>—— 维基百科 (<a href="http://zh.wikipedia.org/wiki/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95" target="_blank">中文</a>，<a href="http://en.wikipedia.org/wiki/Unit_testing" target="_blank">英文</a>)</p></blockquote>
<h3>为什么JavaScript需要单元测试</h3>
<p><span id="more-629"></span><br />
由于存在浏览器解析环境、用户操作习惯等差异，前端程序的许多问题是无法捕捉或重现的，现在前端程序的测试多是<a href="http://zh.wikipedia.org/zh-cn/%E9%BB%91%E7%9B%92%E6%B5%8B%E8%AF%95" target="_blank">黑盒测试</a>，即靠点击点击点击来寻找程序bug。这种方式既费时费力，又无法保证测试的覆盖面。</p>
<p>同时，前端逻辑和交互越来越复杂，和其他编程语言一样，一个函数，一个模块，在修改bug或添加新功能的过程中，很容易就产生新的bug，或使老的bug复活。这种情况下，反复进行黑盒测试，其工作量和测试质量是可想而知的。</p>
<p>此外，浏览器兼容性测试是前端程序测试的重要一环，在多个浏览器之间测试前端程序，上面说的工作量就会成n倍的增加。</p>
<p><strong>为什么我们的前端程序如此脆弱？就是因为没用单元测试。。</strong></p>
<p>假如使用了单元测试，上边的问题就变得很容易了，当然前提是你要花时间去研究和编写测试用例。</p>
<p>根据函数或模块的源代码，编写出包含各种情况的测试用例，每次解决bug或添加新功能，都随时更新这个用例然后进行测试，很容易就找出新bug和“复活”的老bug。</p>
<p>测试兼容性，只需要在不同的浏览器中分别运行这个测试，问题就一目了然了。</p>
<p>也许白盒比黑盒要多费几倍的脑子，但想想我们那脆弱的程序，想想那些随时冒出来的烦人的老bug，费点脑子，值了！</p>
<h3>使用QUnit</h3>
<p>注：下面的内容主要参考了 <a href="http://docs.jquery.com/QUnit" target="_blank">QUnit文档</a> 和 <a href="http://net.tutsplus.com/tutorials/javascript-ajax/how-to-test-your-javascript-code-with-qunit" target="_blank">NetTuts+的这篇文章</a>。</p>
<p>建立一个测试页面，引入 <a href="http://github.com/jquery/qunit/raw/master/qunit/qunit.js" target="_blank">qunit.js</a> 和 <a href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" target="_blank">qunit.css</a> 这两个必需的文件，这两个文件是存放在github上的，鉴于目前操蛋的互联网环境，最好下载到本地调用。</p>
<p>注：body中的元素id命名必须依照如下形式，否则无法正常显示。</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;http://github.com/jquery/qunit/raw/master/qunit/qunit.css&quot; type=&quot;text/css&quot; media=&quot;screen&quot; /&gt;
  &lt;script type=&quot;text/javascript&quot; src=&quot;http://github.com/jquery/qunit/raw/master/qunit/qunit.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1 id=&quot;qunit-header&quot;&gt;QUnit example&lt;/h1&gt;
  &lt;h2 id=&quot;qunit-banner&quot;&gt;&lt;/h2&gt;
  &lt;h2 id=&quot;qunit-userAgent&quot;&gt;&lt;/h2&gt;
  &lt;ol id=&quot;qunit-tests&quot;&gt;&lt;/ol&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<h3>测试示例</h3>
<p>下面是一个最简单的函数测试用例，解释请见程序注释。</p>
<pre class="brush: jscript; title: ; notranslate">
    //定义测试模块
    module( &quot;测试示例&quot; );
    //定义一个简单的函数，判断参数是不是数字
    function simpleTest(para) {
      if(typeof para == &quot;number&quot;) {
        return true;
      }
      else{
        return false;
      }
    }
    //开始单元测试
    test('simpleTest()', function() {
      //列举各种可能的情况，注意使用 ! 保证表达式符合应该的逻辑
      ok(simpleTest(2), '2是一个数字');
      ok(!simpleTest(&quot;2&quot;), '&quot;2&quot;不是一个数字');
    });
</pre>
<p><a href="http://docs.jquery.com/QUnit/module#namelifecycle" target="_blank">module( name, [lifecycle] ) </a>函数指定测试模块和周期。</p>
<p><a href="http://docs.jquery.com/QUnit/ok#statemessage" target="_blank">ok( state, [message] ) </a>是QUnit中最常用的一个判断函数，只能判断true和false。</p>
<p><a href="http://www.oncoding.cn/demos/qunit" target="_blank">DEMO在这里</a>，看一下测试结果：</p>
<p class="aligncenter">
<div class="wp-caption " style="width:336px"><img class="size-full wp-image-644" title="qunit" src="http://www.oncoding.cn/wp-content/uploads/2010/02/qunit.jpg" alt="" width="326" height="227" /></div>
</p>
<p>结果都是绿的，说明两条测试语句都符合设定的规则。可以尝试修改下规则</p>
<pre class="brush: jscript; title: ; notranslate">
//...
ok(simpleTest(&quot;2&quot;), '&quot;2&quot;是一个数字');
//...
</pre>
<p>就可以看到爆红了。。</p>
<h3>更多测试判断</h3>
<p>除了ok()之外，QUnit还有如下几个判断函数：</p>
<h4>相等判断<a href="http://docs.jquery.com/QUnit/equals#actualexpectedmessage" target="_blank">equals( actual, expected, [message] ) </a></h4>
<p>示例：</p>
<pre class="brush: jscript; title: ; notranslate">
  //定义一个简单的函数，返回数字和2的乘积
    function simpleTest1(para) {
      return para * 2;
    }
    //开始单元测试
    test('simpleTest1()', function() {
      //列举各种可能的情况
      equals(simpleTest1(2), 4, '2 * 2 等于 4');
      equals(simpleTest(2), 3, '2 * 2 等于 3');
    });
</pre>
<h4>相同判断(包含数组、对象等)<a href="http://docs.jquery.com/QUnit/same#actualexpectedmessage" target="_blank">same( actual, expected, [message] ) </a></h4>
<p>示例：</p>
<pre class="brush: jscript; title: ; notranslate">
  //定义一个简单的函数，返回一个数组
    function simpleTest2() {
      return [1, 2];
    }
    //开始单元测试
    test('simpleTest2()', function() {
      //列举各种可能的情况
      equals(simpleTest2(), [1, 2], '函数返回数组[1, 2]');
      equals(simpleTest2(), [1, 1], '函数返回数组[1, 1]');
    });
</pre>
<p>same()和意思和equals()差不多，但same()可以判断数组、对象等的相同，而equals不能。</p>
<h4>异步与Ajax</h4>
<p>对于异步程序的测试，如setTimeout、setInterval、Ajax等情况，按照上面的方法，在异步调用执行之前，测试就已完成并输出了结果。这时，配合使用QUnit提供的两个函数：<a href="http://docs.jquery.com/QUnit/stop#timeout" target="_blank">stop( [timeout] ) </a> 和 <a href="http://docs.jquery.com/QUnit/start" target="_blank">start()</a>，也可以轻松搞定。</p>
<p>直接看例子：</p>
<pre class="brush: jscript; title: ; notranslate">
    //异步测试
    module( &quot;异步测试示例&quot; );
    //setTimeout
    test('asynchronous test', function() {
      // 暂停测试
      stop();

      setTimeout(function() {
        ok(true, '完成运行');
        //待测试完成后，恢复
        start();
      }, 100)
    })
    //另一种形式
    asyncTest('asynchronous test', function() {
      setTimeout(function() {
        ok(true);
        //待测试完成后，恢复
        start();
      }, 100)
    })
</pre>
<p>Ajax也是类似的道理：</p>
<pre class="brush: jscript; title: ; notranslate">
    //Ajax测试
    function ajax(successCallback) {
      $.ajax({
        url: 'server.php',
        success: successCallback
      });
    }

    test('asynchronous test', function() {
      // 暂停测试
      stop();

      ajax(function() {
        // 异步调用判断
      })

      setTimeout(function() {
        //异步测试完成后，恢复
        start();
      }, 2000);
    })
</pre>
<h3>了解更多</h3>
<blockquote>
<ul>
<li><a href="http://docs.jquery.com/QUnit" target="_blank">QUnit文档</a></li>
<li><a href="http://net.tutsplus.com/tutorials/javascript-ajax/how-to-test-your-javascript-code-with-qunit" target="_blank">How to Test your JavaScript Code with QUnit</a></li>
<li><a href="http://www.swift-lizard.com/2009/11/24/test-driven-development-with-jquery-qunit/" target="_blank">Development with jQuery &amp; Qunit</a></li>
<li><a href="http://testswarm.com/" target="_blank">TestSwarm</a></li>
</ul>
</blockquote>
<p style="text-align: right;"><a href="http://www.oncoding.cn/2010/javascript-unit-testing-qunit/">幼学笔记</a>原创内容，根据<a href="http://creativecommons.org/licenses/by-nc-sa/2.5/">CC协议</a>发布，欢迎具名转载。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2010/javascript-unit-testing-qunit/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>哥写的不是程序，是寂寞</title>
		<link>http://www.oncoding.cn/2009/lonesome-coding/</link>
		<comments>http://www.oncoding.cn/2009/lonesome-coding/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 08:46:58 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[扯淡]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[寂寞]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=362</guid>
		<description><![CDATA[当一群无限的牛人把一门有限的语言玩到一种山穷水尽又柳暗花明的地步，那个时候，他们写的不再是程序，是寂寞。 JavaScript就是这样一种语言，JavaScript背后就有这样一群牛人，这些人大抵分两种： 一种是Douglas Crockford这样的大牛，他们已经技术上登峰造极，生活上名利双收。剩下要做的就是到处演演讲，搞搞活动，偶尔扔出几篇小文章供人崇拜。他们温文尔雅谦卑和蔼的面孔后面，总是藏着那么一种悲天悯人、众人皆醉我独醒的让人忧伤而蛋疼的笑容。他们带着这样一种态度，去讲课，去布道，去度假。。闲云野鹤，悠哉游哉。 他们是寂寞的，另一种就是在“找寂寞”的。 之前看到有日本人写的JS多线程框架，洋洋洒洒1万5千行代码，把个本来单线程的语言整的像多线程运行一般无二致。粗读代码，令人震精，把传进来个函数拆分组合，顺成一条新的程序去运行，程序严谨，条理清晰。世上函数何止亿万，程序亦分三六九等，他们居然有这个魄力去重建规则。 又见有人写的基于V8的服务器端js框架，V8之快有所耳闻目睹，却从没想过它可以放到服务器上使。asp的时代早已过去，服务端语言变得越来越复杂，让js这个为浏览器而存活的语言去提供网站服务，有魄力，够寂寞。 。。。 这几天看到了太多寂寞的牛人的寂寞程序，每每让我内牛满面欲火焚身。自己皮袍下藏着小顿时暴漏无遗。时时拷问自己，我有什么资格谈寂寞，每思及此，则心情振奋。 撰文以共勉。]]></description>
			<content:encoded><![CDATA[<p>当一群无限的牛人把一门有限的语言玩到一种山穷水尽又柳暗花明的地步，那个时候，他们写的不再是程序，是寂寞。</p>
<p>JavaScript就是这样一种语言，JavaScript背后就有这样一群牛人，这些人大抵分两种：</p>
<p>一种是<a href="http://dancewithnet.com/2009/03/29/douglas-crockford/" target="_blank">Douglas Crockford</a>这样的大牛，他们已经技术上登峰造极，生活上名利双收。剩下要做的就是到处演演讲，搞搞活动，偶尔扔出几篇小文章供人崇拜。他们温文尔雅谦卑和蔼的面孔后面，总是藏着那么一种悲天悯人、众人皆醉我独醒的让人忧伤而蛋疼的笑容。他们带着这样一种态度，去讲课，去布道，去度假。。闲云野鹤，悠哉游哉。</p>
<div id="attachment_363" class="wp-caption aligncenter" style="width: 210px"><a href="http://www.oncoding.cn/wp-content/uploads/2009/11/422986656_dd40fb547b.jpg" target="_blank"><img class="size-full wp-image-363" title="Douglas Crockford的寂寞笑容" src="http://www.oncoding.cn/wp-content/uploads/2009/11/422986656_dd40fb547b.jpg" alt="Douglas Crockford的寂寞笑容" width="200" height="300" /></a><p class="wp-caption-text">Douglas Crockford的寂寞笑容</p></div>
<p>他们是寂寞的，另一种就是在“找寂寞”的。</p>
<p>之前看到有<a href="http://jsthread.sourceforge.net/" target="_blank">日本人写的JS多线程框架</a>，洋洋洒洒1万5千行代码，把个本来单线程的语言整的像多线程运行一般无二致。粗读代码，令人震精，把传进来个函数拆分组合，顺成一条新的程序去运行，程序严谨，条理清晰。世上函数何止亿万，程序亦分三六九等，他们居然有这个魄力去重建规则。</p>
<p>又见有人写的<a href="http://nodejs.org/" target="_blank">基于V8的服务器端js框架</a>，V8之快有所耳闻目睹，却从没想过它可以放到服务器上使。asp的时代早已过去，服务端语言变得越来越复杂，让js这个为浏览器而存活的语言去提供网站服务，有魄力，够寂寞。</p>
<p>。。。</p>
<p>这几天看到了太多寂寞的牛人的寂寞程序，每每让我内牛满面欲火焚身。自己皮袍下藏着小顿时暴漏无遗。时时拷问自己，我有什么资格谈寂寞，每思及此，则心情振奋。</p>
<p>撰文以共勉。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2009/lonesome-coding/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Javascript 最佳实践</title>
		<link>http://www.oncoding.cn/2009/javascript-best-practices/</link>
		<comments>http://www.oncoding.cn/2009/javascript-best-practices/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 14:59:37 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[最佳实践]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=344</guid>
		<description><![CDATA[原文：JavaScript Toolbos 翻译：幸福收藏夹 简介 这个文档是基于Javascript社区众多开发者的意见和经验，在开发Javascript代码上的最佳实践和首选的方案的明细表。因为这是一个推荐的表而非原则性的方案，经验丰富的开发者可能对下面的表达会有略有不同的见解。 文章目录： 1. 总是使用 ‘var’ 2. 特性检测而非浏览器检测 3. 使用方括号记法 4. 避免 ‘eval’ 5. 正确地引用表单和表单元素 6. 避免 ‘with’ 声明 7. 在锚点中使用 “onclick” 替代 “javascript: Pseudo-Protocol” 8. 使用一元 ‘+’ 号运算符使类型转向Number 9. 避免 document.all 10. 不要在脚本代码块中使用HTML注释 11. 避免乱用全局命名空间 12. 避免同步的 ‘Ajax’ 调用 13. 使用 JSON 14. 使用正确的&#60;script&#62;标签 1. 总是使用 ‘var’ 在Javascript中，变量不是全局范围的就是函数范围的，使用”var”关键词将是保持变量简洁明了的关键。当声明一个或者是全局或者是函数级（function-level）的变量，需总是前置”var”关键词，下面的例子将强调不这样做潜在的问题。 不使用 Var 造成的问题 [...]]]></description>
			<content:encoded><![CDATA[<p>原文：<a href="http://www.javascripttoolbox.com/bestpractices/" target="_blank">JavaScript Toolbos</a></p>
<p>翻译：<a href="http://www.happinesz.cn/archives/1171/" target="_blank">幸福收藏夹</a></p>
<h3>简介</h3>
<p>这个文档是基于Javascript社区众多开发者的意见和经验，在开发Javascript代码上的最佳实践和首选的方案的明细表。因为这是一个推荐的表而非原则性的方案，经验丰富的开发者可能对下面的表达会有略有不同的见解。</p>
<h3>文章目录：</h3>
<p><span id="more-344"></span></p>
<blockquote><p>
<a href="#jsbp1">1. 总是使用 ‘var’</a><br />
<a href="#jsbp2">2. 特性检测而非浏览器检测</a><br />
<a href="#jsbp3">3. 使用方括号记法</a><br />
<a href="#jsbp4">4. 避免 ‘eval’</a><br />
<a href="#jsbp5">5. 正确地引用表单和表单元素</a><br />
<a href="#jsbp6">6. 避免 ‘with’ 声明</a><br />
<a href="#jsbp7">7. 在锚点中使用 “onclick” 替代 “javascript: Pseudo-Protocol”</a><br />
<a href="#jsbp8">8. 使用一元 ‘+’ 号运算符使类型转向Number</a><br />
<a href="#jsbp9">9. 避免 document.all</a><br />
<a href="#jsbp10">10. 不要在脚本代码块中使用HTML注释</a><br />
<a href="#jsbp11">11. 避免乱用全局命名空间</a><br />
<a href="#jsbp12">12. 避免同步的 ‘Ajax’ 调用</a><br />
<a href="#jsbp13">13. 使用 JSON</a><br />
<a href="#jsbp14">14. 使用正确的&lt;script&gt;标签</a></p></blockquote>
<h3 id="jsbp1">1. 总是使用 ‘var’</h3>
<p>在Javascript中，变量不是全局范围的就是函数范围的，使用”var”关键词将是保持变量简洁明了的关键。当声明一个或者是全局或者是函数级（function-level）的变量，需总是前置”var”关键词，下面的例子将强调不这样做潜在的问题。</p>
<p>不使用 Var 造成的问题</p>
<pre class="brush: jscript; title: ; notranslate">
var i=0; // This is good - creates a global variable
function test() {
   for (i=0; i&lt;10; i++) {
      alert(&quot;Hello World!&quot;);
   }
}
test();
alert(i); // The global variable i is now 10!
</pre>
<p>因为变量函数中变量 i 并没有使用 var 使其成为函数级的变量，在这个例子中它引用了全局变量。总是使用 var 来声明全局变量是一个很多的做法，但至关重要的一点是使用 var 定义一个函数范围的变量。下面这两个方法在功能上是相同的：</p>
<p>正确的函数</p>
<pre class="brush: jscript; title: ; notranslate">
function test() {
   var i=0;
   for (i=0; i&lt;10; i++) {
      alert(&quot;Hello World!&quot;);
   }
}
</pre>
<p>正确的函数</p>
<pre class="brush: jscript; title: ; notranslate">
function test() {
   for (var i=0; i&lt;10; i++) {
      alert(&quot;Hello World!&quot;);
   }
}
</pre>
<h3 id="jsbp2">2. 特性检测而非浏览器检测</h3>
<p>一些代码是写来发现浏览器版本并基于用户正使用的客户端的对其执行不同行为。这个，总的来说，是一个非常糟的实践。更好的方法是使用特性检测，在使用一个老浏览器可能不支持的高级的特性之前，首先检测（浏览器的）是否有这个功能或特性，然后使用它。这单独检测浏览器版本来得更好，即使你知道它的性能。你可以在 http://www.jibbering.com/faq/faq_notes/not_browser_detect.html找到一个深入讨论这个问题的文章。</p>
<p>例子：</p>
<pre class="brush: jscript; title: ; notranslate">
if (document.getElementById) {
   var element = document.getElementById('MyId');
}
else {
   alert('Your browser lacks the capabilities required to run this script!');
}
</pre>
<h3 id="jsbp3">3. 使用方括号记法</h3>
<p>当访问由执行时决定或者包括要不能用”.”号访问的对象属性，使用方括号记法。如果你不是一个经验丰富的Javascript程序员，总是使用方括号是一个不错的做法</p>
<p>对象的属性由两种固定的方法来访问：”.”记法和”[ ]“方括号记法：</p>
<p>“.”号记法</p>
<pre class="brush: jscript; title: ; notranslate">
MyObject.property
</pre>
<p>“[ ]“方括号记法</p>
<pre class="brush: jscript; title: ; notranslate">
MyObject[&quot;property&quot;]
</pre>
<p>使用”.”号，属性名是硬代码，不能在执行时改变。使用”[ ]“方括号，属性名是一个通过计算属性名而来的字符串。字符串要以是硬代码，也可能是变量，甚至可以是一个调回一个字母串值的函数。如果一个属性名在执行产生，方括号是必须，如果你有 “value1&#8243;, “value2&#8243;, 和 “value3&#8243;这样的属性，并且想利用变量 i=2来访问</p>
<p>这个可以运行：</p>
<pre class="brush: jscript; title: ; notranslate">
MyObject[&quot;value&quot;+i]
</pre>
<p>这个不可以：</p>
<pre class="brush: jscript; title: ; notranslate">
MyObject.value+i
</pre>
<p>并且在某些服务器端环境（PHP、Struts等）下，Form 表单被附加了 [ ] 号来表示 Form 表单在服务器端必须被当作数组来对待。如此，用”.”号来引用一个包含 [ ] 号的字段将不会执行，因为 [ ] 是引用一个 Javascript 数组的语法。所以，[ ] 号记法是必须的：</p>
<p>这个可以运行：</p>
<pre class="brush: jscript; title: ; notranslate">
formref.elements[&quot;name[]&quot;]
</pre>
<p>这个不可以：</p>
<pre class="brush: jscript; title: ; notranslate">
formref.elements.name[]
</pre>
<p>推荐使用”[ ]“方括号记法是说当其需要时（明显地）总是使用它。当不是严格需要使用它的时候，它是一个私人的偏好和习惯。一个好的经验原则是，使用”.”号记法访问标准的对象属性，使用”[ ]“方括号记法访问由页面定义的对象属性。这样，document["getElementById"]() 是一个完美可行的”[ ]“方括号记法用法，但 document.getElementById() 在语法上是首选，因为 getElementById 是一个 DOM 规范中定义的一个标准文档对象属性。混合使用这两个记法使哪个是标准对象属性，哪个属性名是由上下文所定义的，在代码中显得清晰明了：</p>
<pre class="brush: jscript; title: ; notranslate">
document.forms[&quot;myformname&quot;].elements[&quot;myinput&quot;].value
</pre>
<p>这里，forms 是 document 的一个标准属性，而表单名 myformname 则是由页面所定义的。同时，elements 和 value 属性都是由规范所定义的标准属性。而 myinput 则是由页面所定义的。这页是句法让人非常容易理解（代码的内容），是一个推荐遵循的习惯用法，但不是严格原则。</p>
<h3 id="jsbp4">4. 避免 ‘eval’</h3>
<p>在Javascript中，eval()功能是一个在执行期中执行任意代码的方法。在几乎所有的情况下，eval 都不应该被使用。如果它出现在你的页面中，则表明你所做的有更好的方法。举一个例子，eval 通常被不知道要使用方括号记法的程序员所使用。</p>
<p>原则上，”Eval is evil（Eval是魔鬼）”。别使用它，除非你是一个经验丰富的开发者并且知道你的情况是个例外。</p>
<h3 id="jsbp5">5. 正确地引用表单和表单元素</h3>
<p>所有的 HTML 表单都应该有一个 name 属性。对于 XHTML 文档来说，name 属性是不被要求的，但 Form 标签中应有相应有 id 属性，并必须用 document.getElementById() 来引用。使用像 document.forms[0] 这样的索引方法来引用表单，在几乎所有情况下，是一个糟糕的做法。有些浏览器把文档中使用 form 来命名的元素当作一个可用的 form 属性。这样并不可靠，不应该使用。</p>
<p>下面这个例子用使用方括号和正确的对象引用方法来展示如何防止错误地引用一个表单的input：</p>
<p>正确引用表单 Input：</p>
<pre class="brush: jscript; title: ; notranslate">
document.forms[&quot;formname&quot;].elements[&quot;inputname&quot;]
</pre>
<p>糟糕的做法:</p>
<pre class="brush: jscript; title: ; notranslate">
document.formname.inputname
</pre>
<p>如果你要引用一个函数里的两个表单元素，较好的做法是先引用这个form对象，并将其储存在变量中。这样避免了重复查询以解决表单的引用：</p>
<pre class="brush: jscript; title: ; notranslate">
var formElements = document.forms[&quot;mainForm&quot;].elements;
formElements[&quot;input1&quot;].value=&quot;a&quot;;
formElements[&quot;input2&quot;].value=&quot;b&quot;;
</pre>
<p>当你使用 onChange 或者其他类似的事件处理方法，一个好的做法是总是通过一个引来把 input 元素本身引用到函数中来。所有 input 元素都带有一个对包含其在内的Form表单有一个引用：</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;input type=&quot;text&quot; name=&quot;address&quot; onChange=&quot;validate(this)&quot;&gt;

function validate(input_obj) {
   // 引用包含这个元素的form
   var theform = input_obj.form;
   // 现在你可以不需要使用硬代码来引用表单自身
   if (theform.elements[&quot;city&quot;].value==&quot;&quot;) {
      alert(&quot;Error&quot;);
   }
}
</pre>
<p>通过对表单元素的引用来访问表单的属性，你可以写一个不包含硬代码的函数来引用这个页面中任何一个有特定名的表单。这是一个非常好的做法，因为函数变得可重用。</p>
<h3 id="jsbp6">6. 避免 ‘with’</h3>
<p>Javascript 中的 with 声明在一个作用域的前端插入一个对象，所以任何属性/变量的引用将会倚着对象被首先解决。这通常被用作一个避免重复引用的快捷方法：</p>
<p>使用 with 的例子：</p>
<pre class="brush: jscript; title: ; notranslate">
with (document.forms[&quot;mainForm&quot;].elements) {
   input1.value = &quot;junk&quot;;
   input2.value = &quot;junk&quot;;
}
</pre>
<p>但问题在于程序员并没有方法来验证 input1 或 input2 实际上已经被当作 Form 元素数组的属性来解决。它首先以为这些名来检测属性，如果找不到，它将会继续（向下）检测这个作用域。最后，它在全局对象中尝试把input1 和 input2 作为一个全局对象来对待，而这以一个错误作为结尾。</p>
<p>变通的方法是：创建一个引用来减少引用的对象，并使用它来解决这些引用。</p>
<p>使用一个引用：</p>
<pre class="brush: jscript; title: ; notranslate">
var elements = document.forms[&quot;mainForm&quot;].elements;
elements.input1.value = &quot;junk&quot;;
elements.input2.value = &quot;junk&quot;;
</pre>
<h3 id="jsbp7">7. 在锚点中使用 “onclick” 替代 “javascript: Pseudo-Protocol”</h3>
<p>如果你想在&lt;a&gt;标签中触发Javascript 代码，选择 onclick 而非 JavaScript: pseudo-protocol；使用 onclick 来运行的 Javascript 代码必须返回 ture 或者false（or an expression than evalues to true or false [这句要怎么翻译呢? 我是这样理解的：一个优先性高于true 或 false 的表达式]）来返回标签本身：如果返回 true，则锚点的 href 将被当作一个一般的链接；如果返回 false，则 href 会被忽略。这就是为什么”return false;” 经常被包含在 onclick 所处理代码的尾部。</p>
<p>正确句法：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;a onclick=&quot;doSomething(); return false;&quot; href=&quot;javascript_required.html&gt;go&lt;/a&gt;
</pre>
<p>在这个实例中，”doSomething()” 函数(定义于页面的某个角落)将在被点击时调用。href 将永远不会被启用了Javascript 的浏览器访问。在你可以提醒Javascript 是必须的、而用户未启用之的浏览器中，文档 javascript_required.html 才会被加载。通常，当你确保用户将会开启 Javascript 支持，为尽量简化，链接将只包含 href=”#”。 而这个做法是不被鼓励的。通常有一个不错的做法是：可以提供没用启用 javascript 一个返回本地的页面。</p>
<p>有时，众多想要分情况来访问一个链接。例如，当一个用户要离开你的一个表单页面，而想先验证来确保没有东西被改变。在这个情况下，你的 onclick 将会访问一个返回询问链接是否应该被遵循的函数：</p>
<p>有条件的链接访问:</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;a href=&quot;/&quot; onClick=&quot;return validate();&quot;&gt;Home&lt;/a&gt;

function validate() {
 return prompt(&quot;Are you sure you want to exit this page?&quot;);
}
</pre>
<p>在这个实例中，validate() 函数必须只返回 ture 或 false。ture 的时候用户将被允许问题 home 页面，或 false 的时候链接不被访问。这个例子提示确认（其行为），以访问 ture 或 false，这完全由用户点击”确实”或者”取消”决定。</p>
<p>下面是一些”不应该”的例子。如果你在自己的页面中看到下面这样的代码，这是不正确的，需要被修改：</p>
<p>什么是不应该做的：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;a href=&quot;javascript:doSomething()&quot;&gt;link&lt;/a&gt;
&lt;a href=&quot;#&quot; onClick=&quot;doSomething()&quot;&gt;link&lt;/a&gt;
&lt;a href=&quot;#&quot; onClick=&quot;javascript:doSomething();&quot;&gt;link&lt;/a&gt;
&lt;a href=&quot;#&quot; onClick=&quot;javascript:doSomething(); return false;&quot;&gt;link&lt;/a&gt;
</pre>
<h3 id="jsbp8">8. 使用一元 ‘+’ 号运算符使类型转向Number</h3>
<p>在Javascript中，”+”号运算符同时充当数学加号和连接符。这会在form表单的域值相加时出现问题，例如，因为Javascript是一个弱类型语言，form 域的值将会被当作数组来处理，而你把它们”+”一起的时候，”+”将被当成连接符，而非数学加号。</p>
<p>有问题的例子:</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;form name=&quot;myform&quot; action=&quot;[url]&quot;&gt;
&lt;input type=&quot;text&quot; name=&quot;val1&quot; value=&quot;1&quot;&gt;
&lt;input type=&quot;text&quot; name=&quot;val2&quot; value=&quot;2&quot;&gt;
&lt;/form&gt;

function total() {
 var theform = document.forms[&quot;myform&quot;];
 var total = theform.elements[&quot;val1&quot;].value + theform.elements[&quot;val2&quot;].value;
 alert(total); // 这个将会弹出 &quot;12&quot;, 但你想要的是 3!
}
</pre>
<p>解决这个问题，Javascript 需要一个提示来让它把这些值当做数字来处理。你可以使用”+”号来把数组转换成数字。给变量或者表达式前置一个”+”号将会强制其当作一个数字来处理，而这也将使得数学”+”得以成功应用。</p>
<p>修改好的代码：</p>
<pre class="brush: jscript; title: ; notranslate">
function total() {
 var theform = document.forms[&quot;myform&quot;];
 var total = (+theform.elements[&quot;val1&quot;].value) + (+theform.elements[&quot;val2&quot;].value);
 alert(total); // This will alert 3
}
</pre>
<h3 id="jsbp9">9. 避免 document.all</h3>
<p>document.all 是由Microsoft 的 IE 所引进的，并不是一个标准的 Javascript DOM 特性。尽管大多数新的浏览器支持它以支持依赖于它的糟糕代码，（而）还有很多浏览器是不支持的。</p>
<p>并没有理由其他方法都不适用，而一个老的IE浏览器（&lt;5.0）需要支持，而在Javascript中使用 document.all 作为一个折衷方法。 你并不需要使用 document.all 来检测其是不是IE浏览器，因为其他浏览器现在一般都支持。</p>
<p>只把 document.all 当做最后的选择：</p>
<pre class="brush: jscript; title: ; notranslate">
if (document.getElementById) {
 var obj = document.getElementById(&quot;myId&quot;);
}
else if (document.all) {
 var obj = document.all(&quot;myId&quot;);
}
</pre>
<p>一些使用 document.all 的原则：</p>
<ul>
<li>* 同尝试其他方法</li>
<li>* 当其作为最后的选择</li>
<li>* 当需要支持 5.0 版本以下的 IE 浏览器</li>
<li>* 总是使用 “if (document.all) { }” 来查看是否支持.</li>
</ul>
<h3 id="jsbp10">10. 不要在脚本代码块中使用HTML注释</h3>
<p>在 Javascript 的旧日子（1995）里，诸如 Netscape 1.0 的一些浏览器并不支持或认识 &lt;script&gt; 标签。所以，当 Javascript 第一次被发布，需要有一个技术来让实些代码不被当做文本显示于旧版浏览器上。有一个”hack” 是在代码中使用 HTML 注释来隐藏这些代码。</p>
<p>使 HTML 注释并不好：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script language=&quot;javascript&quot;&gt;
&lt;!--
   // code here
//--&gt;
&lt;/script&gt;
</pre>
<p>在今天，没有任何一个常用的浏览器会忽略掉 &lt;script&gt; 标签。因此，再没必要隐藏 Javascript 源代码。事实上，它还可以因为下面的理由，被认为是无益的：</p>
<ul>
<li>* 在 XHTML 文档中，源代码将向所有浏览器隐藏并被渲染成无用的（内容）；</li>
<li>* – 在 HTML 注释并不允许 ，这个会让任何递减操作将失效。</li>
</ul>
<h3 id="jsbp11">11. 避免乱用全局命名空间</h3>
<p>一般很少需要全部变量和函数。全局使用将可能导致 Javascript 源文件文档冲突，和代码中止。因此，一个好的做法是在一个全局命名空间内采用函数性的封装。有多个方法可以完成这个任务，有此相对比较复杂。最简单的方法是创建一个全局对象，并把属性和方法指派给这个对象：</p>
<p>创建一个命名空间：</p>
<pre class="brush: jscript; title: ; notranslate">
var MyLib = {}; // global Object cointainer
MyLib.value = 1;
MyLib.increment = function() { MyLib.value++; }
MyLib.show = function() { alert(MyLib.value); }

MyLib.value=6;
MyLib.increment();
MyLib.show(); // alerts 7
</pre>
<p>命名空间也可以使用 Closures（闭包?） 来创建，并且 Private Member Variables （私有变量?） 也可以伪装于 Javascript中。</p>
<h3 id="jsbp12">12. 避免同步的 ‘Ajax’ 调用</h3>
<p>当使用”Ajax”请求时，你要么选择异步模式，要么使用同步模式。当浏览器行为可以继续执行，异步模式将请求放在后台执行，同步模式则会等待请求完成后才继续。</p>
<p>应该避免同步模式做出的请求。这些请求将会对用户禁用浏览器，直至请求返回。一旦服务器忙，并需要一段时间来完成请求，用户的浏览器（或者 OS）将不能做任何其他的事，直至请求超时。</p>
<p>如果你觉得自己的情况需要同步模式，最大的可能是你需要时间来重新想一下你的设计。很少（如果有的话）实际上需要同步模式的 Ajax 请求。</p>
<h3 id="jsbp13">13. 使用 JSON</h3>
<p>当需要将数据结构存储成纯文本，或者通过 Ajax 发送/取回数据结构，尽可能使用 JSON 代替 XML。JSON (JavaScript Object Notation) 是一个更简洁有效的数据存储格式，并且不依赖任何语言（and is a language-neutral）。</p>
<h3 id="jsbp14">14. 使用正确的 &lt;script&gt; 标签</h3>
<p>不造成在 &lt;script&gt; 中的使用LANGUAGE 属性。一个合适的方式是创建如下的 Javascript 代码块：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot;&gt;
// code here
&lt;/script&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2009/javascript-best-practices/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JavaScript程序执行顺序问题总结</title>
		<link>http://www.oncoding.cn/2009/javascript_execution_sequence/</link>
		<comments>http://www.oncoding.cn/2009/javascript_execution_sequence/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 14:47:48 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[地图]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[回调]]></category>
		<category><![CDATA[执行顺序]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=304</guid>
		<description><![CDATA[好记星不如烂笔头，适时的总结梳理知识让人更轻松愉快。今天总结下学习和开发中遇到的JavaScript执行顺序的问题，今天挖个坑，以后会慢慢填，也希望抛砖引玉，能学到更多的东西。 顺序可能比较乱，写多了再整理，有些术语可能运用也不恰当，欢迎批评指正。以下使用的示例程序都经过了本人的实际验证，兼容各大浏览器。OK，步入正题。 1. 变量的声明和引用 变量必须先声明后引用，这个大家是都知道的，但还是要说说，因为后面要说到一个相关的问题。 2. 函数的声明和调用 JavaScript是一种描述型脚本语言，由浏览器进行动态的解析与执行。函数的定义方式大体有以下两种，浏览器对于不同的方式有不同的解析顺序。 页面加载过程中，浏览器会对页面上或载入的每个js代码块(或文件)进行扫描，如果遇到定义式函数，则进行预处理(类似于C等的编译)，处理完成之后再开始由上至下执行；遇到赋值式函数，则只是将函数赋给一个变量，不进行预处理(类似1中变量必须先定义后引用的原则)，待调用到的时候才进行处理。下面举个简单的例子： 正常执行，弹出“Hello World!”，浏览器对Fn1进行了预处理，再从Fn1();开始执行。 Firebug报错：Fn2 is not a function，浏览器未对Fn2进行预处理，依序执行，所以报错Fn2未定义。 关于Javascript的“编译”和执行过程，射雕在《JavaScript运行机制浅探》中有更深入的分析，推荐阅读。 3. 代码块及js文件的处理 “代码块”是指一对标签包裹着的js代码，文件就是指文件啦，废话:D 浏览器对每个块或文件进行独立的扫描，然后对全局的代码进行顺序执行(2中讲到了)。所以，在一个块(文件)中，函数可以在调用之后进行“定义式”定义；但在两个块中，定义函数所在的块必须在函数被调用的块之前。 很绕口，看例子好了： 4. 重复定义函数会覆盖前面的定义 这和变量的重复定义是一样的，代码： 如果是这样呢： 还是弹出“2”，为什么？2都讲了好吧&#8230; 5. body的onload函数与body内部函数的执行 body内部的函数会先于onload的函数执行，测试代码： body的onload事件触发条件是body内容加载完成，而body中的js代码会在这一事件触发之前运行(为什么呢?6告诉你..) 6. JavaScript是多线程or单线程？ 严格来说，JavaScript是没有多线程概念的，所有的程序都是“单线程”依次执行的。 举个不太恰当的例子： 那你肯定要问：那延时执行、Ajax异步加载，不是多线程的吗？没错，下面这样的程序确实看起来像“多线程”： 看上去，fn2()和延时程序是分两个过程再走，但其实，这是JavaScript中的“回调”机制在起作用，类似于操作系统中的“中断和响应” —— 延时程序设置一个“中断”，然后执行fn2()，待1000毫秒时间到后，再回调执行fn1()。 同样，5中body的onload事件调用的函数，也是利用了回调机制——body加载完成之后，回调执行fnOnLoad()函数。 Ajax请求中的数据处理函数也是一样的道理。 关于JavaScript线程问题的更深入讨论，看这篇 javascript中的线程之我见，以及infoQ上的 JavaScript多线程编程简介。 困了，再说一下回调函数吧。 7. 回调函数 回调函数是干嘛用的？就是回调执行的函数嘛，又废话:D 如6所说，最常见的回调就是onclick、onmouseover、onmousedown、onload等等浏览器事件的调用函数；还有Ajax异步请求数据的处理函数；setTimeOut延时执行、setInterval循环执行的函数等。 干脆我们写一个纯粹的回调函数玩： dating运行完之后再执行回调函数onBack —— 约会结束了，暴风骤雨开始了。 今天先写到这里，一些更深入的东西还有待整理，更多的东西还需要继续学习，欢迎批改补充，欢迎指点迷津。 幼学笔记原创内容，根据CC协议发布，欢迎具名转载。]]></description>
			<content:encoded><![CDATA[<p>好记星不如烂笔头，适时的总结梳理知识让人更轻松愉快。今天总结下学习和开发中遇到的JavaScript执行顺序的问题，今天挖个坑，以后会慢慢填，也希望抛砖引玉，能学到更多的东西。</p>
<p>顺序可能比较乱，写多了再整理，有些术语可能运用也不恰当，欢迎批评指正。以下使用的示例程序都经过了本人的实际验证，兼容各大浏览器。OK，步入正题。</p>
<h3 id="id1">1. 变量的声明和引用</h3>
<p>变量必须先声明后引用，这个大家是都知道的，但还是要说说，因为后面要说到一个相关的问题。</p>
<pre class="brush: jscript; title: ; notranslate">
alert(myStr); // 弹出&quot;undefined&quot;;
var myStr = &quot;Hello World!&quot;;
alert(myStr); // 弹出&quot;Hello World&quot;;
</pre>
<h3 id="id2">2. 函数的声明和调用</h3>
<p><span id="more-304"></span></p>
<p>JavaScript是一种描述型脚本语言，由浏览器进行动态的解析与执行。函数的定义方式大体有以下两种，浏览器对于不同的方式有不同的解析顺序。</p>
<pre class="brush: jscript; title: ; notranslate">
//“定义式”函数定义
function Fn1(){
    alert(&quot;Hello World!&quot;);
}
//“赋值式”函数定义
var Fn2 = function(){
    alert(&quot;Hello wild!&quot;);
}
</pre>
<p>页面加载过程中，浏览器会对页面上或载入的每个js代码块(或文件)进行扫描，如果遇到定义式函数，则进行预处理(类似于C等的编译)，处理完成之后再开始由上至下执行；遇到赋值式函数，则只是将函数赋给一个变量，不进行预处理(类似<a href="#id1">1中变量必须先定义后引用的原则</a>)，待调用到的时候才进行处理。下面举个简单的例子：</p>
<pre class="brush: jscript; title: ; notranslate">
//“定义式”函数定义
Fn1();
function Fn1(){
    alert(&quot;Hello World!&quot;);
}
</pre>
<p>正常执行，弹出“Hello World!”，浏览器对Fn1进行了预处理，再从Fn1();开始执行。</p>
<pre class="brush: jscript; title: ; notranslate">
//“赋值式”函数定义
Fn2();
var Fn2 = function(){
    alert(&quot;Hello wild!&quot;);
}
</pre>
<p>Firebug报错：Fn2 is not a function，浏览器未对Fn2进行预处理，依序执行，所以报错Fn2未定义。</p>
<p>关于Javascript的“编译”和执行过程，射雕在<a href="http://lifesinger.org/blog/2009/01/javascript-run-mechanism/" target="_blank">《JavaScript运行机制浅探》</a>中有更深入的分析，推荐阅读。</p>
<h3>3. 代码块及js文件的处理</h3>
<p>“代码块”是指一对<script type="text/javascript"></script>标签包裹着的js代码，文件就是指文件啦，废话:D</p>
<p>浏览器对每个块或文件进行独立的扫描，然后对全局的代码进行顺序执行(<a href="#id2">2中讲到了</a>)。所以，在一个块(文件)中，函数可以在调用之后进行“定义式”定义；但在两个块中，定义函数所在的块必须在函数被调用的块之前。</p>
<p>很绕口，看例子好了：</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot;&gt;
    Fn();
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
    function Fn(){
        alert(&quot;Hello World!&quot;);
    }
&lt;/script&gt;
// 报错：Fn is notdefined，两个块换过来就对了
</pre>
<h3>4. 重复定义函数会覆盖前面的定义</h3>
<p>这和变量的重复定义是一样的，代码：</p>
<pre class="brush: jscript; title: ; notranslate">
function fn(){
    alert(1);
}
function fn(){
    alert(2);
}
fn();
// 弹出：“2”
</pre>
<p>如果是这样呢：</p>
<pre class="brush: jscript; title: ; notranslate">
fn();
function fn(){
    alert(1);
}
function fn(){
    alert(2);
}
// 还是弹出：“2”
</pre>
<p>还是弹出“2”，为什么？<a href="#id2">2都讲了好吧&#8230;</a></p>
<h3 id="id5">5. body的onload函数与body内部函数的执行</h3>
<p>body内部的函数会先于onload的函数执行，测试代码：</p>
<pre class="brush: jscript; title: ; notranslate">
//html head...
&lt;script type=&quot;text/javascript&quot;&gt;
function fnOnLoad(){
    alert(&quot;I am outside the Wall!&quot;);
}
&lt;/script&gt;
&lt;body onload=&quot;fnOnLoad();&quot;&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
    alert(&quot;I am inside the Wall..&quot;);
&lt;/script&gt;
&lt;/body&gt;
//先弹出“I am inside the Wall..”;
//后弹出“I am outside the Wall!”
</pre>
<p>body的onload事件触发条件是body内容加载完成，而body中的js代码会在这一事件触发之前运行(为什么呢?<a href="#id6">6告诉你..</a>)</p>
<h3 id="id6">6. JavaScript是多线程or单线程？</h3>
<p>严格来说，JavaScript是没有多线程概念的，所有的程序都是“单线程”依次执行的。</p>
<p>举个不太恰当的例子：</p>
<pre class="brush: jscript; title: ; notranslate">
function fn1(){
    var sum = 0;
    for(var ind=0; ind&lt;1000; ind++) {
        sum += ind;
    }
    alert(&quot;答案是&quot;+sum);
}
function fn2(){
    alert(&quot;早知道了，我就是不说&quot;);
}
fn1();
fn2();
//先弹出：“答案是499500”，
//后弹出：“早知道了，我就是不说”
</pre>
<p>那你肯定要问：那延时执行、Ajax异步加载，不是多线程的吗？没错，下面这样的程序确实看起来像“多线程”：</p>
<pre class="brush: jscript; title: ; notranslate">
function fn1(){
    setTimeout(function(){
        alert(&quot;我先调用&quot;)
    },1000);
}
function fn2(){
    alert(&quot;我后调用&quot;);
}
fn1();
fn2();
// 先弹出：“我后调用”，
// 1秒后弹出：“我先调用”
</pre>
<p>看上去，fn2()和延时程序是分两个过程再走，但其实，这是JavaScript中的“回调”机制在起作用，类似于操作系统中的“中断和响应” —— 延时程序设置一个“中断”，然后执行fn2()，待1000毫秒时间到后，再回调执行fn1()。</p>
<p>同样，<a href="#id5">5中body的onload事件</a>调用的函数，也是利用了回调机制——body加载完成之后，回调执行fnOnLoad()函数。</p>
<p>Ajax请求中的数据处理函数也是一样的道理。</p>
<p>关于JavaScript线程问题的更深入讨论，看这篇 <a href="http://blog.csdn.net/turkeyzhou/archive/2008/08/07/2784934.aspx" target="_blank">javascript中的线程之我见</a>，以及infoQ上的 <a href="http://www.infoq.com/cn/articles/js_multithread;jsessionid=15A6283AD9008B0AFAB542C42A10B81F" target="_blank">JavaScript多线程编程简介</a>。</p>
<p>困了，再说一下回调函数吧。</p>
<h3>7. 回调函数</h3>
<p>回调函数是干嘛用的？就是回调执行的函数嘛，又废话:D</p>
<p>如6所说，最常见的回调就是onclick、onmouseover、onmousedown、onload等等浏览器事件的调用函数；还有Ajax异步请求数据的处理函数；setTimeOut延时执行、setInterval循环执行的函数等。</p>
<p>干脆我们写一个纯粹的回调函数玩：</p>
<pre class="brush: jscript; title: ; notranslate">
function onBack(num){
    alert(&quot;姗姗我来迟了&quot;);
    // 执行num个耳光
}
function dating(hours, callBack){
    var SP= 0; // SP,愤怒值
    //女猪脚在雪里站了hours个钟头
    //循环开始..
    SP ++;
    //循环结束...
    callBack(SP);
}

dating(1, onBack);
</pre>
<p>dating运行完之后再执行回调函数onBack —— 约会结束了，暴风骤雨开始了。</p>
<p>今天先写到这里，一些更深入的东西还有待整理，更多的东西还需要继续学习，欢迎批改补充，欢迎指点迷津。</p>
<p style="text-align: right;"><a href="http://www.oncoding.cn/2009/javascript_execution_sequence/">幼学笔记</a>原创内容，根据<a href="http://creativecommons.org/licenses/by-nc-sa/2.5/">CC协议</a>发布，欢迎具名转载。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2009/javascript_execution_sequence/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>JavaScript中使用JSON</title>
		<link>http://www.oncoding.cn/2009/javascript-json/</link>
		<comments>http://www.oncoding.cn/2009/javascript-json/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 13:44:26 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[json]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=717</guid>
		<description><![CDATA[虽说JavaScript原生支持JSON，但真用到的时候，也遇到了一些麻烦。下面整理一些JSON相关的JS程序。 1. 将JSON字串解析为对象 最简单的方法是使用eval： 但如果JSON字符串不严谨或被利用漏洞，eval会产生一些隐患，这是可以使用JSON解析器JSON.parse()进行解析。 需要引入这个 json2.js 文件（必须下载到本地目录，去掉第一行，Crockford太小气了：）。 2. 将JS对象转换为JSON字串 这其实就是一个遍历对象，组装成字符串的过程。json2.js中也有对应的方法JSON.stringify，用法为： 3. jQuery Fdream写的一个jQuery扩展可以实现以上两种操作。 使用方法： 4. JSON的汉字问题 以上方法生成的JSON字串中的汉字都是未经转义的。虽然一般不会影响正常使用，但因为涉及到不同语言之间的传输、存储，有时候还需要对汉字进行unicode编码。 JavaScriptunicode编码函数： 用法： 5. 参考资料 JSON官方网站 JavaScript中的 JSON jQuery方法扩展：type, toJSON, evalJSON]]></description>
			<content:encoded><![CDATA[<p>虽说JavaScript原生支持<a target="_blank" href="http://www.json.org/json-zh.html">JSON</a>，但真用到的时候，也遇到了一些麻烦。下面整理一些JSON相关的JS程序。</p>
<h3>1. 将JSON字串解析为对象</h3>
<p><strong>最简单的方法是使用eval</strong>：</p>
<pre class="brush: jscript; title: ; notranslate">
var jsonStr = '{ &quot;name&quot;: &quot;幼学笔记&quot;, &quot;url&quot;: &quot;oncoding.cn&quot; }'; //定义一个json字符串
var jsonObj = eval( '(' + jsonStr + ')' ); //使用eval解析成对象
console.log(jsonObj);
</pre>
<p><span id="more-717"></span><br />
但如果JSON字符串不严谨或被利用漏洞，eval会产生一些隐患，这是可以<strong>使用JSON解析器JSON.parse()进行解析</strong>。</p>
<p>需要引入这个 <a target="_blank" href="http://www.json.org/json2.js">json2.js</a> 文件（必须下载到本地目录，去掉第一行，Crockford太小气了：）。</p>
<pre class="brush: jscript; title: ; notranslate">
var jsonObj = JSON.parse(jsonStr, function (key, value) {
    var type;
    if (value &amp;&amp; typeof value === 'object') {
        type = value.type;
        if (typeof type === 'string' &amp;&amp; typeof window[type] === 'function') {
            return new (window[type])(value);
        }
    }
    return value;
});
</pre>
<h3>2. 将JS对象转换为JSON字串</h3>
<p>这其实就是一个遍历对象，组装成字符串的过程。json2.js中也有对应的方法<strong>JSON.stringify</strong>，用法为：</p>
<pre class="brush: jscript; title: ; notranslate">
var jsonStr= JSON.stringify(jsonObj , function (key, value) {
    return value;
});
</pre>
<h3>3. jQuery</h3>
<p><a target="_blank" href="http://fdream.net/blog/">Fdream</a>写的一个<a target="_blank" href="http://ooboy.net/blog/article/661.aspx">jQuery扩展</a>可以实现以上两种操作。</p>
<pre class="brush: jscript; collapse: true; light: false; title: ; toolbar: true; notranslate">
/**
 * extension of JSON, type for jQuery
 * AUTHOR: xushengs@gmail.com
 * LICENSE: http://www.opensource.org/licenses/mit-license.php
 * WEBSITE: http://ooboy.net/
 */
(function($){
    // the code of this function is from
    // http://lucassmith.name/pub/typeof.html
    $.type = function(o){
        var _toS = Object.prototype.toString;
        var _types = {
            'undefined': 'undefined',
            'number': 'number',
            'boolean': 'boolean',
            'string': 'string',
            '[object Function]': 'function',
            '[object RegExp]': 'regexp',
            '[object Array]': 'array',
            '[object Date]': 'date',
            '[object Error]': 'error'
        };
        return _types[typeof o] || _types[_toS.call(o)] || (o ? 'object' : 'null');
    };
    // the code of these two functions is from mootools
    // http://mootools.net
    var $specialChars = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '&quot;': '\\&quot;',
        '\\': '\\\\'
    };
    var $replaceChars = function(chr){
        return $specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);
    };
    $.toJSON = function(o){
        var s = [];
        switch ($.type(o)) {
            case 'undefined':
                return 'undefined';
                break;
            case 'null':
                return 'null';
                break;
            case 'number':
            case 'boolean':
            case 'date':
            case 'function':
                return o.toString();
                break;
            case 'string':
                return '&quot;' + o.replace(/[\x00-\x1f\\&quot;]/g, $replaceChars) + '&quot;';
                break;
            case 'array':
                for (var i = 0, l = o.length; i &lt; l; i++) {
                    s.push($.toJSON(o[i]));
                }
                return '[' + s.join(',') + ']';
                break;
            case 'error':
            case 'object':
                for (var p in o) {
                    s.push('\&quot;' + p + '\&quot;' + ':' + $.toJSON(o[p]));
                }
                return '{' + s.join(',') + '}';
                break;
            default:
                return '';
                break;
        }
    };
    $.evalJSON = function(s){
        if ($.type(s) != 'string' || !s.length)
            return null;
        return eval('(' + s + ')');
    };
})(jQuery);
</pre>
<p>使用方法：</p>
<pre class="brush: jscript; title: ; notranslate">
var jsonStr = $.toJSON(jsonData);
</pre>
<pre class="brush: jscript; title: ; notranslate">
var jsonData= $.jsonStr(jsonStr);
</pre>
<h3>4. JSON的汉字问题</h3>
<p>以上方法生成的JSON字串中的汉字都是未经转义的。虽然一般不会影响正常使用，但因为涉及到不同语言之间的传输、存储，有时候还需要对汉字进行unicode编码。</p>
<p>JavaScriptunicode编码函数：</p>
<pre class="brush: jscript; title: ; notranslate">
function unicode(str){
    var a = [], i = 0;
    for (; i &lt; str.length;) {
        var strr = str[i];
        if(check(strr)){
            a[i] = &quot;\\u&quot;+(&quot;00&quot; + str.charCodeAt(i).toString(16)).slice( - 4);
            //alert(a[i]);
        }
        else{
            a[i] = strr;
        }
        i++;
    }
    return (a.join(&quot;&quot;));
}
</pre>
<p>用法：</p>
<pre class="brush: jscript; title: ; notranslate">
jsonStr = unicode(jsonStr);
</pre>
<h3>5. 参考资料</h3>
<ul>
<li><a href="http://www.json.org/" target="_blank">JSON官方网站</a></li>
<li><a href="http://www.dreamdu.com/blog/2008/10/19/json_in_javascript/" target="_blank">JavaScript中的 JSON</a></li>
<li><a href="http://ooboy.net/blog/article/661.aspx" target="_blank">jQuery方法扩展：type, toJSON, evalJSON</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2009/javascript-json/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Maps Api介绍与基础操作</title>
		<link>http://www.oncoding.cn/2009/google-maps-api/</link>
		<comments>http://www.oncoding.cn/2009/google-maps-api/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 14:52:59 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[地图]]></category>
		<category><![CDATA[Google Maps API]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=699</guid>
		<description><![CDATA[一. 关于Google Maps Api “API”，即“应用程序编程接口”，是指软件或网站为第三方开发人员提供的接口，利用这个接口，可以使用软件的一些功能而不必了解它的内部机理。 具体拿Google Maps Api来说，它提供了一个JavaScript库，具体就是我们上节课在页面头部引入的这个url：http://ditu.google.com/maps?file=api&#38;v=2&#38;key=KEY ，它会自动载入地图所需的js文件，Firefox肿的Firebug插件是前端开发必备工具，使用它我们可以方便的查看网页的内容，可以看到Google Maps Api引入的几个JS文件： ( Google Maps Api引入的文件 ) Google Maps Api的作用是，将Google Maps服务器上的地图图片和数据下载到客户端并正确显示，显示程序定义的地标点、折线和多边形，实现地址搜索、驾车导航等扩展功能。你可以在网页中直接调用它定义的类和方法，而不必了解它的运行机制，当然这些js文件是可见的，需要的话你可以重载它的函数，来实现你想要的功能。 二. 概览Google Maps Api 使用Google Maps Api必不可少的东西就是其开发手册：http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html 我们可以看到，Google Maps Api的地图的显示、标点、划线等操作包含59个类，空间、叠加层等包含18个类。 看到这个长达一百多屏的参考手册，是不是有点晕？不要着急，在本节及以后的讲解中，我们只会学习并使用其中一部分的类来实现我们的功能。 三. 在自己的项目中使用Google Maps Api Google Maps Api采用申请密钥的方式授权使用，每个密钥只能对应一个网站，当然，任何一个密钥都可以在Localhost上使用：），申请地址：http://code.google.com/intl/zh-CN/apis/maps/signup.html 我们为apus.net.cn申请了一个密钥： 申请密钥成功 Google Map调用方式 申请成功的页面上给出了三种API调用方式：“JavaScript Maps API”、“Maps API for Flash”、“HTTP Service”，我们使用第一种 — JavaScript Maps API。 OK，下面我们一起看下Google Maps [...]]]></description>
			<content:encoded><![CDATA[<h3>一. 关于Google Maps Api</h3>
<p>“API”，即“应用程序编程接口”，是指软件或网站为第三方开发人员提供的接口，利用这个接口，可以使用软件的一些功能而不必了解它的内部机理。</p>
<p>具体拿Google Maps Api来说，它提供了一个JavaScript库，具体就是我们上节课在页面头部引入的这个url：http://ditu.google.com/maps?file=api&amp;v=2&amp;key=KEY ，它会自动载入地图所需的js文件，Firefox肿的Firebug插件是前端开发必备工具，使用它我们可以方便的查看网页的内容，可以看到Google Maps Api引入的几个JS文件：</p>
<p style="text-align: center;"><a href="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308Bgb.png" target="_blank"><img class="aligncenter" src="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308Bgb.png" alt="" width="435" height="206" /></a><br />
( Google Maps Api引入的文件 )<br />
<span id="more-699"></span><br />
Google Maps Api的作用是，将Google Maps服务器上的地图图片和数据下载到客户端并正确显示，显示程序定义的地标点、折线和多边形，实现地址搜索、驾车导航等扩展功能。你可以在网页中直接调用它定义的类和方法，而不必了解它的运行机制，当然这些js文件是可见的，需要的话你可以重载它的函数，来实现你想要的功能。</p>
<p>二. 概览Google Maps Api</p>
<p>使用Google Maps Api必不可少的东西就是其开发手册：<a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html" target="_blank">http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html</a></p>
<p>我们可以看到，Google Maps Api的地图的显示、标点、划线等操作包含59个类，空间、叠加层等包含18个类。<br />
看到这个长达一百多屏的参考手册，是不是有点晕？不要着急，在本节及以后的讲解中，我们只会学习并使用其中一部分的类来实现我们的功能。</p>
<p>三. 在自己的项目中使用Google Maps Api</p>
<p>Google Maps Api采用申请密钥的方式授权使用，每个密钥只能对应一个网站，当然，任何一个密钥都可以在Localhost上使用：），申请地址：http://code.google.com/intl/zh-CN/apis/maps/signup.html<br />
我们为apus.net.cn申请了一个密钥：</p>
<p style="text-align: center;"><a href="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308J70.png" target="_blank"><img class="aligncenter" src="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308J70.png" alt="" width="548" height="469" /></a><br />
申请密钥成功</p>
<p style="text-align: center;"><a href="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308J70.png" target="_blank"><img class="aligncenter" src="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308J70.png" alt="" width="548" height="469" /></a><br />
Google Map调用方式</p>
<p>申请成功的页面上给出了三种API调用方式：“JavaScript Maps API”、“Maps API for Flash”、“HTTP Service”，我们使用第一种 —  JavaScript Maps API。</p>
<p>OK，下面我们一起看下Google Maps API如何引入地图，和一些基本的操作。</p>
<h3>四. Google Maps Api基本功能</h3>
<h4>1.加载并显示地图</h4>
<p>我们首先要加载Google Maps Api并显示了地图，</p>
<pre class="brush: xml; title: ; notranslate">
 &lt;!DOCTYPE html &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
  &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&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;!--引入Google Maps JS文件，此处key=你申请到的key--&gt;
    &lt;script src=&quot;http://ditu.google.com/maps?file=api&amp;amp;v=2&amp;amp;key=ABQIAAAAira30FR5tVprWCJ-8_WcqxSrc1zAT9YCtP2kOyoD7kBAJfliJBROJEdu9hUE13rp9a4OHneyOoW5gg&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
      //initMap()函数，将地图程序加入页面
      function initMap() {
        if (GBrowserIsCompatible()) {
          //在ID为&quot;Gmap&quot;的层内显示地图
          var map = new GMap2(document.getElementById(&quot;Gmap&quot;));
          //设置地图中心点和缩放级别
          map.setCenter(new GLatLng(36.167, 120.407), 10);
        }
      }
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body onload=&quot;initMap()&quot; onunload=&quot;GUnload()&quot;&gt;
    &lt;!--定义显示地图的层--&gt;
    &lt;div id=&quot;Gmap&quot; style=&quot;width: 600px; height: 400px&quot;&gt;&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>这样，我们就很轻松的在网页上显示出了Google地图：</p>
<p style="text-align: center;"><a href="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308iT6.png" target="_blank"><img class="aligncenter" src="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203308iT6.png" alt="" width="438" height="373" /></a></p>
<p>GMap2是Api中的中心类，作用为在给定的容器DIV中创建地图。可选参数opts.size可以设置地图大小，默认使用容器DIV的大小。</p>
<p><a href="/demos/gmap/loadmap.html" target="_blank">查看演示&gt;&gt;</a></p>
<h4>2.添加控件</h4>
<p>Google Maps的控件包括左侧的“鱼骨”控件和比例尺、右侧的地图类型按钮和小地图。</p>
<p>现在我们加载常用的四种控件：</p>
<pre class="brush: jscript; title: ; notranslate">
          //加载大“鱼骨”，包含方向、缩放按钮和缩放级别控制滑块
          map.addControl(new GLargeMapControl());
          //加载地图类型按钮
          map.addControl(new GMapTypeControl());
          //加载小地图
          map.addControl(new GOverviewMapControl());
          //加载比例尺
          map.addControl(new GScaleControl());
</pre>
<p>此外，还有四种类型的控件，可以在小尺寸地图上选用：</p>
<p>GSmallMapControl() 小“鱼骨”，仅包含方向、缩放按钮<br />
GSmallZoomControl() 更小“鱼骨”，仅包含缩放按钮<br />
GMenuMapTypeControl()  下拉框式地图类型选择<br />
GHierarchicalMapTypeControl()  按钮、下拉框组合式地图类型选择</p>
<p>具体见Api参考中的class GControl   <a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GControlImpl" target="_blank">http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GControlImpl</a></p>
<p><a href="/demos/gmap/addctrl.html" target="_blank">查看演示&gt;&gt;</a></p>
<h4>3. 在地图上添加标注</h4>
<p>基本步骤为：定义一个经纬度点GLatLng，定义一个标注对象GMarker，在地图上加入标注GMap2.addOverlay()</p>
<pre class="brush: jscript; title: ; notranslate">
          //定义一个经纬度点
          var point = new GLatLng(36.07868, 120.3599);
          //定义一个标注对象
          var marker = new GMarker(point);
          //在地图上加入标注
          map.addOverlay(marker);
</pre>
<p>我们还可以为这个标注添加气泡提示，这些要在addOverlay()之前定义：</p>
<pre class="brush: jscript; title: ; notranslate">
          //定义字符串
          var info = &quot;这是我的家&lt;br/&gt;&lt;font color='red'&gt;市北区宁夏路**号&lt;/font&gt;&quot;;
          //设置点击出现气泡，内容为预先定义的HTML字串
          marker.bindInfoWindowHtml(info);
</pre>
<p><a href="/demos/gmap/addpoint.html" target="_blank">查看演示&gt;&gt;</a></p>
<p>关于标注的其他操作、冒泡的方式内容等，还有几个其他的方法，具体可以阅读Api参考的class GMarker：     <a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GMarker" target="_blank">http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GMarker</a></p>
<h4>4. 显示折线GPolyline、多边形GPolygon</h4>
<p>在我们的Apus项目中，显示旅行路径、活动范围必不可少的地图要素就是折线和多边形，</p>
<p>在地图中添加折线的方法非常简单，下面这段程序显示了直升机从我爷爷家飞到学校放下行李然后去金沙滩游玩的路线^_^：</p>
<pre class="brush: jscript; title: ; notranslate">
          //定义一个折线对象
          polyline = new GPolyline([
            //定义这线上的三个折点、线条颜色、宽度、透明度
            new GLatLng(36.07868,120.3599),
            new GLatLng(36.00259,120.1227),
            new GLatLng(35.95482,120.2426)
            ], //折点对象数组
            &quot;#ff6600&quot;, //线条颜色
            3, //线条宽度
            0.9 //线条透明度
            );
          //将折线加入地图
          map.addOverlay(polyline);
</pre>
<p><a href="/demos/gmap/addline.html" target="_blank">查看演示&gt;&gt;</a></p>
<p>其他操作参见GPolyline类参考： <a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GPolyline" target="_blank">http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GPolyline</a></p>
<p>GPolyline的构造函数：GPolyline(latlngs,  color?,  weight?,  opacity?,  opts?)</p>
<p>其中opts? 为可选参数，class GPolylineOptions定义的属性，包括折线是否可点击clickable、表现地球弧度geodesic。<br />
添加多边形的原理和折线类似：</p>
<pre class="brush: jscript; title: ; notranslate">
          //定义一个多边形对象
          polygon = new GPolygon(
            [
               new GLatLng(36.17477,120.37609),
               new GLatLng(36.09167,120.49577),
               new GLatLng(36.06035,120.30181),
               new GLatLng(36.17477,120.37609)
            ], //折点对象数组
            &quot;#FF6600&quot;, //线条颜色
            4, //线条宽度
            0.8, //线条透明度
            &quot;#66FF00&quot;, //填充颜色
            0.5 //填充透明度
            );
          //将多边形加入地图
          map.addOverlay(polygon);
</pre>
<p><a href="/demos/gmap/addgon.html" target="_blank">查看演示&gt;&gt;</a></p>
<p>其他操作参见GPolygon类参考： <a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GPolygon" target="_blank">http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GPolygon</a></p>
<p>GPolyline的构造函数： GPolygon(latlngs,  strokeColor?, strokeWeight?,  strokeOpacity?,  fillColor?,  fillOpacity?,  opts?)<br />
其class GPolygonOptions只包含clickable，即是否可点。</p>
<h4>5. 经纬度编码</h4>
<p>阅读了上边的内容，你可能会产生这样的疑问：如果一条轨迹或区域包含了成百上千个拐点，那岂不是很麻烦。没错，这里我们可以使用一个办法把这些点信息放在一串编码后的简短的字符串里，交给客户端去解码并显示，而我们的网络仅需要传输这一串编码，这里我们要用到GPolyline和GPolygon的工厂方法fromEncoded，</p>
<p>它的原型为：fromEncoded(color?,  weight?, opacity?,  latlngs, zoomFactor,  levels, numLevels)<br />
我们以一个例子来演示它，下面的代码展示了这样的路线：我们乘坐上面那架直升机，从轮渡码头飞往栈桥观光，但栈桥没有停机坪，我们只好转道飞往江苏路教堂游览，稍作停留后回到了宁夏路家中。</p>
<pre class="brush: jscript; title: ; notranslate">
          //编码
          polyline  = new GPolyline.fromEncoded({
            color: &quot;#FF6600&quot;,
            weight: 3,
            opacity: 0.9,
            /*
            未编码的折点数据：
            new GLatLng(36.066570000000006,120.30366000000001),
            new GLatLng(36.05875,120.32037000000001),
            new GLatLng(36.072480000000006,120.32842000000001),
            new GLatLng(36.079930000000004,120.35917)
            */
            points: agc{E{xg}Uzo@mgBytAiq@qm@e_E,  //折点编码
            zoomFactor: 32,  //levels字符串中邻近缩放级别集合之间的放大倍率
            levels: &quot;BBBB&quot;,  //缩放级别编码
            numLevels: 4  //levels字符串中包含的缩放级别数
          });
         map.addOverlay(polyline);
 </pre>
<p><a href="/demos/gmap/encode.html" target="_blank">查看演示&gt;&gt;</a></p>
<p>可以看到，编码后的数据变得非常轻巧，但是这一串字符是怎样编出来的呢？Google给出了一个在线编码工具，</p>
<p>中文版地址(目前有错误无法使用)：<a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/polylineutility.html" target="_blank">http://code.google.com/intl/zh-CN/apis/maps/documentation/polylineutility.html</a></p>
<p>英文版地址(目前可用)：<a href="http://code.google.com/apis/maps/documentation/polylineutility.html" target="_blank">http://code.google.com/apis/maps/documentation/polylineutility.html</a></p>
<p>这可以作为练习时的快速编码工具，但在实际的项目开发中，我们不可能把用户的每个点都手工去编码，由于<a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/polylinealgorithm.html" target="_blank">编码的算法是公开的</a> ，我们可以自己编写程序来进行编码，这里有Javascript版和PHP版的编码程序：<a href="http://oncoding.cn/2009/gmaps-encode.html">http://oncoding.cn/2009/gmaps-encode.html</a></p>
<h3>五. Google Maps Api高级功能介绍</h3>
<h4>1.地址解析与逆地址解析</h4>
<p>所谓“地址解析”，是指根据地点名称得到经纬度坐标；“逆地址解析”则是根据经纬度坐标得出其地点名称。这一功能在实际的地图开发中尤为有用。</p>
<p>Google Maps Api中的GClientGeocoder类提供了这一系列的功能，类参考见： <a href="http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GClientGeocoder" target="_blank">http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html#GClientGeocoder</a></p>
<p>举一个小例子来试一下，下面程序返回“栈桥”的坐标</p>
<pre class="brush: jscript; title: ; notranslate">
          //地址解析
          geocoder = new GClientGeocoder();
          geocoder.getLatLng('栈桥', function(response) {
            alert (response);
          });
</pre>
<p>运行结果：</p>
<blockquote><p>栈桥的坐标：(36.0647287, 120.3184891)</p></blockquote>
<p>getLatLng方法的作用是返回查询地点的经纬度坐标；</p>
<p>另外一个方法getLocations，则同时具备了地址解析和逆地址解析的功能，它可以传入地点名称或坐标值，返回包括坐标、城市等更详细的数据。</p>
<pre class="brush: jscript; title: ; notranslate">
     //initMap()函数，将地图程序加入页面
      function initMap() {
        //GBrowserIsCompatible()确定Api能否兼容当前浏览器
        if (GBrowserIsCompatible()) {
          //在ID为&quot;Gmap&quot;的层内显示地图
          var map = new GMap2(document.getElementById(&quot;Gmap&quot;));
          //设置地图中心点和缩放级别
          map.setCenter(new GLatLng(36.09778, 120.37236), 12);
          //地址解析getLocations
          var geocoder = new GClientGeocoder();
          geocoder.getLocations('栈桥', function(response) {
            place = response.Placemark[0];
            point = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
            marker = new GMarker(point);
            map.addOverlay(marker);
            marker.openInfoWindowHtml(getGeocodeHtml(response));
          });
       }
     }
     //组装冒泡内的HTML数据
     function getGeocodeHtml(response){
       pname = response.name;
       paddress = response.Placemark[0].address;
       plat = response.Placemark[0].Point.coordinates[1];
       plon = response.Placemark[0].Point.coordinates[0];
       return(&quot;地点：&quot;+pname+&quot;&lt;br /&gt;位置：&quot;+paddress+&quot;&lt;br /&gt;坐标：&quot;+plat+&quot;,&quot;+plon);
     }
</pre>
<p><a href="/demos/gmap/geocodelocations.html" target="_blank"> 查看演示&gt;&gt;</a></p>
<p>getLocations以JSON格式返回如下数据，其Placemark可能有许多个，在实际使用时需要考虑多个返回值的情况。JSON格式是一种在JavaScript中使用非常简单方便的数据格式：</p>
<pre class="brush: jscript; title: ; notranslate">
{
  &quot;name&quot;: &quot;栈桥&quot;,
  &quot;Status&quot;: {
    &quot;code&quot;: 200,
    &quot;request&quot;: &quot;geocode&quot;
  },
  &quot;Placemark&quot;: [ {
    &quot;id&quot;: &quot;p1&quot;,
    &quot;address&quot;: &quot;栈桥, 青岛市&quot;,
    &quot;AddressDetails&quot;: {&quot;AddressLine&quot;:[&quot;栈桥&quot;],&quot;Accuracy&quot;: 9},
    &quot;ExtendedData&quot;: {
      &quot;LatLonBox&quot;: {
        &quot;north&quot;: 36.0678763,
        &quot;south&quot;: 36.0615811,
        &quot;east&quot;: 120.3216367,
        &quot;west&quot;: 120.3153415
      }
    },
    &quot;Point&quot;: {
      &quot;coordinates&quot;: [ 120.3184891, 36.0647287, 0 ]
    }
  } ]
}
</pre>
<h4>2. 本地搜索</h4>
<p>我们可以在地图上加入一个位置搜索框，只需要短短几行代码：</p>
<pre class="brush: jscript; title: ; notranslate">
          //在ID为&quot;Gmap&quot;的层内显示地图，设置加载搜索框
          var map = new GMap2(document.getElementById(&quot;Gmap&quot;),
                                                    {googleBarOptions: {showOnLoad : true}} );
          ....

          //加入搜索框
          map.enableGoogleBar();
</pre>
<p><a href="/demos/gmap/search.html" target="_blank">查看演示&gt;&gt;</a></p>
<p>如果要使用更多可定制性的搜索，可以使用Google Ajax Search Api： <a href="http://code.google.com/intl/zh-CN/apis/ajaxsearch/" target="_blank">http://code.google.com/intl/zh-CN/apis/ajaxsearch/</a> ，以后我们需要的话会进一步学习。</p>
<h4>3. 驾车路线：</h4>
<p>使用GDirections类可以获取驾车路线：</p>
<pre class="brush: jscript; title: ; notranslate">
          //驾车导航
          driveLine = new GDirections(map);
          driveLine.load(&quot;from: 青岛 to: 烟台&quot;, { &quot;locale&quot;: &quot;zh-CN&quot; });
</pre>
<p><a href="/demos/gmap/drive.html" target="_blank">查看演示&gt;&gt;</a></p>
<h4>4. 静态地图</h4>
<p>上一节课说过，Google Maps提供三种形式的API，其中一种是“静态地图API”，所谓静态，就是只生成一张图片，不会有任何交互功能。这种方式特别适用于手机的地图应用。</p>
<p>例如：http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203309iz4.jpg</p>
<p>得到图片：</p>
<p style="text-align: center;"><a href="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203309iz4.jpg" target="_blank"><img class="aligncenter" src="http://www.oncoding.cn/wp-content/uploads/09img/2010/03/203309iz4.jpg" alt="" width="420" height="280" /></a></p>
<p>参数：center=地图中心点&amp;zoom=缩放级别&amp;size=宽x高&amp;markers=第一个标点经度,纬度,颜色字母|第二个标点经度,纬度,颜色字母…&amp;key=你的KEY</p>
<h4>5. KML</h4>
<p>KML是用于描述和保存地理信息（如点、线、图像、多边形和模型等）的一种数据语言，它以被Google Earth和Google Maps方便的识别并显示。现在很多便携式GPS设备和手机软件可以生成KML格式的路径文件，事实上已经成为了GPS设备的标准路径文件格式。<br />
以下是一个KML文件的格式：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;kml xmlns=&quot;http://earth.google.com/kml/2.1&quot;&gt;
&lt;Document&gt;
 &lt;name&gt;zhanqiao.kml&lt;/name&gt;
 &lt;Style id=&quot;sh_ylw-pushpin&quot;&gt;
  &lt;IconStyle&gt;
   &lt;scale&gt;1.3&lt;/scale&gt;
   &lt;Icon&gt;
    &lt;href&gt;http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png&lt;/href&gt;
   &lt;/Icon&gt;
   &lt;hotSpot x=&quot;20&quot; y=&quot;2&quot; xunits=&quot;pixels&quot; yunits=&quot;pixels&quot;/&gt;
  &lt;/IconStyle&gt;
 &lt;/Style&gt;
 &lt;Style id=&quot;sn_ylw-pushpin&quot;&gt;
  &lt;IconStyle&gt;
   &lt;scale&gt;1.1&lt;/scale&gt;
   &lt;Icon&gt;
    &lt;href&gt;http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png&lt;/href&gt;
   &lt;/Icon&gt;
   &lt;hotSpot x=&quot;20&quot; y=&quot;2&quot; xunits=&quot;pixels&quot; yunits=&quot;pixels&quot;/&gt;
  &lt;/IconStyle&gt;
 &lt;/Style&gt;
 &lt;StyleMap id=&quot;msn_ylw-pushpin&quot;&gt;
  &lt;Pair&gt;
   &lt;key&gt;normal&lt;/key&gt;
   &lt;styleUrl&gt;#sn_ylw-pushpin&lt;/styleUrl&gt;
  &lt;/Pair&gt;
  &lt;Pair&gt;
   &lt;key&gt;highlight&lt;/key&gt;
   &lt;styleUrl&gt;#sh_ylw-pushpin&lt;/styleUrl&gt;
  &lt;/Pair&gt;
 &lt;/StyleMap&gt;
 &lt;Placemark&gt;
  &lt;name&gt;zhanqiao&lt;/name&gt;
  &lt;LookAt&gt;
   &lt;longitude&gt;120.3157798974425&lt;/longitude&gt;
   &lt;latitude&gt;36.05886498176855&lt;/latitude&gt;
   &lt;altitude&gt;0&lt;/altitude&gt;
   &lt;range&gt;739.971375569545&lt;/range&gt;
   &lt;tilt&gt;4.084272649574626e-011&lt;/tilt&gt;
   &lt;heading&gt;-0.1127864185136748&lt;/heading&gt;
  &lt;/LookAt&gt;
  &lt;styleUrl&gt;#msn_ylw-pushpin&lt;/styleUrl&gt;
  &lt;Point&gt;
   &lt;coordinates&gt;120.3152418576393,36.05858830488904,0&lt;/coordinates&gt;
  &lt;/Point&gt;
 &lt;/Placemark&gt;
&lt;/Document&gt;
&lt;/kml&gt;
</pre>
<p>其中包含主要的标签：Document，Document包含kml的文件信息和显示样式以及所有的地标点信息，每个地标信息对应一个Placemark标签。</p>
<blockquote><p>KML中Placemark中主要标签的定义：<br />
name   该地标名称<br />
description   地标描述，支持HTML代码<br />
LookAt    试图相关信息<br />
styleUrl   样式<br />
Point  地标点</p></blockquote>
<p><a href="/demos/gmap/kml.html" target="_blank">查看演示&gt;&gt;</a></p>
<p>更具体的信息：<a href="http://www.step1.cn/googleapi/map/kml.htm" target="_blank">http://www.step1.cn/googleapi/map/kml.htm</a></p>
<p>编程处理KML文件：</p>
<pre class="brush: jscript; title: ; notranslate">
          //GGeoXml对象，处理KML文件
          var gXml = new GGeoXml(&quot;http://oncoding.net/demos/zhanqiao.kml&quot;);
          //将KML内容在地图上显示
          map.addOverlay(gXml);
</pre>
<h3>后记</h3>
<p>本节所有示例程序的压缩包可以在这里下载：http://code.google.com/p/apus/downloads/list 。注意要改成你自己的KEY，才能正常运行。</p>
<p>这篇文章其实是自己以前计划写的Google Maps API网站开发教程中的一节，后来因为种种原因，没能坚持吧教程写完。现在把这一节单独整理出来，作为一个Google Maps API的入门教程吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2009/google-maps-api/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Javascript判断浏览器和操作系统类型：Ext中的最全面简洁方法</title>
		<link>http://www.oncoding.cn/2009/javascript-browser-judge/</link>
		<comments>http://www.oncoding.cn/2009/javascript-browser-judge/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 13:37:04 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=655</guid>
		<description><![CDATA[前端开发中，经常需要判断浏览器或系统类型，以解决兼容性问题。 使用Javascript判断浏览器和操作系统类型是一件很容易的事情，但如何最全面、最简单的做出判断，是不容易的，Ext中的浏览器判断非常全面且简洁，包含了最新的IE8、Chrome浏览器、Air浏览的判断，下面是从Ext 2.2.1众摘录的代码，并添加了注释：]]></description>
			<content:encoded><![CDATA[<p>前端开发中，经常需要判断浏览器或系统类型，以解决兼容性问题。</p>
<p>使用Javascript判断浏览器和操作系统类型是一件很容易的事情，但如何最全面、最简单的做出判断，是不容易的，Ext中的浏览器判断非常全面且简洁，包含了最新的IE8、Chrome浏览器、Air浏览的判断，下面是从Ext 2.2.1众摘录的代码，并添加了注释：</p>
<pre class="brush: jscript; title: ; notranslate">
var ua = navigator.userAgent.toLowerCase();
var isStrict = document.compatMode == &quot;CSS1Compat&quot;, // 是否定义DOCUMENT类型
    isOpera = ua.indexOf(&quot;opera&quot;)&gt;-1, // 是Opera
    isChrome = ua.indexOf(&quot;chrome&quot;)&gt;-1, //是Chrome
    isSafari = !isChrome&amp;&amp;(/webkit|khtml/).test(ua), //是Safari
    isSafari3 = isSafari&amp;&amp;ua.indexOf(&quot;webkit/5&quot;)! = -1, // Safari3
    isIE = !isOpera&amp;&amp;ua.indexOf(&quot;msie&quot;)&gt;-1, //IE6
    isIE7 = !isOpera&amp;&amp;ua.indexOf(&quot;msie 7&quot;)&gt;-1, // IE7
    isIE8 = !isOpera&amp;&amp;ua.indexOf(&quot;msie 8&quot;)&gt;-1, //IE8
    isGecko = !isSafari&amp;&amp;!isChrome&amp;&amp;ua.indexOf(&quot;gecko&quot;)&gt;-1, // Gecko内核
    isGecko3 = isGecko&amp;&amp;ua.indexOf(&quot;rv:1.9&quot;)&gt;-1, // Gecko3内核
    isBorderBox = isIE&amp;&amp;!isStrict, // 使用盒模型
    isWindows = (ua.indexOf(&quot;windows&quot;)! = -1||ua.indexOf(&quot;win32&quot;)! = -1), // 是Windows系统
    isMac = (ua.indexOf(&quot;macintosh&quot;)! = -1||ua.indexOf(&quot;mac os x&quot;)! = -1), // 是MacOS系统
    isAir = (ua.indexOf(&quot;adobeair&quot;)! = -1), // 是用Adobe Air浏览
    isLinux = (ua.indexOf(&quot;linux&quot;)! = -1), // 是Linux系统
    isSecure = window.location.href.toLowerCase().indexOf(&quot;https&quot;) === 0;  // 是SSL浏览
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2009/javascript-browser-judge/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用JavaScript+CSS制作伸缩菜单</title>
		<link>http://www.oncoding.cn/2009/javascript-css-slide-menu/</link>
		<comments>http://www.oncoding.cn/2009/javascript-css-slide-menu/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 12:12:16 +0000</pubDate>
		<dc:creator>j5726</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.oncoding.cn/?p=680</guid>
		<description><![CDATA[演示地址：http://www.oncoding.cn/demos/jsmenu/index.html 前段时间项目里用到的，项目已经发布，今天整理一下发出来。 不用框架，纯JavaScript+CSS制作的二级伸缩菜单，简单易懂，具有很强的定制性和重复开发性。 页面调用方法： 程序说明： 应该解释的比较清楚了，还有不明白的可以在下边问。 打包下载 幼学笔记原创内容，根据CC协议发布，欢迎具名转载。]]></description>
			<content:encoded><![CDATA[<p>演示地址：<a href="http://www.oncoding.cn/demos/jsmenu/index.html">http://www.oncoding.cn/demos/jsmenu/index.html</a></p>
<p>前段时间项目里用到的，项目已经发布，今天整理一下发出来。</p>
<p>不用框架，纯JavaScript+CSS制作的二级伸缩菜单，简单易懂，具有很强的定制性和重复开发性。</p>
<p>页面调用方法：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
    &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&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;JavaScript可伸缩菜单 - Oncoding编码营原创&lt;/title&gt;
  &lt;!--引入JS文件--&gt;
  &lt;script type=&quot;text/javascript&quot; src=&quot;jsmenu.js&quot;&gt;&lt;/script&gt;

    .....
  &lt;!--加载程序--&gt;
&lt;body onload = &quot;initMenu()&quot;&gt;
  &lt;!--此处须定义ID--&gt;
  &lt;div class=&quot;jsmenu&quot; id=&quot;pm_menu&quot;&gt;
    &lt;!--展开的一级分类--&gt;
    &lt;div&gt;
      &lt;span class=&quot;fath&quot;&gt;业界资讯&lt;/span&gt;
      &lt;p class=&quot;son&quot;&gt;
        &lt;!--class=&quot;current&quot;当前所在二级分类--&gt;
        &lt;a class=&quot;current&quot; href=&quot;#&quot;&gt;业界新闻&lt;/a&gt;
        &lt;a href=&quot;#&quot;&gt;技术动态&lt;/a&gt;
        &lt;a href=&quot;#&quot;&gt;八卦评论&lt;/a&gt;
      &lt;/p&gt;
     &lt;/div&gt;
     &lt;!--闭合的一级分类--&gt;
     &lt;div class=&quot;collapsed&quot;&gt;

       ....

     &lt;/div&gt;
     &lt;!--独立的一级分类--&gt;
     &lt;div&gt;&lt;span class=&quot;single&quot;&gt;&lt;a href=&quot;#&quot;&gt;酷站&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;

    ....
</pre>
<p>程序说明：</p>
<pre class="brush: jscript; title: ; notranslate">
//在ID为“js_menu”的div内开始程序
function initMenu(){
      var pm_menu = new JSMenu(&quot;js_menu&quot;);
        pm_menu.init();
    }
//定义主函数
function JSMenu(id) {
    if (!document.getElementById || !document.getElementsByTagName)
        return false;
    this.menu = document.getElementById(id);
    this.submenus = this.menu.getElementsByTagName(&quot;div&quot;);
}
//引入函数，取得所有span
JSMenu.prototype.init = function() {
    var mainInstance = this;
    for (var i = 0; i &lt; this.submenus.length; i++)
        this.submenus[i].getElementsByTagName(&quot;span&quot;)[0].onclick = function() {
            mainInstance.toggleMenu(this.parentNode);
        };
    this.expandOne();
};
//展开含&quot;current&quot;的菜单
JSMenu.prototype.expandOne = function() {
    for (var i = 0; i &lt; this.submenus.length; i++) {
        var links = this.submenus[i].getElementsByTagName(&quot;a&quot;);
        for (var j = 0; j &lt; links.length; j++){
            if (links[j].className == &quot;current&quot;)
            this.expandMenu(this.submenus[i]);
            }
        }
};
//变换菜单状态函数
JSMenu.prototype.toggleMenu = function(submenu) {
    if (submenu.className == &quot;collapsed&quot;)
        this.expandMenu(submenu);
    else
        this.collapseMenu(submenu);
};
//展开所有菜单函数
JSMenu.prototype.expandMenu = function(submenu) {
    var fullHeight = submenu.getElementsByTagName(&quot;span&quot;)[0].offsetHeight;
    var links = submenu.getElementsByTagName(&quot;a&quot;);
    for (var i = 0; i &lt; links.length; i++)
        fullHeight += links[i].offsetHeight;
    var moveBy = Math.round(5 * links.length);

    var mainInstance = this;
    var intId = setInterval(function() {
        var curHeight = submenu.offsetHeight;
        var newHeight = curHeight + moveBy;
        if (newHeight &lt; fullHeight)
            submenu.style.height = newHeight + &quot;px&quot;;
        else {
            clearInterval(intId);
            submenu.style.height = &quot;&quot;;
            submenu.className = &quot;&quot;;
        }
    }, 30);
    this.collapseOthers(submenu);
};
//折叠菜单函数
JSMenu.prototype.collapseMenu = function(submenu) {
    var minHeight = submenu.getElementsByTagName(&quot;span&quot;)[0].offsetHeight;
    var moveBy = Math.round(5 * submenu.getElementsByTagName(&quot;a&quot;).length);
    var mainInstance = this;
    var intId = setInterval(function() {
        var curHeight = submenu.offsetHeight;
        var newHeight = curHeight - moveBy;
        if (newHeight &gt; minHeight)
            submenu.style.height = newHeight + &quot;px&quot;;
        else {
            clearInterval(intId);
            submenu.style.height = &quot;&quot;;
            submenu.className = &quot;collapsed&quot;;
        }
    }, 30);
};
//折叠其他菜单函数
JSMenu.prototype.collapseOthers = function(submenu) {
        for (var i = 0; i &lt; this.submenus.length; i++)
            if (this.submenus[i] != submenu &amp;&amp; this.submenus[i].className != &quot;collapsed&quot;)
                this.collapseMenu(this.submenus[i]);
};
</pre>
<p>应该解释的比较清楚了，还有不明白的可以在下边问。</p>
<p><a target="_blank" href="http://www.oncoding.cn/demos/jsmenu/jsmenu.zip">打包下载</a></p>
<p style="text-align: right;"><a href="http://www.oncoding.cn/2010/javascript-css-slide-menu/">幼学笔记</a>原创内容，根据<a href="http://creativecommons.org/licenses/by-nc-sa/2.5/">CC协议</a>发布，欢迎具名转载。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oncoding.cn/2009/javascript-css-slide-menu/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

