チュートリアル

はてなブックマークに追加 livedoorクリップに追加 Yahoo!ブックマークに追加 del.icio.usに追加 イザ!ブックマーク ニフティクリップに追加 Choixにブックマーク Buzzurlに追加

今日から作れる ガジェットって何?をクリアした人のための ガジェットHOW TO MAKE

サンプルで学ぶ「Live Gadget」の作り方 Live ガジェット

Windows Live版GadgetsPepperをサンプルにしながら、Window s Live Gadgetsの作り方について学びます。先ず、ガジェットを使ってみて動作を確認したいという方は「ガジェットのインストール方法」へ、主要な6つの機能がどのように実装されているか概要を知りたい方は「主要機能の実装方法へ」、ソースコードをじっくり読みたい方は「ソースコードの詳説」へとお進みください。ソースコードの詳説では、解説アイコンにマウスをあてると、その部分の解説が表示されます。


ガジェットのインストール方法

Webブラウザでwww.live.jpを開きます。ページの左上にあるリンク「コンテンツの追加」をクリックし、「詳細設定」タブを選択します。 「ガジェットのURLを指定して追加/URLを入力して特定のフィードを取得」へGadgetsPepperのURLである

     
 

    http://www.tkrb.jp/gadgets/pepper/wl/GadgetsPepper.xml

 
     

を指定して、「取得」ボタンを押します。Gadgets Pepperが表示されますので、説明をよくお読みになり、「ガジェットのインストール」ボタンを押してください。表示が更新されればインストールの完了です。

主要機能の実装方法

主要機能の実装方法
機能 実装方法
(1)地図を移動 地図表示にはGoogle Maps APIを利用しています。テキストボックスに地名を入力し、エンターキーもしくは検索ボタンを押すと、findAddress()が呼び出されます。ランドマーク、地名から緯度経度へ変換するにはGoogleのジオコーディングAPIであるGClientGeocoderを使用します。得られた結果による中心点の再設定は、
232: geocoder.getLatLng(address, function(point) { 省略 });
で行っています。
(2)ジャンルを選択 ガジェットロード時、initializeGenre()内でジャンルマスターを検索し、返ってきたXMLをonGenreLoad()でパースします。GenreName(ジャンル名)ノード、GenreCD(ジャンルコード)ノードを抽出し、その2つを使って、プルダウンリストの内容をセットします。
(3)グルメ店を検索 読込ボタンが押されると、onFindShops()が呼び出されます。実際の検索はfindAtPoint()内で行っており、地図中心点の緯度経度とジャンルコードを用いURLを組み立て、
199: oReq.open( "GET", url, true );
でグルメサーチAPIを呼び出します。結果のXMLにはグルメ店情報が含まれます。
(4)詳細画面を表示 グルメ店の緯度経度を用い、地図上にグルメ店の位置を表すマーカーをセットします。この時、マーカーにイベントリスナーを追加し、それがクリックされたときにsetShopInfo()が呼び出されるようにします。setShopInfo()内で、グルメ店の詳細表示用のレイヤをvisibleにし、グルメ店詳細情報を表示します。
(5)背景画像を変更 背景画像を選択するためのレイヤは
481:

で記述されています。通常はhiddenになっていますが、showSettings()が呼び出されるとvisibleに変わり、表示されます。
(6)状態の保存と復帰 状態の保存は、unload()が呼ばれるタイミングで行います。実際の処理はsaveState()内で行っており、最後に実行された検索の地図中心点の緯度経度、ズームレベル、料理ジャンル、背景画像番号をCookieに保存します。
102: setCookie( "zoom_level", zl );
104: setCookie( "search_latitude", lastSearchPoint.y );
105: setCookie( "search_longitude", lastSearchPoint.x );
108: setCookie( "search_genre", lastSearchGenre );
110: setCookie( "skin_number", curSkin );
保存した内容の復帰はload()が呼ばれるタイミングでloadState()内で行います。

注)Cookieについて
今回のサンプルプログラムはデータの保存にCookieを用いており、セキュリティ設定によっては「状態の保存と復帰」が機能しません。以下、 Internet Explorer 6.0を例にCookieの設定方法をご案内します。

  • 「ツール」メニューの「インターネットオプション」を選びます。
  • 「インターネットオプション」ウィンドウで「プライバシー」のタブをクリックします。
  • 「詳細設定」をクリックします。
  • 「プライバシー設定の詳細」ウィンドウで「自動Cookie処理を上書きする」にチェックをします。
  • 「ファーストパーティのcookie」「サードパーティのcookie」の両方について、「受け入れる」を選択します。

ソースコード詳説

code    
 
  1: Pepper.html
  2:
  3: ?<html lang="ja" >
  4:  <head>
  5:   <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  6:   <title>Gadgets Pepper</title>
  7:   <link href="HotStyle.css" rel="stylesheet" type="text/css" />
  8:   <script src="http://maps.google.com/maps?file=api&v=2&key=(API KEY)" type="text/javascript" charset="utf-8"></script>
  9:   <script type="text/javascript" src="HotScript.js"></script>
 10:   <script type="text/javascript">
 11:   var urlGourmetSearch = "http://www.tkrb.jp/cgi-bin/pepper/GourmetSearch.cgi";
 12:   var urlGenreMaster = "http://www.tkrb.jp/cgi-bin/pepper/Genre.cgi";
 13:   var googleMaps = null;
 14:   var shopNodeList = null;
 15:   var curShopNode = 0;
 16:   var geocoder = null;
 17:   var lastSearchPoint = null;
 18:   var lastSearchGenre = null;
 19:   var initCenter = new GLatLng( 35.681074, 139.767079 );
 20:   var initZoom = 13;
 21:   var curSkin = 1;
 22:   var idIntervalTimer = null;
 23:
 24:   // お店検索、ジャンル一覧を初期化する
 25:   // HTTP Requestを実行し、onGenreLoadで処理
 26:   //
 27:   function initializeGenre(){
 28:     try{
 29:       var oReq = createHttpRequest();
 30:       oReq.onreadystatechange = function(){
 31:         if( oReq.readyState==4 ){
 32:           onGenreLoad( oReq );
 33:         }
 34:       }
 35:       oReq.open( "GET", urlGenreMaster ); 解説
 36:       oReq.send( null );
 37:     }
 38:     catch( e ){window.alert( "initializeGenre" );}
 39:   }
 40:
 41:   // HTML bodyのロード時
 42:   // 各種初期化処理
 43:   //
 44:   function load() { 解説
 45:     try{
 46:       // Google Mapsの作成
 47:       initCenter = new GLatLng( 35.681074, 139.767079 );
 48:       initZoom = 13;
 49:       loadState();
 50:       if( GBrowserIsCompatible() ){
 51:         googleMaps = new GMap2( document.getElementById( "map" ) );
 52:         googleMaps.addControl( new GSmallMapControl() );
 53:         googleMaps.enableScrollWheelZoom();
 54:         geocoder = new GClientGeocoder();
 55:       }
 56:       initializeGenre(); // ジャンル一覧の初期化
 57:       setDockState();
 58:       // 最後の状態を復元
 59:       if( lastSearchPoint != null ){
 60:         googleMaps.setCenter( lastSearchPoint, initZoom, G_NORMAL_MAP );
 61:         findAtPoint( lastSearchPoint, lastSearchGenre );
 62:       }
 63:       else{
 64:         googleMaps.setCenter( initCenter, initZoom, G_NORMAL_MAP );
 65:       }
 66:       idIntervalTimer = setInterval( "showCurrentTime()", 1000 );
 67:     }
 68:     catch( e ){}
 69:   }
 70:
 71:   // HTML bodyのアンロード時
 72:   //
 73:   function unload(){ 解説
 74:     saveState(); // 状態の保存
 75:     GUnload(); // Google Mapsの終了処理
 76:   }
 77:
 78:   // クッキーの設定
 79:   //
 80:   function setCookie(fieldId,value){ 解説
 81:     var expires = new Date()
 82:     expires.setTime(expires.getTime() + (1*24*60*60*1000))
 83:     document.cookie=fieldId+"="+escape(value)+"; expires="+expires.toGMTString()
 84:   }
 85:
 86:   // クッキーの取得
 87:   //
 88:   function getCookie(fieldId){ 解説
 89:     var tmp=(document.cookie+";").match(fieldId+"=([^;]*);")
 90:     if(tmp!=null){
 91:       return unescape(tmp[1])
 92:     }else{
 93:       return null
 94:     }
 95:   }
 96:
 97:   // 状態の保存
 98:   //
 99:   function saveState(){ 解説
100:     try{
101:       var zl = googleMaps.getZoom();
102:       setCookie( "zoom_level", zl );
103:       if( lastSearchPoint != null ){
104:         setCookie( "search_latitude", lastSearchPoint.y );
105:         setCookie( "search_longitude", lastSearchPoint.x );
106:       }
107:       if(lastSearchGenre != null ){
108:         setCookie( "search_genre", lastSearchGenre );
109:       }
110:       setCookie( "skin_number", curSkin );
111:     }
112:     catch( e ){}
113:   }
114:
115:   // 保存した状態の読み込み
116:   //
117:   function loadState(){ 解説
118:     try{
119:       var skin_number = getCookie( "skin_number" );
120:       if( ! isNullOrEmpty( skin_number ) )
121:         curSkin = parseInt( skin_number, 10 );
122:       var zoom_level = getCookie( "zoom_level" );
123:       if( ! isNullOrEmpty( zoom_level ) )
124:         initZoom = parseInt( zoom_level, 10 );
125:       var search_latitude = getCookie( "search_latitude" );
126:       var search_longitude = getCookie( "search_longitude" );
127:       lastSearchGenre = getCookie( "search_genre" );
128:       if( ! isNullOrEmpty( search_latitude ) && ! isNullOrEmpty( search_longitude ) )
129:         lastSearchPoint = new GLatLng( parseFloat( search_latitude ), parseFloat( search_longitude ) );
130:     }
131:     catch( e ){}
132:   }
133:
134:   // ジャンル一覧のデータ取得
135:   //
136:   function onGenreLoad( oReq ){ 解説
137:     try{
138:       var elmSel = document.getElementById( "genreSelect" );
139:       var oXMLDocument = oReq.responseXML;
140:       genreNodeList = oXMLDocument.getElementsByTagName( "Genre" );
141:       if( genreNodeList == null )
142:         return;
143:       for( var i = 0 ; i < genreNodeList.length ; i++ ){
144:         var node = genreNodeList.item( i );
145:         var ndName = node.getElementsByTagName( "GenreName" );
146:         var ndCD = node.getElementsByTagName( "GenreCD" );
147:         if( ndName.length > 0 && ndCD.length > 0 ){
148:           var opt = document.createElement( "OPTION" );
149:           opt.text = ndName.item(0).firstChild.nodeValue;
150:           opt.value = ndCD.item(0).firstChild.nodeValue;
151:           elmSel.options.add( opt );
152:           if( opt.value == lastSearchGenre )
153:             opt.selected = true;
154:         }
155:       }
156:     }
157:     catch( e ){}
158:   }
159:
160:   // 時刻表示のための書式規格化
161:   //
162:   function format(Num, Format){
163:     var s = new String(Num);
164:     var z = "";
165:     for(c = 0 ; c < Format - s.length ; c++){
166:       z = z + "0";
167:     }
168:     return (z + s);
169:   }
170:
171:   // 現在時刻の表示
172:   //
173:   function showCurrentTime(){
174:     var date = new Date();
175:     var y = date.getFullYear();
176:     var mo = date.getMonth();
177:     var d = date.getDate();
178:     var h = date.getHours();
179:     var m = date.getMinutes();
180:     var s = date.getSeconds();
181:       document.getElementById( "timeView" ).innerHTML = format(y,4) + "." + format(mo+1,2) + "." + format(d,2) + " " + format(h,2) + ":" + format(m,2); 解説
182:   }
183:
184:   // 緯度経度による、お店の検索
185:   //
186:   function findAtPoint( pt, genre ){
187:     try{
188:         if( document.getElementById("shop").style.visibility == "visible" )
189:           return;
190:       var oReq = createHttpRequest();
191:       oReq.onreadystatechange = function(){
192:         if( oReq.readyState==4 ){
193:           onXmlLoad( oReq );
194:         }
195:       }
196:       var url = urlGourmetSearch + "?Latitude=" + pt.y + "&Longitude=" + pt.x;
197:       if( ! isNullOrEmpty( genre ) )
198:         url = url + "&GenreCD=" + genre;
199:       oReq.open( "GET", url, true ); 解説
200:       oReq.send( null );
201:     }
202:     catch( e ){}
203:   }
204:
205:   // お店検索の実行
206:   //
207:   function onFindShops(){ 解説
208:     try{
209:       lastSearchPoint = googleMaps.getCenter();
210:       lastSearchGenre = document.getElementById( "genreSelect" ).value;
211:       findAtPoint( lastSearchPoint, lastSearchGenre );
212:     }
213:     catch( e ){}
214:   }
215:
216:   // 住所検索のためのキーダウン処理
217:   //
218:   function onKeydown(){ 解説
219:     if(event.keyCode == 13){findAddress();}
220:   }
221:
222:   // 住所検索
223:   //
224:   function findAddress(){
225:     try{
226:       if( document.getElementById("shop").style.visibility == "visible" )
227:         return;
228:       var address = document.getElementById( "address" ).value;
229:       if( isNullOrEmpty( address ) )
230:         return;
231:       if (geocoder) {
232:         geocoder.getLatLng(address,function(point) { 解説
233:           if (!point) {
234:             alert(address + " not found");
235:           } else {
236:             googleMaps.setCenter(point);
237:           }
238:         });
239:       }
240:     }
241:     catch( e ){document.writeln( e );}
242:   }
243:
244:   // 地図上へのマーカーの追加
245:   //
246:   function addMarker( pt, idx ){
247:     var marker = new GMarker( pt );
248:   
249:     GEvent.addListener( marker, "click", function(){ 解説
250:       setShopInfo( idx );
251:     });
252:     googleMaps.addOverlay( marker );
253:   }
254:
255:   // お店一覧のXMLデータ、読み込み処理
256:   //
257:   function onXmlLoad( oReq ){ 解説
258:     try{
259:       var oXMLDocument = oReq.responseXML;
260:       shopNodeList = oXMLDocument.getElementsByTagName( "Shop" );
261:       if( shopNodeList == null )
262:         return;
263:       googleMaps.clearOverlays();
264:       for( var i = 0 ; i < shopNodeList.length ; i++ ){
265:         var node = shopNodeList.item(i);
266:         var ndLatitude = node.getElementsByTagName( "Latitude" );
267:         var ndLongitude = node.getElementsByTagName( "Longitude" );
268:         if( ndLatitude.length > 0 && ndLongitude.length > 0 ){
269:           var latitude = parseFloat( ndLatitude.item(0).firstChild.nodeValue );
270:           var longitude = parseFloat( ndLongitude.item(0).firstChild.nodeValue );
271:           addMarker( new GPoint( longitude, latitude ), i );
272:         }
273:       }
274:     }
275:     catch( e ){}
276:   }
277:
278:   // お店情報を表示設定する
279:   //
280:   function setShopInfo( idx ) 解説
281:   {
282:     if( shopNodeList == null || idx < 0 || shopNodeList.length <= idx )
283:       return;
284:     curShopNode = idx;
285:     document.getElementById("shop").style.visibility = "visible";
286:     node = shopNodeList.item( idx );
287:     var ndShopName = node.getElementsByTagName( "ShopName" );
288:     var ndShopURL = node.getElementsByTagName( "ShopUrl" );
289:     var ndGenreCatch = node.getElementsByTagName( "GenreCatch" );
290:     var ndPictureURL = ndPictureURL = node.getElementsByTagName( "PcLargeImg" );
291:     if( ndShopName.length > 0 )
292:       document.getElementById( "shopName" ).innerHTML = ndShopName.item(0).firstChild.nodeValue;
293:     if( ndShopURL.length > 0 )
294:       document.getElementById( "shopName" ).setAttribute( "href", ndShopURL.item(0).firstChild.nodeValue );
295:     if( ndGenreCatch.length > 0 )
296:       document.getElementById( "genreCatch" ).innerHTML = ndGenreCatch.item(0).firstChild.nodeValue;
297:     if( ndPictureURL.length > 0 )
298:       document.getElementById( "shopPicture" ).setAttribute( "src", ndPictureURL.item(0).firstChild.nodeValue );
299:     if( ( curShopNode + 1 ) < shopNodeList.length ) 解説
300:       document.getElementById("btnNext").style.visibility = "inherit";
301:     else
302:       document.getElementById("btnNext").style.visibility = "hidden";
303:     if( curShopNode > 0 )
304:       document.getElementById("btnPrev").style.visibility = "inherit";
305:     else
306:       document.getElementById("btnPrev").style.visibility = "hidden";
307:   }
308:
309:   // 前のお店情報に移動する
310:   //
311:   function prevShop(){
312:     if( curShopNode > 0 ){
313:       setShopInfo( curShopNode -1 );
314:     }
315:   }
316:
317:   // 次のお店情報に移動する
318:   //
319:   function nextShop(){
320:     if( ( curShopNode + 1 ) < shopNodeList.length ){
321:       setShopInfo( curShopNode + 1 );
322:     }
323:   }
324:
325:   // お店情報表示を閉じる
326:   //
327:   function closeShopInfo(){
328:     document.getElementById("shop").style.visibility = "hidden"; 解説
329:   }
330:
331:   // 背景の状態を設定する
332:   //
333:   function setDockState(){ 解説
334:     switch( curSkin ){
335:       case 2:
336:         document.getElementById( "base").style.background = "url(images/b2.png)";
337:         document.getElementById( "timeView" ).style.color = "#0f0f0f";
338:         break;
339:       case 3:
340:         document.getElementById( "base").style.background = "url(images/b3.png)";
341:         document.getElementById( "timeView" ).style.color = "#ffff80";
342:         break;
343:       case 4:
344:         document.getElementById( "base").style.background = "url(images/b4.png)";
345:         document.getElementById( "timeView" ).style.color = "#0f0f0f";
346:         break;
347:       case 5:
348:         document.getElementById( "base").style.background = "url(images/b5.png)";
349:         document.getElementById( "timeView" ).style.color = "#0f0f0f";
350:         break;
351:       default:
352:         document.getElementById( "base").style.background = "url(images/b1.png)";
353:         document.getElementById( "timeView" ).style.color = "#0f0f0f";
354:         break;
355:     }
356:   }
357:
358:   // 背景設定画面を表示する
359:   //
360:   function showSettings(){ 解説
361:     document.getElementById( "settings" ).style.visibility = "visible";
362:     document.getElementById("genreSelect").style.visibility = "hidden";
363:     switch( curSkin ){
364:       case 2:
365:         document.getElementById( "skin2" ).checked = true;
366:         break;
367:       case 3:
368:         document.getElementById( "skin3" ).checked = true;
369:         break;
370:       case 4:
371:         document.getElementById( "skin4" ).checked = true;
372:         break;
373:       case 5:
374:         document.getElementById( "skin5" ).checked = true;
375:         break;
376:       default:
377:         document.getElementById( "skin1" ).checked = true;
378:         break;
379:     }
380:   }
381:
382:   // 背景設定画面を閉じる
383:   //
384:   function closeSettings( bSave ){ 解説
385:     if( bSave ){
386:       if( document.getElementById( "skin1" ).checked )
387:         curSkin = 1;
388:       else if( document.getElementById( "skin2" ).checked )
389:         curSkin = 2;
390:       else if( document.getElementById( "skin3" ).checked )
391:         curSkin = 3;
392:       else if( document.getElementById( "skin4" ).checked )
393:         curSkin = 4;
394:       else if( document.getElementById( "skin5" ).checked )
395:         curSkin = 5;
396:       setDockState();
397:     }
398:     document.getElementById( "settings" ).style.visibility = "hidden";
399:     document.getElementById("genreSelect").style.visibility = "visible";
400:   }
401:   </script>
402:
403: </head>
404: <body onload="load()" onunload="unload()">
405:   <div id="base">
406:     <table width="312px" style="height: 34px;">
407:       <tr>
408:         <td style="width: 132;">
409:           </td>
410:         <td align="right">
411:          <b><span id="timeView"></span></b>
412:         </td>
413:         <td align="right">
414:           <img src="images/settings.png" alt="設定" style="cursor:hand;" onclick="showSettings()" />
415:         </td>
416:       </tr>
417:     </table>
418:     <table cellpadding="0" cellspacing="0" width="312px">
419:       <tr valign="baseline">
420:         <td align="left">
421:           <input id="address" type="text" style="width:190px;" onKeyDown="onKeydown()"/>
422:         </td>
423:         <td align="right">
424:           <img src="images/button1.png" alt="住所やスポットで検索" style="cursor:hand;" onclick="findAddress()" id="findShop" />
425:         </td>
426:       </tr>
427:     </table>
428:     <div id="map" onmousedown=""></div>
429:     <table cellpadding="0" cellspacing="0" width="312px">
430:       <tr valign="baseline">
431:         <td align="left">
432:           <select id="genreSelect" style="width:190px;">
433:             <option value="" >全てのジャンル</option>
434:           </select>
435:         </td>
436:         <td align="right">
437:           <img src="images/button2.png" alt="お店情報読込" style="cursor:hand;" onclick="onFindShops()" />
438:         </td>
439:       </tr>
440:       <tr>
441:         <td align="right" colspan="2">
442:         <div id="poweredby" style="color:#363636;font-size: 9px; text-align:right;" >Powered by ホットペッパー.jp</div>
443:         </td>
444:       </tr>
445:     </table>
446:   </div>
447:   <div id="shop" style="width:290px; height:200px;">
448:     <table width="290px" cellpadding="0" cellspacing="0" >
449:       <tr valign="top">
450:         <td align="right">
451:           <img align="top" src="images/close.png" alt="閉じる" style="cursor: hand;" onclick="closeShopInfo()" /></td>
452:       </tr>
453:       <tr valign="top">
454:         <td style="font-size: 13px;"> 
455:           <a id="shopName" target="_blank"></a>
456:         </td>
457:       </tr>
458:     </table>
459:     <table id="shopTable" width="290px" cellpadding="0" cellspacing="4">
460:       <tr valign="top">
461:         <td width="10px">
462:           <img id="shopPicture" src="" alt="写真" width="120px" height="120px" /></td>
463:         <td align="center" style="font-size: 13px;">
464:           <span id="genreCatch"></span>
465:         </td>
466:       </tr>
467:     </table>
468:     <table width="290px" border="0" cellpadding="0" cellspacing="0">
469:       <tr valign="bottom">
470:         <td align="left">
471:           <img id="btnPrev" src="images/prev.png" style="cursor: hand;" onclick="prevShop()"
472:             alt="戻る" />
473:         </td>
474:         <td align="right">
475:           <img id="btnNext" src="images/next.png" style="cursor: hand;" onclick="nextShop()"
476:             alt="次へ" />
477:         </td>
478:       </tr>
479:     </table>
480:   </div>
481:   <div id="settings">
482:     <table id="settingsTable" >
483:       <tr><td colspan="4">
484:     <h3>
485:       背景の選択</h3>
486:       </td></tr>
487:       <tr style="height:8px"><td></td><td></td><td></td><td></td></tr>
488:       <tr valign="top">
489:         <td>
490:           <input id="skin1" name="skinSelect" type="radio" value="1" /></td>
491:         <td onclick="skin1.checked=true;">
492:           <img src="images/b1.png" alt="背景1" width="64px" height="64" />
493:         </td>
494:         <td>
495:           <input id="skin4" name="skinSelect" type="radio" value="4" /></td>
496:         <td onclick="skin4.checked=true;">
497:           <img src="images/b4.png" alt="背景4" width="64px" height="64" />
498:         </td>
499:       </tr>
500:       <tr valign="top">
501:         <td>
502:           <input id="skin2" name="skinSelect" type="radio" value="2" /></td>
503:         <td onclick="skin2.checked=true;">
504:           <img src="images/b2.png" alt="背景2" width="64px" height="64" />
505:         </td>
506:         <td>
507:           <input id="skin5" name="skinSelect" type="radio" value="5" /></td>
508:         <td onclick="skin5.checked=true;">
509:           <img src="images/b5.png" alt="背景5" width="64px" height="64" />
510:         </td>
511:       </tr>
512:       <tr valign="top">
513:         <td>
514:           <input id="skin3" name="skinSelect" type="radio" value="3" /></td>
515:         <td onclick="skin3.checked=true;">
516:           <img src="images/b3.png" alt="背景3" width="64px" height="64" />
517:         </td>
518:         <td></td><td></td>
519:       </tr>
520:       <tr style="height:8px"><td></td><td></td><td></td><td></td></tr>
521:       <tr><td colspan="4" align="center">
522:     <input type="button" onclick="closeSettings( true )" value="OK" style="width:96px" />
523:            
524:     <input type="button" onclick="closeSettings( false )" value="キャンセル" style="width:96px" />
525:       </td></tr>
526:     </table>
527:   </div>
528: </body>
529: </html>
料理ジャンルの一覧を初期化します。ジャンルマスターAPIを呼び出すHTTP Requestを実行し、取得したXMLデータをonGenreLoad()内で処理します。 HTML bodyがロードされた際に、各種初期化処理を行います。GMap2オブジェクトの生成および地図の初期表示、GClientGeocoderオブジェクトの生成、料理ジャンルの一覧の初期化、背景画像の設定、時計表示のためのインターバルタイマーの設定。ガジェットが前回終了した時の状態を復帰する処理も行います。 HTML bodyがアンロードされた時に、アプリケーションの状態を保存します。 最後に検索された場所の緯度経度、料理ジャンルをCookieに保存します。 最後に検索された場所の緯度経度、料理ジャンルをCookieから取得します。 アプリケーションの状態を保存します。保存されるのは、最後に検索された検索の条件(緯度経度、料理ジャンル)と背景画像の番号です。 保存したアプリケーションの状態を読み込みます。 ジャンルマスターを含むXMLデータを処理します。GenreName(ジャンル名)ノード、GenreCD(ジャンルコード)ノードの値をHTMLのOPTION要素に設定し、プルダウンメニューを設定します。 現在時刻の表示を更新します。 緯度経度、料理ジャンルを指定して、グルメサーチAPIを呼び出します(お店を検索します)。HTTP Requestで取得したデータはonXmlLoad()で処理します。 「読込」ボタンが押されたときに呼び出されます。地図中心の緯度経度、選択されている料理ジャンルを取得し、findAtPoint()を実行します。 住所検索時のリターンキーを処理します。キーコードが13であれば、findAddress()を実行します。 ジオコーダーGClientGeocorderを用い住所を緯度経度に変換します。変換できればその位置に地図中心点を移動、変換できなかった場合はエラーメッセージを表示します。 地図にマーカーを追加します。addListenerメソッドで、マーカーがクリックされた時にsetShopInfo()が呼ばれるようにします。 グルメ検索APIの結果データを処理します。Shop(グルメ店)ノードを詳細画面表示用に保存します。また、Latitude(緯度)ノードとLongitude(経度)ノードを使い、地図にグルメ店マーカーを追加します。 onXmlLoad()内で保存したShop(グルメ店)ノードのリストから、idx番目のお店の情報を表示します。ShopName(店名)、ShopUrl(店URL)、GenreCatch(店キャッチコピー)、PcLargeImg(店画像URL)の各ノードの値を取得し、該当するHTML要素にセット。グルメ店詳細情報の表示は、div要素のvisibilityスタイルをhiddenからvisibleに変えることで行います。 idxの値により「前へ」「次へ」ボタンの表示、非表示を制御します。 表示されているグルメ店詳細情報を閉じます。グルメ店詳細情報のdiv要素をhiddenにします。 背景画像を設定します。 背景画像の設定画面を表示します。設定画面の表示は、グルメ店詳細情報の表示と同様、div要素のvisibilityスタイルをhiddenからvisibleに変えることで行います。 背景画像の設定画面を閉じます。設定画面のdiv要素をhiddenにします。
 
Google Gadget チュートリアル Google Desktop Gadget チュートリアル Live Gadget チュートリアル Vista Sidebar Gadget チュートリアル Y! Widget チュートリアル