OSDN Git Service

- gitignore updated.
[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                 entryList.unshift(entry);\r
49 \r
50                 // ログ一覧を更新する\r
51                 refleshEntrylistBox();\r
52 \r
53                 // 更新後、選択されている項目を、先刻追加した日記に移動する\r
54                 document.getElementById("logBox").selectedIndex = 1;\r
55                 editIndex = 0;\r
56         } else {\r
57                 entryList[editIndex].title = document.getElementById("entry_title").value;\r
58                 entryList[editIndex].updated = getDate();\r
59                 entryList[editIndex].content = document.getElementById("entry_stdin").value.replace(/\r\n/g, "\n");\r
60 \r
61                 document.getElementById("logBox").options[parseInt(editIndex) + 1].text = entryList[editIndex].title;\r
62         }\r
63 \r
64         document.getElementById("stdout").value = toXml(feedInfo, entryList);\r
65 \r
66         // プレビューエリアにHTMLを表示します\r
67         document.getElementById("previewArea").innerHTML = entryList[editIndex].content.replace(/\n/g, "<br>");\r
68 }\r
69 \r
70 /**\r
71  * mixi用に記事を変換し、ウインドウを立ち上げて表示します\r
72  */\r
73 function openMixiWindow() {\r
74         // 日記が選択されていない場合は何もしない\r
75         if(editIndex < 0) {\r
76                 return;\r
77         }\r
78 \r
79         // HTMLを生成します\r
80         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
81 \r
82         // ウインドウに書き出します\r
83         var mixi_win = window.open('', 'feedblog_mixi_wrapper', 'width = 850, height = 490, scrollbars=yes');\r
84         mixi_win.document.open();\r
85         mixi_win.document.write(window_str);\r
86         mixi_win.document.close();\r
87 }\r
88 \r
89 /**\r
90  * mixi用に通常のHTMLを変換します\r
91  * @param {String} contents 日記の本文が格納されている文字列\r
92  */\r
93 function mixiWrapper(contents) {\r
94         // 置換に使用する変数\r
95         var target_tag;\r
96         var target_element;\r
97 \r
98         // ニコニコ動画のタグを置換\r
99         while( target_tag = contents.match(/<iframe[^>]*src=["']http:\/\/ext.nicovideo.jp\/thumb\/[A-Za-z]*\d*["'][^>]*>[^<]*<\/iframe>/i)) {\r
100                 // src="..."の部分だけ抜き出す\r
101                 target_element = target_tag[0].match(/src=["'][^"']*["']/i);\r
102                 target_element = '&lt;externalvideo src=&quot;NC:' + target_element[0].replace(/src=["']http:\/\/ext.nicovideo.jp\/thumb\/|["']/ig, "") + ':D&quot;&gt;';\r
103                 // iframeタグ全体を置換する\r
104                 contents = contents.replace(target_tag, target_element);\r
105         }\r
106 \r
107         // Aタグを変換する\r
108         while(contents.match(/<a[^>]*>/)) {\r
109                 // 置換対象のAタグを抽出する\r
110                 target_tag = contents.match(/<a[^>]*>/i);\r
111                 // href="..."の部分のみを抜き出す\r
112                 target_element = target_tag[0].match(/href=["'][^"']*["']/i);\r
113                 // 相対URIが検出された場合、フルに置換する\r
114                 var baseUri = document.location.href.replace(/[^\/]+$/, '');\r
115                 target_element = target_element[0].replace(/\.\//, baseUri).replace(/\.\.\//g, "");\r
116                 // Aタグ全体を消去し、再度Aクローズタグの置換を行う\r
117                 contents = contents.replace(target_tag, "");\r
118                 contents = contents.replace(/<\/a>/i, " ( " + target_element.replace(/href=|["']/g, "") + " ) ");\r
119         }\r
120 \r
121         // ブロック要素のタグが存在した場合、改行をその後に挿入します。\r
122         if(document.getElementById("isCoverBlockTag").checked) {\r
123                 // contents = contents.replace(/<(div|h\d|p)[^>]*>/ig, "-----------------------------------------------------------------------------\n");\r
124                 // contents = contents.replace(/(\n|)<\/(div|h\d|p)>/ig, "\n-----------------------------------------------------------------------------\n");\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                 editIndex = -1;\r
336         } else {\r
337                 document.getElementById("entry_title").value = entryList[index].title;\r
338                 document.getElementById("entry_stdin").value = entryList[index].content;\r
339                 editIndex = index;\r
340         }\r
341 \r
342         // プレビューエリアをクリアします\r
343         document.getElementById("previewArea").innerHTML = "";\r
344 }\r
345 \r
346 /**\r
347  * 記事一覧の情報を表示するセレクトボックスにentryListの情報を反映させます\r
348  */\r
349 function refleshEntrylistBox() {\r
350         var stringBuffer = [];\r
351         stringBuffer.push("<form name='logform'><select id='logBox' onchange='entryLoader(this.options[this.selectedIndex].value)'>");\r
352         stringBuffer.push("<option value='-1'>新規作成</option>");\r
353         for(var i = 0; i < entryList.length; i++) {\r
354                 stringBuffer.push("<option value='" + i + "'/>" + entryList[i].title + "</option>");\r
355         }\r
356         stringBuffer.push("</select></form>");\r
357         // コンボボックス要素を生成\r
358         document.getElementById("feedblog_entryselect").innerHTML = stringBuffer.join("");\r
359 }\r
360 \r
361 /**\r
362  * Feed基本情報保持クラス\r
363  * @param {Object} obj\r
364  */\r
365 function FeedInfo(obj) {\r
366         this.title = $("title:first", obj).text();\r
367         this.subtitle = $("subtitle:first", obj).text();\r
368         this.self = $("link[rel=self]", obj).attr("href");\r
369         this.alternate = $("link[rel=alternate]", obj).attr("href");\r
370         this.updated = $("updated:first", obj).text();\r
371         this.id = $("id:first", obj).text();\r
372         this.rights = $("rights:first", obj).text();\r
373         this.authorname = $("author>name", obj).text();\r
374         this.authoremail = $("author>email", obj).text();\r
375 }\r
376 \r
377 /**\r
378  * 記事クラス\r
379  * @param {Object} obj entry 要素の DOM オブジェクト\r
380  */\r
381 function Entry(obj) {\r
382         this.id = $("id:first", obj).text();\r
383         this.title = $("title:first", obj).text();\r
384         this.summary = $("summary:first", obj).text();\r
385         this.published = $("published:first", obj).text();\r
386         this.updated = $("updated:first", obj).text();\r
387         this.link = $("link:first", obj).attr("href");\r
388         this.content = $("content:first", obj).text();\r
389 \r
390         if(inputValidateMode == 1) {\r
391                 this.content = this.content.replace(/[\r\n]|\r\n/g, "");\r
392                 this.content = this.content.replace(/<br[ \/]*>/ig, "\n");\r
393                 this.content = this.content.replace(/^[ \t]*/mg, "");\r
394         }\r
395 }\r
396 \r
397 /**\r
398  * グローバル変数からXMLを生成し、返却します\r
399  * @param {FeedInfo} finfo\r
400  * @param {Entry[]} elist\r
401  */\r
402 function toXml(finfo, elist) {\r
403         var stringBuffer = [];\r
404 \r
405         stringBuffer.push('<?xml version="1.0" encoding="utf-8"?>');\r
406         stringBuffer.push('<feed xml:lang="ja-jp" xmlns="http://www.w3.org/2005/Atom">');\r
407         stringBuffer.push('');\r
408 \r
409         stringBuffer.push('<title type="text">' + finfo.title + '</title>');\r
410         stringBuffer.push('<subtitle type="text">' + finfo.subtitle + '</subtitle>');\r
411         stringBuffer.push('<link rel="self" type="application/atom+xml" href="' + finfo.self + '" />');\r
412         stringBuffer.push('<link rel="alternate" type="text/html" href="' + finfo.alternate + '" />');\r
413         stringBuffer.push('<updated>' + getDate() + '</updated>');\r
414         stringBuffer.push('<id>' + finfo.id + '</id>');\r
415         stringBuffer.push('<rights type="text">' + finfo.rights + '</rights>');\r
416         stringBuffer.push('<author>');\r
417         stringBuffer.push('    <name>' + finfo.authorname + '</name>');\r
418         stringBuffer.push('    <email>' + finfo.authoremail + '</email>');\r
419         stringBuffer.push('</author>');\r
420         stringBuffer.push('');\r
421 \r
422         for(var i = 0; i < elist.length; i++) {\r
423                 var temp_content;\r
424                 if(document.getElementById("feedblog_addcontentbr").checked) {\r
425                         temp_content = xmlAttrContentEscape(convertContent(elist[i].content));\r
426                 } else {\r
427                         temp_content = xmlAttrContentEscape(elist[i].content);\r
428                 }\r
429 \r
430                 stringBuffer.push('<entry>');\r
431                 stringBuffer.push('<id>' + elist[i].id + '</id>');\r
432                 stringBuffer.push('<title>' + elist[i].title + '</title>');\r
433                 stringBuffer.push('<summary>' + elist[i].summary + '</summary>');\r
434                 stringBuffer.push('<published>' + elist[i].published + '</published>');\r
435                 stringBuffer.push('<updated>' + elist[i].updated + '</updated>');\r
436                 stringBuffer.push('<link href="' + elist[i].link + '" />');\r
437                 stringBuffer.push('<content type="html">' + temp_content + '</content>');\r
438                 stringBuffer.push('</entry>');\r
439                 stringBuffer.push('');\r
440         }\r
441 \r
442         stringBuffer.push('</feed>');\r
443 \r
444         return stringBuffer.join("\n");\r
445 }\r
446 \r
447 /**\r
448  * <content>要素の変換を行います\r
449  * @param {String} content\r
450  */\r
451 function convertContent(content) {\r
452         if(document.getElementById("feedblog_addcontentbr").checked) {\r
453                 content = content.replace(/[\n\r]|\r\n/g, "<br>\n");\r
454         } else {\r
455                 content = content.replace(/<br>/ig, "\n");\r
456         }\r
457 \r
458         return content;\r
459 }\r
460 \r
461 /**\r
462  * XMLのエスケープを行う関数\r
463  * @param {String} str エスケープを行う文字列\r
464  */\r
465 function xmlAttrContentEscape(str) {\r
466         return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/^[ ]+/mg, "&nbsp;").replace(/^[\t]+/mg, "");\r
467 }\r
468 \r
469 /**\r
470  * XMLの逆エスケープを行う関数\r
471  * @param {String} str 逆エスケープを行う文字列\r
472  */\r
473 function xmlAttrContentUnescape(str) {\r
474         return str.replace(/^[\t]+/mg, "").replace(/^[ ]+/mg, "&nbsp;").replace(/&quot;/g, '"').replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");\r
475 }\r
476 \r
477 /**\r
478  * jQueryでのパネル開閉を制御します\r
479  * @param {String} id 開閉するオブジェクトのid\r
480  */\r
481 function closePanel(id) {\r
482         $("#" + id).slideToggle();\r
483 }\r
484 \r
485 /**\r
486  * エラー画面を表示します\r
487  */\r
488 function showError() {\r
489         alert("XMLファイルのローディング中にエラーが発生しました!");\r
490 }\r
491 \r
492 /**\r
493  * RFC3339形式の日時を出力します\r
494  */\r
495 function getDate() {\r
496         var dNow = new Date();\r
497         var sYear = dNow.getFullYear();\r
498         var sMonth = dNow.getMonth() + 1;\r
499         var sDate = dNow.getDate();\r
500         var sHour = dNow.getHours();\r
501         var sMinute = dNow.getMinutes();\r
502         var sSecond = dNow.getSeconds();\r
503 \r
504         // 10以下の時は頭に"0"を挿入\r
505         if(sMonth < 10)\r
506                 sMonth = "0" + sMonth;\r
507         if(sDate < 10)\r
508                 sDate = "0" + sDate;\r
509         if(sHour < 10)\r
510                 sHour = "0" + sHour;\r
511         if(sMinute < 10)\r
512                 sMinute = "0" + sMinute;\r
513         if(sSecond < 10)\r
514                 sSecond = "0" + sSecond;\r
515 \r
516         return sYear + "-" + sMonth + "-" + sDate + "T" + sHour + ":" + sMinute + ":" + sSecond + "+09:00";\r
517 }\r