1 // option.js
  2 // (2007/02/02)
  3 // オプションダイアログを動的に作成/管理する
  4 // pref.jsと連携するようにできてるので勝手にマージ
  5 
  6 /**
  7  * @fileOverview オプション関係を扱います。
  8  */
  9 
 10 /**
 11  * globalStorage にアクセスします。デフォルトスキンの pref.js がベースになっています。
 12  * @static
 13  */
 14 var SkinPref = {
 15 	/** スキンの名称
 16 	 * @type String
 17 	 */
 18 	_skinName: "smorgasbord",
 19 	/** スキンのバージョン
 20 	 * @type String
 21 	 */
 22 	_skinVersion: "2007/09/25 afternoon (still unstable)",
 23 	/** URI
 24 	 * @type String
 25 	 */
 26 	_skinURI: "http://smorgasbord.drwatson.nobody.jp/",
 27 	/** メールアドレス
 28 	 * @type String
 29 	 */
 30 	_skinMail: "\u0064\u0072\u0077\u0061\u0074\u0073\u006f\u006e\u002e\u0065\u0078\u0065\u002b\u0073\u006d\u006f\u0072\u0067\u0061\u0073\u0062\u006f\u0072\u0064\u0040\u0067\u006d\u0061\u0069\u006c\u002e\u0063\u006f\u006d",
 31 	/** globalStorage
 32 	 * @type StorageList
 33 	 */
 34 	_storage: (location.href.indexOf("http://localhost", 0) == -1) ? globalStorage["127.0.0.1"] : globalStorage["localhost.localdomain"],
 35 	/** スキン名とキーの名前を結合して、名前を解決します。
 36 	 * @param  {String} aPrefName キー
 37 	 * @return {String} 結果
 38 	 */
 39 	_resolvePrefName: function(aPrefName){
 40 		return this._skinName + "_" + aPrefName;
 41 	},
 42 	/** globalStorage から文字列を取得します。
 43 	 * @param  {String} aPrefName     キー
 44 	 * @return {String} aDefaultValue デフォルト値
 45 	 * @return {String} 値
 46 	 */
 47 	getStr: function(aPrefName, aDefaultValue){
 48 		var item = this._storage.getItem(this._resolvePrefName(aPrefName));
 49 		if(item == null) return aDefaultValue || "";
 50 		return item.value;
 51 	},
 52 	/** globalStorage に文字列を設定します。
 53 	 * @param  {String} aPrefName キー
 54 	 * @return {String} aValue    値
 55 	 * @return {String} 値
 56 	 */
 57 	setStr: function(aPrefName, aValue){
 58 		var value = String(aValue);
 59 		if (value != this.getStr(aPrefName))
 60 			this._storage.setItem(this._resolvePrefName(aPrefName), value);
 61 		return value;
 62 	},
 63 	/** globalStorage から数値を取得します。
 64 	 * @param  {String} aPrefName     キー
 65 	 * @return {Number} aDefaultValue デフォルト値
 66 	 * @return {Number} 値
 67 	 */
 68 	getInt: function(aPrefName, aDefaultValue){
 69 		var item = this._storage.getItem(this._resolvePrefName(aPrefName));
 70 		if(item == null) return aDefaultValue || 0;
 71 		return parseInt(item.value);
 72 	},
 73 	/** globalStorage に数値を設定します。
 74 	 * @param  {String} aPrefName キー
 75 	 * @return {Number} aValue    値
 76 	 * @return {Number} 値
 77 	 */
 78 	setInt: function(aPrefName, aValue){
 79 		var value = parseInt(aValue);
 80 		if (value != this.getInt(aPrefName))
 81 			this._storage.setItem(this._resolvePrefName(aPrefName), value);
 82 		return value;
 83 	},
 84 	/** globalStorage からブール値を取得します。
 85 	 * @param  {String}  aPrefName     キー
 86 	 * @return {Boolean} aDefaultValue デフォルト値
 87 	 * @return {Boolean} 値
 88 	 */
 89 	getBool: function(aPrefName, aDefaultValue){
 90 		var item = this._storage.getItem(this._resolvePrefName(aPrefName));
 91 		if(item == null) return aDefaultValue || false;
 92 		return (item.value == "true");
 93 	},
 94 	/** globalStorage からブール値を取得します。
 95 	 * @param  {String}  aPrefName キー
 96 	 * @return {Boolean} aValue    値
 97 	 * @return {Boolean} 値
 98 	 */
 99 	setBool: function(aPrefName, aValue){
100 		var value = (aValue) ? "true" : "false";
101 		if (value != String(this.getBool(aPrefName)))
102 			this._storage.setItem(this._resolvePrefName(aPrefName), value);
103 		return value;
104 	},
105 	/** globalStorage からキーを削除します。
106 	 * @param  {String}  aPrefName キー
107 	 */
108 	remove: function(aPrefName){
109 		this._storage.removeItem(this._resolvePrefName(aPrefName));
110 	}
111 
112 };
113 
114 /**
115  * [オプション] ダイアログを管理します。
116  * @static
117  */
118 var dialogOptions = {
119 	/** ダイアログの親要素
120 	 * @type element
121 	 */
122 	content: document.createElement("div"),
123 	/** [OK] ボタンが押されたときの処理をします。*/
124 	onOK: function(){
125 		var items = document.getElementsByTagName("label");
126 		for (var i = 0; i < items.length; i++) {
127 			if (items[i].className == "dialogOptionsLabel") {
128 				if (items[i].firstChild.tagName == "INPUT") {
129 					switch (items[i].firstChild.getAttribute("type")) {
130 					case "checkbox":
131 						SkinPref.setBool(items[i].firstChild.id, items[i].firstChild.checked);
132 						break;
133 					case "radio":
134 						SkinPref.setBool(items[i].firstChild.id, items[i].firstChild.checked);
135 					}
136 				} else if (items[i].lastChild.tagName == "INPUT") {
137 					if (items[i].lastChild.getAttribute("type") == "text") {
138 						SkinPref.setStr(items[i].lastChild.id, items[i].lastChild.value);
139 					}
140 				} else if (items[i].lastChild.tagName == "SELECT") {
141 					SkinPref.setInt(items[i].lastChild.id, items[i].lastChild.selectedIndex);
142 				}
143 			}
144 		}
145 		this.hide();
146 	},
147 	/** [キャンセル] ボタンが押されたときの処理をします。*/
148 	onCancel: function(){
149 		this.hide();
150 	},
151 	/** リサイズされたときの処理をします。*/
152 	onResize: function(){
153 		dialogOptions.content.style.left = (document.body.offsetWidth - dialogOptions.content.offsetWidth) / 2
154 		dialogOptions.content.style.top  = (window.innerHeight - dialogOptions.content.offsetHeight) / 2
155 		var bg = document.getElementById("dialogOptionsBackground");
156 		if (bg) {
157 			bg.style.width = document.body.offsetWidth;
158 			bg.style.height = window.innerHeight;
159 		}
160 	},
161 	/** ダイアログを表示します。*/
162 	show: function(){
163 		var bg = document.createElement("div");
164 		bg.id = "dialogOptionsBackground";
165 		bg.style.width = document.body.offsetWidth;
166 		bg.style.height = window.innerHeight;
167 		document.body.appendChild(bg);
168 
169 		this.content.style.position   = "fixed";
170 		this.content.style.width      = 512;
171 		this.content.style.visibility = "hidden"
172 		this.content.style.display    = "block";
173 		this.selectPage(this.content.childNodes[1].id.replace("Page_", ""));
174 		this.content.style.left = (document.body.offsetWidth - this.content.offsetWidth) / 2
175 		this.content.style.top  = (window.innerHeight - this.content.offsetHeight) / 2
176 		this.content.style.visibility = "visible";
177 		window.addEventListener("resize", dialogOptions.onResize, false);
178 	},
179 	/** ダイアログを非表示にします。*/
180 	hide: function(){
181 		this.content.style.display = "none";
182 		var bg = document.getElementById("dialogOptionsBackground");
183 		if (bg) document.body.removeChild(bg);
184 		window.removeEventListener("resize", dialogOptions.onResize, false);
185 	},
186 	/** ダイアログのページを切り替えます。
187 	 * @param {String} id ページの ID
188 	 */
189 	selectPage: function(id){
190 		var divHeader = document.getElementById("dialogOptionsHeader");
191 		for (var i = 0; i < divHeader.childNodes.length - 1; i++) {
192 			var icon = divHeader.childNodes[i];
193 			if (icon.id == "Icon_" + id) {
194 				icon.className = "icon" + " " + "selected";
195 			} else {
196 				icon.className = "icon";
197 			}
198 		}	
199 		for (var i = 1; i < this.content.childNodes.length - 1; i++) {
200 			var page = this.content.childNodes[i];
201 			if (page.id == "Page_" + id) {
202 				page.style.display = "block";
203 			} else {
204 				page.style.display = "none";
205 			}
206 		}
207 		if ((this.content.offsetTop + this.content.offsetHeight) > window.innerHeight) this.onResize();
208 	},
209 	/** ページを追加します。
210 	 * @param {String} id      ID
211 	 * @param {String} caption キャプション
212 	 * @param {String} icon    アイコンの URI
213 	 */
214 	addPage: function(id, caption, icon){
215 		if (!this.content.id) this.content.id = "dialogOptions";
216 		if (!document.getElementById("dialogOptions")) document.body.appendChild(this.content);
217 		var divHeader = document.getElementById("dialogOptionsHeader");
218 		if (!divHeader) {
219 			divHeader = document.createElement("div");
220 			divHeader.id = "dialogOptionsHeader";
221 			divHeader.className = "header";
222 			var divHeaderEnd = document.createElement("div");
223 			divHeaderEnd.id = "dialogOptionsHeaderEnd";
224 			divHeaderEnd.className = "null";
225 			divHeader.appendChild(divHeaderEnd);
226 			this.content.appendChild(divHeader);
227 			
228 			var p      = document.createElement("p");
229 			var ok     = document.createElement("input");
230 			ok.setAttribute("type",  "submit");
231 			ok.setAttribute("value", "OK");
232 			ok.setAttribute("onclick", "dialogOptions.onOK()");
233 			var cancel = document.createElement("input");
234 			cancel.setAttribute("type",  "button");
235 			cancel.setAttribute("value", "キャンセル");
236 			cancel.setAttribute("onclick", "dialogOptions.onCancel()");
237 			p.appendChild(ok);
238 			p.appendChild(cancel);
239 			this.content.appendChild(p);
240 		}
241 		
242 		var divIcon = document.createElement("div");
243 		divIcon.id = "Icon_" + id;
244 		divIcon.className = "icon";
245 		divIcon.textContent = caption;
246 		divIcon.style.backgroundImage = "url(" + icon + ")";
247 		divIcon.setAttribute("onclick", "dialogOptions.selectPage('" + id + "')");
248 		divHeader.insertBefore(divIcon, document.getElementById("dialogOptionsHeaderEnd"));
249 		
250 		var divPage = document.createElement("div");
251 		divPage.id = "Page_" + id;
252 		divPage.style.display = "none";
253 		this.content.insertBefore(divPage, this.content.lastChild);
254 	},
255 	/** フレームを追加します。
256 	 * @param {String} page      追加するページの ID
257 	 * @param {String} id        ID
258 	 * @param {String} caption   キャプション
259 	 */
260 	addFrame: function(page, id, caption){
261 		var fieldset = document.createElement("fieldset");
262 		fieldset.id = "Frame_" + page + "_" + id;
263 		var legend  = document.createElement("legend");
264 		legend.textContent = caption;
265 		fieldset.appendChild(legend);
266 		fieldset.appendChild(document.createElement("ul"));
267 		var divPage = document.getElementById("Page_" + page);
268 		if (divPage) divPage.appendChild(fieldset);
269 	},
270 	/** ラベルを追加します。
271 	 * @param {String} page      追加するページの ID
272 	 * @param {String} frame     フレームの ID
273 	 * @param {String} id        ID
274 	 * @param {String} caption   キャプション
275 	 * @param {String} [level]   インデントする階層
276 	 */
277 	addLabel: function(page, frame, id, caption, level){
278 		var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild;
279 		if (level > 0) {
280 			for (var i = 1; i <= level; i++) {
281 				parentObject.appendChild(document.createElement("ul"));
282 				parentObject = parentObject.lastChild;
283 			}
284 		}
285 		var li = document.createElement("li");
286 		var label = document.createElement("label");
287 		label.className = "dialogOptionsLabel";
288 		var span = document.createElement("span");
289 		span.textContent = caption;
290 		label.appendChild(span);
291 		li.appendChild(label);
292 		parentObject.appendChild(li);
293 	},
294 	/** リンクを追加します。
295 	 * @param {String} page      追加するページの ID
296 	 * @param {String} frame     フレームの ID
297 	 * @param {String} id        ID
298 	 * @param {String} caption   キャプション
299 	 * @param {String} uri     URI
300 	 * @param {Number} [level]   インデントする階層
301 	 */
302 	addLink: function(page, frame, id, caption, uri, level){
303 		var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild;
304 		if (level > 0) {
305 			for (var i = 1; i <= level; i++) {
306 				parentObject.appendChild(document.createElement("ul"));
307 				parentObject = parentObject.lastChild;
308 			}
309 		}
310 		var li = document.createElement("li");
311 		var label = document.createElement("label");
312 		label.className = "dialogOptionsLabel";
313 		var a = document.createElement("a");
314 		a.setAttribute("href", uri);
315 		a.setAttribute("target", "_blank");
316 		a.textContent = caption;
317 		label.appendChild(a);
318 		li.appendChild(label);
319 		parentObject.appendChild(li);
320 	},
321 	/** チェックボックスを追加します。
322 	 * @param {String}  page         追加するページの ID
323 	 * @param {String}  frame        フレームの ID
324 	 * @param {String}  id           ID
325 	 * @param {String}  caption      キャプション
326 	 * @param {Boolean} defaultValue デフォルト値
327 	 * @param {Number}  [level]      インデントする階層
328 	 */
329 	addCheckBox: function(page, frame, id, caption, defaultValue, level){
330 		var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild;
331 		if (level > 0) {
332 			for (var i = 1; i <= level; i++) {
333 				parentObject.appendChild(document.createElement("ul"));
334 				parentObject = parentObject.lastChild;
335 			}
336 		}
337 		var li = document.createElement("li");
338 		var label = document.createElement("label");
339 		label.className = "dialogOptionsLabel";
340 		var input = document.createElement("input");
341 		input.setAttribute("type", "checkbox");
342 		input.id = id;
343 		input.checked = SkinPref.getBool(id, defaultValue);
344 		label.appendChild(input);
345 		var span = document.createElement("span");
346 		span.textContent = caption;
347 		label.appendChild(span);
348 		li.appendChild(label);
349 		parentObject.appendChild(li);
350 	},
351 	/** ラジオボタンを追加します。
352 	 * @param {String}  page         追加するページの ID
353 	 * @param {String}  frame        フレームの ID
354 	 * @param {String}  id           ID
355 	 * @param {String}  caption      キャプション
356 	 * @param {Boolean} defaultValue デフォルト値
357 	 * @param {Number}  [level]      インデントする階層
358 	 */
359 	addRadio: function(page, frame, id, caption, defaultValue, level){
360 		var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild;
361 		if (level > 0) {
362 			for (var i = 1; i <= level; i++) {
363 				parentObject.appendChild(document.createElement("ul"));
364 				parentObject = parentObject.lastChild;
365 			}
366 		}
367 		var li = document.createElement("li");
368 		var label = document.createElement("label");
369 		label.className = "dialogOptionsLabel";
370 		var input = document.createElement("input");
371 		input.setAttribute("type", "radio");
372 		input.setAttribute("name", frame);
373 		input.id = id;
374 		input.checked = SkinPref.getBool(id, defaultValue);
375 		label.appendChild(input);
376 		var span = document.createElement("span");
377 		span.textContent = caption;
378 		label.appendChild(span);
379 		li.appendChild(label);
380 		parentObject.appendChild(li);
381 	},
382 	/** エディットボックスを追加します。
383 	 * @param {String} page         追加するページの ID
384 	 * @param {String} frame        フレームの ID
385 	 * @param {String} id           ID
386 	 * @param {String} caption      キャプション
387 	 * @param {String} defaultValue デフォルト値
388 	 * @param {Number} [size]       サイズ
389 	 * @param {Number} [level]      インデントする階層
390 	 */
391 	addEditBox: function(page, frame, id, caption, defaultValue, size, level){
392 		var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild;
393 		if (level > 0) {
394 			for (var i = 1; i <= level; i++) {
395 				parentObject.appendChild(document.createElement("ul"));
396 				parentObject = parentObject.lastChild;
397 			}
398 		}
399 		var li = document.createElement("li");
400 		var label = document.createElement("label");
401 		label.className = "dialogOptionsLabel";
402 		var span = document.createElement("span");
403 		span.textContent = caption;
404 		label.appendChild(span);
405 		var input = document.createElement("input");
406 		input.setAttribute("type", "text");
407 		input.value = SkinPref.getStr(id, defaultValue);
408 		if (size) {
409 			input.style.width = size + "em";
410 		}
411 		input.id = id;
412 		
413 		label.appendChild(input);
414 		li.appendChild(label);
415 		parentObject.appendChild(li);
416 	},
417 	/** 数値のみを入力できるエディットボックスを追加します。
418 	 * @param {String} page         追加するページの ID
419 	 * @param {String} frame        フレームの ID
420 	 * @param {String} id           ID
421 	 * @param {String} caption      キャプション
422 	 * @param {Number} defaultValue デフォルト値
423 	 * @param {Number} [size]       サイズ
424 	 * @param {Number} [level]      インデントする階層
425 	 */
426 	addNumberBox: function(page, frame, id, caption, defaultValue, size, level){
427 		var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild;
428 		if (level > 0) {
429 			for (var i = 1; i <= level; i++) {
430 				parentObject.appendChild(document.createElement("ul"));
431 				parentObject = parentObject.lastChild;
432 			}
433 		}
434 		var li = document.createElement("li");
435 		var label = document.createElement("label");
436 		label.className = "dialogOptionsLabel";
437 		var span = document.createElement("span");
438 		span.textContent = caption;
439 		label.appendChild(span);
440 		var input = document.createElement("input");
441 		input.setAttribute("type", "text");
442 		input.style.textAlign = "right";
443 		if (size) {
444 			input.style.width = size + "em";
445 		}
446 		input.id = id;
447 		input.value = SkinPref.getStr(id, defaultValue);
448 		input.setAttribute("onkeydown", "var i = event.keyCode; if ((i >= 96 && i <= 105) || (i >= 48 && i <= 57) || (i == 190) | (i == 8) || (i == 35) || (i == 36) ||(i == 37) || (i == 39) || (i == 46)) { return true; } return false;");
449 		input.setAttribute("onkeyup",  "if (event.target.value.match(/[^0-9\.]+/)) event.target.value='';");
450 		input.setAttribute("onfocus",  "if (event.target.value.match(/[^0-9\.]+/)) event.target.value='';");
451 		input.setAttribute("onblur",  "if (event.target.value.match(/[^0-9\.]+/)) event.target.value='';");
452 		label.appendChild(input);
453 		li.appendChild(label);
454 		parentObject.appendChild(li);
455 	},
456 	/** コンボボックスを追加します。
457 	 * @param {String} page         追加するページの ID
458 	 * @param {String} frame        フレームの ID
459 	 * @param {String} id           ID
460 	 * @param {String} caption      キャプション
461 	 * @param {Array}  value        項目
462 	 * @param {Number} defaultValue デフォルト値
463 	 * @param {Number} [size]       サイズ
464 	 * @param {Number} [level]      インデントする階層
465 	 */
466 	addComboBox: function(page, frame, id, caption, value, defaultValue, level){
467 		var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild;
468 		if (level > 0) {
469 			for (var i = 1; i <= level; i++) {
470 				parentObject.appendChild(document.createElement("ul"));
471 				parentObject = parentObject.lastChild;
472 			}
473 		}
474 		var li = document.createElement("li");
475 		var label = document.createElement("label");
476 		label.className = "dialogOptionsLabel";
477 		var span = document.createElement("span");
478 		span.textContent = caption;
479 		label.appendChild(span);
480 		var select = document.createElement("select");
481 		select.id = id;
482 		for (var i = 0; i < value.length; i++) {
483 			var option = document.createElement("option");
484 			option.textContent = value[i];
485 			option.setAttribute("value", value[i]);
486 			select.appendChild(option);
487 		}
488 		select.selectedIndex = SkinPref.getInt(id, defaultValue);
489 		label.appendChild(select);
490 		li.appendChild(label);
491 		parentObject.appendChild(li);
492 	}
493 };
494 
495 /** [オプション] ダイアログを初期化します。*/
496 function initOptionDialog(){
497 	dialogOptions.addPage     ("General", "一般",  SKIN_PATH + "img/general.png");
498 	dialogOptions.addFrame    ("General", "Popup", "ポップアップ");
499 	//dialogOptions.addLabel    ("General", "Popup", "labelPopup", "次のポップアップを有効にする:");
500 	dialogOptions.addCheckBox ("General", "Popup", "enableResPopup", "アンカー", true);
501 	dialogOptions.addCheckBox ("General", "Popup", "enableIDPopup", "ID", true);
502 	dialogOptions.addCheckBox ("General", "Popup", "enableIDPopupOnClick", "クリックしてポップアップ", false, 1);
503 	dialogOptions.addCheckBox ("General", "Popup", "enableIDPopupAll", "すべてのレスを一度に表示する", false, 1);
504 	dialogOptions.addCheckBox ("General", "Popup", "enableImagePopup", "画像", true);
505 	dialogOptions.addComboBox ("General", "Popup", "valuePixelationMethod",   "フィルタ: ", ["モザイク", "ガウスぼかし(Fx3)"], 0, 1);
506 	dialogOptions.addComboBox ("General", "Popup", "valuePixelationSize",     "レベル: ", ["強", "中", "弱"], 1, 1);
507 	dialogOptions.addCheckBox ("General", "Popup", "enableDefaultPixelation", "デフォルトでぼかす", false, 1);
508 	dialogOptions.addCheckBox ("General", "Popup", "enablePrecisePixelation", "正確にモザイク化する(遅い)", false, 1);
509 	dialogOptions.addCheckBox ("General", "Popup", "enableUrlPopup", "リンク先サムネイル", true);
510 	dialogOptions.addComboBox ("General", "Popup", "valueUrlPopupSize", "サイズ: ", ["大", "小"], 0, 1);
511 	dialogOptions.addCheckBox ("General", "Popup", "enableVideoPopup", "動画", true);
512 	dialogOptions.addCheckBox ("General", "Popup", "videoPopupAutoStart", "自動再生", true, 1);
513 	dialogOptions.addCheckBox ("General", "Popup", "enableTrackBackPopup", "逆参照", true);
514 	dialogOptions.addCheckBox ("General", "Popup", "enableTrackBackPopupAll", "すべてのレスを一度に表示する", false, 1);
515 	
516 	dialogOptions.addPage     ("Special", "詳細",  SKIN_PATH + "img/special.png");
517 	dialogOptions.addFrame    ("Special", "Link",  "リンク");
518 	dialogOptions.addCheckBox ("Special", "Link",  "enableNewWindow", "リンクを新しいウィンドウで開く", true);
519 	dialogOptions.addCheckBox ("Special", "Link",  "enableNoReferer", "リファラを送信しない", true);
520 	
521 	dialogOptions.addFrame    ("Special", "Visualisation",  "視覚効果");
522 	dialogOptions.addCheckBox ("Special", "Visualisation",  "enableContract", "スレッドタイトルを表示幅に合わせて省略表示する", true);
523 	dialogOptions.addCheckBox ("Special", "Visualisation",  "enablePopupFade", "ポップアップのフェードアウトを有効にする", true);
524 	dialogOptions.addComboBox ("Special", "Visualisation",  "valuePopupFadeStep", "フェードのステップ: ", new Array(0.1,0.2,0.25,0.33,0.5), 1, 1);
525 	dialogOptions.addCheckBox ("Special", "Visualisation",  "enableFindHighlight", "検索/抽出時に強調表示を行う", false);
526 
527 	dialogOptions.addFrame    ("Special", "Browse", "ブラウズ");
528 	dialogOptions.addNumberBox("Special", "Browse", "valueHistoryItemCounts", "保存する履歴の件数: ", 32, 3);
529 	dialogOptions.addCheckBox ("Special", "Browse", "enableHookReload", "F5 キーをフックして動的に更新を行う", true);
530 	dialogOptions.addCheckBox ("Special", "Browse", "enableSmoothScroll", "スムーズスクロールを有効にする", true);
531 	dialogOptions.addComboBox ("Special", "Browse", "valueSmoothScrollFrames", "フレーム数: ", new Array("最小","中","最大"), 1, 1);
532 	
533 	dialogOptions.addFrame    ("Special", "AutoPilot",  "オートパイロット");
534 	dialogOptions.addCheckBox ("Special", "AutoPilot", "enableAutoReloadOnLiveThread", "実況板では自動更新をデフォルトにする", false);
535 	dialogOptions.addCheckBox ("Special", "AutoPilot", "enableAutoReloadWhenInactive", "非アクティヴ時でも自動更新を強制する", false);
536 	dialogOptions.addComboBox ("Special", "AutoPilot", "valueAutoReloadInterval", "自動更新の間隔: ", new Array("15 秒","30 秒","60 秒"), 1);
537 	
538 	dialogOptions.addPage     ("About", "スキン情報",  "chrome://bbs2chreader/content/icon.png");
539 	dialogOptions.addFrame    ("About", "Info",  "このスキンについて");
540 	if (SkinPref._skinName)
541 		dialogOptions.addLabel("About", "Info", "labelSkinName", SkinPref._skinName);
542 	if (SkinPref._skinVersion)
543 		dialogOptions.addLabel("About", "Info", "labelSkinVersion", "バージョン: " + SkinPref._skinVersion);
544 	if (SkinPref._skinURI) {
545 		// dialogOptions.addLabel("About", "Info", "labelSkinBlank", " ");
546 		dialogOptions.addLink ("About", "Info", "labelSkinURI", SkinPref._skinURI, SkinPref._skinURI);
547 	}
548 	if (SkinPref._skinMail)
549 		dialogOptions.addLink ("About", "Info", "labelSkinMail", SkinPref._skinMail, "mailto:" + SkinPref._skinMail);	
550 	
551 	dialogOptions.addFrame    ("About", "Keymap",  "キーボードショートカット");
552 	dialogOptions.addLabel    ("About", "Keymap", "", "F5: 最新の情報に更新");
553 	dialogOptions.addLabel    ("About", "Keymap", "", "←: 前のレスへ移動");
554 	dialogOptions.addLabel    ("About", "Keymap", "", "→: 次のレスへ移動");
555 	dialogOptions.addLabel    ("About", "Keymap", "", "Ctrl + Enter: 書き込む");
556 	dialogOptions.addLabel    ("About", "Keymap", "", "Ctrl + Space: すべて表示");
557 	dialogOptions.addLabel    ("About", "Keymap", "", "Ctrl + Alt + F: 検索/抽出");
558 	dialogOptions.addLabel    ("About", "Keymap", "", "数字キー: 入力されたレス番号へスクロール");
559 }
560 window.addEventListener("load", initOptionDialog, false);
561