k01ken’s b10g

He110 W0r1d!

jQueryで詰まった部分

【問題】スクロールした途中で、一番上まで戻るようにする
・id属性がright-bottom-naviの部分をクリックすると上まで戻るようにする。
【解決】

$(function(){
	$('#right-bottom-navi').on('click',function(){
		window.scrollTo(0,0);
	});
});

上記のコードでは一気に上まで行くので、ちょっとずつ上昇するようにするには、以下のようにすると良かった。

$(function(){
	$('#right-bottom-navi').on('click',function(){
          $('html, body').animate({
             scrollTop: 0
          }, 200);
	});
});

animateメソッドが指定しているhtml,bodyの部分は、bodyだけ指定するときちんと動作せず、htmlだけ指定するときちんと動作した。


参考リンク
【jQuery】手っ取り早くScrollToTopを実装する。


【問題】submitボタンでの連続クリックを防止したい
・投稿フォームなどで、連続クリックによる多重投稿を禁止したいと思います。以下のコードを追加しておくことで、クリックしたsubmitボタンのクリックが無効になります。
【解決】

$(function(){
  $('button[type="submit"],input[type="submit"]').on('click',function(){
    $(this).prop('disabled',true);
  });
});

上記のコードだと、chromeではページ遷移しなかったので、調べたところ改善できたので、以下のコードに書き換える。

$(function(){
  $('button[type="submit"],input[type="submit"]').on('click',function(){
    setTimeout(function(){
      $('button[type="submit"],input[type="submit"]').prop('disabled',true);
    },0);
  });
});

参考リンク
ブラウザバックするとボタンが反応しなくなる問題 - Qiita


【問題】親要素や兄弟要素を指定する
【解決】
・指定した要素の親要素を指定する場合は、closest()メソッドを用いる。closest("親要素名や親要素のclass,id属性名")で直近のその要素や属性を指定できる。
・指定した要素の前や後の兄弟要素を指定する場合は、prev()メソッドやnext()メソッドを用いる。prev("直前の兄弟要素名や兄弟要素のclass,id属性名")かnext("直後の兄弟要素名や兄弟要素のclass,id属性名")

・試しに、入力フォーム内にテキストボックスが3つあるけれど、1つだけしか見せない入力フォームを作りたいと思います。余計な情報を見せないでユーザーに情報を入力してもらいやすくするための仕組みです。
HTML側

<form method="post" action="./">
<div class="input_form"><input type="text" placeholder="form1"><input type="button" class="next_form_btn" value="次へ"></div>
<div class="input_form" style="display:none;"><input type="text" placeholder="form2"><input type="button" class="back_form_btn" value="前へ"><input type="button" class="next_form_btn" value="次へ"></div>
<div class="input_form" style="display:none;"><input type="text" placeholder="form3"><input type="button" class="back_form_btn" value="前へ"><input type="submit" value="送信"></div>
</form>

JavaScript

/* headタグ内のscriptタグに */
$(function(){
	$(document).on('click','.next_form_btn',function(){
		$(this).closest(".input_form").css("display","none");
		$(this).closest(".input_form").next(".input_form").css("display","block");
	});

	$(document).on('click','.back_form_btn',function(){
		$(this).closest(".input_form").css("display","none");
		$(this).closest(".input_form").prev(".input_form").css("display","block");
	});

});

実行結果
f:id:k01ken:20180605103700p:plain
参考リンク
closest([expr]) - jQuery 日本語リファレンス
prev([expr]) - jQuery 日本語リファレンス
next([expr]) - jQuery 日本語リファレンス


【問題】class属性を追加/削除する
【解決】
『変更』ボタンをクリックすると、赤い太字に変化し、『元に戻す』ボタンをクリックすると、元に戻ります。
HTML部分

<input type="button" id="btn" value="変更">
<input type="button" id="btn" value="元に戻す">
<div>こんにちは</div>

CSS部分

.test{
	color:red;
	font-weight:bold;
}

jQuery部分

$(function(){
	$('#btn').on('click',function(){
		$('div').addClass("test");
	});

	$('#btn2').on('click',function(){
		$('div').removeClass("test");
	});
});

・class属性は半角スペースで区切って複数指定することができる。
参考リンク
jQueryでclassを追加したり削除する〜addClass,removeClass,toggleClass


【問題】getElementByIdをjQueryで行うには?
【解決】
例えば、testという名前のid属性があったとして、

var id = document.getElementById("test");
// 同じことをjQueryで行う場合
$(function(){
	var id = $("#test")[0];
});

参考リンク
Javascriptでひたすら円を生成し続けるプログラムを書いてみる - Qiita


【問題】特定の要素があるのか調べる方法が知りたい
【解決】
lengthを用いて要素の数を数えてなければ、要素がないと判断します。

$(function(){
	if($("#sample").length){

	}
});

参考リンク
jQueryで特定の要素が存在するかどうかを判別する処理 | BlackFlag
・このサイトで、jQueryのsizeメソッドを使えば同様のことができると書いてありましたが、自分でやってみると、なぜかうまく動作しませんでした。
size() - jQuery 日本語リファレンス


【問題】マウスのdisabled状態(無効化状態)を切り替えるにはどうすれば良いか?
【解決】
※trueで無効化、falseで無効化解除なので間違えないように!

// 無効化状態にする
$("#btn").prop('disabled',true);
// 無効化状態を解除する
$("#btn").prop('disabled',false);

参考リンク
jQueryのprop()でdisabled属性を切り替える - Qiita


【問題】動的に生成したDOM要素にイベントをつけるにはどうすれば良いのか?
【解決】
例えば、ボタンをクリックしたら、そのボタンを消して、新しいボタンを追加し、またそのボタンを押したら、そのボタンを消して...を繰り返すプログラムを作るとします。

<div id="field"><input type="button" value="ボタン1" class="btn1"></div>
$(function(){
	$(document).on('click','.btn1',function(){
		$("#field").html('<input type="button" value="ボタン2", class="btn2">');
	});

	$(document).on('click','.btn2',function(){
		$("#field").html('<input type="button" value="ボタン1", class="btn1">');
	});
});

このようにdocumentにonメソッドを登録するだけです。onメソッドは内部で、deligate,live,bindという3つのメソッドを統合したものらしく、今回のケースでは、後から追加した要素にイベントを実行させるliveを用いている。on/offメソッドを利用して、イベント周りのことをもっと色々やってみたい。
参考リンク
jQuery 便利なonを使おう(on click) - Qiita
jQueryで動的に追加した要素はクリックイベントが発火しない?いやそんなことはないぞ - Qiita
動的に生成したDOM要素に対してjQueryでイベントを設定する場合 - Qiita


【問題】デバッグをするにはどうすればいいか?
【解決】
Webブラウザの開発ツールを使う。Firefoxならば、調査したいサイトを見ている状態で『F12キー』を押すと、そのページをチェックする状態になり、さらに、『コンソール』タブをクリックすると、JavaScriptでエラーがあったときに、メッセージがリストされる。(エラーしているファイル名とその行数部分)また、下の入力部分から、そのサイトにjavascriptのコードを埋め込むこともできる。

Ajaxの結果をチェックするときも、HTTPステータスコードや、応答した内容をチェックして、バグの原因を見つける。


【問題】onメソッドのclickをする際の呼び出しについて

$(document).on('click',function(){});

とすると、どこをクリックしても、すべてでクリックイベントが発動してしまう。

$(document).on('click','input[type="button"]',function(){});

とすれば、inputタグのボタンをクリックしたときだけ、イベントが発動する。また、$("")は複数指定することができる。

$(document).on('click','input[type="button"],button',function(){});

これで、inputタグのボタンもしくはbuttonタグをクリックしたときだけ、イベントが発動する。そのタグに、data属性を追加しておいて条件分岐で処理を振り分けるというテクニックも可能。
こうすれば、idやclassに依存せずに、処理できる。
例えば、以下のようなコードのことだ。
HTML部分

<input type="button" data-name="tarou" value="押してください">
<button type="button" data-name="hanako">押してください</button>

JavaScritpt(jQuery)部分

$(function(){
	$(document).on('click','input[type="button"],button',function(){
		var i = $('input[type="button"],button').index(this);
		var data = $('input[type="button"],button').eq(i).data("name");
		data == "hanako" ? alert("花子です") : alert("太郎です");
	});
});


【問題】データ属性を書き換えるには?
ボタンをクリックすると、data-status属性の値が変更するようなプログラムを作ります。
HTML部分

<input type="button" id="btn" value="変更">
<div id="test" data-status="hidden"></div>

jQueryの部分

$(function(){
	$(document).on('click','#btn',function(){
		var status = $('#test').data('status');

		if(status == "hidden"){
			$('#test').data('status','show');
		}else if(status == "show"){
			$('#test').data('status','hidden');
		}
		alert(status);
	});
});

参考リンク
jQueryのdata()で属性を取得・設定・変更する方法まとめ! | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
[jQuery] data属性を動的に変更する場合の注意点 - Qiita

【問題】.onメソッド内でalertが1回で良いのに2回表示されてしまう
【解決】return falseを直後に追加するか、preventDefault()を直後に追加すると、1回の表示で済んだ。原因がどうしても分からなかったので、対処療法として用いた。preventDefault()は、イベントはキャンセルするけれど、親要素へ伝播するというメソッド。return falseは、イベントのキャンセルと親要素への伝播のキャンセルの両方を行う。

preventDefault()やstopPropagation()は、onメソッド内の一番最初に書いても、その後の、alertは動作するが、return falseの場合は、それ以降にalertを書いていても、すべてストップしてしまう違いがある。

参考リンク
jQuery のバブリング、preventDefault() や stopPropagation() の使用例 | Tips Note by TAM


■【問題】連続クリックを防ぐ
【解決】
HTML側

<input type="button" id="btn" value="送信">

jQuery

$(function(){
	$('#btn').on('click',function(){
		$('#btn').prop('disabled', true);
	});
});

もっと書けば、テキストエリアやテキストボックスに何も入力していなければ、クリックを無効化し、入力していれば、1回だけクリックを許すようなプログラムは以下のように作ります。
disabledを有効にしてしまうと、firefoxではページ遷移するけれど、chromeじゃページ遷移しないので、submit()を追加しておく。
HTML側

<form method="post" action="./hoge">
	<textarea id="form_textarea">
        <input type="text" id="form_textbox">
	<input type="submit" value="送信" id="form_btn">
</form>

jQuery

$(function(){
	$("#form_btn").on('click',function(){
		if($("#form_textarea").val() === "" || $("#form_textbox").val() === ""){
			return false;
		}

		$('#form_btn').prop('disabled',true);
                $(this).closest('form').submit();
	});
});

参考リンク
jQueryでフォームのsubmitボタンをdisabledにする - (゚∀゚)o彡 sasata299's blog
closest([expr]) - jQuery 日本語リファレンス
【jQuery】submit前に処理を行う方法 - Qiita


【問題】テキストボックスやテキストエリアなどに何も入力していなければボタンを無効化する
テキストエリアの場合は、テキストボックス部分を置き換えるだけ。
【解決】
HTML側

<form method="post" action="./hoge">
	<input type="text" id="form_text">
	<input type="submit" id="form_submit">
</form>

jQuery

$(function(){
	$('#form_submit').on('click', function(){
		if($('#form_text').val() === ""){
			return false;
		}
	});
});

form内にテキストボックスとテキストエリアの両方を置いて、両方の内、どちらかが空であれば、submitボタンのイベントをreturn falseするというプログラムにすると、
1.どちらも入力していない→submitは機能しない
2.テキストボックスは入力したが、テキストエリアは入力していない→submitは機能しない
3.テキストボックスは入力していないが、テキストエリアは入力した→submitが機能した
という挙動をする。原因は何だろうか?

一応、解決したので、メモしておきます。

HTML側

<form method="post" action="./hoge" id="form_id">
	<input type="text" id="form_text">
	<textarea id="form_textarea"></textarea>
	<input type="submit" id="form_button" value="送信">
</form>

jQuery

$(function(){
	$('#form_button').on('click',function(e){
		e.stopPropagation();
		if($('#form_textarea').val() === "" || $('#form_text').val() === ""){
			return false;
		}
	});
});

これを書いて、成功したと思った後に、今度は、stopPropagation部分を外して、やってみると、これもうまく挙動しました。一体何が原因なのか?キャッシュだろうか?


【問題】.click()や.submit()を使ってもフォームのページ遷移が始まらない
【解決】
clickイベントは起動するが、ページ遷移が始まらない状態だった。
原因は以下のようにinputタグのsubmit属性をformタグの外に設置していたこと。

<form method="post" action="./hoge">
 <input type="text">
</form>
<input type="submit" value="送信" id="btn">

例えば、テキストボックスとボタンの間に何か入れたい場合に、別々の位置に設置したい時はどうすればいいのだろうか?

思いついた対処方法として、以下のようなものがあります。formタグにid属性を付与して、クリックイベントと同時に、そこにsubmit()メソッドを用いています。

HTML側

<form method="post" action="./hoge" id="frm">
<input type="text">
</form>
<!-- ここに何かを設置する -->
<input type="submit" id="btn" value="送信">


jQuery

$(function(){
	$('#btn').on('click',function(){
		$('#frm').submit();
	});
});


【問題】ツールチップを自作する
CSSだけで実現できないこともないですが、自分の場合は、ツールチップを表示させたいタグにカスタムデータ属性をつけただけで、手軽に表示させたかったので、JavaScript(jQuery)を用いました。
【解決】
HTML側

<!-- head部分に -->
<script src="jquery-3.2.1.min.js"></script>
<!-- body部分に -->
<a href="./top" data-title="トップページ">トップページ(アイコンのつもり)</a>

CSS
現時点では上向きの矢印になります。位置を変更したければ、
.tooltip-window:beforeを修正する必要があって、
下向きにしたければ、bottom:100%→top:100%、border-color: transparent transparent black transparent→border-color: black transparent transparent transparent;
とするだけ。

/* headタグのstyle属性に */
.tooltip-window:before{
	content: " ";
	position: absolute;
	bottom: 100%;
	left: 50%;
	margin-left: -5px;
	border-width: 5px;
	border-style: solid;
	border-color: transparent transparent black transparent;
}

.tooltip-window{
	position:absolute;
	background-color:rgba(0,0,0,0.9);
	color:white;
	padding:5px 8px;
	font-size:12px;
	border-radius:3px;
}

JavaScript

/* headタグのscript属性に */
$(function(){
	$('*[data-title]').on({
		'mouseenter' : function(){
			var p = $(this).position();
			var p_top = p.top + $(this).height() + 5;
			var p_left = p.left + $(this).width() * 0.25;
			$(this).append('<div class="tooltip-window" style="left:' + p_left + 'px;top:' + p_top + 'px;">' + $(this).data("title") + '</div>');
		},
		'mouseleave' : function(){
			$(".tooltip-window").remove();
		}
	});
});

参考リンク
CSSのみで作る幅可変ツールチップ - Qiita


jQueryは結局
1.どこに?: $()
2.何をする?: .method()
だけか?