アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんにちは。
https://oshiete.goo.ne.jp/qa/8966803.html で質問したものです。
回答者様No.2の fujillin様のご回答で下記を頂きました。

////////////////////
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head><title>sample</title>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">

<script type="text/javascript">

//読込先のURLデータ(複数化できるように)
var urls = {
 fuga : "fugafuga.html"
}

//クリック時の処理関数
function hoge(e, id){
 var elm = document.getElementById(id);
//対象要素が存在しなければ何もしない
 if(!elm) return;

 var obj = elm.getElementsByTagName("iframe");

//「表示」処理
 if(e.value == "表示"){

//  すでに読み込んでいる場合(CSSで表示する)
  if(obj.length){
   obj[0].style.display = "block";
   statusSet("非表示→表示");
  }

//  最初に読み込む場合(要素を追加する)
  else {
   var o = document.createElement("iframe");
   o.src = urls[id];
   elm.appendChild(o);
   statusSet("要素作成、読込み");
  }
  e.value = "隠す";
 }

//「隠す」処理
 else {
  obj[0].style.display = "none";
  e.value = "表示";
  statusSet("表示→非表示");
 }

//動作状況表示用(本来は不要です)
 function statusSet(str){
  var c, elm = document.getElementById("message");
  while(c = elm.firstChild) elm.removeChild(c);
  elm.appendChild(document.createTextNode(str));
 }
}
</script>
</head>

<body>
<div>
<input type="button" onclick="hoge(this, 'fuga')" value="表示">
&emsp;【 状態 】 <span id="message">初期状態</span>
</div>

<div id="fuga"></div>

</body>
</html>
////////////////////
思っていたことはこれで適いましたが、JavaScriptを外部.jsに入れることがどうしても出来ませんでした。<script>内を全て外部.jsへ入れましたがダメでした。

また、提示された方法はボタンをクリックなのですが、私は
<a href="~">開くにはここをクリック</a>
みたいにしてやりたいです。

これの方法として試したのは、
<div>
<a href="JavaScript:hoge(this, 'fuga');" id="開くにはここをクリック" value="開くにはここをクリックラ">&emsp;【 状態 】 <span id="message">開くにはここをクリック</span></a>
</div><div id="fuga"></div>
などいろいろ試したのですが、どうしてもボタンではないためか、関数呼び出しが出来ませんでした。また、thisの使い方も検索したのですが判りませんでした。
そもそも外部ファイルの関数にした場合、thisでもOKなものなのか…?


お分かりの方、御教示願えないでしょうか?
よろしくお願いいたします。

質問者からの補足コメント

  • 外部ファイル.jsに関数を書いて参照することは出来ました。

    後は、ボタンではなく
    <a href="~">開くにはここをクリック</a>
    をクリックして出したいです。

      補足日時:2015/05/02 19:40
  • fujillinさん、お忙しいところ再度のご回答ありがとうございます。

    今現在、ちょっと手が離せないので明日辺り試してみます。
    それまでお待ち下さい。申し訳ございません。

    No.1の回答に寄せられた補足コメントです。 補足日時:2015/05/07 16:51
  • iframeにclassを追加したくて、前回の質問でご提示頂いたJavaScriptに
    // 最初に読み込む場合(要素を追加する)
    else { //alert("ようこそ23!");
     var o = document.createElement("iframe");
     o.setAttribute('class','the_class_name');
     o.className = 'the_class_name';
     o.src = urls[id];
     elm.appendChild(o);
     }
     e.value = "閉じる";
    }
    とsetAttributeとclassNameを追加したのですが、どうも1回目の”開く”だと表示されません。alertや”閉じる”と言うへの変化などからelseには入っているのですが。

    No.2の回答に寄せられた補足コメントです。 補足日時:2015/05/09 15:01
  • すいません。直前のclassの追加、できました。
    どうもcssにdisplay:none;が設定してあったから最初は非表示で、2回目の時はdisplay:block;が明示してあったからOKになったみたいです。

    はやとちりですみません。

      補足日時:2015/05/09 15:10

A 回答 (3件)

ANo2です




>複数の関数化が必要と思うのですが、関数化した場合、
>  ~~~~~
>として、呼び出し側ではどう関数を呼び出したら良いでしょうか?
hogehoge.js全体を一つの関数化して(匿名関数でもOK)、それぞれの関数内で、hoge、fuga、status等を定義するようにして実行すれば可能です。(No2は一個限定なのでグルーバル変数にしているものを個別に定義するため)
対象が2~3箇所であるなら、個々に設定しても大したことはないでしょうが、多くなってくると一括で処理できる方が便利ですよね。
その際には、「クリックされた要素」、「対象とする要素」、「URL」などを特定できるような仕組みが必要となります。最初の回答は、多少それを意識したものでした。
(thisはクリック要素、idが対象要素、urlsがurlの連想配列などになっていました)

基本的にクリックイベントの発生時の処理として記述していますが、前回はHTML内に「onclick="~~"」を記述することで行っていましたが、ANo2ではスクリプト内からイベント設定を行っています。
 trigger.onclick = function(){ ~~ }
がこれにあたります。


ご質問文からは実際の使われ方がよくわからなかったので(HTML構成や複数あるのかなどなど)、手探りで(適当に)例として作成していました。
HTMLの構成にある程度のルールを決められれば、this値やidを使用しなくとも特定できるようになるので、スクリプトが多少複雑になっても、HTMLを単純化することが可能になります。
また、変更が生じる毎にスクリプトを書き直さねばならないとか、ページ毎にjsファイルを作成しなければならないという不便さも解消できます。
できるだけ個別の情報はHTML側に記載して、一般化した処理をスクリプトで行うようにしておく方が再利用しやすくなるでしょう。

何度か説明を頂いて、だいたいの雰囲気が分かってきましたのが、勝手に想定しましたが、下記のようなものが良いのかも知れません。


おまけ
>trigger.innerHTML = status==1?str[1]:str[0];
>などという書き方は意味不明
「条件演算子(三項演算子)」と言われるもので、上記の例で言えば
 if(status==1) trigger.innerHTML = str[1];
  else trigger.innerHTML = str[0];
と等価です。
https://developer.mozilla.org/ja/docs/Web/JavaSc …



【構文ルール】
基本構成を以下のようなものにしています。
 <div class="linkLoader">
  <a class="open" href="piyopiyo.html">開く</a>
  <a class="close" href="#">閉じる</a>
  <div class="showbox"></div>
 </div>
※ クラスlinkLoader要素を単位として、.open、.close、.showboxを設置
※ .open、.closeはA要素で、表示用の文字列は個別に記述できます
※ .openをクリックすると.showbox内にiframeが生成され(最初のみ)
  A要素のhref属性が参照するurlを意味します
※ 要素の位置関係は.linkLoader内であれば自由。階層が変わってもOK。
※ linkLoaderどうしや他のクラスもネストすることはできません

【HTML(サンプル)】
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head><title>sample</title>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<style type="text/css">
.linkLoader .showbox iframe{ width:100%; height:300px; }
</style>
</head>

<body>
<div class="linkLoader">
日経新聞
<a class="open" href="http://www.nikkei.com/">開く</a>
<a class="close" href="#">閉じる</a>
<div class="showbox"></div>
</div>

<div class="linkLoader">
読売新聞
<a class="open" href="http://www.yomiuri.co.jp/">表示</a>
<a class="close" href="#">隠す</a>
<div class="showbox"></div>
</div>

<div class="linkLoader">
朝日新聞
<a class="open" href="http://www.asahi.com/">オープン</a>
<a class="close" href="#">クローズ</a>
<div class="showbox"></div>
</div>

<script type="text/javascript" src="hogehoge.js"></script>
</body>
</html>


【hogehoge.js】
(全角空白は半角に)
(function(){
 var clsCheck = function(e, c){
  return new RegExp("(^| )" + c + "( |$)").test(e.className);
 }

 var searchLoader = function(e){
  while(e && !clsCheck(e, "linkLoader")) e = e.parentNode;
  return e;
 }

 var dispControl = function(e, sel, disp){
  var i, e, elms = e.querySelectorAll(sel);
  for(i = 0; e = elms[i++];) e.style.display = disp;
 }

 var handler = function(evt){
  var t = evt.target || evt.srcElement;
  if(t.nodeName != "A") return;
  var e = searchLoader(t);
  if(!e) return;

  if(clsCheck(t, "open")){
   var box = e.querySelector(".showbox");
   if(!box) return;
   if(!box.querySelector("iframe")){
    var frm = document.createElement("iframe");
    frm.src = t.href;
    box.appendChild(frm);
   }
   box.style.display = "block";
   dispControl(e, ".open", "none");
   dispControl(e, ".close", "inline");

  } else if(clsCheck(t, "close")){
   dispControl(e, ".close", "none");
   dispControl(e, ".showbox", "none");
   dispControl(e, ".open", "inline");
  }
  if(evt.preventDefault) evt.preventDefault(); else evt.returnValue = false;
 }


 dispControl(document, ".linkLoader .close", "none");
 dispControl(document, ".linkLoader .showbox", "none");
 if(document.addEventListener) {
  document.addEventListener('click', handler, false);
 } else if(document.attachEvent) {
  document.attachEvent('onclick', handler);
 }
})();
    • good
    • 0
この回答へのお礼

fujillinさん、
再度のご回答本当にありがとうございます。

このサンプルすごいですね。明示的にJavaScriptの関数を呼び出しているとは思えないのですが。傍目にはただ単にclassで就職していてdivもあるだけに思える…。

JavaScriptってすごい!もちろんfujillinさんもです!何度もお時間をかけてのご回答本当に嬉しいです!

是非使わせて下さい!

ありがとうございました!!!

お礼日時:2015/05/12 02:10

ANo1です。



記述法を直截にして単純化しました。thisも不使用です。
(1箇所限定です)


 【 HTML 】
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head><title>sample</title>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>

<div>
<a href="#" id="hoge">開く</a>
<div id="fuga"></div>
</div>

<script type="text/javascript" src="hogehoge.js"></script>
</body>
</html>



 【 hogehoge.js 】
var trigger = document.getElementById("hoge");
var target = document.getElementById("fuga");
var targetUrl = "http://www.goo.ne.jp/";
var str = ["開く", "閉じる"];
var status = 0;

trigger.onclick = function(){
if(status == 0) target.innerHTML = "<iframe src='" + targetUrl + "'></iframe>";
else if(status == 1) target.style.display = "none";
else { status = 2; target.style.display = "block"; }

status = status % 2 + 1;
trigger.innerHTML = status==1?str[1]:str[0];
return false;
}
この回答への補足あり
    • good
    • 0
この回答へのお礼

fujillinさん、
再度のご回答ありがとうございます!
No.1の最初のご回答「ボタンのボタンじゃない化」、すごいですね。こんなCSS知りませんでした!とても手軽で良いなと思いました。私のサイトでは複数のページを「~~ここをクリック~~」で呼び出しているので、そうするのには
var urls = {
 uga0 : "sample0.html";
 uga2 : "sample1.html";
}
の様にすれば良いでしょうか?

No.1の後半の「どうしても、マークアップがリンク要素である必要があるのなら…」ですが、もし完璧であるならばこの様なものがいいです。
node.textContent || node.innerText の利用とか難しいですね。
私の頭の中の言語はかなり厳密で、JavaScriptは奔放という感じがしているので勉強が必要です。またスレを立てさせて下さい。

---------------------------

No.2のご回答ですが、素晴らしく完結ですね!
これ、「Googleはここをクリック」、「Yahooはここをクリック」と1ページに複数ある場合で1つの.jsファイルに記述したい場合は複数の関数化が必要と思うのですが、関数化した場合、
function kansuu0{
 ~~ご提示の内容で、var targetUrl = "http://www.google.com/";
}
function kansuu1{
 ~~ご提示の内容で、var targetUrl = "http://www.yahoo.co.jp/";
}
として、呼び出し側ではどう関数を呼び出したら良いでしょうか?

---------------------------

勉強していると面白いですね!ただ本当に厳密な私の頭の中では、
trigger.innerHTML = status==1?str[1]:str[0];
などという書き方は意味不明…頭固いですね…すみません。

本当にありがとうございました!!!

お礼日時:2015/05/09 10:48

こんにちは。

 前回答者です。


>JavaScriptを外部.jsに入れることがどうしても出来ませんでした。
そのままタグ内(タグは不要)を外部ファイル化して、読み込めば動作するはずです。
 https://www.google.co.jp/search?q=CSS+font-size& …

>また、提示された方法はボタンをクリックなのですが、私は
><a href="~">開くにはここをクリック</a>
>みたいにしてやりたいです。
見た目がリンク表示の様に見えれば良いのであれば、CSSで…
input[type=button] {
border:none;
font-size:medium;
color: blue;
text-decoration:underline;
background-color:white;
cursor:pointer;
}
のようなことではどうでしょうか?

あと、前回答の『 statusSet() 』に関係する部分は、処理の内容が見えるようにするために説明的に付加しているものなので、実際には削除したほうが良いと思います。(コメントにもそう記したつもりでした。)


どうしても、マークアップがリンク要素である必要があるのなら…
呼び出し側を
 <a href="#" onclick="return hoge(this, id);">piyopiyo</a>
などとして、
リンク要素内のテキストを取得するのは、value属性では取得できませんので、
 node.textContent || node.innerText
などを利用してください。(後述のinnerHTMLでも可)
 https://developer.mozilla.org/ja/docs/Web/API/No …
 https://msdn.microsoft.com/ja-jp/library/ms53389 …

テキストを書き換える場合は、例示のstatusSet()でやっているように、createTextNode()でテキスト要素を生成してappend()するか、innerHTMLなどを利用して流し込んでください。
 https://developer.mozilla.org/ja/docs/Web/API/El …

また、リンク要素の場合は、クリックするとスクリプト処理後にブラウザ本来のリンクの処理を行おうとしますので、これをキャンセルするために戻り値としてfalseを返す必要があります。
あるいは、スクリプトからイベントの伝播をキャンセルすることでも良ろしいかと。
 https://developer.mozilla.org/ja/docs/Web/API/Ev …
 https://msdn.microsoft.com/ja-jp/Library/ff97546 …

>また、thisの使い方も検索したのですが判りませんでした。
this値は、示す内容を変えられる便利な(? or わかりにくい?)オブジェクトです。
回答例での場合は、イベントをセットした(=クリックされた)要素になります。
(前回回答ではinput[type=button]、上記リンクの場合はリンク要素)
 https://developer.mozilla.org/ja/docs/Web/JavaSc …


C言語の知識がおありとのことですので、書式やメソッド名は異なるものの、コード化の考え方にはたいして違いはないのではと想像します。(私はC言語を知りませんが…)
この回答への補足あり
    • good
    • 0

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