﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Jasper's Java Jacal-随笔分类-桌面技术</title><link>http://www.blogjava.net/zhenandaci/category/37468.html</link><description>嘉士伯的Java小屋</description><language>zh-cn</language><lastBuildDate>Mon, 09 Mar 2009 17:28:56 GMT</lastBuildDate><pubDate>Mon, 09 Mar 2009 17:28:56 GMT</pubDate><ttl>60</ttl><item><title>Google Gadget 开发入门（六）界面二三事</title><link>http://www.blogjava.net/zhenandaci/archive/2009/02/10/254135.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Tue, 10 Feb 2009 14:05:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/02/10/254135.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/254135.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/02/10/254135.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/254135.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/254135.html</trackback:ping><description><![CDATA[<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Word.Document" />
<meta name="Generator" content="Microsoft Word 12" />
<meta name="Originator" content="Microsoft Word 12" />
<link rel="File-List" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml" />
<link rel="themeData" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx" />
<link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml" /><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
EN-US
ZH-CN
X-NONE
</xml><![endif]--><!--[if gte mso 9]><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:微软雅黑;
panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
{font-family:Verdana;
panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
{font-family:""@微软雅黑";
panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
{font-family:""@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
line-height:14.0pt;
font-size:12.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
p.MsoHeader, li.MsoHeader, div.MsoHeader
{
mso-style-link:"页眉 Char";
margin:0cm;
margin-bottom:.0001pt;
text-align:center;
line-height:12.0pt;
tab-stops:center 207.65pt right 415.3pt;
layout-grid-mode:char;
border:none;
padding:0cm;
font-size:9.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{
mso-style-link:"页脚 Char";
margin:0cm;
margin-bottom:.0001pt;
line-height:12.0pt;
tab-stops:center 207.65pt right 415.3pt;
layout-grid-mode:char;
font-size:9.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:21.0pt;
line-height:14.0pt;
font-size:12.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
span.Char
{mso-style-name:"页眉 Char";
font-family:"微软雅黑","sans-serif";}
span.Char0
{mso-style-name:"页脚 Char";
font-family:"微软雅黑","sans-serif";}
p.a, li.a, div.a
{
mso-style-link:"代码 Char";
margin:0cm;
margin-bottom:.0001pt;
line-height:150%;
background:#EEEEEE;
font-size:11.0pt;
font-family:"Verdana","sans-serif";
color:black;}
span.Char1
{mso-style-name:"代码 Char";
font-family:"Verdana","sans-serif";
color:black;
background:#EEEEEE;}
.MsoChpDefault
{
mso-bidi-font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:595.3pt 841.9pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
layout-grid:15.6pt;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{}
@list l0:level1
{
margin-left:21.0pt;
text-indent:-21.0pt;
font-family:Wingdings;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.5pt;
font-family:"Calibri","sans-serif";}
</style>
<![endif]-->
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">目前为止不管后台写了多少逻辑（已经登录了</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，取了相册数据），我们的</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">都还是那个看上去白白的</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">。而要想让它看上去有所不同，就要在</span>main.xml<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这个文件中，制定我们想要的&#8220;长相&#8221;（就跟征婚启事里写的一样，身高</span>1<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">米</span>6<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">至</span>1<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">米</span>7<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，体重不超过</span>55<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">公斤，相貌端正，贤良淑惠）。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">如果你已经下载了我提供的源码，就可以打开看看，对照实际效果来看代码，应该很好理解。我们总计在界面上放了几样东西：</span></p>
<ul>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">一张背景图（就是白白的那个）</span></li>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">一张</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的</span>Logo</li>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">两行表示欢迎的文字（就是</span>label<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">啦）</span></li>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">一个用来显示相册信息的列表（</span>listbox<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">），当然，目前列表中还一个列表项都没有（列表项称之为</span>item<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">）</span></li>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">最后又贴了两张图，其中一张是某企业的</span>logo<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">（笑）</span></li>
</ul>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">其中值得注意的事情有这么几件：</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">一是背景图片绝非可有可无，按</span>google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的说法，像</span>label<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这种东西，如果没有放在一张背景图片之上的话，是显示不出来的。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">二是</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">中界面的内容，样式和布局都在这一个文件中指定。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">三是</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的界面没有</span>HTML<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">那种流动布局的效果，就是说，所有要显示的元素，必须明明白白的指出它的位置，也就是每个元素的</span>x<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">和</span>y<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">属性，是从该元素的父元素左上角开始计算的坐标。如果你先写了一个</span>label<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">（拿</span>label<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">举个例子，实际上用什么效果都是一样的），再挨着它写了一个</span>label<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，两个</span>label<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">你都没有指定</span>x<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">和</span>y<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的值，那么这个两个</span>label<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">会重叠着显示在一起。不信你可以试一试。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">四是图片的源文件位置，从代码中可以看到指定本机上的相对目录是可以的，那么指定一个网络上的</span>url<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">可以么？例如</span>http://www.sina.com.cn/images/logo.gif<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">？如果你头脑中还存在着</span>HTML<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的印象，可能想当然的以为可以这么做，而事实上不行，</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">与</span>Web<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">没有天然的联系（没记错的话，我已经说过四次了）。后面处理相册缩略图的时候，我们会看到怎么把网络上的图片显示出来。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">写过图形用户界面程序的人一定想问，如何让界面上的元素与代码产生联系呢？例如我们的列表，我想在代码中对它作些修改的时候，如何取得它的引用呢？在</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">中这一点还比较方便，主要有两个途径：一是只要你给元素赋了</span>name<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">属性，例如我就给列表项起了一个名字叫做</span>contentListBox<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，在</span>main.xml<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">中的这一行：</span></p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">listbox&nbsp;</span><span style="color: #ff0000;">height</span><span style="color: #0000ff;">="130"</span><span style="color: #ff0000;">&nbsp;name</span><span style="color: #0000ff;">="contentListBox"</span><span style="color: #ff0000;">&nbsp;width</span><span style="color: #0000ff;">="200"</span><span style="color: #ff0000;">&nbsp;x</span><span style="color: #0000ff;">="25"</span><span style="color: #ff0000;">&nbsp;y</span><span style="color: #0000ff;">="100"</span></div>
<p>&nbsp;</p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">之后就可以直接在代码中用</span>contentListBox<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这个值来访问这个列表项了（而且任你在代码中怎么找，也找不到声明或者初始化这个变量的地方）——当然前提是起的名字必须是唯一的。有意思吧？</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">第二种方式比较传统也比较少用，可以通过</span>DOM<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">对象访问每个元素。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">废话不多说，来看看在代码中给列表插入列表项怎么做。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">列表项对应着</span><span>Gadget
API</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">提供的一个名为</span>item<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的对象实例，但我们要用</span>new item()<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这样的语法来得到一个新的列表项并逐一设置它的属性么？不不，有更简便也更好玩的方法，我们只要新建一个字符串：</span></p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;itemXml</span><span style="color: #000000;">=</span><span style="color: #000000;"> '</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">item&nbsp;name</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">album_item"&gt;&lt;label&gt;列表项&lt;/label&gt;&lt;/item&gt;';</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">然后调用列表</span>contentListBox<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的方法来添加就可以，像这样：</span></p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;newItem&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;contentListBox.appendElement(itemXml);</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">方便么？这种用法使得开发人员不需要为一个图形界面的组件掌握两套语法（</span>XML<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的和</span>JavaScript<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的），非常贴心。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">好，现在来说另一个问题，既然不能为一个</span>img<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">对象的</span>src<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">属性指定一个网络地址，那到底如何显示网络上的图片呢？答案很长，如果你有了图片的</span>url<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">（就是</span> http://<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">开头的那种啦），首先要通过</span>XmlHttpRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">把图片的数据取回来，然后把这部分数据赋给</span>src<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">属性。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">具体点，记得一个请求最重要的四部分数据么？</span>url<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">：就是该图片的</span>url<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">；请求类型：因为是要求数据，自然是&#8220;</span>GET<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&#8221;；请求头：对本请求来说没有；消息体：同样没有。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">所以发请求的部分并不困难，待请求的状态变为</span>4<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，也就是说明回传数据已到达的时候，就可以从请求的</span>responseStream<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这个属性得到图片的二进制数据。假设在代码中我们要显示的图片是</span>&lt;img name=&#8221;myImg&#8221;/&gt;,<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">记得么，使用名字可以直接访问这个图片，再假设我们的请求对象取名为</span>xhRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，像下面这样：</span></p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">myImg.src</span><span style="color: #000000;">=</span><span style="color: #000000;">xhRequest.&nbsp;responseStream;</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">如此就可以了！哈哈，简单吧（我当初倒是找了半天，读过了</span>YouTube Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的代码才参透呢，愚笨愚笨）。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">在我们剩下的唯一一个重要函数</span>Main<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的</span>fetchAlbumThumbnail()<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">中，就是使用这种方法来取得相册缩略图的图片并显示在</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的界面中的。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这个函数我就不逐一分解了，相信你一定看得懂。</span></p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/254135.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-02-10 22:05 <a href="http://www.blogjava.net/zhenandaci/archive/2009/02/10/254135.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Gadget开发入门（五）Gadget中从Picasa取得相册数据</title><link>http://www.blogjava.net/zhenandaci/archive/2009/02/10/254110.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Tue, 10 Feb 2009 09:28:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/02/10/254110.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/254110.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/02/10/254110.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/254110.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/254110.html</trackback:ping><description><![CDATA[<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);"><br />
</span></div>
<p>大的方向上说，从Picasa服务器上取数据，有两种方式，一种是使用Google已经开放的各种语言的API，可以在页面http://code.google.com/apis/picasaweb/developers_guide_protocol.html找到很多相关的信息。另一种方式便是使用最朴素的网络请求方式来自己构造请求并解析回传的数据。 </p>
<p>由于Picasa只提供了Java,.NET,Python和PHP的接口，而Gadget目前只能使用JavaScript，因此我们只能使用朴素方式。 </p>
<p>继续第三节的路子，仍然使用XmlHttpRequest向Picasa服务发起请求，也要处理好四部分信息。 </p>
<p><strong>请求发向哪个URL</strong><strong>：</strong>为了获取Picasa的相册信息，要向http://picasaweb.google.com/data/feed/api/user/default发请求，这个URL其实可以有很多变化的地方。例如user/default这个地方是请求所附token所属的用户相册信息，这里当然可以明确的指定用户名。&#8221;api&#8221;可以换成&#8221;base&#8221;，这个将影响回传数据的格式，但Goolge推荐使用api而不是base。 </p>
<p><strong>请求的类型：</strong>我们是要索取数据，因此这是一个查询的动作，应该使用GET。 </p>
<p><strong>请求头：</strong>只需要把token放进去就好。这样来放： </p>
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">xhRequest.setRequestHeader('Authorization','GoogleLogin&nbsp;auth</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;token);</span></div>
<p> </p>
<p><strong>消息体：</strong>对于我们查询相册的请求，不需要任何的消息体。 </p>
<p>具体的代码都在Main.prototype.fetchAlbumsInfo()函数中，就像这样： </p>
<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">Main.prototype.fetchAlbumsInfo</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">function</span><span style="color: rgb(0, 0, 0);">()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;url</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">http://picasaweb.google.com/data/feed/api/user/default</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;token</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">options.getValue(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">token</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhRequest</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;createXhr();<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.open(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">GET</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;url,&nbsp;</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.setRequestHeader('Authorization','GoogleLogin&nbsp;auth</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;token);<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.send(</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.onreadystatechange&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">function</span><span style="color: rgb(0, 0, 0);">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">xhRequest)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(xhRequest.readyState&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main.albums</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">parseAlbumFeed(xhRequest.responseText);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main.fetchAlbumThumbnail();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
};<br />
</span></div>
<p>最后两个函数是下一步要做的工作：解析回传的相册数据，并下载每个相册的缩略图。 </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GadgetGadgetPicasa_F598/clip_image001_2.jpg"></a>&nbsp;</p>
<p>要想解析回传数据，首先得知道回传的数据是什么。你可以把这些数据打印出来看看，应该是类似下面的样子：</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GadgetGadgetPicasa_F598/clip_image001_2.jpg"><img style="border: 0px none ; display: inline;" title="clip_image001" alt="clip_image001" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GadgetGadgetPicasa_F598/clip_image001_thumb.jpg" width="622" border="0" height="418" hspace="12" /></a></p>
<p>怎么，看着有点眼熟？没错，这个回传数据所使用的格式正是标准的Atom Feed（更多的描述可以参考W3C的标准和下面的链接：http://code.google.com/intl/zh-CN/apis/picasaweb/developers_guide_protocol.html）。 </p>
<p>可以根据Atom Feed的格式来编写我们解析回传数据的函数parseAlbumFeed()，这个函数的作用是从回传的xml数据中找出我们关心的几样东西：该用户目前拥有的所有的相册信息，包括每个相册的标题，描述，访问权限以及缩略图的地址。找出这些信息以后，将会拼成一个包含相册（Album）的数组作为函数返回值。 </p>
<p>具体代码如下： </p>
<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">function</span><span style="color: rgb(0, 0, 0);">&nbsp;parseAlbumFeed(response)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;doc&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;createDomDocument();<br />
&nbsp;&nbsp;doc.loadXML(response);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">用户已经建立过的相册集合，函数的返回值</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;albums&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;[];<br />
<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;entryElements&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;doc.getElementsByTagName('entry');<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">具体处理每个Album的信息</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;entryElements.length;&nbsp;i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;entry&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;entryElements[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;album</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Album();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">相册标题</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;album.title</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">entry.getElementsByTagName('title')[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">].text;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">相册描述</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;album.summary</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">entry.getElementsByTagName('summary')[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">].text;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">相册的访问权限</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;album.access</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">entry.getElementsByTagName('gphoto:access')[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">].text;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">相册的缩略图</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;thumbnail</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">entry.getElementsByTagName('media:thumbnail')[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;album.thumbnail</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Thumbnail(thumbnail.getAttribute('url'));<br />
&nbsp;&nbsp;&nbsp;&nbsp;albums.push(album);<br />
&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;albums;<br />
};<br />
</span></div>
<p>这个函数中用到了一些我们还没有新建的类，相册（Album）以及缩略图(Thumbnail)。这些类的声明可以放在一个新的名为album.js的文件中，并在我们整个Gadget的main.xml文件中指名要导入它。因此main.xml的最后几行应该看上去是这个样子： </p>
<span style="color: rgb(0, 0, 0);"><br />
</span>
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">script&nbsp;</span><span style="color: rgb(255, 0, 0);">src</span><span style="color: rgb(0, 0, 255);">="album.js"</span><span style="color: rgb(255, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">script&nbsp;</span><span style="color: rgb(255, 0, 0);">src</span><span style="color: rgb(0, 0, 255);">="main.js"</span><span style="color: rgb(255, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">view</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
</span></div>
<p>而album.js的内容大体如下： </p>
<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">function</span><span style="color: rgb(0, 0, 0);">&nbsp;Album()&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.title&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">""</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.summary</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">""</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.access</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">""</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.thumbnail</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">#ff0000;<br />
}<br />
<br />
</span><span style="color: rgb(0, 0, 255);">function</span><span style="color: rgb(0, 0, 0);">&nbsp;Thumbnail(url)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.url&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;url;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.width&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">40</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.height&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">40</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.src&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;undefined;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;XML&nbsp;response&nbsp;stream</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">}<br />
</span></div>
<p>最后还要在main.js里面添加一个函数createDomDocument()，用来提供一个DOM对象供我们解析XML用。代码如下： </p>
<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">function</span><span style="color: rgb(0, 0, 0);">&nbsp;createDomDocument()&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;doc&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;DOMDocument();<br />
<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;doc.resolveExternals&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;doc.validateOnParse&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;doc.setProperty('ProhibitDTD',&nbsp;</span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">(e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;debug.warning('Could&nbsp;not&nbsp;set&nbsp;MS&nbsp;specific&nbsp;properties.');<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;doc;<br />
}<br />
</span></div>
<p>下一节来说说怎么取得相册的缩略图并显示在Gadget的界面中。  </p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/254110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-02-10 17:28 <a href="http://www.blogjava.net/zhenandaci/archive/2009/02/10/254110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Gadget开发入门（四）处理token</title><link>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253594.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Fri, 06 Feb 2009 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253594.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/253594.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253594.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/253594.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/253594.html</trackback:ping><description><![CDATA[<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Word.Document" />
<meta name="Generator" content="Microsoft Word 12" />
<meta name="Originator" content="Microsoft Word 12" />
<link rel="File-List" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml" />
<link rel="themeData" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx" />
<link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml" /><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
EN-US
ZH-CN
X-NONE
</xml><![endif]--><!--[if gte mso 9]><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:微软雅黑;
panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
{font-family:Verdana;
panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
{font-family:""@微软雅黑";
panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
{font-family:""@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
line-height:14.0pt;
font-size:12.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
p.MsoHeader, li.MsoHeader, div.MsoHeader
{
mso-style-link:"页眉 Char";
margin:0cm;
margin-bottom:.0001pt;
text-align:center;
line-height:12.0pt;
tab-stops:center 207.65pt right 415.3pt;
layout-grid-mode:char;
border:none;
padding:0cm;
font-size:9.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{
mso-style-link:"页脚 Char";
margin:0cm;
margin-bottom:.0001pt;
line-height:12.0pt;
tab-stops:center 207.65pt right 415.3pt;
layout-grid-mode:char;
font-size:9.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
span.Char
{mso-style-name:"页眉 Char";
font-family:"微软雅黑","sans-serif";}
span.Char0
{mso-style-name:"页脚 Char";
font-family:"微软雅黑","sans-serif";}
p.a, li.a, div.a
{
mso-style-link:"代码 Char";
margin:0cm;
margin-bottom:.0001pt;
line-height:150%;
background:#EEEEEE;
font-size:11.0pt;
font-family:"Verdana","sans-serif";
color:black;}
span.Char1
{mso-style-name:"代码 Char";
font-family:"Verdana","sans-serif";
color:black;
background:#EEEEEE;}
.MsoChpDefault
{
mso-bidi-font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:595.3pt 841.9pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
layout-grid:15.6pt;}
div.Section1
{page:Section1;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.5pt;
font-family:"Calibri","sans-serif";}
</style>
<![endif]-->
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">向</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的服务器发起登录请求之后，得到了免死金牌</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，以后就可以拿着这个</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">去犯罪，不是，去</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的其它服务取数据，但是在此之前应该第一，从响应的消息中把</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">找出来；第二，这个</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">应该想办法保存起来，以备以后使用。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">上一节已经把响应的内容打印了出来，它的格式也很简单，因此用下面的代码很容易就可以把响应的内容转成方便我们使用的形式，即一个</span>map<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的形式，通过键值对来存储：</span></p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">function</span><span style="color: #000000;">&nbsp;parseResponse(response)&nbsp;{<br />
<br />
&nbsp;</span><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;responseLines&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;response.split('</span><span style="color: #000000;">\</span><span style="color: #000000;">n');<br />
<br />
&nbsp;var&nbsp;responseData&nbsp;=&nbsp;{};<br />
<br />
&nbsp;for&nbsp;(var&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;responseLines.length;&nbsp;++i)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;split&nbsp;=&nbsp;responseLines[i].indexOf('=');<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;key&nbsp;=&nbsp;responseLines[i].substr(0,&nbsp;split);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;value&nbsp;=&nbsp;responseLines[i].substr(split&nbsp;+&nbsp;1);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;responseData[key]&nbsp;=&nbsp;value;<br />
<br />
&nbsp;}<br />
<br />
&nbsp;return&nbsp;responseData;<br />
<br />
};</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">在我们的相应回调函数里，就可以调用这个函数处理一下响应，从结果中取键为</span>&#8221;Auth&#8221;<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这一项的值，并保存在</span><span>Gadget
Host</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">为我们准备好的一个负责持久化的对象</span>options<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">中。找到上一节</span>Main.prototype.login<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的代码，把响应的回调函数改成下面的样子：</span></p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">xhRequest.onreadystatechange&nbsp;</span><span style="color: #000000;">=</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">xhRequest)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(xhRequest.readyState&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">调用新写的函数来解析响应内容</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;responseData&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;parseResponse(xhRequest.responseText);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;token&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;responseData['Auth'];<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">这里来记住已经登录过的用户名和密码</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.putValue(</span><span style="color: #000000;">"</span><span style="color: #000000;">username</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="font-size: 10.5pt; color: red;">mymail</span><span style="color: #000000;">2009.test@gmail.com</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.putValue(</span><span style="color: #000000;">"</span><span style="color: #000000;">password</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="font-size: 10.5pt; color: red;">mymail</span><span style="color: #000000;">2009</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.putValue(</span><span style="color: #000000;">"</span><span style="color: #000000;">token</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;token);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.encryptValue(</span><span style="color: #000000;">"</span><span style="color: #000000;">token</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red;">main.onLoginSuccess();</span><br />
<br />
}</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">最后加的一行</span><span style="color: #c0504d;">main.onLoginSuccess()</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">就是我们下一步动作的起点，在这里应该开始去取用户</span><span style="font-size: 10.5pt; color: red;">mymail</span>2009.test@gmail.com<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">所拥有的相册信息了，我们先声明一个空函数放在那里。</span></p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Main.prototype.onLoginSuccess</span><span style="color: #000000;">=</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){<br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.fetchAlbumsInfo();<br />
<br />
};<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">取相册信息的函数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
Main.prototype.fetchAlbumsInfo</span><span style="color: #000000;">=</span><span style="color: #0000ff;">function</span><span style="color: #000000;">()&nbsp;{<br />
<br />
};</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">继续之前多扯两句</span>options<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这个对象，这是</span>Gadget Host<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">提供的持久化对象，你可以从代码中看到它还有对存储的内容进行加密的功能，</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的文档中提到这个</span>options<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">对象在后台实际上是把内容保存在一个</span>XML<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">文件中，当然该文件的位置是不会告诉你的啦，哈哈。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">下一节将向</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">服务发起请求！</span></p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/253594.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-02-06 16:35 <a href="http://www.blogjava.net/zhenandaci/archive/2009/02/06/253594.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Gadget开发入门（三）在Gadget中做Google帐户的登录</title><link>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253579.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Fri, 06 Feb 2009 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253579.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/253579.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253579.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/253579.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/253579.html</trackback:ping><description><![CDATA[<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;"><br />
</span></div>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Word.Document" />
<meta name="Generator" content="Microsoft Word 12" />
<meta name="Originator" content="Microsoft Word 12" />
<link rel="File-List" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml" />
<link rel="Edit-Time-Data" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_editdata.mso" /><!--[if !mso]>
<style>
v":* {behavior:url(#default#VML);}
o":* {behavior:url(#default#VML);}
w":* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<![endif]-->
<link rel="themeData" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx" />
<link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml" /><!--[if gte mso 9]><xml>
Normal
0
false
7.8 磅
0
2
false
false
false
EN-US
ZH-CN
X-NONE
</xml><![endif]--><!--[if gte mso 9]><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:微软雅黑;
panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
{font-family:Verdana;
panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
{font-family:"MS Shell Dlg 2";
panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
{font-family:""@微软雅黑";
panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
{font-family:""@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
line-height:14.0pt;
font-size:12.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
p.MsoHeader, li.MsoHeader, div.MsoHeader
{
mso-style-link:"页眉 Char";
margin:0cm;
margin-bottom:.0001pt;
text-align:center;
line-height:12.0pt;
tab-stops:center 207.65pt right 415.3pt;
layout-grid-mode:char;
border:none;
padding:0cm;
font-size:9.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{
mso-style-link:"页脚 Char";
margin:0cm;
margin-bottom:.0001pt;
line-height:12.0pt;
tab-stops:center 207.65pt right 415.3pt;
layout-grid-mode:char;
font-size:9.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
code
{
font-family:"Courier New";
mso-ascii-font-family:"Courier New";
mso-hansi-font-family:"Courier New";
mso-bidi-font-family:"Courier New";
color:#007000;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:21.0pt;
line-height:14.0pt;
font-size:12.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
span.Char
{mso-style-name:"页眉 Char";
font-family:"微软雅黑","sans-serif";}
span.Char0
{mso-style-name:"页脚 Char";
font-family:"微软雅黑","sans-serif";}
p.a, li.a, div.a
{
mso-style-link:"代码 Char";
margin:0cm;
margin-bottom:.0001pt;
line-height:150%;
background:#EEEEEE;
font-size:11.0pt;
font-family:"Verdana","sans-serif";
color:black;}
span.Char1
{mso-style-name:"代码 Char";
font-family:"Verdana","sans-serif";
color:black;
background:#EEEEEE;}
.MsoChpDefault
{
mso-bidi-font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:595.3pt 841.9pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
layout-grid:15.6pt;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{}
@list l0:level1
{
margin-left:21.0pt;
text-indent:-21.0pt;
font-family:Wingdings;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.5pt;
font-family:"Calibri","sans-serif";}
</style>
<![endif]--><!--[if gte mso 9]><![endif]--><!--[if gte mso 9]><![endif]-->
<p style="margin: 15.6pt 0cm; text-align: left;" align="left">Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">帐户最早用来申请巨大的</span>Gmail<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">邮箱（如今看来，一般个大吧），随着后来的</span>Blogger<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，</span>Docs<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">等各种服务上线，也就顺路继承了过来。现在使用一个</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">帐户，就可以同时使用这些服务。</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">既然我们打算写一个从</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">取相册数据的</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，就免不了要先了解一些和</span>Goolge<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">帐户有关的知识。因为</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的数据也是受保护的，并非谁要看都可以（公开的相册除外哦，那都是炫耀册，巴不得全天下人都看见呢），我们的程序也不例外，要想取到相册的数据，程序必须向</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的服务器证明自己得到了相应用户的授权。</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">一个人类用户当然可以这样做：打开</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的首页，发现要求登录，于是输入自己的用户名密码，成功后就查看自己的相册。我们的程序可干不了，它不会打开浏览器，好吧，这个它会，但打开以后它找不着用户名的输入框在哪，即便找到了，也不知该往里面填什么，即便填对了，也不知要看什么，即便看到了，也看不懂，即便看懂了也学不会&#8230;&#8230;（读者：你贫不贫？）</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">所以一切的一切都还要咱们自己来写，当然少不了</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的帮忙。</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">为了方便应用程序的登录，</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">在自己的服务器上开放了被称之为&#8220;</span>Google Account Authentication<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&#8221;的服务，我们只用到其中一种方式：</span>ClientLogin<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">。使用这种方式访问</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的服务大致是下面的流程：</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;"><img src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadgetGoogle_DEFD/clip_image002[8]_thumb.jpg" alt="" width="320" border="0" height="275" /><br />
</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><!--[if gte vml 1]>
<![endif]--></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">很容易看出来，这基本上是一个两步骤的工作：首先使用一个</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">帐户访问</span><span>Google
Account Authentication </span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">服务，并得到一个可以合法访问服务数据的</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">（</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">把它叫做得到一个&#8220;授权&#8221;，不过习惯上还是叫</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">吧，就是令牌，拿了以后皇帝不能砍你头的那种，此过程也叫做申请一个</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">）；使用上一步得到的</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">去访问具体的服务并取得数据（我们的例子中就是访问</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">服务）。</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">有一些东西从图上看不出，我来说一说。一是程序访问</span>Gmail<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的时候使用的不是这种方式（毕竟</span>Gmail<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">太早啦，那时连</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">自己都没有考虑清楚吧），但其他大部分</span>Goolge<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">服务，包括</span><span>Calendar,Docs,Picasa,Blogger,Contacts,Google
Apps</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">等等，都是上面这个流程。二是并非申请了一个</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">以后，就可以访问</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">所有的服务，实际上需要为每个服务申请不同的</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">具体到代码中，我们使用</span>XmlHttpRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">对象来发送请求并且接受回传的数据。</span></p>
<p style="margin: 15.6pt 0cm;">XmlHttpRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">是</span>Gadget Host<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">提供的一个类型（注意我没有说对象，因此要用的时候你还得自己初始化，也就是</span>new<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">一下，哈哈），其行为与</span>W3C<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">所指定的标准</span>XmlHttpRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">相同。再一次的，不要联想到浏览器，你不能假设这个</span>XmlHttpRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">与</span>IE<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">或者</span>FireFox<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">提供的</span>XmlHttpRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">有任何联系，更不能依赖这样的假设来编写程序。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">好，废话少说，还用上一节新建的&#8220;白</span>Gadget<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&#8220;（笑），在</span>main.js<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">文件里添加这样一个函数：</span></p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">function</span><span style="color: #000000;">&nbsp;createXhr()&nbsp;{<br />
<br />
&nbsp;</span><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;xhr;<br />
<br />
&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;framework.google.betaXmlHttpRequest2();<br />
<br />
&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(e)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;XMLHttpRequest();<br />
<br />
&nbsp;}<br />
<br />
&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;xhr;<br />
<br />
}</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">调用这个函数就可以得到一个</span><span style="color: black;">XmlHttpRequest</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;; color: black;">的对象啦。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;; color: black;">然后为我们的</span><span style="color: black;">Gadget</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;; color: black;">添加一个主类，并把需要的对象引用也声明好，这些都写在</span><span style="color: black;">main.js</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;; color: black;">文件中，像这样：</span></p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;xhRequest</span><span style="color: #000000;">=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
<br />
</span><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;main</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Main();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">Gadget启动时便登录</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">function</span><span style="color: #000000;">&nbsp;view_onOpen()&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main.login();<br />
<br />
}<br />
<br />
</span><span style="color: #0000ff;">function</span><span style="color: #000000;">&nbsp;Main(){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.albums</span><span style="color: #000000;">=</span><span style="color: #000000;">[];<br />
<br />
}<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">具体的登录函数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
Main.prototype.login</span><span style="color: #000000;">=</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){<br />
<br />
}</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">我们就要在</span>Main.login()<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">函数中写我们取</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的逻辑。</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">详细说说申请</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的过程。请求是通过</span>XmlHttpRequest<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">对象发起的，而对一个请求来说，最重要的信息有四个：请求的</span>URL<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，请求的类型，请求头和消息体。</span></p>
<p style="margin: 15.6pt 0cm;">URL<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">是说你的请求要发往哪里，既然我们要使用</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的服务，那当然要往</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">那里发了，具体应该为：</span></p>
<p style="margin: 15.6pt 0cm;"><code><span style="font-size: 10pt;"><span style="color: #00ff3f;"><span style="color: #000556;">https://www.google.com/accounts/ClientLogin</span></span></span></code></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">如果你没有看出这是一个安全的</span>https<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">请求，那我提醒一下（如果你看出来了，我就不提醒了，笑）。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">请求的类型是指你要</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的服务器替你做什么事情，是返回你要<span style="color: #4f81bd;">查询</span>的数据？还是为你<span style="color: #4f81bd;">更新</span>已有的数据，抑或仅仅是<span style="color: #4f81bd;">提交</span>一些数据，还是要服务器帮你<span style="color: #4f81bd;">删除</span>一些数据？</span></p>
<p style="margin: 15.6pt 0cm;">Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">的服务器通过你提交请求的类型来做相应的操作，每一种操作的类型对应如下：</span></p>
<ul>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">查询　　</span>GET</li>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">提交　　</span>POST</li>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">更新　　</span>PUT</li>
    <li><span style="font-family: Wingdings;">&nbsp;</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">删除　　</span>DELETE</li>
</ul>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">看着眼熟么？没错，正是轻量级的</span>Web Service<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">接口</span>REST<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">！</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">我们做登录显然是一个<span style="color: #4f81bd;">提交</span>的动作，</span>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Word.Document" />
<meta name="Generator" content="Microsoft Word 12" />
<meta name="Originator" content="Microsoft Word 12" />
<link rel="File-List" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml" />
<link rel="themeData" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx" />
<link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cjasper%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml" /><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
EN-US
ZH-CN
X-NONE
</xml><![endif]--><!--[if gte mso 9]><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:微软雅黑;
panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
{font-family:""@微软雅黑";
panose-1:2 11 5 3 2 2 4 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
line-height:14.0pt;
font-size:12.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";}
.MsoChpDefault
{
mso-bidi-font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
{page:Section1;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.5pt;
font-family:"Calibri","sans-serif";}
</style>
<![endif]--><span style="font-size: 12pt; font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">要把我们的用户名和密码告诉</span><span style="font-size: 12pt; font-family: &quot;Calibri&quot;,&quot;sans-serif&quot;;">Google</span><span style="font-size: 12pt; font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">因此我们的请求类型是</span>POST<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">。</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">对登录来说，请求头没有特殊要求，只需要请求头</span><code><span style="font-size: 10pt;">Content-Type</span></code><code><span style="font-size: 10pt; font-family: 宋体;">，</span></code><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">其值为</span><code><span style="font-size: 10pt;">application/x-www-form-urlencoded</span></code></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">所需的用户名，密码等信息被统一称为&#8220;属性&#8221;，属性的值将放在消息体中发送。因此你的消息体看起来是下面这个样子的一个字符串：</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="font-size: 10.5pt; color: #92d050;">Email=</span><span style="font-size: 10.5pt; color: red;">mymail2009.test%40gmail.com</span><span style="font-size: 10.5pt; color: #92d050;">&amp;Passwd=</span><span style="font-size: 10.5pt; color: red;">mymail</span><span style="font-size: 10.5pt; color: red;">2009</span><span style="font-size: 10.5pt; color: #92d050;">&amp;</span><span style="font-size: 10.5pt; color: red;">service=lh2</span><span style="font-size: 10.5pt; color: #92d050;">&amp;source=gd-picasa-gadget-1.0.0.0&amp;accountType=HOSTED_OR_GOOGLE</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">注意其中红色的部分，用户名和密码的位置你当然很容易找到，</span>&#8221;<span style="font-size: 10.5pt; color: red;">service=lh2</span>&#8221;<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">这一项就指明了你要为访问什么服务申请</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，</span>lh2<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">是指</span>Picasa<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，如果访问</span>Google Docs<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">则要填</span>writely<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">，详细的列表可以看这一节最后的附录。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">好，把登录的代码整个贴出来，你应该很容易找到以上四部分对应的地方。</span></p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Main.prototype.login</span><span style="color: #000000;">=</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xhRequest</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;createXhr();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">请求的URL</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;url</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">https://www.google.com/accounts/ClientLogin</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">消息体</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">var</span><span style="color: #000000;">&nbsp;data</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">Email=</span><span style="font-size: 10.5pt; color: red;">mymail</span><span style="color: #000000;">2009.test%40gmail.com&amp;Passwd=</span><span style="font-size: 10.5pt; color: red;">mymail</span><span style="color: #000000;">2009&amp;service=lh2&amp;source=gd-picasa-gadget-1.0.0.2&amp;accountType=HOSTED_OR_GOOGLE</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.onreadystatechange&nbsp;</span><span style="color: #000000;">=</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">xhRequest)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(xhRequest.readyState&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">如果下面这行能够被执行，说明登录请求已经有数据返回</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&#8220;登录动作完毕啦！&#8221;);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(xhRequest.responseText);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #008000;">//</span><span style="color: #008000;">接受数据后的回调函数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">请求的类型，是POST</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.open('POST',&nbsp;url,&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">请求头</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.setRequestHeader(</span><span style="color: #000000;">"</span><span style="color: #000000;">Content-Type</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">application/x-www-form-urlencoded</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xhRequest.send(data);<br />
<br />
};</span></div>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">在请求的回调函数中，目前只是先简单的打印了相应的文本内容，实际上应该在这里做更多的事，详情咱们下节再聊。如果你看到类似下面这样的输出内容，说明登录的请求成功了。如果没有成功，很可能是因为我已经换掉了用户名和密码，用你自己的</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">帐户试试看。</span></p>
<p style="margin: 15.6pt 0cm;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">应该看到的内容：</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left">SID<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">＝</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left">DQAAAHYAAADYQ4hToTAEYRu0uEXP9yXZ1uc_W3-kBtZFpug78XQDGiykOb-Sv2qdXtdUOL-<br />
npRJm9SSq-AEvSBodrcuy3UwgFM8SX_z6fXzpGaJzHzQx5YTzR0AJHCEkFh<br />
4yOoBFs0iCE2LI0LWQs6_2BFyIuLLMwRA8m3vfuVzNE3CHjrUHZA</p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left">LSID<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">＝</span><br />
</p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left">DQAAAHgAAAClSiMWRfKAonW8zIytZ7NEizJNMQZojiNqsDxm3elei36MV<br />
7GzM72bMiqdQawt8Fd1Dpp68p5bs1XYOXUPmDunUsZM1BZsAiXbIEouAJz1XjlysUQG-0p9969zYCvUm2tqWkA1BFVU2UqvjMAaBSgj10VkZzvcAbZB8nQf_mwRyg</p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left"><span style="color: #92d050;">Auth</span><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">＝</span></p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left">DQAAAHcAAAClSiMWRfKAonW8zIytZ7NEizJNMQZojiNqsDxm3elei36<br />
MV7GzM72bMiqdQawt8FcmxySIt75kfLxcis5BZnNCsyVuCwKM-DtNZcToUtm9IWoJyvNbUD9UTFYZPdBu1OyXsfY_QJHZfZdAT2QC<br />
cExSIYKMvLfhhit9RPz4Gk2xlQ/n</p>
<p style="margin: 15.6pt 0cm; text-align: left;" align="left">Auth<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">那一项后面的值就是</span>token<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">啦，可以不被砍头了。</span></p>
<p style="margin: 15.6pt 0cm;"><strong><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">附录：</span></strong><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">已知的</span>Google<span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">服务及服务名</span></p>
<table style="border: 1.5pt outset ; width: 300pt; margin-left: 39.65pt;" width="400" border="1" cellpadding="0" cellspacing="10">
    <tbody>
        <tr>
            <td style="padding: 7.5pt; width: 204.95pt;" width="273">
            <p style="margin: 15.6pt 0cm;"><span>Calendar
            Data API</span></p>
            </td>
            <td style="padding: 7.5pt; width: 72.55pt;" width="97">
            <p style="margin: 15.6pt 0cm;">cl</p>
            </td>
        </tr>
        <tr>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span>Google
            Base Data API</span></p>
            </td>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;">gbase</p>
            </td>
        </tr>
        <tr>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span>Blogger
            Data API</span></p>
            </td>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;">blogger</p>
            </td>
        </tr>
        <tr>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span>Contacts
            Data API</span></p>
            </td>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;">cp</p>
            </td>
        </tr>
        <tr>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span>Documents
            List Data API</span></p>
            </td>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span style="color: #4f81bd;">writely</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span>Picasa
            Web Albums Data API</span></p>
            </td>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;">lh2</p>
            </td>
        </tr>
        <tr>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span>Google
            Apps Provisioning API</span></p>
            </td>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;">apps</p>
            </td>
        </tr>
        <tr style="height: 13.85pt;">
            <td style="padding: 7.5pt; height: 13.85pt;">
            <p style="margin: 15.6pt 0cm;"><span>Spreadsheets
            Data API</span></p>
            </td>
            <td style="padding: 7.5pt; height: 13.85pt;">
            <p style="margin: 15.6pt 0cm;">wise</p>
            </td>
        </tr>
        <tr>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;"><span>YouTube
            Data API</span></p>
            </td>
            <td style="padding: 7.5pt;">
            <p style="margin: 15.6pt 0cm;">youtube</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/253579.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-02-06 15:51 <a href="http://www.blogjava.net/zhenandaci/archive/2009/02/06/253579.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Gadget 开发入门（二）啰嗦的Gadget例子</title><link>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253494.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Fri, 06 Feb 2009 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253494.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/253494.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/02/06/253494.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/253494.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/253494.html</trackback:ping><description><![CDATA[<p>前文说道开发一个Gadget可以分为两个步骤：先写界面的XML文件，再写逻辑部分的JavaScript。我们就遵循这个步骤来写一个再简单也不过的Gadget。 </p>
<p>用到的工具有两个，一个是随Google Desktop SDK附带的Gadget Designer，用来编写并有限的预览界面，还可以调试JavaScript（这个就更有限了）；一个是Google Desktop，用来测试写好的Gadget。下面要写的例子是我在为某研究院某个项目策划阶段作POC时所写的一个小例子，可以显示一个Google用户的Picasa相册中的Album名称和缩略图。虽然很小，但包含了Google账户的自动登录，显示网络图片，XmlHttpRequest的使用等很多实用技巧。整个完成之后是这个样子： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadget_8E92/clip_image001_2.jpg"></a><img alt="" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/clip_image001_2.jpg" width="289" border="0" height="350" />&nbsp;</p>
<p>请跟我一起来。现在打开Gadget Designer，选择File-&gt;New Gadget，输入了名称&#8220;Picasa&#8221;之后，就可以看到一个完整Gadget的雏形了。你可以找到这个项目所在的文件夹，双击其中的gadget.gmanifest，此时如果你已经安装了Google Desktop，就可以看到Desktop自动启动，并把这个很&#8220;白&#8221;的Gadget（别笑，除了一张白色背景图片以外，确实什么也没有）显示在Sidebar中。如图： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadget_8E92/clip_image002_2.jpg"><img style="border: 0px none ; display: inline;" title="clip_image002" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadget_8E92/clip_image002_thumb.jpg" width="244" border="0" height="234" hspace="12" /></a> </p>
<p>到项目文件夹里可以看到一个main.xml文件和一个main.js文件。我们的界面就是在main.xml文件里指定的，打开它，可以看见它指定了一张GadgetDesigner帮我们生成的白色png图片作背景，还指定了我们要导入哪些个.js文件。我们来小改两个地方： </p>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 98%; font-size: 13px;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;"><br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 98%; font-size: 13px;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">view&nbsp;</span><span style="color: #ff0000;">height</span><span style="color: #0000ff;">="150"</span><span style="color: #ff0000;">&nbsp;width</span><span style="color: #0000ff;">="250"</span><span style="color: #ff0000;">&nbsp;onopen</span><span style="color: #0000ff;">="view_onOpen()"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">img&nbsp;</span><span style="color: #ff0000;">src</span><span style="color: #0000ff;">="stock_images\background.png"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script&nbsp;</span><span style="color: #ff0000;">src</span><span style="color: #0000ff;">="main.js"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">view</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"> <br />
</span></div>
</div>
<p>一是把view的height改成250，二是给img元素添加一个属性name并给一个值，就像这样： </p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 98%; font-size: 13px;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">img&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">=&#8221;bgImage&#8221;&nbsp;</span><span style="color: #ff0000;">src</span><span style="color: #0000ff;">="stock_images\background.png"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"> <br />
</span></div>
<p>&nbsp;</p>
<p>然后双击gadget.gmanifest，看看更改效果： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadget_8E92/clip_image003_2.jpg"><img style="border: 0px none ; display: inline;" title="clip_image003" alt="clip_image003" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadget_8E92/clip_image003_thumb.jpg" width="209" border="0" height="244" hspace="12" /></a> </p>
<p>乍一看貌似没什么改变，但是注意看我用黑色线圈出来的那一条横杠，那是我们的Gadget的下边沿，说明它的高度还是变化了，但是白色的背景没有变，因为我们没有改变背景图片的大小。现在通过.js文件中代码的方式来改变背景图片的高度，可以看出些有意思的东西。 </p>
<p>打开main.js文件，你应该会看到一个view_onOpen()函数，这就是Gadget启动时会自动调用的第一个函数（好吧，并不严格，但是在调用的顺序上，它的确是相当靠前的），我们就在这个函数内部添加下面这一句： </p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 98%; font-size: 13px;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">bgImage.height</span><span style="color: #000000;">=</span><span style="color: #000000;">250</span><span style="color: #000000;">; <br />
</span></div>
<p>再双击gadget.gmanifest运行看看，白色背景也变高了吧。 </p>
<p>我知道你一定会问，代码里的bgImage是什么东西？怎么没见在任何地方声明这个变量，也没见任何地方作初始化呢？回想我们刚才在main.xml文件里做了什么？我们给背景图片取了一个名字，叫bgImage，而且别怀疑，你在代码里访问的这个bgImage，正是那张图片！背后的工作就是Gadget Host通过JavaScript引擎为我们做的，凡是在.xml文件里放置的东西（无论什么，图片也好，按钮也好，一个抽象的div也好），只要你给了一个name属性，在JavaScript代码中就可以直接使用这个名字来访问该对象（前提是你给的名字得是独一无二的），这与浏览器中随时可以访问document对象而不用做任何声明一样，那是浏览器这个运行环境提供的对象，随时可用。 </p>
<p>另一个值得注意的地方是在.xml文件里，属性的值都必须加上引号，像height=&#8221;250&#8221;（因为那里使用的是标准的xml语法），而在JavaScript代码中，就要根据属性具体的类型来决定，像高度这种整数型的值，就不用加。 </p>
<p>你可能还会问，那么bgImage这个对象，是什么类型的，它有些什么属性和方法可供我使用呢？它是一个img类型的对象，参考<a href="http://code.google.com/intl/zh-CN/apis/desktop/docs/gadget_apiref.html">http://code.google.com/intl/zh-CN/apis/desktop/docs/gadget_apiref.html</a>这个链接，这也是Google Desktop Gadget的API参考页面，列出了Gadget Host提供的各种对象属性和方法的说明（虽然事实验证，Google自己列的这些都不全面，后话）。 </p>
<p>最后叮嘱一句：尽管main.xml文件里的东西（什么img啊，以后还会加进div啊，checkbox之类的东西）看起来多么的像HTML，Gadget都和Web没有天然的联系。Google自己发布了一些Gadget，例如Gmail和Google Docs，外观与这两个服务的网页非常像，再加上Gadget也主要使用JavaScript开发（也少不了Universal Gadget跟着掺合），间接导致了总有人把Gadget显示的地方考虑成一个小的浏览器窗口，而想把Web的一些东西简单的放在这里，到底行不行呢？李宁说：一切皆有可能。阿迪说：没有不可能。匹克说：我能，无限可能。我要说：可能，但很难（笑）。 </p>
<p>所以在编写Gadget的时候，最好的方法是把它当成纯粹的桌面程序，忘掉Web的那一套。 </p>
<p>这一节给大家入个门，下一节开始说说在Gadget中怎么做Google帐户的登录，还会很罗嗦的，请见谅（笑）。 <br />
</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/253494.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-02-06 10:08 <a href="http://www.blogjava.net/zhenandaci/archive/2009/02/06/253494.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Gadget 开发入门（一）Gadget的组成&amp;mdash;&amp;mdash;两个视角</title><link>http://www.blogjava.net/zhenandaci/archive/2009/02/05/253460.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Thu, 05 Feb 2009 14:23:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/02/05/253460.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/253460.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/02/05/253460.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/253460.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/253460.html</trackback:ping><description><![CDATA[<p><font face="微软雅黑">在Gadget开发人员看来——我当然是指你我这样的IT民工，来开发一个Gadget的人，而不是Google大楼里成天琢磨怎么和微软对着干的那帮子人——一个Gadget由三大部分组成：描述UI的一系列.xml文件；存放程序逻辑的.js文件以及资源。</font> </p>
<p><font face="微软雅黑">下面是一个Gadget项目在Google Desktop Disigner里面的结构截图。</font></p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadget_13ABF/clip_image001_2.jpg"><font color="#000000" face="微软雅黑"><img style="border-width: 0px; display: inline;" title="clip_image001" alt="clip_image001" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/GoogleGadgetGadget_13ABF/clip_image001_thumb.jpg" width="224" border="0" height="244" hspace="12" /></font></a></p>
<p><strong><font face="微软雅黑"></font></strong> </p>
<p><strong><font face="微软雅黑"></font></strong> </p>
<p><strong><font face="微软雅黑"></font></strong> </p>
<p><font face="微软雅黑">资源这东西好理解，无非是程序要用到的各种图片啦，字符串啦等等。读者：字符串？什么意思？答：把程序会用到的一系列字符串统一存放，想引用的时候使用一个常量名字就可以，而不必在需要这些字符串的地方每次都重写一遍，和Java中的property文件作用类似。</font> </p>
<p><font face="微软雅黑">其余的两部分会分节来详细讲解。</font> </p>
<p><font face="微软雅黑">当然说只有三部分，是指我们大多只关心这么多，实际上还有第四部分，一个Gadget Settings文件，其中大多是关于这个Gadget的元信息，什么作者啊，创建日期啊，uuid啊，户口所在地啊，最高学历啊，婚姻状况啊，哦，我给说成简历了（笑）。</font> </p>
<p><font face="微软雅黑">前面也说到过，一个Gadget其实就是一个桌面应用程序（再一次的，不管写起来某些语法多么得像HTML，Gadget与Web都没有天然的联系），只不过这个程序在Gadget Host的管理之下，行话叫&#8220;托管&#8221;。Windows下没有单独的Gadget Host，它被合并在Google Desktop里面（算是另一种捆绑吧）。而Linux下的确有干干净净的Gadget Host，且有源码下载，我们所有对Gadget的理解也都源于这个版本和相关的文档。</font> </p>
<p><font face="微软雅黑">那么在Gadget Host看来，一个Gadget是什么东西呢？</font> </p>
<p><font face="微软雅黑">以我写的一个小Picasa Gadget为例，在Picasa Gadget初次加载之前，它是一个.gg的压缩包（其实就是一个标准的zip包，被改了后缀名而已），Gadget Host会从中读取需要的文件，然后做相应的解释。</font> </p>
<p><font face="微软雅黑">Gadget Host可以看成只有两部分组成：一个UI的渲染器和一个JavaScript引擎。</font> </p>
<p><font face="微软雅黑">说UI渲染器之前就不得不回头重提刚才说到的一个Gadget包括了一系列.xml文件这件事。实际上这些.xml文件就是用来指定你想写的Gadget的界面的，就是说，你的Gadget跑起来以后长成什么样子，是由这些个.xml文件来决定的（当然，严格说来可以使用JavaScript在运行时改变一些内容，但请不要抬杠，笑）。</font> </p>
<p><font face="微软雅黑">这些.xml文件中最主要的是main.xml这个文件，你的Gadget窗口有多大，在什么位置有几个按钮，列表有没有滚动条，背景是什么颜色等等，都在这里指定。还包括这些东西上的事件监听函数也一并在这里声明（不知为何，让我莫名的想起微软的MFC，当然，严格说来可以使用JavaScript在运行时动态改变这些内容，但请不要再次抬杠，笑）。</font> </p>
<p><font face="微软雅黑">UI渲染器干什么呢？就是来把这个.xml所要求的界面转换成具体的系统调用，让操作系统来完成绘图（好吧好吧，你喜欢严格，那我告诉你，Linux版本下首先被转换为Qt的C++类，由Qt来发起对系统绘图的调用）。</font> </p>
<p><font face="微软雅黑">既然Gadget的程序逻辑都使用JavaScript来编写，理所应当的，Gadget Host必然要包含一个JavaScript解释器来解释这些代码，这个解释器也被叫做JavaScript引擎。Gadget Host里确实有这么个东西，叫做Spider Monkey，它恰好也是FireFox所使用的JavaScript引擎。广义上说，一个引擎的作用主要是解释它遇到的一切JavaScript代码，如果代码使用到核心JavaScript的功能和对象，它便直接提供；如果代码使用到了一些依赖于底层的对象（例如Gadget Host就提供了很多专有的JavaScript对象和方法供使用，这些都是核心JavaScript之外的东西），则引擎还要负责转发这样的请求（你可以说，这实际上是适配器做的事，我这样简化有助于理解，请不要一再抬杠，笑）。</font> </p>
<p><font face="微软雅黑">也可以这样从逻辑上看Gadget的组成：即一个Gadget就是一组图形界面，加这些界面上每个控件（按钮啊，列表啊，输入框等等）的事件监听函数，这种界面描述与事件逻辑分离的程序模型，和微软的XAML+C#简直如出一辙。因此一个Gadget的开发实际上也就可以分为这两大步骤：先写界面的XML文件，再写逻辑部分的JavaScript。下面一节就用一个小例子来看看具体如何做。别嫌我说得太详细哦。</font> </p>
<p><font face="微软雅黑"></font></p>
<p><font face="微软雅黑"></font></p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/253460.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-02-05 22:23 <a href="http://www.blogjava.net/zhenandaci/archive/2009/02/05/253460.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>