OSDN Git Service

update generator and mixi.
[feedblog/feedblog_ext.git] / js / lunardial / feedblog_mixi.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 0.1.0.0
8  */
9 // ログのリストが書かれたXMLのファイルパスを記入してください
10 var logXmlUrl = "./xml/loglist.xml";
11 // Feex XMLの<content>要素で、<br>を使用しているか?
12 var inputValidateMode = 0;
13
14 // フィードの基本情報を記録する変数
15 var feedInfo;
16 // 記事リストを格納する変数
17 var entryList;
18 // 現在編集中の記事の位置を示す変数
19 var viewIndex;
20 // コンボボックスの横幅を指定します
21 var comboWidth = 300;
22
23 /**
24  * 全DOMが使用可能になり次第、自動的に呼ばれる関数
25  */
26 function initLoad(){
27     logXMLLoader();
28 }
29
30 /**
31  * ログファイル選択用のコンボボックスをid名:logSelecterに生成します
32  */
33 function logXMLLoader(){
34     // ログ用のXMLを読み込みます
35     jQuery.ajax({
36         url: logXmlUrl,
37         method: "GET",
38         success: function(xmlData){
39             var separateTag = xmlData.getElementsByTagName("file");
40             var fileList = new Array(separateTag.length);
41             var initUrl;
42             
43             // 読み込んだ要素をStoreに格納して表示
44             var boxBuffer = [];
45             boxBuffer.push("<form name='logform'><select name='logbox' style='width: " + comboWidth + "px' onchange='xmlLoader(this.options[this.selectedIndex].value)'>");
46             for (var i = 0; i < separateTag.length; i++) {
47                 if (i == 0) {
48                     initUrl = separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue;
49                 }
50                 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>");
51             }
52             boxBuffer.push("</select></form>");
53             
54             // コンボボックス要素を生成
55             document.getElementById("logSelecter").innerHTML = boxBuffer.join("");
56             
57             // 最新の日記をローディングする
58             xmlLoader(initUrl);
59         }
60     });
61 }
62
63 /**
64  * URLを指定し、指定されたFeedXmlを読み込み、解析を行います
65  * @param {String} url
66  */
67 function xmlLoader(url){
68     // 日記本体のデータをローディングする
69     var loader = new jQuery.ajax({
70         url: url,
71         method: "GET",
72         success: analyzeTargetXml
73     });
74 }
75
76 /**
77  * 引数に存在するXMLデータを解析し、画面に反映します
78  * @param {Object} xmlData
79  */
80 function analyzeTargetXml(xmlData){
81     var rootTag = xmlData.getElementsByTagName("feed");
82     var entryTag = xmlData.getElementsByTagName("entry");
83     
84     // グローバル変数を初期化
85     feedInfo = null;
86     entryList = [];
87     
88     for (var i = 0; i < entryTag.length; i++) {
89         entryList.push(new Entry(entryTag[i]));
90     }
91     
92     refleshEntrylistBox();
93     entryLoader(0);
94 }
95
96 /**
97  * HTMLの内容をFeedInfoに変換します
98  */
99 function applyFeedinfo(){
100     var finfo = new Object();
101     finfo.title = document.getElementById("feed_title").value;
102     finfo.subtitle = document.getElementById("feed_subtitle").value;
103     finfo.self = document.getElementById("feed_self").value;
104     finfo.alternate = document.getElementById("feed_alternate").value;
105     finfo.id = document.getElementById("feed_id").value;
106     finfo.rights = document.getElementById("feed_rights").value;
107     finfo.authorname = document.getElementById("feed_authorname").value;
108     finfo.authoremail = document.getElementById("feed_authoremail").value;
109     
110     return finfo;
111 }
112
113 /**
114  * 指定したEntryList上のインデックスの記事をロードします
115  * @param {int} index
116  */
117 function entryLoader(index){
118     document.getElementById("entry_title").value = entryList[index].title;
119     document.getElementById("entry_stdin").value = validateText(entryList[index].content);
120     viewIndex = index;
121 }
122
123 /**
124  * 記事一覧の情報を表示するセレクトボックスにentryListの情報を反映させます
125  */
126 function refleshEntrylistBox(){
127     var stringBuffer = [];
128     stringBuffer.push("<form name='logform'><select name='logbox' style='width: " + comboWidth + "px' onchange='entryLoader(this.options[this.selectedIndex].value)'>");
129     for (var i = 0; i < entryList.length; i++) {
130         stringBuffer.push("<option value='" + i + "'/>" + entryList[i].title + "</option>");
131     }
132     stringBuffer.push("</select></form>");
133     // コンボボックス要素を生成
134     document.getElementById("entrySelect").innerHTML = stringBuffer.join("");
135 }
136
137 /**
138  * Feed基本情報保持クラス
139  * @param {Object} obj
140  */
141 function FeedInfo(obj){
142     this.title = xmlAttrContentUnescape($("title:first", obj).text());
143     this.subtitle = xmlAttrContentUnescape($("subtitle:first", obj).text());
144     this.self = xmlAttrContentUnescape($("link[rel=self]", obj).attr("href"));
145     this.alternate = xmlAttrContentUnescape($("link[rel=alternate]", obj).attr("href"));
146     this.updated = xmlAttrContentUnescape($("updated:first", obj).text());
147     this.id = xmlAttrContentUnescape($("id:first", obj).text());
148     this.rights = xmlAttrContentUnescape($("rights:first", obj).text());
149     this.authorname = xmlAttrContentUnescape($("author>name", obj).text());
150     this.authoremail = xmlAttrContentUnescape($("author>email", obj).text());
151 }
152
153 /**
154  * 記事クラス
155  * @param {Object} obj entry 要素の DOM オブジェクト
156  */
157 function Entry(obj){
158     this.id = xmlAttrContentUnescape($("id:first", obj).text());
159     this.title = xmlAttrContentUnescape($("title:first", obj).text());
160     this.summary = xmlAttrContentUnescape($("summary:first", obj).text());
161     this.published = xmlAttrContentUnescape($("published:first", obj).text());
162     this.updated = xmlAttrContentUnescape($("updated:first", obj).text());
163     this.link = xmlAttrContentUnescape($("link:first", obj).attr("href"));
164     this.content = xmlAttrContentUnescape($("content:first", obj).text());
165     
166     if (inputValidateMode == 0) {
167         this.content = this.content.replace(/[\r\n]|\r\n/g, "");
168         this.content = this.content.replace(/<br>/ig, "\n");
169     }
170 }
171
172 /**
173  * 日記本文のバリデーション処理を行います
174  * @param {String} contents 日記の本文が格納されている文字列
175  */
176 function validateText(contents){
177     // 置換に使用する変数
178     var target_tag;
179     var target_element;
180     
181     // ニコニコ動画のタグを置換
182     while (target_tag = contents.match(/<iframe[^>]*src=["']http:\/\/ext.nicovideo.jp\/thumb\/sm\d*["'][^>]*>[^<]*<\/iframe>/i)) {
183         // src="..."の部分だけ抜き出す
184         target_element = target_tag[0].match(/src=["'][^"']*["']/i);
185         target_element = '&lt;externalvideo src=&quot;NC:' + target_element[0].replace(/src=["']http:\/\/ext.nicovideo.jp\/thumb\/|["']/ig, "") + ':D&quot;&gt;';
186         // iframeタグ全体を置換する
187         contents = contents.replace(target_tag, target_element);
188     }
189     
190     // Aタグを変換する
191     /*
192      var base_uri = document.location.href.replace(/[^\/]+$/, '');
193      var func = function(target, quote, url){
194      // 相対URIが検出された場合、フルに置換する
195      return '( ' + url.replace(/^(?!http)(?:\.\/)?/, base_uri) + ' )';
196      };
197      contents = contents.replace(/<a[^>]*href=(["'])(.*?)\1[^>]*>.*?<\/a>/i, func);
198      */
199     // Aタグを変換する
200     while (contents.match(/<a[^>]*>/)) {
201         // 置換対象のAタグを抽出する
202         target_tag = contents.match(/<a[^>]*>/i);
203         // href="..."の部分のみを抜き出す
204         target_element = target_tag[0].match(/href=["'][^"']*["']/i);
205         // 相対URIが検出された場合、フルに置換する
206         target_element = target_element[0].replace(/\.\//, document.location.href.replace(/[^\/]+$/, ''));
207         // Aタグ全体を消去し、再度Aクローズタグの置換を行う
208         contents = contents.replace(target_tag, "");
209         contents = contents.replace(/<\/a>/i, " ( " + target_element.replace(/href=|["']/g, "") + " ) ");
210     }
211     
212     // 通常のタグすべてを削除する
213     contents = contents.replace(/<[^>]*>|<\/[^>]*>/ig, "");
214     
215     // 通常のタグ置換後、ニコニコ動画のタグを元に戻す
216     contents = contents.replace(/&lt;externalvideo src=&quot;NC:/g, "<externalvideo src='NC:");
217     contents = contents.replace(/:D&quot;&gt;/, ":D'>");
218     
219     // 半角を置換する
220     contents = contents.replace(/&nbsp;/g, " ");
221     
222     return contents;
223 }
224
225 /**
226  * <content>要素の変換を行います
227  * @param {String} content
228  */
229 function convertContent(content){
230     if (document.getElementById("addContentBr").checked) {
231         content = content.replace(/[\n\r]|\r\n/g, "<br>\n");
232     }
233     else {
234         content = content.replace(/<br>/ig, "\n");
235     }
236     
237     return content;
238 }
239
240 /**
241  * XMLのエスケープを行う関数
242  * @param {String} str エスケープを行う文字列
243  */
244 function xmlAttrContentEscape(str){
245     return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
246 }
247
248 /**
249  * XMLのエスケープを行う関数
250  * @param {String} str エスケープを行う文字列
251  */
252 function xmlAttrContentUnescape(str){
253     return str.replace(/&quot;/g, '"').replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");
254 }