チュートリアル

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

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

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

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


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

GadgetsPepper.gadgetファイルをダブルクリックし、「インストール」してください。インストールが完了するとサイドバーにGadgetsPepperが表示されます。GadgetsPepper.gadgetファイルはこちらからダウンロードできます

主要機能の実装方法

主要機能の実装方法
機能 実装方法
(1)地図を移動 地図表示にはVirtual Earth Map Control 5.0を利用しています。必要なスクリプト・ファイルをインポートしVEMapクラスのオブジェクトを生成するだけで簡単に地図が表示できます。特別な設定や登録作業は必要ありません。
テキストボックスに地名を入力し、エンターキーもしくは検索ボタンを押すと、findAddress()が呼び出されます。地名から緯度経度を得るには、地名を条件にグルメサーチAPIを呼び出し、得られるグルメ店の位置を使用するという方法をとっています。得られた緯度経度を地図の中心点として再設定は、
veMapObj.SetCenter( new VELatLong( latitude, longitude ) );
で行っています。
(2)ジャンルを選択 ガジェットロード時、load()内でジャンルマスターAPIを使ってジャンルマスターを含むXMLを取得します。XMLをonGenreLoad()でパースし、GenreName(ジャンル名)ノード、GenreCD(ジャンルコード)ノードの2つを使って、プルダウンリストの内容をセットします。
(3)グルメ店を検索 読込ボタンが押されると、onFindShops()が呼び出されます。実際の検索はfindAtPoint()内で行っており、地図中心点の緯度経度とジャンルコードを用いURLを組み立て、
oReq.open( "GET", url, true );
でグルメサーチAPIを呼び出します。結果のXMLにはグルメ店情報が含まれます。
(4)詳細画面を表示 グルメ店の緯度経度を用い、地図上にグルメ店の位置を表すマーカーをセットします。この時、マーカーにイベントリスナーを追加し、それがクリックされたときにsetShopInfo()が呼び出されるようにします。setShopInfo()内で、グルメ店の詳細表示用のレイヤをvisibleにし、グルメ店詳細情報を表示します。
(5)背景画面の変更 背景画像の選択画面は
System.Gadget.settingsUI = "Settings.html";
System.Gadget.onSettingsClosed = settingsClosed;
で定義しています。System.Gadget.settingsUIにHTMLファイル名をセットすることにより、ガジェットの右側にある設定ボタンから、そのHTMLファイルの表示ができるようになります。System.Gadget.onSettingsClosed には設定終了時に呼び出されるファンクションを定義します。Settings.html内でSystem.Gadget.Settings.writeを使って背景画像の番号を保持し、settingsClosed()内でSystem.Gadget.Settings.readでそれを読み取り、背景画像を切り替えます。
(6)状態の保存と復帰 状態の保存は、unload()が呼ばれるタイミングで行います。実際の処理はsaveState()内で行っており、最後に実行された検索の地図中心点の緯度経度、ズームレベル、料理ジャンル、背景画像番号をSystem.Gadget.Settings.writeを使って保存します。
System.Gadget.Settings.write("zoom_level", zl );
System.Gadget.Settings.write("search_latitude", lastSearchPoint.y );
System.Gadget.Settings.write("search_longitude", lastSearchPoint.x );
保存した内容の復帰はload()が呼ばれるタイミングでloadState()内で行います。これらのデータは、各ガジェット共通の設定ファイルSettings.iniに記録されています。

ソースコード詳説

code
  1 : ?<html lang="ja" >
  2 : <head>
  3 : <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  4 : <title>Hot Pepper</title>
  5 : <link href="StylePepper.css" rel="stylesheet" type="text/css" />
  6 : <script type="text/javascript" src="ScriptPepper.js"></script>
  7 : <script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5"></script>
  8 : <script type="text/javascript">
  9 : var urlGourmetSearch = "http://api.hotpepper.jp/GourmetSearch/V110/?key=guest";
 10 : var urlGenreMaster = "http://api.hotpepper.jp/Genre/V110/?key=guest";
 11 : var veMapObj = null;
 12 : var shopNodeList = null;
 13 : var curShopNode = 0;
 14 : var lastSearchPoint = null;
 15 : var lastSearchGenre = null;
 16 : var initCenter = null;
 17 : var initZoom = 13;
 18 : var curSkin = 1;
 19 : var idIntervalTimer = null;
 20 : System.Gadget.settingsUI = "Settings.html"; 解説
 21 : System.Gadget.onSettingsClosed = settingsClosed; 解説
 22 : System.Gadget.onUndock = setDockState; 解説
 23 : System.Gadget.onDock = setDockState;
 24 :
 25 : // HTML bodyのロード時
 26 : // 各種初期化処理
 27 : //
 28 : function load() 解説
 29 : {
 30 :   try{
 31 :     initCenter = new VELatLong( 35.681074, 139.767079 );
 32 :     loadState();
 33 :     veMapObj = new VEMap( "map" );
 34 :     veMapObj.SetDashboardSize( VEDashboardSize.Small );
 35 :     veMapObj.LoadMap();
 36 :     veMapObj.SetMapStyle( "r" );
 37 :     veMapObj.AttachEvent("onclick", ShapeInfo);
 38 :     veMapObj.AttachEvent("onmouseover", function(e){ return true; } );
 39 :     veMapObj.SetScaleBarDistanceUnit( VEDistanceUnit.Kilometers );
 40 :     var oReq = createHttpRequest();
 41 :     if( oReq != null ){
 42 :       oReq.onreadystatechange = function(){
 43 :         if( oReq.readyState==4 ){
 44 :           onGenreLoad( oReq );
 45 :         }
 46 :       }
 47 :       oReq.open( "GET", urlGenreMaster, true ); 解説
 48 :       oReq.send( null );
 49 :     }
 50 :     setDockState();
 51 :     if( lastSearchPoint != null ){
 52 :       veMapObj.SetCenterAndZoom( lastSearchPoint, initZoom );
 53 :       findAtPoint( lastSearchPoint, lastSearchGenre );
 54 :     }
 55 :     else{
 56 :       veMapObj.SetCenterAndZoom( initCenter, initZoom );
 57 :     }
 58 :   }
 59 :   catch( e ){
 60 :     setDockState();
 61 :   }
 62 : }
 63 :
 64 : //
 65 : // HTML bodyのアンロード時
 66 : //
 67 : function unload() 解説
 68 : {
 69 :   saveState();
 70 : //  GUnload();
 71 : }
 72 :
 73 : //
 74 : // 設定UIがクローズされた時の処理
 75 : //
 76 : function settingsClosed( event ) 解説
 77 : {
 78 :   if( event.closeAction == event.Action.commit ){
 79 :     curSkin = System.Gadget.Settings.read( "skin_number" );
 80 :     setDockState();
 81 :   }
 82 : }
 83 :
 84 : //
 85 : // 状態の保存
 86 : //
 87 : function saveState() 解説
 88 : {
 89 :   try{
 90 :     var zl = veMapObj.GetZoomLevel();
 91 :     System.Gadget.Settings.write("zoom_level", zl );
 92 :     if( lastSearchPoint != null ){
 93 :       System.Gadget.Settings.write("search_latitude", lastSearchPoint.Latitude );
 94 :       System.Gadget.Settings.write("search_longitude", lastSearchPoint.Longitude );
 95 :     }
 96 :     else{
 97 :       System.Gadget.Settings.write("search_latitude", "" );
 98 :       System.Gadget.Settings.write("search_longitude", "" );
 99 :     }
100 :     if( ! isNullOrEmpty( lastSearchGenre ) ){
101 :       System.Gadget.Settings.writeString("search_genre", lastSearchGenre );
102 :     }
103 :     else{
104 :       System.Gadget.Settings.writeString("search_genre", "" );
105 :     }
106 :     System.Gadget.Settings.write( "skin_number", curSkin );
107 :   }
108 :   catch( e ){
109 :   }
110 : }
111 :
112 : //
113 : // 保存した状態の読み込み
114 : //
115 : function loadState() 解説
116 : {
117 :   try{
118 :     var skin_number = System.Gadget.Settings.readString( "skin_number" );
119 :     if( ! isNullOrEmpty( skin_number ) )
120 :       curSkin = parseInt( skin_number, 10 );
121 :     else
122 :       curSkin = 1;
123 :     var zoom_level = System.Gadget.Settings.readString( "zoom_level" );
124 :     if( ! isNullOrEmpty( zoom_level ) )
125 :       initZoom = parseInt( zoom_level, 10 );
126 :     var search_latitude = System.Gadget.Settings.readString( "search_latitude" );
127 :     var search_longitude = System.Gadget.Settings.readString( "search_longitude" );
128 :     lastSearchGenre = System.Gadget.Settings.readString( "search_genre" );
129 :     if( ! isNullOrEmpty( search_latitude ) && ! isNullOrEmpty( search_longitude ) )
130 :       lastSearchPoint = new VELatLong( parseFloat( search_latitude ), parseFloat( search_longitude ) );
131 :   }
132 :   catch( e ){
133 :   }
134 : }
135 :
136 : //
137 : // ジャンル一覧のデータ取得
138 : //
139 : function onGenreLoad( oReq ) 解説
140 : {
141 :   try{
142 :     var elmSel = document.getElementById( "genreSelect" );
143 :     var oXMLDocument = oReq.responseXML;
144 :     genreNodeList = oXMLDocument.selectNodes( "//Genre" );
145 :     if( genreNodeList == null )
146 :       return;
147 :     for( var i = 0 ; i < genreNodeList.length ; i++ ){
148 :       var node = genreNodeList.item( i );
149 :       var ndName = node.selectSingleNode( "GenreName" );
150 :       var ndCD = node.selectSingleNode( "GenreCD" );
151 :       if( ndName != null && ndCD != null ){
152 :         var opt = document.createElement( "OPTION" );
153 :         elmSel.options.add( opt );
154 :         opt.innerText = ndName.text;
155 :         opt.value = ndCD.text;
156 :         if( opt.value == lastSearchGenre )
157 :           opt.selected = true;
158 :       }
159 :     }
160 :   }
161 :   catch( e ){
162 :   }
163 : }
164 :
165 : //
166 : // 時刻表示のための書式規格化
167 : //
168 : function format(Num, Format)
169 : {
170 :   var s = new String(Num);
171 :   var z = "";
172 :   for(c = 0 ; c < Format - s.length ; c++){
173 :     z = z + "0";
174 :   }
175 :   return (z + s);
176 : }
177 :
178 : //
179 : // 現在時刻の表示
180 : //
181 : function showCurrentTime() 解説
182 : {
183 :   var date = new Date();
184 :   var y = date.getFullYear();
185 :   var mo = date.getMonth();
186 :   var d = date.getDate();
187 :   var h = date.getHours();
188 :   var m = date.getMinutes();
189 :   var s = date.getSeconds();
190 :   document.getElementById( "timeView" ).innerHTML = format(y,4) + "." + format(mo+1,2) + "." + format(d,2) + " " + format(h,2) + " : " + format(m,2);
191 : }
192 :
193 : //
194 : // 緯度経度による、お店の検索
195 : //
196 : function findAtPoint( pt, genre ) 解説
197 : {
198 :   var oReq = createHttpRequest();
199 :   oReq.onreadystatechange = function(){
200 :     if( oReq.readyState==4 ){
201 :       onXmlLoad( oReq, true, false );
202 :     }
203 :   }
204 :   var url = urlGourmetSearch + "&Latitude=" + pt.Latitude + "&Longitude=" + pt.Longitude;
205 :   if( ! isNullOrEmpty( genre ) )
206 :     url = url + "&GenreCD=" + genre;
207 :   oReq.open( "GET", url );
208 :   oReq.send();
209 : }
210 :
211 : //
212 : // お店検索の実行
213 : //
214 : function onFindShops() 解説
215 : {
216 :   try{
217 :     lastSearchPoint = veMapObj.GetCenter();
218 :     lastSearchGenre = document.getElementById( "genreSelect" ).value;
219 :     findAtPoint( lastSearchPoint, lastSearchGenre );
220 :   }
221 :   catch( e ){
222 :     window.alert( e );
223 :     document.writeln( e );
224 :   }
225 : }
226 :
227 : //
228 : // 住所検索
229 : //
230 : function findAddress() 解説
231 : {
232 :   try{
233 :     var address = document.getElementById( "address" ).value;
234 :     if( isNullOrEmpty( address ) )
235 :       return;
236 :     var oReq = createHttpRequest();
237 :     oReq.onreadystatechange = function(){
238 :       if( oReq.readyState==4 ){
239 :         onXmlLoad( oReq, false, true );
240 :       }
241 :     }
242 :     var url = urlGourmetSearch + "&ShopAddress=" + encodeURL( address );
243 :     oReq.open( "GET", url, true );
244 :     oReq.send( null );
245 :   }
246 :   catch( e ){
247 :     document.writeln( e );
248 :   }
249 : }
250 :
251 : function ShapeInfo( e ) 解説
252 : {
253 :   try{
254 :     if( e.elementID != null ){
255 :       var shape = veMapObj.GetShapeByID(e.elementID);
256 :       var idx = shape.GetDescription();
257 :       setShopInfo( parseInt( idx, 10 ) );
258 :     }
259 :   }
260 :   catch( e ){
261 :     window.alert( e.message );
262 :   }
263 : }
264 :
265 : //
266 : // 地図上へのマーカーの追加
267 : //
268 : function addMarker( pt, idx, title ) 解説
269 : {
270 :   var shape = veMapObj.AddPushpin( pt );
271 :   shape.SetDescription( "" + idx );
272 :   shape.SetTitle( title );
273 : }
274 :
275 : //
276 : // お店一覧のXMLデータ、読み込み処理
277 : //
278 : function onXmlLoad( oReq, bSetMarker, bForceCenter ) 解説
279 : {
280 :   try{
281 :     var oXMLDocument = oReq.responseXML;
282 :     shopNodeList = oXMLDocument.selectNodes( "//Shop" );
283 :     if( shopNodeList == null )
284 :       return;
285 :     veMapObj.DeleteAllShapes();
286 :     for( var i = 0 ; i < shopNodeList.length ; i++ ){
287 :       var node = shopNodeList.item(i);
288 :       var ndLatitude = node.selectSingleNode( "Latitude" );
289 :       var ndLongitude = node.selectSingleNode( "Longitude" );
290 :       var ndShopName = node.selectSingleNode( "ShopName" );
291 :       if( ndLatitude != null && ndLongitude != null ){
292 :         var latitude = parseFloat( ndLatitude.text );
293 :         var longitude = parseFloat( ndLongitude.text );
294 :         if( bSetMarker ){
295 :           addMarker( new VELatLong( latitude, longitude ), i, ndShopName.text );
296 :         }
297 :         if( bForceCenter ){
298 :           veMapObj.SetCenter( new VELatLong( latitude, longitude ) );
299 :           bForceCenter = true;
300 :         }
301 :       }
302 :     }
303 :   }
304 :   catch( e ){
305 :   }
306 : }
307 :
308 : //
309 : // お店情報を表示設定する
310 : //
311 : function setShopInfo( idx ) 解説
312 : {
313 :   if( shopNodeList == null || idx < 0 || shopNodeList.length <= idx )
314 :     return;
315 :   curShopNode = idx;
316 :   document.getElementById("shop").style.visibility = "visible";
317 :   node = shopNodeList.item( idx );
318 :   var ndShopName = node.selectSingleNode( "ShopName" );
319 :   var ndShopURL = node.selectSingleNode( "ShopUrl" );
320 :   var ndGenreCatch = node.selectSingleNode( "GenreCatch" );
321 :   var ndPictureURL;
322 :   if( isDocked() )
323 :     ndPictureURL = node.selectSingleNode( "PictureUrl/PcSmallImg" );
324 :   else
325 :     ndPictureURL = node.selectSingleNode( "PictureUrl/PcLargeImg" );
326 :   if( ndShopName != null )
327 :     document.getElementById( "shopName" ).innerHTML = ndShopName.text;
328 :   if( ndShopURL != null )
329 :     document.getElementById( "shopName" ).setAttribute( "href", ndShopURL.text );
330 :   if( ndGenreCatch != null )
331 :     document.getElementById( "genreCatch" ).innerHTML = ndGenreCatch.text;
332 :   if( ndPictureURL != null )
333 :     document.getElementById( "shopPicture" ).setAttribute( "src", ndPictureURL.text );
334 :   if( ( curShopNode + 1 ) < shopNodeList.length )
335 :     document.getElementById("btnNext").style.visibility = "inherit";
336 :   else
337 :     document.getElementById("btnNext").style.visibility = "hidden";
338 :   if( curShopNode > 0 )
339 :     document.getElementById("btnPrev").style.visibility = "inherit";
340 :   else
341 :     document.getElementById("btnPrev").style.visibility = "hidden";
342 : }
343 :
344 : //
345 : // 前のお店情報に移動する
346 : //
347 : function prevShop() 解説
348 : {
349 :   if( curShopNode > 0 ){
350 :     setShopInfo( curShopNode -1 );
351 :   }
352 : }
353 :
354 : //
355 : // 次のお店情報に移動する
356 : //
357 : function nextShop()
358 : {
359 :   if( ( curShopNode + 1 ) < shopNodeList.length ){
360 :     setShopInfo( curShopNode + 1 );
361 :   }
362 : }
363 :
364 : //
365 : // お店情報表示を閉じる
366 : //
367 : function closeShopInfo() 解説
368 : {
369 :   document.getElementById("shop").style.visibility = "hidden";
370 : }
371 :
372 : //
373 : // サイドバーに格納されているかどうか
374 : //
375 : function isDocked() 解説
376 : {
377 :   try{
378 :     return System.Gadget.docked;
379 :   }
380 :   catch( e ){
381 :     return true;
382 :   }
383 : }
384 :
385 : //
386 : // サイドバー格納状態変更処理
387 : //
388 : function setDockState() 解説
389 : {
390 :   try{
391 :     if( isDocked() ){
392 :       document.getElementById( "header").style.visibility = "hidden";
393 :       document.getElementById( "header").style.position="absolute";
394 :       document.getElementById( "shop" ).style.width = "126px";
395 :       document.getElementById( "shop" ).style.height = "140px";
396 :       document.getElementById( "shop" ).style.top = "0px";
397 :       document.getElementById( "shop" ).style.left = "0px";
398 :       document.getElementById( "shop").style.background = "url(../images/white126_140.png)";
399 :       document.getElementById( "shopTable" ).style.height = "110px";
400 :       document.getElementById( "shopName" ).style.fontSize = "9px";
401 :       document.getElementById( "genreCatch" ).style.fontSize = "9px";
402 :       document.getElementById( "shopNameTD" ).style.textAlign = "left";
403 :       document.getElementById( "genreCatchTD" ).style.textAlign = "left";
404 :       document.getElementById( "shopPicture" ).style.width="";
405 :       document.getElementById( "shopPicture" ).style.height="";
406 :       document.getElementById( "ShopPrevNext" ).style.top="116px";
407 :       document.body.style.width = "130px";
408 :       document.body.style.height = "140px";
409 :       document.getElementById( "base").style.width = "126px";
410 :       document.getElementById( "base").style.height = "140px";
411 :       document.getElementById( "base").style.paddingTop = "12px";
412 :       document.getElementById( "bottomPane").style.padding = "2px,0px,2px,0px";
413 :       document.getElementById( "genreSelect" ).style.width = "100px";
414 :       switch( curSkin ){
415 :         case 2 :
416 :           document.getElementById( "base").style.background = "url(../images/s2.png)";
417 :           break;
418 :         case 3 :
419 :           document.getElementById( "base").style.background = "url(../images/s3.png)";
420 :           break;
421 :         case 4 :
422 :           document.getElementById( "base").style.background = "url(../images/s4.png)";
423 :           break;
424 :         case 5 :
425 :           document.getElementById( "base").style.background = "url(../images/s5.png)";
426 :           break;
427 :         default :
428 :           document.getElementById( "base").style.background = "url(../images/s1.png)";
429 :           break;
430 :       }
431 :       var mapHeight = 144 - document.getElementById( "genreSelect" ).offsetHeight
432 :                 - document.getElementById( "findShop" ).offsetHeight - 22;
433 :       if( veMapObj != null ){
434 :          veMapObj.Resize( 118, mapHeight );
435 :         veMapObj.HideDashboard();
436 :       }
437 :       document.getElementById( "genreSelect" ).style.width = "112px";
438 :       if( idIntervalTimer != null ){
439 :         clearInterval( idIntervalTimer );
440 :         idIntervalTimer = null;
441 :       }
442 :     }
443 :     else{
444 :       document.getElementById( "header").style.visibility = "visible";
445 :       document.getElementById( "header").style.position="fixed";
446 :       document.getElementById( "shop" ).style.width = "290px";
447 :       document.getElementById( "shop" ).style.height = "200px";
448 :       document.getElementById( "shop" ).style.top = "56px";
449 :       document.getElementById( "shop" ).style.left = "14px";
450 :       document.getElementById( "shop").style.background = "url(../images/white290_200.png)";
451 :       document.getElementById( "shopTable" ).style.height = "172px";
452 :       document.getElementById( "shopName" ).style.fontSize = "13px";
453 :       document.getElementById( "genreCatch" ).style.fontSize = "13px";
454 :       document.getElementById( "shopNameTD" ).style.textAlign = "center";
455 :       document.getElementById( "genreCatchTD" ).style.textAlign = "center";
456 :       document.getElementById( "shopPicture" ).style.width="140px";
457 :       document.getElementById( "shopPicture" ).style.height="140px";
458 :       document.getElementById( "ShopPrevNext" ).style.top="172px";
459 :       document.body.style.width = "320px";
460 :       document.body.style.height = "320px";
461 :       document.getElementById( "base").style.width = "320px";
462 :       document.getElementById( "base").style.height = "320px";
463 :       document.getElementById( "base").style.paddingTop = "0px";
464 :       document.getElementById( "bottomPane" ).style.padding = "0px,8px,0px,8px";
465 :       document.getElementById( "genreSelect" ).style.width = "140px";
466 :       switch( curSkin ){
467 :         case 2 :
468 :           document.getElementById( "base").style.background = "url(../images/b2.png)";
469 :           document.getElementById( "timeView" ).style.color = "#0f0f0f";
470 :           break;
471 :         case 3 :
472 :           document.getElementById( "base").style.background = "url(../images/b3.png)";
473 :           document.getElementById( "timeView" ).style.color = "#ffff80";
474 :           break;
475 :         case 4 :
476 :           document.getElementById( "base").style.background = "url(../images/b4.png)";
477 :           document.getElementById( "timeView" ).style.color = "#0f0f0f";
478 :           break;
479 :         case 5 :
480 :           document.getElementById( "base").style.background = "url(../images/b5.png)";
481 :           document.getElementById( "timeView" ).style.color = "#0f0f0f";
482 :           break;
483 :         default :
484 :           document.getElementById( "base").style.background = "url(../images/b1.png)";
485 :           document.getElementById( "timeView" ).style.color = "#0f0f0f";
486 :           break;
487 :       }
488 :       if( veMapObj != null ){
489 :         veMapObj.Resize( 312, 226 );
490 :         veMapObj.ShowDashboard();
491 :       }
492 :       idIntervalTimer = setInterval( "showCurrentTime()", 1000 );
493 :     }
494 :     if( document.getElementById("shop").style.visibility == "visible" )
495 :       setShopInfo( curShopNode );
496 :   }
497 :   catch( e ){
498 :   }
499 : }
500 :
501 : //
502 : // 住所検索のためのキーダウン処理
503 : //
504 : function onKeydown() 解説
505 : {
506 :   if( event.keyCode == 13 && isDocked() == false ){
507 :     findAddress();
508 :   }
509 : }
510 : </script>
511 : </head>
512 : <body onload="load()" onunload="unload()">
513 : <g : background id="partsBackground" />
514 : <div id="base">
515 : <div id="header" style="height : 46px;">
516 : <table width="310px" cellspacing="0" cellpadding="0" style="margin : 3,0,2,0">
517 : <tr>
518 : <td style="width : 10%;">
519 : <img src="../images/title.png" alt="GadgetsPepper" /></td>
520 : <td align="right" style="white-space : nowrap">
521 : <span id="timeView" style="font-size : 13px; font-family : MS ゴシック"></span>
522 : </td>
523 : </tr>
524 : <tr valign="top">
525 : <td colspan="2" align="center">
526 : <input id="address" type="text" onkeydown="onKeydown()" />
527 : <img align="top" src="../images/button1.png" alt="住所やスポットで検索" onclick="findAddress()" id="findShop" style="cursor : pointer" />
528 : </td>
529 : </tr>
530 : </table>
531 : </div>
532 : <div id="map" onmousedown="" style="width : 118px; height : 80px; background-color : #000000">
533 : <span style="color : #ffffff; font-weight : bold;">ネット回復時に再起動してください.</span></div>
534 : <table id="bottomPane" cellspacing="0" cellpadding="0" width="100%">
535 : <tr valign="bottom">
536 : <td align="center" style="height : 24px;">
537 : <select id="genreSelect">
538 : <option value="">全部のジャンル</option>
539 : </select>
540 : <img align="top" src="../images/button2.png" alt="お店情報読込" onclick="onFindShops()" id="readShop" style="cursor : pointer" />
541 : </td>
542 : </tr>
543 : <tr>
544 : <td id="poweredby" style="color : #363636; font-size : 9px; text-align : right;">
545 : Powered by ホットペッパー.jp
546 : </td>
547 : </tr>
548 : </table>
549 : </div>
550 : <div id="shop">
551 : <table id="shopTable" width="100%">
552 : <tr valign="bottom">
553 : <td colspan="2" id="shopNameTD">
554 : <a id="shopName" target="_blank"></a>
555 : </td>
556 : </tr>
557 : <tr valign="top">
558 : <td colspan="2" id="genreCatchTD">
559 : <span id="genreCatch"></span>
560 : </td>
561 : </tr>
562 : <tr valign="top">
563 : <td align="center">
564 : <img id="shopPicture" src="null" alt="写真" /></td>
565 : <td align="right">
566 : <img src="../images/close.png" alt="閉じる" onclick="closeShopInfo()" style="cursor : pointer" />
567 : </td>
568 : </tr>
569 : </table>
570 : <table width="100%" border="0" cellpadding="0" cellspacing="0" id="ShopPrevNext" style="position : absolute;">
571 : <tr valign="bottom">
572 : <td align="left">
573 : <img id="btnPrev" src="../images/prev.png" onclick="prevShop()" alt="戻る" style="cursor : pointer" />
574 : </td><td align="right">
575 : <img id="btnNext" src="../images/next.png" onclick="nextShop()" alt="次へ" style="cursor : pointer" />
576 : </td>
577 : </tr>
578 : </table>
579 : </div>
580 : </body>
581 : </html>
背景画像を設定するUI(画面)のHTMLを指定します。 背景画像を設定するUI(画面)がクローズされた時の処理を指定します。 サイドバー格納状態が変更されたときの処理を指定します。 料理ジャンルの一覧を初期化します。ジャンルマスターAPIを呼び出すHTTP Requestを実行し、取得したXMLデータをonGenreLoad()内で処理します。 HTML bodyがロードされた際に、各種初期化処理を行います。VEMapオブジェクトの生成および地図の初期表示、料理ジャンルの一覧の初期化、表示スタイルの設定。ガジェットが前回終了した時の状態を復帰する処理も行います。 HTML bodyがアンロードされた時に、アプリケーションの状態を保存します。 背景画像を設定するUI(画面)がクローズされた時の処理を定義しています。 アプリケーションの状態を保存します。最後に検索された場所の緯度経度、ズーム、料理ジャンル、背景画像を保存します。 保存したアプリケーションの状態を読み込みます。最後に検索された場所の緯度経度、ズーム、料理ジャンル、背景画像を取得します。 ジャンルマスターを含むXMLデータを処理します。GenreName(ジャンル名)ノード、GenreCD(ジャンルコード)ノードの値をHTMLのOPTION要素に設定し、プルダウンメニューを設定します。 現在時刻の表示を更新します。 緯度経度、料理ジャンルを指定して、グルメサーチAPIを呼び出します(お店を検索します)。HTTP Requestで取得したデータはonXmlLoad()で処理します。 「読込」ボタンが押されたときに呼び出されます。地図中心の緯度経度、選択されている料理ジャンルを取得し、findAtPoint()を実行します。 地名から地図の中心点を決定します。地名を条件にグルメサーチAPIを呼び出し、得られるグルメ店の緯度経度を地図の中心点にします。 マーカーがクリックされた場合に呼び出されます。マーカーに対応したショップ情報を表示します。 地図にマーカーを追加します。shape.SetDescriptionでマーカーにショップ情報のインデックスを記録し、ShapeInfoが呼ばれた時に、どのマーカーがクリックされたかを識別できるようにしています。 グルメ検索APIの結果データを処理します。Shop(グルメ店)ノードを詳細画面表示用に保存します。また、Latitude(緯度)ノードとLongitude(経度)ノードを使い、地図にグルメ店マーカーを追加します。 onXmlLoad()内で保存したShop(グルメ店)ノードのリストから、idx番目のお店の情報を表示します。ShopName(店名)、ShopUrl(店URL)、GenreCatch(店キャッチコピー)、PcLargeImg(店画像URL)の各ノードの値を取得し、該当するHTML要素にセット。グルメ店詳細情報の表示は、div要素のvisibilityスタイルをhiddenからvisibleに変えることで行います。 idxの値により「前へ」「次へ」ボタンの表示、非表示を制御します。 表示されているグルメ店詳細情報を閉じます。グルメ店詳細情報のdiv要素をhiddenにします。 サイドバーに格納されているかどうかを調べます。System.Gadget.dockedプロパティをラップすることによりサイドバー上ではなくても動作するようにして開発を容易にしています。 サイドバー格納状態が変更された場合の処理を定義しています。このガジェットは、サイドバーに格納した状態と格納していない状態で全体の大きさや表示する要素が異なりますが、その制御を、このファンクションで行っています。IDからHTML要素のオブジェクトを取得しスタイルを再設定するのが主な処理となっています。また、背景の設定もここで行っています。 住所検索時のリターンキーを処理します。キーコードが13であれば、findAddress()を実行します。
Google Gadget チュートリアル Google Desktop Gadget チュートリアル Live Gadget チュートリアル Vista Sidebar Gadget チュートリアル Y! Widget チュートリアル