2 * FeedBlog CoreScript Ext Version
4 * @copyright 2009 FeedBlog Project (http://sourceforge.jp/projects/feedblog/)
5 * @author Kureha Hisame (http://lunardial.sakura.ne.jp/) & Yui Naruse (http://airemix.com/)
9 // ブログ本体のHTMLファイルの名前を記入してください
10 var blogUrl = "./index.html"
12 // 最新の日記を示すパスへの文字列です。最新の日記を置く場所を変えたいときは変更してください。
13 var latestXml = "./xml/diary.xml";
15 // ログのリストが書かれたXMLのファイルパスを記入してください
16 var logXmlUrl = "./xml/loglist.xml";
18 // Ext jsパネルのサイズを記述してください
19 var extPanelWidth = 580;
21 // ログを表示するコンボボックスのサイズを記述してください
22 var extComboWidth = 150;
24 // 日記間のスパン(間隔)をPIXEL単位で記述してください
34 * XMLファイルから読み込んだファイルのバリデートモードを選択します。
35 * 0 = 改行コード部分に<br/>を挿入
36 * 1 = 改行コード部分に<br/>を挿入しない
38 var validateMode = "1";
41 * Ext jsパネルを実際に生成します。この部分を編集することでデザインを変更可能です。
42 * @param {String} title パネルのタイトル部分に表示する文字列
43 * @param {String} drawitem パネルの本文を格納したDIV要素のid
44 * @param {String} renderto 「タイトル・更新日時・本文」の1日分の日記データを焼き付けるDIV要素のid
45 * @param {String} closed (Ext jsパネルオプション)日記をクローズ状態で生成するか否か
47 function generatePanel(title, drawitem, renderto, closed){
53 hideCollapseTool: false,
62 * Extへのイベント登録です。すべてのDOMが利用可能になった時点で実行されます。
64 $(document).ready(function(){
65 // 特定の過去ログの探索モードか否かを判別するためにハッシュを取得する
66 var urlhash = "" + location.hash.substring(1);
68 // ハッシュが空か、ハッシュ形式の正規表現に一致しないようなら通常モードで実行
69 if (urlhash.length == 0) {
73 // ハッシュ形式の正規表現に一致したら探索モード
82 * @param {Object} obj entry 要素の DOM オブジェクト
85 this.title = $("title:first", obj).text();
87 requiredElementError(obj, "title");
88 this.title = "<span>" + validateText(this.title) + "</span>";
89 this.content = $("content:first", obj).text();
90 this.content = "<span>" + validateText(this.content) + "</span>";
91 this.id = $("id:first", obj).text();
93 requiredElementError(obj, "id");
94 this.date = $("updated:first", obj).text();
96 requiredElementError(obj, "updated");
97 this.date = validateData(this.date);
101 * 呼び出すとDIV:id名:writeArea上のHTMLを削除し、ロードエフェクトを表示します
103 function loadingEffect(){
104 document.getElementById("writeArea").innerHTML = '<div id="drawPanel"><div id="drawItem" class="code" style="text-align: center;"><\/div><\/div>';
105 document.getElementById("drawItem").innerHTML = '<br/><img src="./js/ext/resources/images/default/shared/blue-loading.gif"><br/>長時間画面が切り替わらない場合はページをリロードしてください。<br/><br/>';
108 generatePanel("Now Loading .....", "drawItem", "drawPanel", false);
114 function requiredElementError(parent, name){
115 Ext.Msg.alert("Error!", parent.ownerDocument.URL + ": 必須な要素 " +
122 function xmlAttrContentEscape(str){
123 // return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
124 return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/^[ ]+/mg, " ").replace(/^[\t]+/mg, "");
128 * 日付のHTML表示用バリデーション処理を行います
129 * @param {String} data RFC3339形式のdate-time文字列
131 function validateData(data){
132 var regT = new RegExp("T", "gm");
133 data = data.replace(regT, " ");
136 data = data.substring(0, 19);
142 * 日記本文のバリデーション処理を行います
143 * @param {String} contents 日記の本文が格納されている文字列
145 function validateText(contents){
147 if (validateMode == 0) {
148 contents = contents.replace(/[\n\r]|\r\n/g, "<br />");
156 * @param {String} contents 日記の本文が格納されている文字列
157 * @param {String} id 日記の初公開日を示す日付文字列
159 function contentsWithid(contents, id){
161 var hashTag = '<br/><div style="text-align: right;"><a href="' +
162 xmlAttrContentEscape(blogUrl) +
164 xmlAttrContentEscape(id) +
165 '" target="_blank">- この日の記事にリンクする -<\/a><\/span>';
166 return contents + hashTag;
170 * ログファイル選択用のコンボボックスをid名:logSelecterに生成します
172 function logXMLLoader(){
174 var PathRecord = new Ext.data.Record.create([{
183 var logXMLData = new Ext.data.Store();
188 success: function(xmlData){
189 var separateTag = xmlData.getElementsByTagName("file");
191 // 読み込んだ要素をStoreに格納して表示
192 for (var i = 0; i < separateTag.length; i++) {
194 var record = new PathRecord({
195 path: separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue,
196 display: separateTag[i].getElementsByTagName("display")[0].firstChild.nodeValue
198 logXMLData.add(record);
202 document.getElementById("logSelecter").innerHTML = "<input type='text' id='logbox' style='width: " + extComboWidth + "px'/>";
205 var comboBox = new Ext.form.ComboBox({
208 displayField: "display",
211 triggerAction: "all",
212 emptyText: "ログを選択してください..."
216 comboBox.on("change", function(){
217 xmlLoader("" + comboBox.getValue());
224 * 日記のデータが記述されたXMLデータを読み込むロジックを生成します
225 * @param {String} fileName 読み込み日記のデータが記述されているXMLファイルのパス
227 function xmlLoader(fileName){
234 var loader = new jQuery.ajax({
245 function showError(){
246 document.getElementById("writeArea").innerHTML = '<div id="drawPanel"><div id="drawItem" class="code" style="text-align: center;"><\/div><\/div>';
247 document.getElementById("drawItem").innerHTML = '<br/>日記ファイルのロードに失敗しました!<br/><br/>';
250 generatePanel("Error!", "drawItem", "drawPanel", false);
252 Ext.Msg.alert("Error!", "日記ファイルが読み込めません!");
256 * 渡された文字列と一致するfeed1.0:updated要素を持った日記を検索し、表示します
257 * @param {String} urlhash feed1.0:updated要素と一致する文字列
259 function searchMode(urlhash){
264 var loader = new jQuery.ajax({
268 success: function(xmlData){
270 var separateTag = xmlData.getElementsByTagName("file");
271 var filelist = new Array(separateTag.length);
273 // すべてのファイルパスを配列に格納する
274 for (var i = 0; i < separateTag.length; i++) {
276 filelist[i] = separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue;
279 // 終端まで検索した日記XMLファイルの数を格納する変数
280 var searchFileNumbers = 0;
282 // ファイルパス配列に格納されているすべての日記に対し、探索を開始する
283 for (var i = 0; i < separateTag.length; i++) {
284 // ファイルパス配列の要素からリクエストを生成し、対象データをロードする
285 var searchlog = new jQuery.ajax({
288 success: function(xmlData){
290 var searchSeparateTag = xmlData.getElementsByTagName("entry");
292 for (var j = 0; j < searchSeparateTag.length; j++) {
293 // entryタグ内部のidノードの値のみ抽出し、入力されたhashと比較を行う
294 var id = searchSeparateTag[j].getElementsByTagName("id")[0].firstChild.nodeValue;
298 var entry = new Entry(searchSeparateTag[j]);
300 document.getElementById("writeArea").innerHTML = '<div><table class="pager" width="' + extPanelWidth + '" cellspacing="1"><tbody>' +
301 '<tr><td class="pager" colspan="3">1件~1件(全1件)目の記事を表示中<br/></td></tr>' +
302 '<tr><td align="left"><<< 前の3件を表示</td><td align="center">[ 0 ]</td><td align="right">次の3件を表示 >>></td></tr></tbody></table></div>' +
303 '<div style="line-height: ' +
306 '<div id="drawPanel"><div id="drawItem" class="code"><\/div><\/div>' +
307 '<div style="line-height: ' +
310 '<div><table class="pager" width="' +
312 '" cellspacing="1"><tbody>' +
313 '<tr><td align="left"><<< 前の3件を表示</td><td align="center">[ 0 ]</td><td align="right">次の3件を表示 >>></td></tr>' +
314 '<tr><td class="pager" colspan="3">1件~1件(全1件)目の記事を表示中<br/></td></tr></tbody></table></div>';
315 document.getElementById("drawItem").innerHTML = contentsWithid(entry.content, entry.id);
317 // 探索されたパネルはオープン状態で展開する
318 generatePanel(entry.title + " / " + entry.date, "drawItem", "drawPanel", false);
323 if (j == searchSeparateTag.length - 1) {
324 // 日記を最後まで検索してもファイルが見つからなかった場合、検索済み日記ファイル数に1加算する
325 searchFileNumbers = searchFileNumbers + 1;
327 // もうファイルがない場合はエラーを表示する
328 if (searchFileNumbers == separateTag.length) {
329 // ファイルパス配列から日記が見つからなかった場合の処理
330 document.getElementById("writeArea").innerHTML = '<div id="drawPanel"><div id="drawItem" class="code"><\/div><\/div>';
331 document.getElementById("drawItem").innerHTML = "指定された日記は存在しません。";
334 generatePanel("Search Failed.", "drawItem", "drawPanel", false);
348 * @param {int} showLength 一回の画面に表示する記事数
349 * @param {int} startIndex 表示を開始する日記のインデックス
351 function showEntriesRange(showLength, startIndex){
353 var entries = loadedEntries;
355 // 表示インデックスが範囲外の場合はエラーパネルを表示して終了
356 if (startIndex < 0 || (entries.length <= startIndex && entries.length != 0)) {
361 var stringBuffer = [];
364 var loopLimit = (showLength + startIndex > entries.length) ? entries.length : showLength + startIndex;
365 var indexShowEntries = loopLimit + 1;
368 var menuInfoBuffer = [];
369 menuInfoBuffer.push("<tr><td colspan='3' class='pager'>");
370 var viewStartIndex = 0;
371 entries.length == 0 ? viewStartIndex = 0 : viewStartIndex = startIndex + 1
372 menuInfoBuffer.push(viewStartIndex + "件~" + loopLimit + "件(全" + entries.length + "件)目の記事を表示中<br/>");
373 menuInfoBuffer.push("</td></tr>");
375 // ページ移動メニュー表示用バッファです
376 var menuMoveBuffer = [];
377 menuMoveBuffer.push("<tr>");
379 if (startIndex - showLength >= 0) {
380 menuMoveBuffer.push("\<td align='left'><a href='' onclick='showEntriesRange(" +
383 (startIndex - showLength) +
384 "); return false;'>\<\<\< 前の" +
389 menuMoveBuffer.push("\<td align='left'>\<\<\< 前の" +
395 menuMoveBuffer.push("<td align='center'>[ ");
396 var menuNumbers = Math.ceil(entries.length / showLength);
397 for (i = 0; i < menuNumbers; i++) {
398 if (startIndex / showLength == i) {
399 menuMoveBuffer.push(i + " ");
402 menuMoveBuffer.push("<a href='' onclick='showEntriesRange(" +
406 "); return false;'>");
407 menuMoveBuffer.push(i);
408 menuMoveBuffer.push("</a> ");
411 menuMoveBuffer.push("]</td>");
414 if (entries.length > startIndex + showLength) {
415 menuMoveBuffer.push("\<td align='right'><a href='' onclick='showEntriesRange(" +
418 (startIndex + showLength) +
419 "); return false;'>\次の" +
421 "件を表示 \>\>\></a\></td>");
424 menuMoveBuffer.push("\<td align='right'>次の" +
426 "件を表示 \>\>\></a\></td>");
428 menuMoveBuffer.push("</tr>");
430 // メニューを結合してパネル(前方)に組み込みます
431 stringBuffer.push("<div><table cellspacing='1' width='" +
433 "px' class='pager'><tbody>");
434 stringBuffer.push(menuInfoBuffer.join(""));
435 stringBuffer.push(menuMoveBuffer.join(""));
436 stringBuffer.push("</tbody></table></div>");
438 stringBuffer.push('<div style="line-height: ' + entrySpan + 'px;"><br/></div>');
441 for (var i = startIndex; i < loopLimit; i++) {
442 stringBuffer.push('<div id="drawPanel');
443 stringBuffer.push(i);
444 stringBuffer.push('"><div id="drawItem');
445 stringBuffer.push(i);
446 stringBuffer.push('" class="code"><\/div><\/div><div style="line-height: ' + entrySpan + 'px;"><br/></div>')
449 // メニューを結合してパネル(後方)に組み込みます
450 stringBuffer.push("<div><table cellspacing='1' width='" +
452 "px' class='pager'><tbody>");
453 stringBuffer.push(menuMoveBuffer.join(""));
454 stringBuffer.push(menuInfoBuffer.join(""));
455 stringBuffer.push("</tbody></table></div>");
457 document.getElementById("writeArea").innerHTML = stringBuffer.join("");
459 for (var i = startIndex; i < loopLimit; i++) {
461 var entry = entries[i];
462 document.getElementById("drawItem" + i).innerHTML = contentsWithid(entry.content, entry.id);
464 // すべてのパネルをオープン状態で生成します
465 generatePanel(entry.title + " / " + entry.date, "drawItem" + i, "drawPanel" + i, false);
470 * 日記のログファイルデータが記述されているXMLファイルを読み込んで表示します。DIV:id名:writeArea上に読み込んだ日記の内容を表示します
471 * @param {Object} xmlData 日記が記述されたXMLファイル(feed 1.0準拠)
473 function writeHtml(xmlData){
474 var separateTag = xmlData.getElementsByTagName("entry");
475 var stringBuffer = [];
479 // メモリ上の変数に全ての日記要素を格納します
480 for (var i = 0; i < separateTag.length; i++) {
481 loadedEntries.push(new Entry(separateTag[i]));
485 showEntriesRange(showLength, 0);