プロが教えるわが家の防犯対策術!

タイトルの通り、開いたツリーメニューからリンクを踏んで、またメニューのあるページに戻ってきた時にメニューを開いたままにしたいです。

色々と調べるうちにcookieを使うことはわかったのですが、どこもツリーメニューの方法が違うため載っているソースのどこを弄れば自分の使ったツリーメニューに対応させられるのかわかりませんでした。

javascriptを切った状態では開いたまま表示させたいので、ツリーメニューのソースは以下を参考にさせていただきました。
http://blog.ptlabo.net/index.php?id=06100064
これを利用して「戻ってきた時ツリーメニューを開いた状態に」することはできますか?

できない場合、
・cssオン、javascriptオフの状態では開いている
・ブラウザバックしたときに開いている
この条件に合うツリーメニューであれば何でも良いのでお教えいただきたいです。

初心者ですので詳細にご教授いただければ幸いです。
よろしくお願いします。

A 回答 (5件)

要望を実現するためには、折りたたみのある項目すべて(もしくはどちらか一方をすべて)を保存する必要があります。


クッキーに保存できる文字数は限られています(4kだったかな?)
それ以下なら実現できると思いますが、私にはそこまで書く気力がありません。
これまでの事をヒントにご自分で努力することをお勧めします
私は、自分の書いたコードが最良だと思っていません。
むしろ毎日勉強している立場です。
今度はあなたの自助努力の成果を見せていただきたいと思っております
    • good
    • 0

訂正します。


これまでの場合はツリーメニュー以外のLIとかULにも処理が及んでしますので、一番親のULにclass="treemenu"を追加します
クリックされるとその度にチェックしにいきます。
なのでそこを訂正しました!
しかも初の説明付き!

<html>
<body>
 <ul id="a" class="treemenu">
  <li>A
   <ul>
    <li><a href="htp://blove.cc/tes1/">A-1</a></li>
    <li>A-2
     <ul>
      <li><a href="htp://blove.cc/tes1/">ページ1へ飛ぶ</a></li>
      <li><a href="htp://blove.cc/tes2/">ページ2へ飛ぶ</a></li>
     </ul>
    </li>
    <li>A-3
     <ul>
      <li><a href="htp://blove.cc/tes1/">ページ1へ飛</a></li>
      <li><a href="htp://blove.cc/tes2/">ページ2へ飛ぶ</a></li>
     </ul>
    </li>
   </ul>
  </li>
  <li>b
  <ul>
   <li><a href="htp://blove.cc/tes1/">ページ1へ飛ぶ</a></li>
   <li><a href="htp://blove.cc/tes2/">ページ2へ飛ぶ</a></li>
  </ul>
  </li>
 </ul>

<script>
addEvent( window,'load', function(){ openTreeMenu2('a') }); //イベントはwindow.onload=function(){ でもいいが、他のプログラムとの共用ができないかも!なので追加
addEvent( document.body, 'click', chkClick );//onclickイベントは、いろいろなところにとりつけるよりも、body1箇所ですませるとすっきり

function chkClick( evt ){//クリックのイベント処理
 var element = evt.target || event.srcElement;//イベントが起きた箇所のエレメントを調べる
 if( element.tagName != 'LI' ) return; //タグがLI以外なら必要ないのでやめる
 if( !checkParentCSS( element, 'ul', 'treemenu' ) ) return;//エレメントが属する親を調べてclassに"tremenu"があるか調べる。このおかげで普通のULなのかメニューなのかわかる
 putCookie( 'li', getFirstText( element ),10);//LI要素の最初の#textノードの文字を調べ、クッキーに保存する。期間は10日
 putCookie( 'lic', getChildDisplay( element ),10);//li要素の子のulが開いているか閉じているかも調べクッキーに保存する
 if(1) openTreeMenu2('a'); //1なら対象外は隠す。メニューの折りたたみに好みがあるみたいなので0か1を指定
 else {
  var ul = element.firstChild;//liの中にあるulを調べて開くか閉じるか決める
  while( ul.nodeName != 'UL' ){ ul = ul.nextSibling; if( !ul ) return }//ulを探す。そうでなければ戻る
  ul.style.display = ( ul.style.display == 'none') ? 'block':'none';//閉じていれば開き、そうでなければ逆に三項演算子を利用
 }
}
function checkParentCSS( element, tag, css ){//親のタグとクラスを探る。今回は li で treemenu
 var tag = tag.toUpperCase();//タグを返す関数は大文字を返すので、大文字にしておく
 var reg = new RegExp( '\b*'+ css+ '\b*' );//正規表現で検索。なので className=" abc treemenu di dfji" みたいなのでも見つけ出せる
 while( element = element.parentNode ){//treeの親をどんどん探す。
  if( element.tagName == tag && element.className.match( reg ) ) return true;//タグが同じでクラスも同じなら有りで帰る
  if( element.tagName == 'BODY' ) return false;//親をたどると結局、空になるがBODYでやめる。だからなくてもいいかな?
 }
}
function openTreeMenu2( elementId, keyword, flag ){//折りたたみメニューの本体
 var element = ( typeof( elementId ) == 'string' )? document.getElementById( elementId ): elementId;//idでもオブジェクトでも処理
 var ul = element.getElementsByTagName('ul');//id="a"以下のすべてのulを拾い出す
 for( var i=0, m= ul.length; i<m; i++) ul[i].style.display = 'none';//すべてのULを一旦、消す
 keyword = keyword || getCookie('li');//keywordは今回使用していないが、無い場合はクッキーに保存したliのテキストを読み込む
 flag = flag || getCookie('lic') - 0;//flafはそのLI要素の中のULが、開いているかどうかを保存してある
 if( keyword ) {//LIにあるテキストをさがす
  var li = element.getElementsByTagName( 'li' );//すべてのLIのテキストを検索するために収集
  for( var i=0, m=li.length;i<m;i++){//ループ処理
   if( getFirstText( li[i] ) == keyword ){//LI要素のテキストと検索するテキストを比較
    var descendant = li[i];//一致したので、ここを基準に閉じたULを開いていく
    do {
     var descendant = descendant.parentNode;//親の親
     if( descendant.nodeName == 'UL' ) descendant.style.display = 'block';//表示
    } while( descendant.nodeName != 'BODY' )//親がBODYならやめる
    
    if( !flag ){//今度はLIの中のULを開くかどうか?
     var nd = li[i].firstChild;
     while( nd ){
      if( nd.nodeName == 'UL' ) nd.style.display = 'block';//ULタグが見つかったら表示する
      nd = nd.nextSibling;//次のエレメント(兄弟を探す)
     }
    }
   }
  }
 }
 element.style.display = 'block';//対象を開く
}
function getFirstText( element ){//タグで囲まれた中の文字を拾い出す
 var nd = element.firstChild;
 while( nd ){//例えば<span>abc<span> <p>~ 見たいに<p>の前に空白があると#textノードとみなされる。ブラウザによって処理が微妙
  if( nd.nodeName == '#text' ) return nd.nodeValue;
  nd = nd.nextSibling;
 }
 return false;
}
function getChildDisplay( element ){//今回の場合LI要素の中のUlが開いていれば1、閉じていれば0を返す
 var child = element.firstChild;
 while( child ){
  if( child.nodeName == 'UL') if( child.style.display == 'block') return 1;
  child = child.nextSibling;
 }
 return 0;
}
function addEvent(elementId, evt, eventHandler, flag){//イベント追加処理/cc_onは、IEだけが実行される。最近はこれが主流?
 var element = ( typeof( elementId ) == 'string' )? document.getElementById( elementId ): elementId;
 element./*@cc_on @if(1)attachEvent('on'+ @else @*/addEventListener(/*@end@*/evt, eventHandler, flag);
}
function getCookie( valueName ){//クッキーを得る
 var value = '', c, cookies = document.cookie.split('; ');
 for(var i in cookies)
  if((c = cookies[i].split(/=/), c[0]==valueName)) return c[1]? decodeURIComponent( c[1] ): '';//文字をそのまま保存するとやばいのでエスケープ処理
 return false;
}
function putCookie( valueName, value, day ){//クッキーの保存、保存期間は日単位
 document.cookie = valueName + '=' + encodeURIComponent( value )+ '; expires='
  + new Date( (new Date).getTime() + day * 86400000).toGMTString();
}
</script>
</body>
</html>
    • good
    • 0
この回答へのお礼

とても丁寧にありがとうございます!
無知故に苦労しましたが、お陰でなんとかやりたかったデザインに組み込むことができました。

重ねて質問なのですが、
>if(1) openTreeMenu2('a'); //1なら対象外は隠す。メニューの折りたたみに好みがあるみたいなので0か1を指定
↑この値を0の「対象外も隠さない」設定にしたあと、メニューを複数開く場合、クッキーの保存が最後に開いたもののみになるようですが(メニューAを開き、そのあとBも開く→飛んで戻ってくる→Bしか開いていない という状態です)、
「複数開いた」ことを保存させるようにする事はできますか?
(AもBも開いたら、AもBも開いたままにしておきたいです)

しつこく聞くようで申し訳ないのですが、ご回答いただければ幸いです。

お礼日時:2008/11/26 02:00

遅くなりました!なんとなくカレンダーを作るのにハマってました!


まじめに作ると長いね~。補足説明は、これが記憶にあるうちにね!
字下げするために全角スペースにしました。タブとかに置きかえして
使用のこと。スクリプトとスタイルシートは外部に。

<html>
<body>
 <ul id="a">
  <li>A
   <ul>
    <li><a href="htp://blove.cc/tes1/">A-1</a></li>
    <li>A-2
     <ul>
      <li><a href="htp://blove.cc/tes1/">ページ1へ飛ぶ</a></li>
      <li><a href="htp://blove.cc/tes2/">ページ2へ飛ぶ</a></li>
     </ul>
    </li>
    <li>A-3
     <ul>
      <li><a href="htp://blove.cc/tes1/">ページ1へ飛</a></li>
      <li><a href="htp://blove.cc/tes2/">ページ2へ飛ぶ</a></li>
     </ul>
    </li>
   </ul>
  </li>
  <li>b
  <ul>
   <li><a href="htp://blove.cc/tes1/">ページ1へ飛ぶ</a></li>
   <li><a href="htp://blove.cc/tes2/">ページ2へ飛ぶ</a></li>
  </ul>
  </li>
 </ul>

<script>
addEvent( window,'load', function(){ openTreeMenu2('a') });
addEvent( document.body, 'click', chkClick );

function chkClick( evt ){
 var element = evt.target || event.srcElement; if( element.tagName != 'LI' ) return;
 putCookie( 'li', getFirstText( element ),10);
 putCookie( 'lic', getChildDisplay( element ),10);
 if(1) openTreeMenu2('a'); //1なら対象外は隠す
 else {
  var ul = element.firstChild;
  while( ul.nodeName != 'UL' ){ ul = ul.nextSibling; if( !ul ) return }
  ul.style.display = ( ul.style.display == 'none') ? 'block':'none';
 }
}
function openTreeMenu2( elementId, keyword, flag ){
 var element = ( typeof( elementId ) == 'string' )? document.getElementById( elementId ): elementId;
 var ul = element.getElementsByTagName('ul');
 for( var i=0, m= ul.length; i<m; i++) ul[i].style.display = 'none';
 keyword = keyword || getCookie('li');
 flag = flag || getCookie('lic') - 0;
 if( keyword ) {
  var li = element.getElementsByTagName( 'li' );
  for( var i=0, m=li.length;i<m;i++){
   if( getFirstText( li[i] ) == keyword ){
    
    var descendant = li[i];
    do {
     var descendant = descendant.parentNode;
     if( descendant.nodeName == 'UL' ) descendant.style.display = 'block';
    } while( descendant.nodeName != 'BODY' )
    
    if( !flag ){
     var nd = li[i].firstChild;
     while( nd ){
      if( nd.nodeName == 'UL' ) nd.style.display = 'block';
      nd = nd.nextSibling;
     }
    }
   }
  }
 }
 element.style.display = 'block';
}
function getFirstText( element ){
 var nd = element.firstChild;
 while( nd ){
  if( nd.nodeName == '#text' ) return nd.nodeValue;
  nd = nd.nextSibling;
 }
 return false;
}
function getChildDisplay( element ){
 var child = element.firstChild;
 while( child ){
  if( child.nodeName == 'UL') if( child.style.display == 'block') return 1;
  child = child.nextSibling;
 }
 return 0;
}
function addEvent(elementId, evt, eventHandler, flag){
 var element = ( typeof( elementId ) == 'string' )? document.getElementById( elementId ): elementId;
 element./*@cc_on @if(1)attachEvent('on'+ @else @*/addEventListener(/*@end@*/evt, eventHandler, flag);
}
function getCookie( valueName ){
 var value = '', c, cookies = document.cookie.split('; ');
 for(var i in cookies)
  if((c = cookies[i].split(/=/), c[0]==valueName)) return c[1]? decodeURIComponent( c[1] ): '';
 return false;
}
function putCookie( valueName, value, day ){
 document.cookie = valueName + '=' + encodeURIComponent( value )+ '; expires='
  + new Date( (new Date).getTime() + day * 86400000).toGMTString();
}
</script>
</body>
</html>
    • good
    • 0

参考にした!っていうより


書いたプログラムを見せていただいたほうが早い。

「javascriptオフでも見れる」というのであれば
逆に考えて、スクリプトが実行できるなら、
読み込みが終わった時点でメニューを折りたためば?
    • good
    • 0
この回答へのお礼

引き続き回答ありがとうございます。
参考にした、というかそのまま当てはめただけなので…

<script type="text/javascript" language="javascript">
document.writeln("<style type=\"text/css\">");
document.writeln("#ほにゃらら{display:none;}");
document.writeln("<\/style>");
</script>

をhead内に入れて、メニューの部分を、

<span onclick="this.nextSibling.style.display=(this.nextSibling.style.display=='block'?'none':'block');">
メニュー名</span>
<div id="ほにゃらら">
<a href="該当URL">項目1</a><br>
<a href="該当URL">項目2</a><br>
</div>

という風に書きました。本当にそのままですが…
これならjavascriptを切ると同時にdisplay:noneも無効になってくれそうな事が理解できたので使いたいと思ったのです。

>「javascriptオフでも見れる」というのであれば
>逆に考えて、スクリプトが実行できるなら、
>読み込みが終わった時点でメニューを折りたためば?
そんな事ができるのですか!
過去の質問でpipi様が回答されていたプログラムを参考に「クッキー保存させるツリーメニュー」を作成して、それを「読み込みが終わった時点でメニューを折りたたむ」ように改変、もしくは書き足しする、という事でいいのでしょうか。
お恥ずかしながらまだ、javascriptの何がどうなっているのかもわからないもので、どこをどのように弄ればそのようにプログラムすることができるのか、よろしければ教えていただきたいです。

お礼日時:2008/11/23 04:10
    • good
    • 0
この回答へのお礼

他の回答も一応見たのですが、
「javascriptオフでも見れる」という条件に合うものかどうかわからなかったので質問させていただきました。
display:noneをcssで指定するだけでは、cssがオンでjsがオフな時ツリー開きませんよね?
今回私が参考にしている方法で作ったツリーメニューをcookieに保存させる事はできないのでしょうか。

お礼日時:2008/11/21 00:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!