ソースコード

作った自己満ガジェット(mixiで少し配布した)のソースコード
真夜中に書かれた汚いコードですが,ガジェット作ろうと思ってる方は参考にどうぞ。
JavaScript良く分かってないので「こうするべきだ!」という点とかありましたらついでに教えてやってください。笑
common.js

var ImageInfo = function( title, baseUri, width, height )
{
	this.title = title;
	this.baseUri = baseUri;
	this.width = width;
	this.height = height;
}
ImageInfo.prototype = {
	getImageUri : function() {
		// キャッシュを回避するため,URIにユニーク文字列を付加する
		var id = "?" + (new Date()).getTime();
		return this.baseUri + id;
	}
};


var ImageInfoCollection = function() {}
ImageInfoCollection.prototype = {
	images : new Array(
		new ImageInfo( "STV(北1西8)", "http://www.stv.ne.jp/camera/sapporo.jpg", 320, 240 ),
		new ImageInfo( "大通西4", "http://www.stv.ne.jp/camera/ohdori4.jpg", 320, 240 ),
		new ImageInfo( "テレビ塔からの大通公園", "http://www.ilive.hokkaido.isp.ntt-east.co.jp/jpeg/sap103.jpg", 384, 288 ),// もとは1024x768
		new ImageInfo( "すすきの", "http://www.hbc.co.jp/videont/susuki_l.jpg", 312, 240 ),// もとは624x480
		new ImageInfo( "琴似(C葉氏宅)", "http://kotoni.info/cam/live.jpg", 320, 240 ),// もとは640x480
		new ImageInfo( "小樽", "http://www.stv.ne.jp/camera/otaru.jpg", 320, 240 ),
		new ImageInfo( "旭川", "http://www.stv.ne.jp/camera/asahikawa.jpg", 320, 240 ),
		new ImageInfo( "函館山", "http://www.stv.ne.jp/camera/hakodate.jpg", 320, 240 ),
		new ImageInfo( "小清水原生花園(網走)", "http://www.stv.ne.jp/camera/abashiri.jpg", 320, 240 ),
		new ImageInfo( "帯広", "http://www.stv.ne.jp/camera/obihiro.jpg", 320, 240 ),
		new ImageInfo( "稚内", "http://www.stv.ne.jp/camera/wakkanai.jpg", 320, 240 ),
		new ImageInfo( "釧路", "http://www.stv.ne.jp/camera/kushiro.jpg", 320, 240 ),
		new ImageInfo( "新千歳空港", "http://www.stv.ne.jp/camera/chitose.jpg", 320, 240 ),
		new ImageInfo( "仙台", "http://www.tbc-sendai.co.jp/live/live_01.jpg", 320, 240 ),
		new ImageInfo( "新潟県中越", "http://www.live-cam.pref.niigata.jp/camera/img/cam8_06590D.jpg", 320, 240 ),
		new ImageInfo( "さいたまスーパーアリーナ", "http://webcam.wni.co.jp/USZ84660/camera.jpg", 352, 240 ),// もとは704x480
		new ImageInfo( "熊本城", "http://www.city.kumamoto.kumamoto.jp/castle/push.jpg", 320, 240 ),
		new ImageInfo( "イタリア/トリノ", "http://www.regione.piemonte.it/webcam/im/image_fc.jpg", 352, 288 ),
		new ImageInfo( "スイス/リーダーアルプ", "http://www.swisswebcams.ch/customerpics/1194266616.jpg", 352, 288 )// もとは704x576
	)
};

var Common_imgInfoCollection = new ImageInfoCollection();


var SettingManager = function() {}
SettingManager.prototype = {

	getCurrentImageInfo : function() {
		var index = this.getSelectedIndex();
		if ( (index >= 0) && (index < Common_imgInfoCollection.images.length) )
			return Common_imgInfoCollection.images[ index ];
		return Common_imgInfoCollection.images[ this.getDefaultCameraIndex() ];
	},

	getSelectedIndex : function() {
		var index = System.Gadget.Settings.read( "selectedCamera" );
		var index_int;
		if ( index == "" )
		{
			index_int = this.getDefaultCameraIndex();
			this.setSelectedIndex( index_int );
		}
		else
		{
			index_int = parseInt( index );
		}
		return index_int;
	},
	
	setSelectedIndex : function( index ) {
		var index_int = parseInt( index );
		if ( (index_int < 0) || (index_int >= Common_imgInfoCollection.images.length) )
			index_int = this.getDefaultCameraIndex();
		System.Gadget.Settings.write( "selectedCamera", index_int );
	},
	
	getDefaultCameraIndex : function() { return 0; }
};

var Common_settingManager = new SettingManager();


main.html

<html>
	<head>
	<title>Sapporo !</title>
	<script src="common.js" type="text/javascript"></script>
    <script>
	
		System.Gadget.settingsUI = 'settings.html';
		System.Gadget.onSettingsClosed = updateImage;


		var SapporoLive = function() {}
		SapporoLive.prototype = {
			getGadgetWidth : function() { return 130; },
			getRefreshInterval : function() { return 120 * 1000; },
			getPictureElement : function() { return document.images[ "picture" ]; },
			
			calcImageHeight : function( imgInfo ) {
				var result = (imgInfo.height * this.getGadgetWidth()) / imgInfo.width;
				return Math.round( result );
			},
			resizeGadget : function( width, height ) {
				document.body.style.width  = width;
				document.body.style.height  = height;
				var htmlImgElement = this.getPictureElement();
				htmlImgElement.width = width;
				htmlImgElement.height = height;
			},
			// マウスオーバー
			makeBig : function() {
				var info = Common_settingManager.getCurrentImageInfo();
				this.resizeGadget( info.width, info.height );
			},
			// マウスアウト
			makeSmall : function() {
				var info = Common_settingManager.getCurrentImageInfo();
				this.resizeGadget( this.getGadgetWidth(), this.calcImageHeight( info ) );
			},
			
			updateImage : function() {
				this.getPictureElement().src = Common_settingManager.getCurrentImageInfo().getImageUri();
			}
		};
		
		var sapporolive = new SapporoLive();
		
		
		
		function updateImage() { sapporolive.updateImage(); }
		function makeBig() { sapporolive.makeBig(); }
		function makeSmall() { sapporolive.makeSmall(); }
		
		function initialize()
		{
			makeSmall();
			timerLoop();
		}

		function timerLoop()
		{
			updateImage();
			setTimeout( "timerLoop()", sapporolive.getRefreshInterval() );
		}
    </script>
	</head>

	<body style='margin:0px; background-color: #003366;' onload='initialize()'>
	<!--<span id="message"></span>-->
	<img name="picture" src="" onmouseover="makeBig()" onmouseout="makeSmall()" />
    </body>
</html>


settings.html

<html>
  <head>
    <title></title>
	<script src="common.js" type="text/javascript"></script>
    <script>
		System.Gadget.onSettingsClosing = closing;
		
		function closing( event ) {
			if ( event.closeAction == event.Action.commit ) {
				Common_settingManager.setSelectedIndex( getSelectedIndexFromRadioButton() );
			}
		}
		
		function getSelectedIndexFromRadioButton() {
			var index = 0;
			for ( var i=0 ; i<listForm.camera.length; i++ ) {
				if ( listForm.camera[ i ].checked ) {
					index = i;
					break;
				}
			}
			return index;
		}
		
		function initalizeWindow() {
		    writeHtmlElements( generateHtmlElements() );
		}
		
		function writeHtmlElements( html ) {
		    listForm.innerHTML = html;
		}
		
		function generateHtmlElements() {
			var index = Common_settingManager.getSelectedIndex();
			var html = "";
			for ( var i=0 ; i<Common_imgInfoCollection.images.length ; i++ ) {
				html += createRadioButtonElement( "camera", i, Common_imgInfoCollection.images[ i ].title, (i == index) );
			}
			return html;
		}
		
		function createRadioButtonElement( name, value, content, isChecked ) {
			var html = '<input type=radio name="' + name + '" value="' + value + '"';
			if ( isChecked )
				html += " checked";
			return html += ">" + content + "<br />";
		}
    </script>
  </head>

  <body style='margin: 0px; padding: 10px; width: 230px; height: 380px;' onload='initalizeWindow()'>
	カメラ選択<br />
	<!--<span id="hoge">aa</span>-->
	<form name="listForm" id="listForm" style="overflow: scroll; height: 330px;">
	</form>
  </body>
</html>


8割強テキストエディタで書きましたが,途中からVS2008にシフト。
インテリセンス便利やぁ。
何のためらいもなくテキストエディタでゴリゴリやってました。
もっと早く気づけば良かった。。。