OSDN Git Service

- update tag execution and optimize.
[feedblog/feedblog.git] / js / lunardial / feedblog_generator.js
1 /**
2  * FeedBlog Generator
3  *
4  * @copyright 2009 FeedBlog Project (http://sourceforge.jp/projects/feedblog/)
5  * @author Kureha Hisame (http://lunardial.sakura.ne.jp/) & Yui Naruse (http://airemix.com/)
6  * @since 2009/06/03
7  * @version 4.2.1.0
8  */
9
10 // Feex XMLの<content>要素で、<br>を使用しているか?
11 var inputValidateMode = 1;
12 // 出力時に<content>要素に<br>を付加するか否かを格納する変数
13 var outputValidateMode = 1;
14 // ログのリストが書かれたXMLのファイルパスを記入してください
15 var logXmlUrl;
16
17 // フィードの基本情報を記録する変数
18 var feedInfo;
19 // 記事リストを格納する変数
20 var entryList;
21 // 現在編集中の記事の位置を示す変数
22 var editIndex;
23 // feedblogの設置アドレスを格納する変数
24 var pageAddr;
25
26 /**
27  * 編集中の内容を反映し、画面に出力します
28  */
29 function applyChange() {
30         feedInfo = applyFeedinfo();
31         pageAddr = feedInfo.alternate;
32
33         if (document.getElementById("entry_title").value == "" || document.getElementById("entry_stdin").value == "") {
34                 if (confirm("タイトルか記事が空白です!FeedBlogでの表示時にエラーが出ますがよろしいですか?") == false) {
35                         return;
36                 }
37         }
38
39         if (editIndex < 0) {
40                 var entry = new Object();
41                 var dateRfc3339 = getDate();
42                 entry.id = pageAddr + "?" + dateRfc3339;
43                 entry.title = document.getElementById("entry_title").value;
44                 entry.summary = "";
45                 entry.published = dateRfc3339;
46                 entry.updated = dateRfc3339;
47                 entry.link = pageAddr + "#" + entry.id;
48                 entry.content = document.getElementById("entry_stdin").value.replace(/\r\n/g, "\n");
49                 entry.category = getTags();
50                 entryList.unshift(entry);
51
52                 // ログ一覧を更新する
53                 refleshEntrylistBox();
54
55                 // 更新後、選択されている項目を、先刻追加した日記に移動する
56                 document.getElementById("logBox").selectedIndex = 1;
57                 editIndex = 0;
58         } else {
59                 entryList[editIndex].title = document.getElementById("entry_title").value;
60                 entryList[editIndex].updated = getDate();
61                 entryList[editIndex].content = document.getElementById("entry_stdin").value.replace(/\r\n/g, "\n");
62                 entryList[editIndex].category = getTags();
63
64                 document.getElementById("logBox").options[parseInt(editIndex) + 1].text = entryList[editIndex].title;
65         }
66
67         document.getElementById("stdout").value = toXml(feedInfo, entryList);
68
69         // プレビューエリアにHTMLを表示します
70         document.getElementById("previewArea").innerHTML = entryList[editIndex].content.replace(/\n/g, "<br>");
71 }
72
73 /**
74  * mixi用に記事を変換し、ウインドウを立ち上げて表示します
75  */
76 function openMixiWindow() {
77         // 日記が選択されていない場合は何もしない
78         if (editIndex < 0) {
79                 return;
80         }
81
82         // HTMLを生成します
83         var window_str = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>FeedBlog Mixi用変換</title><style type="text/css">body {font-size: 12px;line-height: 18px;color: #004488;margin-top: 10px; margin-bottom: 10px;}td.default {font-size: 12px;line-height: 18px;color: #004488;border: 1px solid #8888ff;text-align: left;vertical-align: top;}div {text-align: left;}div.code {background: #f8f8ff;border: 1px solid #c8c8ff;padding: 10px;margin: 10px;margin-left: 0px;border-left: 5px solid #e8e8ff;font-size: 12px;line-height: 18px;}table.pager {padding: 0px;margin: 0px;border: 1px solid #8888ff;}td.pager {border: 1px solid #8888ff;padding-left: 3px;}td.formheader {font-size: 9pt;line-height: 13pt;font-family: sans-serif;font-weight: bold;padding: 3px;border: 1px solid #C5C5DE;background-color: #FAFAFF;}td.forminput {font-size: 9pt;line-height: 13pt;font-family: sans-serif;padding: 5px;border: 1px dotted #C5C5DE;}input {font-size: 9pt;line-height: 13pt;font-family: sans-serif;color: #1E4080;border: 1px dotted #BABAFE;background-color: #F5F5FF;}textarea {font-size: 9pt;line-height: 13pt;font-family: sans-serif;color: #1E4080;border: 1px dotted #BABAFE;background-color: #F5F5FF;}</style></head><body><center><table align="center" style="width: 800px;"><tbody><tr><td class="default" colspan="2" style="padding: 5px; text-align: center; vertical-align: bottom;"><table style="width: 100%"><tbody><tr><td class="formheader" style="text-align: center; width: 100px;">タイトル</td><td class="forminput" style="padding: 0px 5px 0px 3px;"><input type="text" id="entry_title" style="width: 100%" value="' + entryList[editIndex].title + '"></td></tr><tr><td class="formheader" style="text-align: center;">本文</td><td class="forminput" style="padding: 0px 5px 0px 3px;"><textarea id="entry_stdin" rows="20" style="width: 100%">' + mixiWrapper(entryList[editIndex].content) + '</textarea></td></tr></tbody></table></td></tr></tbody></table><br><input type="button" value="ウインドウを閉じる" onclick="javascript: window.close();"></center></body></html>';
84
85         // ウインドウに書き出します
86         var mixi_win = window.open('', 'feedblog_mixi_wrapper', 'width = 850, height = 490, scrollbars=yes');
87         mixi_win.document.open();
88         mixi_win.document.write(window_str);
89         mixi_win.document.close();
90 }
91
92 /**
93  * mixi用に通常のHTMLを変換します
94  * @param {String} contents 日記の本文が格納されている文字列
95  */
96 function mixiWrapper(contents) {
97         // 置換に使用する変数
98         var target_tag;
99         var target_element;
100
101         // ニコニコ動画のタグを置換
102         while ( target_tag = contents.match(/<iframe[^>]*src=["']http:\/\/ext.nicovideo.jp\/thumb\/[A-Za-z]*\d*["'][^>]*>[^<]*<\/iframe>/i)) {
103                 // src="..."の部分だけ抜き出す
104                 target_element = target_tag[0].match(/src=["'][^"']*["']/i);
105                 target_element = '&lt;externalvideo src=&quot;NC:' + target_element[0].replace(/src=["']http:\/\/ext.nicovideo.jp\/thumb\/|["']/ig, "") + ':D&quot;&gt;';
106                 // iframeタグ全体を置換する
107                 contents = contents.replace(target_tag, target_element);
108         }
109
110         // Aタグを変換する
111         while (contents.match(/<a[^>]*>/)) {
112                 // 置換対象のAタグを抽出する
113                 target_tag = contents.match(/<a[^>]*>/i);
114                 // href="..."の部分のみを抜き出す
115                 target_element = target_tag[0].match(/href=["'][^"']*["']/i);
116                 // 相対URIが検出された場合、フルに置換する
117                 var baseUri = document.location.href.replace(/[^\/]+$/, '');
118                 target_element = target_element[0].replace(/\.\//, baseUri).replace(/\.\.\//g, "");
119                 // Aタグ全体を消去し、再度Aクローズタグの置換を行う
120                 contents = contents.replace(target_tag, "");
121                 contents = contents.replace(/<\/a>/i, " ( " + target_element.replace(/href=|["']/g, "") + " ) ");
122         }
123
124         // ブロック要素のタグが存在した場合、改行をその後に挿入します。
125         if (document.getElementById("isCoverBlockTag").checked) {
126                 contents = contents.replace(/<(div|h\d)[^>]*>/ig, "-----------------------------------------------------------------------------\n");
127                 contents = contents.replace(/(\n|)<\/(div|h\d)>/ig, "\n-----------------------------------------------------------------------------\n");
128         } else {
129                 contents = contents.replace(/<\/(div|h\d|p)>/ig, "\n");
130         }
131
132         // li要素を置換する
133         contents = contents.replace(/<[\/]{0,1}ul>/ig, "");
134         contents = contents.replace(/<li>/ig, "・");
135         contents = contents.replace(/<\/li>/ig, "\n");
136
137         // 通常のタグすべてを削除する
138         contents = contents.replace(/<[^>]*>|<\/[^>]*>/ig, "");
139
140         // 通常のタグ置換後、ニコニコ動画のタグを元に戻す
141         contents = contents.replace(/&lt;externalvideo src=&quot;NC:/g, "<externalvideo src='NC:");
142         contents = contents.replace(/:D&quot;&gt;/, ":D'>");
143
144         // 半角を置換する
145         contents = contents.replace(/&nbsp;/g, " ");
146
147         return contents;
148 }
149
150 /**
151  * 選択中の記事を削除します
152  * @param {int} index entryListから削除される記事のインデックス
153  */
154 function removeEntry(index) {
155         if (editIndex == 0) {
156                 entryList.splice(editIndex, 1);
157                 refleshEntrylistBox();
158                 editIndex = -1;
159
160                 document.getElementById("stdout").value = "";
161                 document.getElementById("entry_title").value = "";
162                 $("#entry_stdin").jqte();
163                 document.getElementById("entry_stdin").value = "";
164                 $("#entry_stdin").jqte();
165         }
166         if (editIndex > 0) {
167                 var prevIndex = document.getElementById("logBox").selectedIndex - 1;
168                 entryList.splice(editIndex, 1);
169                 refleshEntrylistBox();
170                 document.getElementById("logBox").selectedIndex = prevIndex;
171                 editIndex = editIndex - 1;
172
173                 entryLoader(editIndex);
174         }
175
176         // プレビューエリアをクリアします
177         document.getElementById("previewArea").innerHTML = "";
178 }
179
180 /**
181  * すべての記事を削除します
182  */
183 function allRemoveEntry() {
184         entryList = [];
185
186         editIndex = -1;
187         refleshEntrylistBox();
188
189         document.getElementById("stdout").value = "";
190         document.getElementById("entry_title").value = "";
191         $("#entry_stdin").jqte();
192         document.getElementById("entry_stdin").value = "";
193         $("#entry_stdin").jqte();
194 }
195
196 /**
197  * 全ての定数を取得・セットします
198  */
199 function initialize() {
200         inputValidateMode = $("#feedblog_inputvalidatemode").val();
201         outputValidateMode = $("#feedblog_outputvalidatemode").val();
202         logXmlUrl = $("#feedblog_loglistxmlurl").val();
203
204         if (outputValidateMode == "1") {
205                 document.getElementById("feedblog_addcontentbr").checked = true;
206         } else {
207                 document.getElementById("feedblog_addcontentbr").checked = false;
208         }
209 }
210
211 /**
212  * 全DOMが使用可能になり次第、自動的に呼ばれる関数
213  */
214 $(document).ready(function() {
215         // 初期処理を実施
216         initialize();
217
218         // jquery-teを初期として適用します
219         $("#entry_stdin").jqte();
220
221         // ログ一覧のXMLをロードします
222         logXMLLoader();
223 });
224
225 /**
226  * ログファイル選択用のコンボボックスをid名:feedblog_logselecterに生成します
227  */
228 function logXMLLoader() {
229         // ログ用のXMLを読み込みます
230         jQuery.ajax({
231                 url : logXmlUrl + "?time=" + (+new Date()),
232                 method : "GET",
233                 success : function(xmlData) {
234                         var separateTag = xmlData.getElementsByTagName("file");
235                         var urls = new Array(separateTag.length);
236                         var initUrl;
237
238                         // 読み込んだ要素をStoreに格納して表示
239                         var boxBuffer = [];
240                         boxBuffer.push("<form name='logform'><select name='logbox' onchange='xmlLoader(this.options[this.selectedIndex].value)'>");
241                         for (var i = 0; i < separateTag.length; i++) {
242                                 if (i == 0) {
243                                         initUrl = separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue;
244                                 }
245                                 boxBuffer.push("<option value='" + separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue + "'/>" + separateTag[i].getElementsByTagName("display")[0].firstChild.nodeValue + " (" + separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue + ")" + "</option>");
246                         }
247                         boxBuffer.push("</select></form>");
248
249                         // コンボボックス要素を生成
250                         document.getElementById("feedblog_logselecter").innerHTML = boxBuffer.join("");
251
252                         // 最新の日記をローディングする
253                         xmlLoader(initUrl);
254                 },
255                 error : showError
256         });
257 }
258
259 /**
260  * URLを指定し、指定されたFeedXmlを読み込み、解析を行います
261  * @param {String} url
262  */
263 function xmlLoader(url) {
264         // 記事本体のデータをローディングする
265         var loader = new jQuery.ajax({
266                 url : url + "?time=" + (+new Date()),
267                 method : "GET",
268                 success : analyzeTargetXml,
269                 error : showError
270         });
271 }
272
273 /**
274  * 引数に存在するXMLデータを解析し、画面に反映します
275  * @param {Object} xmlData
276  */
277 function analyzeTargetXml(xmlData) {
278         var rootTag = xmlData.getElementsByTagName("feed");
279         var entryTag = xmlData.getElementsByTagName("entry");
280
281         // グローバル変数を初期化
282         feedInfo = null;
283         entryList = [];
284
285         feedInfo = new FeedInfo(rootTag[0]);
286         for (var i = 0; i < entryTag.length; i++) {
287                 entryList.push(new Entry(entryTag[i]));
288         }
289
290         feedinfoLoader(feedInfo);
291         pageAddr = feedInfo.alternate;
292
293         refleshEntrylistBox();
294         document.getElementById("entry_title").value = "";
295         $("#entry_stdin").jqte();
296         document.getElementById("entry_stdin").value = "";
297         $("#entry_stdin").jqte();
298         document.getElementById("entry_category").innerHTML = "";
299         document.getElementById("stdout").value = "";
300         editIndex = -1;
301
302         // プレビューエリアをクリアします
303         document.getElementById("previewArea").innerHTML = "";
304 }
305
306 /**
307  * feedInfo変数の内容をHTMLに反映します
308  * @param {FeedInfo} finfo 反映するfeedInfo変数
309  */
310 function feedinfoLoader(finfo) {
311         document.getElementById("feed_title").value = finfo.title;
312         document.getElementById("feed_subtitle").value = finfo.subtitle;
313         document.getElementById("feed_self").value = finfo.self;
314         document.getElementById("feed_alternate").value = finfo.alternate;
315         document.getElementById("feed_id").value = finfo.id;
316         document.getElementById("feed_rights").value = finfo.rights;
317         document.getElementById("feed_authorname").value = finfo.authorname;
318         document.getElementById("feed_authoremail").value = finfo.authoremail;
319 }
320
321 /**
322  * HTMLの内容をFeedInfoに変換します
323  */
324 function applyFeedinfo() {
325         var finfo = new Object();
326         finfo.title = document.getElementById("feed_title").value;
327         finfo.subtitle = document.getElementById("feed_subtitle").value;
328         finfo.self = document.getElementById("feed_self").value;
329         finfo.alternate = document.getElementById("feed_alternate").value;
330         finfo.id = document.getElementById("feed_id").value;
331         finfo.rights = document.getElementById("feed_rights").value;
332         finfo.authorname = document.getElementById("feed_authorname").value;
333         finfo.authoremail = document.getElementById("feed_authoremail").value;
334
335         return finfo;
336 }
337
338 /**
339  * 指定したEntryList上のインデックスの記事をロードします
340  * @param {int} index
341  */
342 function entryLoader(index) {
343         if (index < 0) {
344                 document.getElementById("entry_title").value = "";
345                 $("#entry_stdin").jqte();
346                 document.getElementById("entry_stdin").value = "";
347                 $("#entry_stdin").jqte();
348                 addTagSelectBoxFromCategory([]);
349                 editIndex = -1;
350         } else {
351                 document.getElementById("entry_title").value = entryList[index].title;
352                 $("#entry_stdin").jqte();
353                 document.getElementById("entry_stdin").value = entryList[index].content;
354                 $("#entry_stdin").jqte();
355                 addTagSelectBoxFromCategory(entryList[index].category);
356                 editIndex = index;
357         }
358
359         // プレビューエリアをクリアします
360         document.getElementById("previewArea").innerHTML = "";
361 }
362
363 /**
364  * 記事一覧の情報を表示するセレクトボックスにentryListの情報を反映させます
365  */
366 function refleshEntrylistBox() {
367         var stringBuffer = [];
368         stringBuffer.push("<form name='logform'><select id='logBox' onchange='entryLoader(this.options[this.selectedIndex].value)'>");
369         stringBuffer.push("<option value='-1'>新規作成</option>");
370         for (var i = 0; i < entryList.length; i++) {
371                 stringBuffer.push("<option value='" + i + "'/>" + entryList[i].title + "</option>");
372         }
373         stringBuffer.push("</select></form>");
374         // コンボボックス要素を生成
375         document.getElementById("feedblog_entryselect").innerHTML = stringBuffer.join("");
376 }
377
378 /**
379  * Feed基本情報保持クラス
380  * @param {Object} obj
381  */
382 function FeedInfo(obj) {
383         this.title = $("title:first", obj).text();
384         this.subtitle = $("subtitle:first", obj).text();
385         this.self = $("link[rel=self]", obj).attr("href");
386         this.alternate = $("link[rel=alternate]", obj).attr("href");
387         this.updated = $("updated:first", obj).text();
388         this.id = $("id:first", obj).text();
389         this.rights = $("rights:first", obj).text();
390         this.authorname = $("author>name", obj).text();
391         this.authoremail = $("author>email", obj).text();
392 }
393
394 /**
395  * 記事クラス
396  * @param {Object} obj entry 要素の DOM オブジェクト
397  */
398 function Entry(obj) {
399         this.id = $("id:first", obj).text();
400         this.title = $("title:first", obj).text();
401         this.summary = $("summary:first", obj).text();
402         this.published = $("published:first", obj).text();
403         this.updated = $("updated:first", obj).text();
404         this.link = $("link:first", obj).attr("href");
405         this.content = $("content:first", obj).text();
406
407         var categoryList = [];
408         var categories = $("category", obj);
409         var tempCategory = {};
410         for (var i = 0; i < categories.length; i++) {
411                 tempCategory = {
412                         "term" : categories.eq(i).attr("term"),
413                         "label" : categories.eq(i).attr("label")
414                 };
415                 categoryList.push(tempCategory);
416         }
417         this.category = categoryList;
418
419         if (inputValidateMode == 1) {
420                 this.content = this.content.replace(/[\r\n]|\r\n/g, "");
421                 this.content = this.content.replace(/<br[ \/]*>/ig, "\n");
422                 this.content = this.content.replace(/^[ \t]*/mg, "");
423         }
424 }
425
426 /**
427  * グローバル変数からXMLを生成し、返却します
428  * @param {FeedInfo} finfo
429  * @param {Entry[]} elist
430  */
431 function toXml(finfo, elist) {
432         var stringBuffer = [];
433
434         stringBuffer.push('<?xml version="1.0" encoding="utf-8"?>');
435         stringBuffer.push('<feed xml:lang="ja-jp" xmlns="http://www.w3.org/2005/Atom">');
436         stringBuffer.push('');
437
438         stringBuffer.push('<title type="text">' + finfo.title + '</title>');
439         stringBuffer.push('<subtitle type="text">' + finfo.subtitle + '</subtitle>');
440         stringBuffer.push('<link rel="self" type="application/atom+xml" href="' + finfo.self + '" />');
441         stringBuffer.push('<link rel="alternate" type="text/html" href="' + finfo.alternate + '" />');
442         stringBuffer.push('<updated>' + getDate() + '</updated>');
443         stringBuffer.push('<id>' + finfo.id + '</id>');
444         stringBuffer.push('<rights type="text">' + finfo.rights + '</rights>');
445         stringBuffer.push('<author>');
446         stringBuffer.push('    <name>' + finfo.authorname + '</name>');
447         stringBuffer.push('    <email>' + finfo.authoremail + '</email>');
448         stringBuffer.push('</author>');
449         stringBuffer.push('');
450
451         for (var i = 0; i < elist.length; i++) {
452                 var temp_content;
453                 if (document.getElementById("feedblog_addcontentbr").checked) {
454                         temp_content = xmlAttrContentEscape(convertContent(elist[i].content));
455                 } else {
456                         temp_content = xmlAttrContentEscape(elist[i].content);
457                 }
458
459                 stringBuffer.push('<entry>');
460                 stringBuffer.push('<id>' + elist[i].id + '</id>');
461                 stringBuffer.push('<title>' + elist[i].title + '</title>');
462                 stringBuffer.push('<summary>' + elist[i].summary + '</summary>');
463                 stringBuffer.push('<published>' + elist[i].published + '</published>');
464                 stringBuffer.push('<updated>' + elist[i].updated + '</updated>');
465                 stringBuffer.push('<link href="' + elist[i].link + '" />');
466                 stringBuffer.push('<content type="html">' + temp_content + '</content>');
467
468                 for (var j = 0; j < elist[i].category.length; j++) {
469                         var tmpElist = elist[i].category[j];
470                         stringBuffer.push('<category term="' + tmpElist["term"] + '" label="' + tmpElist["label"] + '"/>');
471                 }
472
473                 stringBuffer.push('</entry>');
474                 stringBuffer.push('');
475         }
476
477         stringBuffer.push('</feed>');
478
479         return stringBuffer.join("\n");
480 }
481
482 /**
483  * <content>要素の変換を行います
484  * @param {String} content
485  */
486 function convertContent(content) {
487         if (document.getElementById("feedblog_addcontentbr").checked) {
488                 content = content.replace(/[\n\r]|\r\n/g, "<br>\n");
489         } else {
490                 content = content.replace(/<br>/ig, "\n");
491         }
492
493         return content;
494 }
495
496 /**
497  * XMLのエスケープを行う関数
498  * @param {String} str エスケープを行う文字列
499  */
500 function xmlAttrContentEscape(str) {
501         return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/^[ ]+/mg, "&nbsp;").replace(/^[\t]+/mg, "");
502 }
503
504 /**
505  * XMLの逆エスケープを行う関数
506  * @param {String} str 逆エスケープを行う文字列
507  */
508 function xmlAttrContentUnescape(str) {
509         return str.replace(/^[\t]+/mg, "").replace(/^[ ]+/mg, "&nbsp;").replace(/&quot;/g, '"').replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");
510 }
511
512 /**
513  * jQueryでのパネル開閉を制御します
514  * @param {String} id 開閉するオブジェクトのid
515  */
516 function closePanel(id) {
517         $("#" + id).slideToggle();
518 }
519
520 /**
521  * エラー画面を表示します
522  */
523 function showError() {
524         alert("XMLファイルのローディング中にエラーが発生しました!");
525 }
526
527 /**
528  * RFC3339形式の日時を出力します
529  */
530 function getDate() {
531         var dNow = new Date();
532         var sYear = dNow.getFullYear();
533         var sMonth = dNow.getMonth() + 1;
534         var sDate = dNow.getDate();
535         var sHour = dNow.getHours();
536         var sMinute = dNow.getMinutes();
537         var sSecond = dNow.getSeconds();
538
539         // 10以下の時は頭に"0"を挿入
540         if (sMonth < 10)
541                 sMonth = "0" + sMonth;
542         if (sDate < 10)
543                 sDate = "0" + sDate;
544         if (sHour < 10)
545                 sHour = "0" + sHour;
546         if (sMinute < 10)
547                 sMinute = "0" + sMinute;
548         if (sSecond < 10)
549                 sSecond = "0" + sSecond;
550
551         return sYear + "-" + sMonth + "-" + sDate + "T" + sHour + ":" + sMinute + ":" + sSecond + "+09:00";
552 }
553
554 /**
555  * タグ情報一覧を返却する関数です
556  */
557 function getTags() {
558         var tagList = [];
559         var tagListHtml = $("*[name=tag]");
560         var tagTemp = {};
561         for (var i = 0; i < tagListHtml.length; i++) {
562                 // 各tag要素を取得して配列に格納
563                 if (tagListHtml.eq(i).val() != "") {
564                         tagTemp = {
565                                 "term" : tagListHtml.eq(i).val(),
566                                 "label" : tagListHtml.eq(i).find(":selected").text()
567                         };
568                         tagList.push(tagTemp);
569                 }
570         }
571
572         return tagList;
573 }
574
575 /**
576  * デフォルトのタグ一覧を取得する関数です
577  */
578 function getDefaultTags() {
579         // デフォルトのタグ一覧を取得
580         // $term1,$label1|$term2,$label2 ... で定義されている
581         var plainTagText = $("#feedblog_tagdefine").val();
582         var tagList = [];
583         var tagTemp = {};
584         // 値が空のタグを初期値として先頭に追加
585         tagList.push({
586                 "term" : "",
587                 "label" : "タグを選択してください"
588         });
589         for (var i = 0; i < plainTagText.split('|').length; i++) {
590                 // 各tag要素を取得して配列に格納
591                 tagTemp = {
592                         "term" : plainTagText.split('|')[i].split(',')[0],
593                         "label" : plainTagText.split('|')[i].split(',')[1]
594                 };
595                 tagList.push(tagTemp);
596         }
597
598         return tagList;
599 }
600
601 /**
602  * HTMLにタグ選択用のセレクトボックスを追加します
603  */
604 function addTagSelectBox() {
605         var tagList = getDefaultTags();
606         var addHtml = [];
607
608         addHtml.push('<select name="tag">');
609         for (var i = 0; i < tagList.length; i++) {
610                 addHtml.push('<option value="' + tagList[i]["term"] + '">' + tagList[i]["label"] + '</option>');
611         }
612         addHtml.push('</select>');
613
614         $("#entry_category").append(addHtml.join('') + "<br>");
615 }
616
617 /**
618  * 現在のカテゴリーオブジェクトに従いセレクトボックスを追加します
619  */
620 function addTagSelectBoxFromCategory(categoryList) {
621         $("#entry_category").html("");
622         for (var j = 0; j < categoryList.length; j++) {
623                 // 選択対象を取得
624                 var selectedTagTerm = categoryList[j]["term"];
625                 var selectedTagLabel = categoryList[j]["label"];
626                 var selectedTagSetFlag = false;
627
628                 var tagList = getDefaultTags();
629                 var addHtml = [];
630                 addHtml.push('<select name="tag">');
631                 for (var i = 0; i < tagList.length; i++) {
632                         if (tagList[i]["term"] == selectedTagTerm && tagList[i]["label"] == selectedTagLabel) {
633                                 addHtml.push('<option value="' + tagList[i]["term"] + '" selected="selected">' + tagList[i]["label"] + '</option>');
634                                 selectedTagSetFlag = true;
635                         } else {
636                                 addHtml.push('<option value="' + tagList[i]["term"] + '">' + tagList[i]["label"] + '</option>');
637                         }
638                 }
639
640                 if (!selectedTagSetFlag) {
641                         addHtml.push('<option value="' + selectedTagTerm + '" selected="selected">' + selectedTagLabel + '</option>');
642                 }
643
644                 addHtml.push('</select>');
645                 $("#entry_category").append(addHtml.join('') + "<br>");
646         }
647 }