2 * FeedBlog CoreScript
\r
4 * @copyright 2013 FeedBlog Project (http://sourceforge.jp/projects/feedblog/)
\r
5 * @author Kureha Hisame (http://lunardial.sakura.ne.jp/) & Yui Naruse (http://airemix.com/)
\r
10 // ブログ本体のHTMLファイルのURL
\r
19 // ログのリストが書かれたXMLのファイルパス
\r
26 * XMLファイルから読み込んだファイルのバリデートモード
\r
27 * 0 = 改行コード部分に<br/>を挿入
\r
28 * 1 = 改行コード部分に<br/>を挿入しない
\r
35 // fetchEntries 用のセマフォ
\r
36 var fetchEntriesSemaphore = new Semaphore();
\r
39 * 記事を実際に生成します。この部分を編集することでデザインを変更可能です。
\r
40 * @param {Entry} entry 記事の情報が代入されたEntryオブジェクト
\r
41 * @param {String} drawitem 「本文」を描画すべきパネルのDIV要素のid
\r
42 * @param {String} renderto 「タイトル・更新日時・本文」の1日分の記事データを最終的に描画すべきパネルのDIV要素のid
\r
43 * @param {String} closed (Ext jsパネルオプション)記事をクローズ状態で生成するか否か
\r
45 function generatePanel(entry, drawitem, renderto, closed) {
\r
47 if ( typeof ($("#" + renderto).feedblog_contents_plugin) == "function") {
\r
48 $("#" + renderto).feedblog_contents_plugin({
\r
50 mainPageUrl : mainPageUrl,
\r
51 searchPageUrl : searchPageUrl
\r
56 var htmlBuffer = [];
\r
59 var feedblogContentId = "" + renderto + "_content_div";
\r
62 $("#" + drawitem).html(entry.content);
\r
64 // ヘッダパネルを生成 class= .feedblog_header
\r
65 htmlBuffer.push("<div class='feedblog_header' onclick='closePanel(\"" + feedblogContentId + "\")'><span>" + entry.title + "</span></div>" +
\r
67 // 本体記事を作成 class= .feedblog_content
\r
68 "<div class='feedblog_content' id='" + feedblogContentId + "'><span>" + document.getElementById(renderto).innerHTML + "</span></div>");
\r
71 $("#" + renderto).html(htmlBuffer.join(""));
\r
75 * システム表示画面を実際に生成します。この部分を編集することでデザインを変更可能です。
\r
76 * @param {Entry} entry 記事の情報が代入されたEntryオブジェクト
\r
77 * @param {String} drawitem パネルの本文を格納したDIV要素のid
\r
78 * @param {String} renderto 「タイトル・更新日時・本文」の1日分の記事データを焼き付けるDIV要素のid
\r
79 * @param {String} closed (Ext jsパネルオプション)記事をクローズ状態で生成するか否か
\r
81 function generateSystemPanel(entry, drawitem, renderto, closed) {
\r
83 var htmlBuffer = [];
\r
86 var feedblogContentId = "" + renderto + "_content_div";
\r
89 $("#" + drawitem).html(entry.content);
\r
91 // ヘッダパネルを生成 class= .feedblog_header
\r
92 htmlBuffer.push("<div class='feedblog_header' onclick='closePanel(\"" + feedblogContentId + "\")'><span>" + entry.title + "</span></div>" +
\r
94 // 本体記事を作成 class= .feedblog_content
\r
95 "<div class='feedblog_content' id='" + feedblogContentId + "'><span>" + document.getElementById(renderto).innerHTML + "</span></div>");
\r
97 $("#" + renderto).html(htmlBuffer.join(""));
\r
103 function initialize() {
\r
104 mainPageUrl = $("#feedblog_mainpageurl").val();
\r
105 searchPageUrl = $("#feedblog_searchpageurl").val();
\r
106 latestXml = $("#feedblog_latestxml").val();
\r
107 logXmlUrl = $("#feedblog_loglistxmlurl").val();
\r
108 showLength = parseInt($("#feedblog_showlength").val());
\r
109 if (isNaN(showLength)) {
\r
112 validateMode = $("#feedblog_validatemode").val();
\r
116 * jQueryへのイベント登録です。すべてのDOMが利用可能になった時点で実行されます。
\r
118 $(document).ready(function() {
\r
122 // 制御に必要な各種パラメタを取得する
\r
123 var tag = getParamFromUrl("tag");
\r
124 var id = getParamFromUrl("id");
\r
125 var urlhash = getHashFromUrl();
\r
127 // ハッシュが空か、ハッシュ形式の正規表現に一致しないようなら通常モードで実行
\r
128 if (urlhash.length == 0 && tag.length == 0 && id.length == 0) {
\r
129 fullWriteMode(latestXml);
\r
131 } else if (urlhash.length == 0 && id.length == 0) {
\r
132 // タグが指定されているのでタグ探索モード
\r
133 searchTagMode(tag);
\r
135 } else if (urlhash.length == 0) {
\r
136 // IDが指定されているのでID探索モード
\r
140 // ハッシュ形式の正規表現に一致したら探索モード
\r
141 searchHashMode(urlhash);
\r
147 * jQueryでのパネル開閉を制御します
\r
149 function closePanel(id) {
\r
150 $("#" + id).slideToggle();
\r
155 * @param {Object} obj entry 要素の DOM オブジェクト
\r
157 function Entry(obj) {
\r
158 this.title = $("title:first", obj).text();
\r
159 if (this.title == "")
\r
160 requiredElementError(obj, "title");
\r
161 this.title = validateText(this.title);
\r
162 this.content = $("content:first", obj).text();
\r
163 this.content = validateText(this.content);
\r
164 this.id = $("id:first", obj).text();
\r
166 requiredElementError(obj, "id");
\r
167 this.date = $("updated:first", obj).text();
\r
168 if (this.date == "")
\r
169 requiredElementError(obj, "updated");
\r
170 this.date = validateData(this.date);
\r
171 this.category = $("category", obj);
\r
176 * @param {Object} obj entry 要素の DOM オブジェクト
\r
178 function SystemEntry(obj) {
\r
179 this.title = $("title:first", obj).text();
\r
180 this.title = validateText(this.title);
\r
181 this.content = $("content:first", obj).text();
\r
182 this.content = validateText(this.content);
\r
183 this.id = $("id:first", obj).text();
\r
184 this.date = $("updated:first", obj).text();
\r
185 this.date = validateData(this.date);
\r
186 this.category = $("category", obj);
\r
190 * 呼び出すとDIV:id名:feedblog_writearea上のHTMLを削除し、ロードエフェクトを表示します
\r
192 function loadingEffect() {
\r
193 $("#feedblog_writearea").html('<div id="feedblog_drawpanel" class="feedblog_drawpanel"><div id="feedblog_drawitem" class="feedblog_drawitem"> <\/div><\/div>');
\r
196 var systemEntry = new SystemEntry();
\r
197 systemEntry.title = "Now Loading .....";
\r
198 systemEntry.content = '<br/>長時間画面が切り替わらない場合はページをリロードしてください。<br/><br/>';
\r
199 generateSystemPanel(systemEntry, "feedblog_drawitem", "feedblog_drawpanel", false);
\r
203 * 記事データのエラー時の処理を行います
\r
205 function showError() {
\r
206 $("#feedblog_writearea").html('<div id="feedblog_drawpanel" class="feedblog_drawpanel"><div id="feedblog_drawitem" class="feedblog_drawitem"> <\/div><\/div>');
\r
209 var systemEntry = new SystemEntry();
\r
210 systemEntry.title = "エラー";
\r
211 systemEntry.content = '<br/>記事ファイルのロードに失敗しました!<br/><br/>';
\r
212 generateSystemPanel(systemEntry, "feedblog_drawitem", "feedblog_drawpanel", false);
\r
214 alert("記事ファイルが読み込めません!");
\r
218 * 記事データのエラー時の処理を行います
\r
220 function notFoundError() {
\r
221 $("#feedblog_writearea").html('<div id="feedblog_drawpanel" class="feedblog_drawpanel"><div id="feedblog_drawitem" class="feedblog_drawitem"> <\/div><\/div>');
\r
224 var systemEntry = new SystemEntry();
\r
225 systemEntry.title = "検索失敗";
\r
226 systemEntry.content = '<br/>検索条件に一致する記事は見つかりませんでした。<br/><br/>';
\r
227 generateSystemPanel(systemEntry, "feedblog_drawitem", "feedblog_drawpanel", false);
\r
231 * 記事データのエラー時の処理を行います
\r
233 function requiredElementError(parent, name) {
\r
234 alert(parent.ownerDocument.URL + ": 必須な要素 " + name + " が存在しないか空な " + parent.tagName + " 要素が存在します");
\r
237 function xmlAttrContentEscape(str) {
\r
238 return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/^[ ]+/mg, " ").replace(/^[\t]+/mg, "");
\r
242 * 日付のHTML表示用バリデーション処理を行います
\r
243 * @param {String} data RFC3339形式のdate-time文字列
\r
245 function validateData(data) {
\r
246 var regT = new RegExp("T", "gm");
\r
247 data = data.replace(regT, " ");
\r
249 // 秒数の小数点以下の部分はカットする
\r
250 data = data.substring(0, 19);
\r
256 * 記事本文のバリデーション処理を行います
\r
257 * @param {String} contents 記事の本文が格納されている文字列
\r
259 function validateText(contents) {
\r
261 if (validateMode == 0) {
\r
262 contents = contents.replace(/[\n\r]|\r\n/g, "<br />");
\r
269 * URLからパラメタを取得するための関数
\r
271 function getParamFromUrl(paramName) {
\r
272 // GETパラメタよりタグを取得する
\r
274 if (location.search.length > 1) {
\r
275 var queries = location.search.substring(1).split('&');
\r
276 for (var i = 0; i < queries.length; i++) {
\r
277 if (("" + queries[i].split('=')[0]) == paramName) {
\r
278 tag = "" + queries[i].split('=')[1];
\r
287 * URLからハッシュを取得するための関数
\r
289 function getHashFromUrl() {
\r
290 return "" + location.hash.substring(1);
\r
295 * @param {String} a 比較対象(1)
\r
296 * @param {String} b 比較対象(2)
\r
298 function compareLengthDecrease(a, b) {
\r
301 return a > b ? -1 : a < b ? 1 : 0;
\r
307 function Semaphore() {
\r
317 Semaphore.prototype.init = function() {
\r
318 while (this.xhrs.length > 0) {
\r
319 this.xhrs.shift().abort();
\r
321 this.id = Math.random();
\r
327 * ログファイル選択用のコンボボックスをid名:feedblog_logselecterに生成します
\r
328 * class - .feedblog_logform, .feedblog_logselecter
\r
330 function logXMLLoader() {
\r
333 url : logXmlUrl + '?time=' + (+new Date()),
\r
336 success : function(xmlData) {
\r
337 var separateTag = xmlData.getElementsByTagName("file");
\r
339 // 読み込んだ要素をStoreに格納して表示
\r
340 var boxBuffer = [];
\r
341 boxBuffer.push("<form class='feedblog_logselecter' name='feedblog_logform'><select class='feedblog_logselecter' id='feedblog_logbox' onchange='fullWriteMode(this.options[this.selectedIndex].value)'>");
\r
342 for (var i = 0; i < separateTag.length; i++) {
\r
343 boxBuffer.push("<option value='" + separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue + "'>" + separateTag[i].getElementsByTagName("display")[0].firstChild.nodeValue + "</option>");
\r
345 boxBuffer.push("</select></form>");
\r
348 $("#feedblog_logselecter").html(boxBuffer.join(""));
\r
354 * 記事のデータが記述されたXMLデータを読み込むロジックを生成します
\r
355 * @param {String} fileName 読み込み記事のデータが記述されているXMLファイルのパス
\r
357 function fullWriteMode(fileName) {
\r
361 var url = fileName;
\r
364 var loader = new jQuery.ajax({
\r
365 url : url + '?time=' + (+new Date()),
\r
367 success : function(xmlData) {
\r
368 var separateTag = xmlData.getElementsByTagName("entry");
\r
369 var stringBuffer = [];
\r
370 // メモリ上での保持変数を初期化します
\r
371 loadedEntries = [];
\r
373 // メモリ上の変数に全ての記事要素を格納します
\r
374 for (var i = 0; i < separateTag.length; i++) {
\r
375 loadedEntries.push(new Entry(separateTag[i]));
\r
379 showEntriesRange(showLength, 0);
\r
386 * 渡された文字列と一致するfeed1.0:updated要素を持った記事を検索し、表示します
\r
387 * @param {String} urlhash feed1.0:updated要素と一致する文字列
\r
389 function searchHashMode(urlhash) {
\r
394 var loader = new jQuery.ajax({
\r
395 url : logXmlUrl + '?time=' + (+new Date()),
\r
398 success : function(xmlData) {
\r
399 // ファイルパスの要素のみを抽出する
\r
400 var separateTag = xmlData.getElementsByTagName("file");
\r
401 var urls = new Array(separateTag.length);
\r
403 // すべてのファイルパスを配列に格納する
\r
404 for (var i = 0; i < separateTag.length; i++) {
\r
406 urls[i] = separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue;
\r
410 fetchEntriesSemaphore.init();
\r
411 fetchEntriesSemaphore.urls = urls;
\r
412 fetchEntriesSemaphore.count = urls.length;
\r
414 // ファイルパス配列に格納されているすべての記事に対し、探索を開始する
\r
415 for (var i = 0; i < separateTag.length; i++) {
\r
416 // ファイルパス配列の要素からリクエストを生成し、対象データをロードする
\r
417 var xhr = new jQuery.ajax({
\r
420 success : fetchHashEntries
\r
422 fetchEntriesSemaphore.xhrs.push(xhr);
\r
429 * URLハッシュ検索用のjQueryコールバック関数
\r
431 function fetchHashEntries(xmlData) {
\r
433 var urlhash = getHashFromUrl();
\r
436 var entries = xmlData.getElementsByTagName("entry");
\r
438 for (var i = 0; i < entries.length; i++) {
\r
439 // entryタグ内部のidノードの値のみ抽出し、入力されたhashと比較を行う
\r
440 var entry = new Entry(entries[i]);
\r
443 if (urlhash == entry.id) {
\r
444 // 一致した場合は該当記事を表示する
\r
445 $("#feedblog_writearea").html('<div id="feedblog_drawpanel" class="feedblog_drawpanel"><div id="feedblog_drawitem" class="feedblog_drawitem"> <\/div><\/div>');
\r
446 generatePanel(entry, "feedblog_drawitem", "feedblog_drawpanel", false);
\r
448 fetchEntriesSemaphore.buf.push(entry);
\r
452 // セマフォのカウンタを減少させます (Ajaxとの同期のため)
\r
453 fetchEntriesSemaphore.count--;
\r
455 // 最後のファイルまで探索しても記事が見つからなかった場合はエラーを表示します。
\r
456 if (fetchEntriesSemaphore.count == 0) {
\r
457 var entries = fetchEntriesSemaphore.buf;
\r
459 if (entries.length == 0) {
\r
468 * 渡された文字列と一致するfeed1.0:id(sha-1)要素を持った記事を検索し、表示します
\r
469 * @param {String} urlhash feed1.0:id(sha-1)要素と一致する文字列
\r
471 function searchIdMode(urlhash) {
\r
476 var loader = new jQuery.ajax({
\r
477 url : logXmlUrl + '?time=' + (+new Date()),
\r
480 success : function(xmlData) {
\r
481 // ファイルパスの要素のみを抽出する
\r
482 var separateTag = xmlData.getElementsByTagName("file");
\r
483 var urls = new Array(separateTag.length);
\r
485 // すべてのファイルパスを配列に格納する
\r
486 for (var i = 0; i < separateTag.length; i++) {
\r
488 urls[i] = separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue;
\r
492 fetchEntriesSemaphore.init();
\r
493 fetchEntriesSemaphore.urls = urls;
\r
494 fetchEntriesSemaphore.count = urls.length;
\r
496 // ファイルパス配列に格納されているすべての記事に対し、探索を開始する
\r
497 for (var i = 0; i < separateTag.length; i++) {
\r
498 // ファイルパス配列の要素からリクエストを生成し、対象データをロードする
\r
499 var xhr = new jQuery.ajax({
\r
502 success : fetchIdEntries
\r
504 fetchEntriesSemaphore.xhrs.push(xhr);
\r
511 * ID検索用のjQueryコールバック関数
\r
513 function fetchIdEntries(xmlData) {
\r
515 var id = getParamFromUrl("id");
\r
518 var entries = xmlData.getElementsByTagName("entry");
\r
520 for (var i = 0; i < entries.length; i++) {
\r
521 // entryタグ内部のidノードの値のみ抽出し、入力されたhashと比較を行う
\r
522 var entry = new Entry(entries[i]);
\r
525 if (id == CryptoJS.SHA1(entry.id).toString()) {
\r
526 // 一致した場合は該当記事を表示する
\r
527 $("#feedblog_writearea").html('<div id="feedblog_drawpanel" class="feedblog_drawpanel"><div id="feedblog_drawitem" class="feedblog_drawitem"> <\/div><\/div>');
\r
528 generatePanel(entry, "feedblog_drawitem", "feedblog_drawpanel", false);
\r
530 fetchEntriesSemaphore.buf.push(entry);
\r
534 // セマフォのカウンタを減少させます (Ajaxとの同期のため)
\r
535 fetchEntriesSemaphore.count--;
\r
537 // 最後のファイルまで探索しても記事が見つからなかった場合はエラーを表示します。
\r
538 if (fetchEntriesSemaphore.count == 0) {
\r
539 var entries = fetchEntriesSemaphore.buf;
\r
541 if (entries.length == 0) {
\r
550 * 渡された文字列と一致するfeed1.0:category:termタグ要素を持った記事を検索し、表示します
\r
551 * @param {String} urlhash feed1.0:category:term要素と一致する文字列
\r
553 function searchTagMode(tag) {
\r
558 var loader = new jQuery.ajax({
\r
559 url : logXmlUrl + '?time=' + (+new Date()),
\r
562 success : function(xmlData) {
\r
563 // ファイルパスの要素のみを抽出する
\r
564 var separateTag = xmlData.getElementsByTagName("file");
\r
565 var urls = new Array(separateTag.length);
\r
567 // すべてのファイルパスを配列に格納する
\r
568 for (var i = 0; i < separateTag.length; i++) {
\r
570 urls[i] = separateTag[i].getElementsByTagName("path")[0].firstChild.nodeValue;
\r
574 fetchEntriesSemaphore.init();
\r
575 fetchEntriesSemaphore.urls = urls;
\r
576 fetchEntriesSemaphore.count = urls.length;
\r
578 // ファイルパス配列に格納されているすべての記事に対し、探索を開始する
\r
579 for (var i = 0; i < separateTag.length; i++) {
\r
580 // ファイルパス配列の要素からリクエストを生成し、対象データをロードする
\r
581 var xhr = new jQuery.ajax({
\r
584 success : fetchTagEntries
\r
586 fetchEntriesSemaphore.xhrs.push(xhr);
\r
593 * タグ検索用のjQueryコールバック関数
\r
595 function fetchTagEntries(xmlData) {
\r
596 // 既に記事の表示が行われている場合、何も実施しない
\r
597 if (fetchEntriesSemaphore.buf.length > 0) {
\r
602 var tag = getParamFromUrl("tag");
\r
605 var entries = xmlData.getElementsByTagName("entry");
\r
607 for (var j = 0; j < entries.length; j++) {
\r
608 var entry = new Entry(entries[j]);
\r
610 for (var k = 0; k < entry.category.length; k++) {
\r
612 if (tag == entry.category.eq(k).attr("term")) {
\r
614 fetchEntriesSemaphore.buf.push(entry);
\r
619 // セマフォのカウンタを減少させます (Ajaxとの同期のため)
\r
620 fetchEntriesSemaphore.count--;
\r
622 if (fetchEntriesSemaphore.count == 0) {
\r
623 var entries = fetchEntriesSemaphore.buf;
\r
625 if (entries.length == 0) {
\r
631 entries = entries.sort(function(a, b) {
\r
634 return a > b ? -1 : a < b ? 1 : 0;
\r
637 loadedEntries = entries;
\r
640 showEntriesRange(showLength, 0);
\r
646 * class - div.feedblog_pager, ul.feedblog_pager, li.feedblog_pager などなど
\r
647 * @param {int} showLength 一回の画面に表示する記事数
\r
648 * @param {int} startIndex 表示を開始する記事のインデックス
\r
650 function showEntriesRange(showLength, startIndex) {
\r
652 var entries = loadedEntries;
\r
654 // 表示インデックスが範囲外の場合はエラーパネルを表示して終了
\r
655 if (startIndex < 0 || (entries.length <= startIndex && entries.length != 0)) {
\r
660 var stringBuffer = [];
\r
663 var loopLimit = (showLength + startIndex > entries.length) ? entries.length : showLength + startIndex;
\r
664 var indexShowEntries = loopLimit + 1;
\r
667 var menuInfoBuffer = [];
\r
668 menuInfoBuffer.push("<div class='feedblog_pager_shownumber'>");
\r
669 var viewStartIndex = 0;
\r
670 entries.length == 0 ? viewStartIndex = 0 : viewStartIndex = startIndex + 1;
\r
671 menuInfoBuffer.push(viewStartIndex + "件~" + loopLimit + "件(全" + entries.length + "件)目の記事を表示中<br/>");
\r
672 menuInfoBuffer.push("</div>");
\r
674 // ページ移動メニュー表示用バッファです
\r
675 var menuMoveBuffer = [];
\r
676 menuMoveBuffer.push("<ul class='feedblog_pager'>");
\r
679 menuMoveBuffer.push("<li class='feedblog_pager_blank'></li>");
\r
682 if (startIndex - showLength >= 0) {
\r
683 menuMoveBuffer.push("\<li class='feedblog_pager_goback'><span class='feedblog_pager_goback' onclick='showEntriesRange(" + showLength + ", " + (startIndex - showLength) + "); return false;'>\< 前の" + showLength + "件を表示</span\></li>");
\r
685 menuMoveBuffer.push("\<li class='feedblog_pager_goback'>\< 前の" + showLength + "件を表示</a\></li>");
\r
689 menuMoveBuffer.push("<li class='feedblog_pager_center'>[ ");
\r
690 var menuNumbers = Math.ceil(entries.length / showLength);
\r
691 for ( i = 0; i < menuNumbers; i++) {
\r
692 if (startIndex / showLength == i) {
\r
693 menuMoveBuffer.push(i + " ");
\r
695 menuMoveBuffer.push("<span class='feedblog_pager_center' onclick='showEntriesRange(" + showLength + ", " + (i * showLength) + "); return false;'>");
\r
696 menuMoveBuffer.push(i);
\r
697 menuMoveBuffer.push("</span> ");
\r
700 menuMoveBuffer.push("]</li>");
\r
703 if (entries.length > startIndex + showLength) {
\r
704 menuMoveBuffer.push("\<li class='feedblog_pager_gonext'><span class='feedblog_pager_gonext' onclick='showEntriesRange(" + showLength + ", " + (startIndex + showLength) + "); return false;'>\次の" + showLength + "件を表示 \></span\></li>");
\r
706 menuMoveBuffer.push("\<li class='feedblog_pager_gonext'>次の" + showLength + "件を表示 \></li>");
\r
710 menuMoveBuffer.push("<li class='feedblog_pager_blank'></li>");
\r
712 menuMoveBuffer.push("</ul>");
\r
714 // メニューを結合してパネル(前方)に組み込みます
\r
715 stringBuffer.push("<div class='feedblog_pager_wrapper'>");
\r
716 stringBuffer.push(menuInfoBuffer.join(""));
\r
717 stringBuffer.push(menuMoveBuffer.join(""));
\r
718 stringBuffer.push("</div>");
\r
720 // 記事描画部分のパネルを生成します
\r
721 for (var i = startIndex; i < loopLimit; i++) {
\r
722 stringBuffer.push('<div class="feedblog_drawpanel" id="feedblog_drawpanel');
\r
723 stringBuffer.push(i);
\r
724 stringBuffer.push('"><div class="feedblog_drawitem" id="feedblog_drawitem');
\r
725 stringBuffer.push(i);
\r
726 stringBuffer.push('"><\/div><\/div>');
\r
729 // メニューを結合してパネル(後方)に組み込みます
\r
730 stringBuffer.push("<div class='feedblog_pager_wrapper'>");
\r
731 stringBuffer.push(menuMoveBuffer.join(""));
\r
732 stringBuffer.push(menuInfoBuffer.join(""));
\r
733 stringBuffer.push("</div>");
\r
735 $("#feedblog_writearea").html(stringBuffer.join(""));
\r
737 for (var i = startIndex; i < loopLimit; i++) {
\r
738 // 各要素をオブジェクトに格納します
\r
739 var entry = entries[i];
\r
741 // すべてのパネルをオープン状態で生成します
\r
742 generatePanel(entry, "feedblog_drawitem" + i, "feedblog_drawpanel" + i, false);
\r