• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:onclickを使わずにイベント処理をする方法について。)

オンクリックイベントを使わずにイベント処理をする方法

このQ&Aのポイント
  • オンクリックイベントを使用せずに、特定の要素をクリックすると表示/非表示を切り替えるイベント処理を実装する方法について説明します。
  • 現在のコードに問題があり、IEで動作しないため、書き直す必要があります。
  • 制約があるため、class属性を使用して特定の要素を選択することが必要です。

質問者が選んだベストアンサー

  • ベストアンサー
  • think49
  • ベストアンサー率59% (285/482)
回答No.11

>> #9 yuu_xさん なるほど…。スタイルシートのルールを書き換えればいいんですね! 質問者さんの動作確認環境はIE7以上だから、兄弟セレクタが使える、と。 (全角空白を半角空白に置換してください) <script type="text/javascript"><!-- (function(){  var styleSheets = this.document.styleSheets;  var lastStyleSheet = styleSheets[styleSheets.length - 1];  try{   lastStyleSheet.insertRule('.text + p { display: none; }', lastStyleSheet.cssRules.length);  } catch(e){   lastStyleSheet.addRule('.text + p', 'display: none;', -1);  } })(); //--></script> stylesheet.insertRule - MDC https://developer.mozilla.org/En/DOM/Stylesheet.insertRule document.styleSheets https://developer.mozilla.org/ja/DOM/document.styleSheets CSSStyleSheet Prototype (style) http://msdn.microsoft.com/en-us/library/dd347054%28v=VS.85%29.aspx addRule Method (styleSheet, CSSStyleSheet Constructor) http://msdn.microsoft.com/ja-jp/library/aa358796%28v=VS.85%29.aspx Javascript cssRules - とみぞーノート http://wiki.bit-hive.com/tomizoo/pg/Javascript%20cssRules # 最後に質問者さんにアドバイス。 質問当初に知らないことがあるのは別にいいんですが、回答をもらってそこかしこにある知らないキーワードをGoogle検索してみたり、MDCの資料に目を通したり、Firebugで検証したり…、といろいろやった方が自分のためになると思います。 それから再質問すれば、質問が具体的になって回答も寄せられやすくなると思いますよ。 実際、私も調べながら回答しています。(このスレッドが立つ前から、ここに書いたことを全部知っていたわけではありません)

agonigiri
質問者

お礼

think49様、ありがとうございます。 仰る通りです。結果を急いでしまいました。 情報不足の中、何度も相談しお手数をおかけしました。 MDCやFirebugという言葉も知りませんでした。。!本当に勉強になります。 期日にも余裕が出たので、ひとつひとつ分からない点をじっくり勉強したいと思います。 今回はこれにて締め切らせていただきます。 有難うございました!

その他の回答 (10)

  • think49
  • ベストアンサー率59% (285/482)
回答No.10

#4,5,7,8 です。 以下、#8の補足より引用。 > 以前のご回答と今回のご回答を両方参考にすれば実現可能でしょうか? ヒントは十分に出ていると思います。

agonigiri
質問者

お礼

了解です!

  • yuu_x
  • ベストアンサー率52% (106/202)
回答No.9

... click が抜けとる。いぁ、しょーもないことで、連投して申し訳ない。 [javascript] /*@cc_on@*/ document./*@if(1)attachEvent('on'+@else@*/addEventListener(/*@end@*/'click', function(ev) { var t = ev./*@if(1)srcElement@else@*/target/*@end@*/; if (t.tagName === 'H1' && /(?:^|\s)text(?:\s|$)/.test(t.parentNode.className)) { while ((t = t.nextSibling) && t.tagName !== 'P'); t && (t.style.display = t.style.display === 'block' ? 'none' : 'block'); } }, false); document.write('\u003Cstyle type="text/css"\u003E.text p{display:none;}\u003C/style\u003E'); [/javascript] > 初期に本文を非表示にしたいのでしたら、JavaScriptで display:none; にするのが賢いと思います。 ん~、、、これね、、、該当要素をぐるぐる回すのも嫌だから、分かりきってる場合は、上でいいよ。 特定クラスに限定するなら、スタイルシートを書き換えるのが筋だけど、結局ぐるぐる回さなきゃならない。しかも判定が面倒。StyleSheet API にも、querySelector がほしい。

agonigiri
質問者

お礼

いえいえ、丁寧に有難うございます。 私の方こそ質問を続けてばかりで申し訳ないです。 document.writeでcssを書く方法もありましたね・・! bodyタグはいじれないし、onloadをどう書くか…でまたはまってしまっていました;;

  • think49
  • ベストアンサー率59% (285/482)
回答No.8

#4,5,7です。 以下、#5の補足より引用。 > 外部cssでdisplay:noneにしてしまうとjavaScriptで上書き出来ないようです。 > yuu_x様の外部css参照を使えば、実現出来るのでしょうか。 #3でyuu_xさんが紹介された getComputedStyle(currentStyle) は #5 のコードでも使われています。 しかし、そんなこととは関係なく、JavaScriptでしか使われない display:none; を外部CSSで指定するのは好ましくないと思います。 以下、いわゆる「アコーディオンメニュー」を実装する場合で「初期に内容を表示したくない」という前提で書きますが。 下記コードを試してみてください。(全角空白を半角空白に置換してください) ------- <style type="text/css"><!-- p {  display: none; } --></style> <script type="text/javascript"><!-- function test(event){  var target = event.target || event.srcElement;  var p = target.parentNode.getElementsByTagName('p').item(0);  p.style.display = (p.style.display === 'none') ? 'block': 'none'; } //--></script> </head> <body> <div> <h1 class="text" onclick="test(event);">見出し</h1> <p>本文</p> </div> ------- これはアコーディオンメニューのサンプルとして、よく見られるコードです。 期待通りに動作してくれているように見えますが、スタイルシート、JavaScriptの両方が有効でないと動きません。 CSSが有効でJavaScriptが無効なブラウザで閲覧したとすると、アコーディオンは正しく働かず、「JavaScriptを有効にしない限りは本文を表示できない」という事態になります。 ですので、初期に本文を非表示にしたいのでしたら、JavaScriptで display:none; にするのが賢いと思います。 ------- <script type="text/javascript"><!-- function test(event){  var target = event.target || event.srcElement;  var p = target.parentNode.getElementsByTagName('p').item(0);  p.style.display = (p.style.display === 'none') ? 'block': 'none'; } function init(event){  var doc = event.target || document;  var text = doc.querySelectorAll('.text'); // for Gecko/Webkit/Opera/IE8 (IE7以下は動作しません)  var p;  for(var i=0,l=text.length; i<l; i++){   p = text[i].parentNode.getElementsByTagName('p').item(0);   p.style.display = 'none';  } } //--></script> </head> <body onload="init(event);"> <div> <h1 class="text" onclick="test(event);">見出し</h1> <p>本文</p> </div> ------- JavaScriptが無効であれば、アコーディオンが働かず、全ての内容が表示されます。 JavaScriptが有効であれば、アコーディオンが働き、初期の本文は非表示になります。

agonigiri
質問者

お礼

think49様更なるご回答ありがとうございます。 >#3でyuu_xさんが紹介された getComputedStyle(currentStyle) は #5 のコードでも使われています。 なるほど!チェック不足でした。 >JavaScriptでしか使われない display:none; を外部CSSで指定するのは好ましくないと思います。 >「JavaScriptを有効にしない限りは本文を表示できない」 はい、特に後者はユーザを限定してしまう点で今回の制作条件からアウトになってしまいます。 h1にonclickをつけずに実装するには、 以前のご回答と今回のご回答を両方参考にすれば実現可能でしょうか?

  • think49
  • ベストアンサー率59% (285/482)
回答No.7

#4,5 です。 「cssTextをreplaceする」って手もありますね。 これなら全てのスタイルを削除しなくてすみますし、実装依存なコードではないので、最悪catchで拾えます。 <script type="text/javascript"> <!-- document./*@cc_on @if(@_jscript_version <= 5.8) attachEvent('on' + @else @*/addEventListener(/*@end @*/ 'click', function(event){  var h1 = event.target || event.srcElement;  var p, style;  if(h1.nodeName !=='H1' || (' '+h1.className+' ').indexOf(' text ') === -1){ return false; }  p = h1.parentNode.getElementsByTagName('p').item(0);  if(p.style.display !== 'none'){   p.style.display = 'none';  } else {   try{ // for Gecko/Webkit/Opera    p.style.removeProperty('display');   } catch(e) { // for IE    p.style.cssText = p.style.cssText.replace(/(^|[ ;])display *: *none(?: *;|$)/i, '$1');   }  } }, false); //--> </script> >> #6 yuu_xさん > IE の場合、属性名 ではなく、プロパティ名を使ってるから、きっとそのせいだろうね。 多分、そうですね…。 自分から書いておいて何ですが、element.style.removeAttribute() はやっぱりお勧めしがたいコードに思えてきました。 問題はIEがWeb標準に準拠し始めているってことだと思います。 例えば、IE9から addEventListener() に対応しますが、同じ流れで「removeAttribute() の対象がプロパティ」というバグ(仕様?)も修正されるかもしれません。 すると、こういう可能性もありえます。 // IE9がやってくる try{  child.style.removeProperty('display'); // IE9は removeProperty() に対応しないので、catchへ } catch(e) {  child.style.removeAttribute('display'); // removeAttribute() の対象が属性ではないので、シンタックスエラー! } IE9が中途半端な実装をしなければ起こりえないことではありますが…。

agonigiri
質問者

お礼

IE9まで考えないといけないなんて… cssだけでなくJavaScriptも…! 生半可な知識でJavaScript書けないですね。後々怖いです。

  • yuu_x
  • ベストアンサー率52% (106/202)
回答No.6

なんてこった。まだあった。 [javascript] while (t && t.nodeType !== 1) t = t.nextSibling; t && (t.style.display = t.style.display === 'block' ? 'none' : 'block'); } [/javascript] ↓ [javascript] while ((t = nextSibling) && t.nodeType !== 1); t && (t.style.display = t.style.display === 'block' ? 'none' : 'block'); } [/javascript] > なぜか element.style.removeAttribute('display') が有効なIEの仕様 IE の場合、属性名 ではなく、プロパティ名を使ってるから、きっとそのせいだろうね。 IE の場合、無理に標準化するより、まったく別に書いたほうが、と思っている今日この頃。 2度同じものを書かなきゃいけないのは手間だけど、欠点はそれくらいで、利点のが大きい気がする。

agonigiri
質問者

お礼

yuu_x様沢山の回答ありがとうございます。 取り急ぎのお礼になりますが、後日全ての回答をもとに勉強させていただきます。

  • think49
  • ベストアンサー率59% (285/482)
回答No.5

#4です。 #4では(いわゆる)クロージャを取り上げましたが、クロージャに各々の要素のデフォルトスタイルを保持するのは難しそうなので、className に保持してみました。 以下、全角空白は半角空白にしてください。 <script type="text/javascript"> <!-- /*@cc_on @if(@_jscript_version <= 5.8) attachEvent('on' + @else @*/addEventListener(/*@end @*/ 'load', function(event){  var doc = event.target || document;  var text = doc.querySelectorAll('.text') || doc.getElementsByClassName('.text'); // IE6を踏まえるなら、この部分は getElemensByTagName() で得るなど適宜修正してください。  var p, defaultDisplay;  for(var i=0,l=text.length; i<l; i++){   p = text[i].parentNode.getElementsByTagName('p').item(0);   defaultDisplay = doc.defaultView ? doc.defaultView.getComputedStyle(p, '').display : p.currentStyle.display;   p.className += ' defaultDisplay_'+defaultDisplay;  } }, false); document./*@cc_on @if(@_jscript_version <= 5.8) attachEvent('on' + @else @*/addEventListener(/*@end @*/ 'click', function(event){  var h1 = event.target || event.srcElement;  var p, className;  if(h1.nodeName !=='H1' || (' '+h1.className+' ').indexOf(' text ') === -1){ return false; }  p = h1.parentNode.getElementsByTagName('p').item(0);  if(className = (' '+p.className+' ').match(/ defaultDisplay_(\w+) /)){   if(p.style.display !== 'none'){    p.style.display = 'none';   } else {    p.style.display = className[1];   }  } }, false); //--> </script>

agonigiri
質問者

お礼

丁寧に有難うございます。組み込んでみたところ、IEで表示/非表示することができました。 感動です!! 記入し忘れていましたが、<p>の内容は初期非表示にしたく、現在試行錯誤中です。 外部cssでdisplay:noneにしてしまうとjavaScriptで上書き出来ないようです。 yuu_x様の外部css参照を使えば、実現出来るのでしょうか。 あと1歩頑張ります。。。 厚かましいですがもしアドバイス頂けましたら嬉しいです。

  • think49
  • ベストアンサー率59% (285/482)
回答No.4

removeProperty() の代替策としては、 ・element.style.cssText=''; や element.removeProperty('display'); で上書きする ・clickを定義する前に、getComputedStyle(IEはcurrentStyle)でデフォルトのスタイルを読み込み、クロージャが保持する変数等に保持しておく ・なぜか element.style.removeAttribute('display') が有効なIEの仕様を利用する (実装依存) 以下、全角空白は半角空白にしてください。 <script type="text/javascript"> <!-- document./*@cc_on @if(@_jscript_version <= 5.8) attachEvent('on' + @else @*/addEventListener(/*@end @*/ 'click', function(event){  var h1 = event.target || event.srcElement;  var doc, child, childs;  if(h1.nodeName !=='H1' || (' '+h1.className+' ').indexOf(' text ') === -1){ return false; }  doc = h1.ownerDocument;  childs = h1.parentNode.childNodes;  for(var i=0,l=childs.length; i<l; i++){   child = childs[i];   if(child.nodeName === 'P'){    if(child.style.display !== 'none'){     child.style.display = 'none';    } else {     try{ // for Gecko/Webkit/Opera      child.style.removeProperty('display');     } catch(e) { // for IE      child.removeAttribute('style'); // ただし、styleが保持する全てのプロパティを全てを削除する //     child.style.cssText = ''; // 同上 //     child.style.removeAttribute('display'); // IEの仕様を利用した実装依存     }    }   }  } }, false); //--> </script> cssRule.cssText - MDC https://developer.mozilla.org/en/DOM/cssRule.cssText getComputedStyle - MDC https://developer.mozilla.org/ja/DOM/window.getComputedStyle currentStyle http://msdn.microsoft.com/ja-jp/library/ms535231%28VS.85%29.aspx 掲示板/スタイルシート質問板/テキストボックスのスタイル初期化 - TAG index Webサイト http://www.tagindex.com/cgi-lib/q3bbs/patio.cgi?mode=view&no=1373

agonigiri
質問者

お礼

回答ありがとうございます。 大変参考になります! クロージャという言葉、初めて聞きました。 JavaScript、奥が深いです。

  • yuu_x
  • ベストアンサー率52% (106/202)
回答No.3

抜けがあった。 [javascript] /*@cc_on@*/ document./*@if(1)attachEvent('on'+@else@*/addEventListener, function(ev) { var t = ev./*@if(1)srcElement@else@*/target/*@end@*/; if (t.tagName === 'H1' && t.parentNode.tagName === 'DIV' && /(?:^|\s)text(?:$|\s)/.test(t.parentNode.className)) { while (t && t.nodeType !== 1) t = t.nextSibling; t && (t.style.display = t.style.display === 'block' ? 'none' : 'block'); } }, false); [/javascript] > onclickを使わずに [CSS] .text > h1 + p { display : none; } .text:hover > h1 + p { display : block; } [/CSS] 結局 IE では、使えないけどね。 ついで。 [javascript] next.style.display === 'block' ? (next.style.display = 'none') : (next.style.display/*@if(1) = ''@else@*/.removeProperty('display')/*@end@*/; [/javascript] # removeProperty をちゃんと使ってるコードを久しぶりに見た気がする。 ちなみに、style プロパティはインラインスタイルを参照するので、外部 CSS の設定を取得する場合は、getComputedStyle(currentStyle)

agonigiri
質問者

お礼

cssで実現出来たら気持ちいいんですが、またIEの壁がありますね。。。;; 外部スタイルの参照、勉強になります!

  • yuu_x
  • ベストアンサー率52% (106/202)
回答No.2

IE は removeProperty 持ってないから、強引に書くしかないんでない。

agonigiri
質問者

お礼

有難うございます!IEで使えないコード、沢山あるのですね。

  • yuu_x
  • ベストアンサー率52% (106/202)
回答No.1

var listener = function(ev){ var t = ev./*@if(1)srcElement@else@*/target/*@end@*/; if (t.tagName === 'H1' && t.parentNode.tagName === 'DIV' && /(?:^|\s)text(?:$|\s)/.test(t.parentNode.className)) { while (t && t.nodeType !== 1) t = t.nextSibling; t && (t.style.display = t.style.display === 'none' ? 'block' : 'none'); } };

agonigiri
質問者

お礼

丁寧な回答ありがとうございます! 現在試行錯誤中です…。解決しましたら、改めてご回答させていただきます。

関連するQ&A