« 先人に学ぶ~Permalinkの形式を日時に変更する~ | メイン | わけわかんない »

[ MovableType ] エントリを部分的に折りたたむ

エントリの追記部分を折りたたむ(デフォルト非表示)方法はあちこちで見たけど、部分的に折りたたむ常套手段は見つけられなかったので作ってみた。

MovableTypeの固有タグで出来ないか試行錯誤した結果、上手く実現できなかったのでJavaScriptで実装。
実装した後でJUGEMカスタマイズ講座さんが「記事の内容」の一部を隠すで同様のScriptを紹介されているのを見つけてしまい、..."MovableType"を検索ワードに入れてなければ自前で実装する前に見つけられたかも...検索が下手なだけで実は方法があるんじゃ...などとブルーになったのは内緒。
「記事の内容」の一部を隠すのScriptにあった「隠す(折りたたむ)リンク位置をカスタマイズ可能にする」ことに考えが及んでなくて、感心しつつ自作Scriptにも実装しちゃったのも内緒。


落ち込んでみても仕方ないし、せっかく作ったものを捨てるのもアレなので、記録の意味もこめて書き込んでおくことにする。


やりたいこと(記事の部分的な折りたたみ)ははっきりしてるので、要件として(あんまり時間はかけてないけど)考えたのは以下の2点。
  • 折りたたみ部分の見栄えを他とは変更できるようにしたい
    divを折りたたみ部のコンテナとして使用すれば、CSSで制御できて楽。
  • エントリ書き込み時に、なるべく手間を掛けたくない
    JavaScriptで要素を操作する場合、一意のidが必要だったりするが、トップページやアーカイブページのように同ページ内に複数のエントリが並ぶことを考慮すると「エントリを書き込む際に自力でidを付ける」というのは現実的では無いし、なにより面倒。

ということで、エントリ書き込み時は以下のように折りたたみたい部分を「折りたたみ部」を示すクラス"TextCollapse"を指定したdivでくくるだけにして、面倒なid付けや折りたたみを制御するスイッチはScript任せに出来るようにした。


<div class="TextCollapse">
折りたたみたい部分
</div>

JavaScriptソース。



//
// 記事の折りたたみを制御する
// textcollapse.js ver 0.1
//

// 折りたたみ対象部分のコンテナになるtag
// 注)'div'以外で動作するかは未検証
gTextCollapseTagName = 'div';
// 折りたたみ対象部分のclass名
gTextCollapseClassName = 'TextCollapse';
// 折りたたみを切替えるスイッチ(ラベル)部のclass名
gTextCollapseSw1ClassName = 'TextCollapseLabel'; // 上部
gTextCollapseSw2ClassName = 'TextCollapseLabel'; // 下部
// 折りたたみを切替えるスイッチ(ラベル)部のid名のプレフィックス
gTextCollapseSw1IdPrefix = 'TextCollapseSW1'; // 上部
gTextCollapseSw2IdPrefix = 'TextCollapseSW2'; // 下部
// 折りたたみ部のclass名
gTextCollapseBodyClassName = 'TextCollapseBody';
// 折りたたみ部のid名のプレフィックス
gTextCollapseBodyIdPrefix = 'TextCollapseBody';
// 折りたたみを切替えるスイッチ(ラベル)の表示位置
// 0:上部のみ 1:下部のみ 2:上部下部両方
gTextCollapseSwPosition = 2;
// 折りたたみを切替えるスイッチのテキスト
gTextCollapseExpand = '[詳細を表示]';
gTextCollapseCollapse = '[詳細を隠す]';


//--------------------------------------
// 展開リンク組み立て
//--------------------------------------
function makeTextExpandLink( idNum )
{
return ( '<a href="' + gTextCollapseExpand + '" ' +
'onclick="return( SwitchTextCollapse(' + idNum + ') );" ' +
'onkeypress="return( SwitchTextCollapse(' + idNum + ') );">' +
gTextCollapseExpand + '</a></span>' );
}

//--------------------------------------
// 折りたたみリンク組み立て
//--------------------------------------
function makeTextCollapseLink( idNum )
{
return ( '<a href="' + gTextCollapseCollapse + '" ' +
'onclick="return( SwitchTextCollapse(' + idNum + ') );" ' +
'onkeypress="return( SwitchTextCollapse(' + idNum + ') );">' +
gTextCollapseCollapse + '</a></span>' );
}

//--------------------------------------
// 折りたたみの初期化
//--------------------------------------
function initTextCollapse()
{
var tagObjs = this.document.getElementsByTagName( gTextCollapseTagName );
var sw1Text = ''
var sw2Text = ''
var bdyText = ''

for ( var i = 0; i < tagObjs.length; i++ )
{
if ( tagObjs[i].className == gTextCollapseClassName )
{
bdyText = tagObjs[i].innerHTML.replace(/^<br>/ig, '' );
bdyText = bdyText.replace(/^<br \/>/ig, '' );
bdyText = bdyText.replace(/\r\n$/ig, '' );
bdyText = bdyText.replace(/\r$/ig, '' );
bdyText = bdyText.replace(/\n$/ig, '' );
bdyText = bdyText.replace(/<br>$/ig, '' );
bdyText = bdyText.replace(/<br \/>$/ig, '' );

sw1Text = '<span id="' + gTextCollapseSw1IdPrefix + i + '" ' +
'class="' + gTextCollapseSw1ClassName + '">' +
makeTextExpandLink ( i ) + '</span>';

if ( gTextCollapseSwPosition > 0 )
{
sw2Text = '<span id="' + gTextCollapseSw2IdPrefix + i + '" ' +
'class="' + gTextCollapseSw2ClassName + '">' +
makeTextCollapseLink ( i ) + '</span>';
}

tagObjs[i].innerHTML = sw1Text +
'<div id="' + gTextCollapseBodyIdPrefix + i + '" ' +
'class="' + gTextCollapseBodyClassName + '">' +
bdyText + '</div>' + sw2Text;

document.getElementById( gTextCollapseBodyIdPrefix + i ).style.display = "none";
if ( gTextCollapseSwPosition > 0 )
{
document.getElementById( gTextCollapseSw2IdPrefix + i ).style.display = "none";
}
}
}
}

//--------------------------------------
// 折りたたみ/展開の切替え
//--------------------------------------
function SwitchTextCollapse( idNum )
{
var objSW1 = document.getElementById( gTextCollapseSw1IdPrefix + idNum );
var objSW2 = document.getElementById( gTextCollapseSw2IdPrefix + idNum );
var objBody = document.getElementById( gTextCollapseBodyIdPrefix + idNum );

if ( objBody )
{
if ( objBody.style.display == 'none' )
{
if ( objSW1 )
{
if ( gTextCollapseSwPosition == 1 )
{
objSW1.style.display = "none";
}
else
{
objSW1.innerHTML = makeTextCollapseLink ( idNum );
}
}

objBody.style.display = "block";

if ( objSW2 )
{
objSW2.style.display = "block";
}
}
else
{
if ( objSW1 )
{
if ( gTextCollapseSwPosition == 1 )
{
objSW1.style.display = "block";
}
else
{
objSW1.innerHTML = makeTextExpandLink ( idNum );
}
}

objBody.style.display = "none";

if ( objSW2 )
{
objSW2.style.display = "none";
}
}
}

return false;
}


設置手順。



  1. 上記JavaScriptを"textcollapse.js"として、サーバのMovableTypeディレクトリにアップする。

  2. テンプレートを編集し、折りたたみを有効にする。
    対象のテンプレートは以下など、<$MTEntryBody$>を含むもの。
     メイン・メニュー > (BLOG名) > テンプレート > メインページ
     メイン・メニュー > (BLOG名) > テンプレート > アーカイブページ
     メイン・メニュー > (BLOG名) > テンプレート > 日付アーカイブ

    • テンプレートのHTMLヘッダ部分(<head>~</head>の間)に以下を挿入。

      <script type="text/javascript" language="JavaScript" src="<$MTBlogURL$>textcollapse.js"></script>

    • テンプレートの末尾あたり(エントリよりも確実に下になる部分)に以下を挿入。

      <script type="text/javascript">
      <!--
      initTextCollapse();
      // -->
      </script>




IE6とFirefox1.0(Windows)では取りあえず動作しているが、NS4.x系やOpera、Mac上のブラウザでの動作は未確認。

2005/04/29追記
このページで、このスクリプトを更新しています。

投稿者 Kobito : 2005年03月09日 01:57

このエントリーのトラックバックURL

トラックバックはご自由にどうぞ。報告は不要です。

http://kobito.dnsalias.com/kobito/mt/mt-application/mt-tb.cgi/8

このエントリーへのトラックバック

» エントリを部分的に折りたたむ(v0.2) from Kobito's weblog
エントリを部分的に折りたたむのスクリプトを微改造。 [隠す][表示する]のラベル... [続きを読む]

トラックバック時刻: 2005年05月07日 21:45

» エントリーの部分的な折りたたみ from 心にうつりゆく由無しごと
ようするに、こういうヤツです↓ この部分を折りたたむ これがやりたくて検索してみ... [続きを読む]

トラックバック時刻: 2007年01月17日 14:42

このエントリーへのコメント

f7Q9ZQ

投稿者 Fnhvkuel : 2009年07月16日 14:34

コメントしてください

ご感想など残してもらえると励みになります




保存しますか?