OSDN Git Service

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