【jQuery】イベントオブジェクト ー親要素で発火するイベントを特定の子孫では解除したいー
こんにちは、マリンです。
今回はJSでのイベントを発火させる要素の特定です。
親要素で指定するが、特定の子孫要素では実行してほしくない。
そんな時どのように指定すればよいでしょうか?
:not
とか調べてみたのですが、
子孫要素でのやり方がイマイチよくわからず。。。
そこで今回はイベントオブジェクトを使ってこれを実装しました。
もっと簡単に実装できる、
セレクタとか、便利なメソッドとか、
皆様ぜひ教えてください。
概要
table
の概要を記述したtr
をクリックした時、詳細の列が表示されるようにする。tr
の中には承認ボタンがある。親の
tr
にイベントを付けているので、子要素のボタンのクリックでもshow
hide
が実行されてしまう。
以上のことから、子要素のボタンだけクリックイベントを外したいわけです。
最初は:not
などを使って特定しようとしたのですが、
うまくボタンだけを取ることが出きませんでした。
そこで、イベントオブジェクトを使ってみました。
詳細
サンプルコード
まずは解説に使うサンプルコードを記載しておきます。
<form action="sample/create" method="post"> <table class="table"> <tr id="sample-tr"> <td>Name: Yamada Hanako</td> <td>Age: 20</td> <td><button name="approve" type="submit" value="approve">承認</button></td> </tr> <tr id="sample-hidden-tr style="display: none"> <td>Address: Tokyo Minato-Ku</td> <td>Email: sample@example.com</td> <td>Password: password</td> </tr> </table> </form>
上段のtr
が表示されている行。
下段のtr
が非表示部分で、上段をクリックすると表示されます。
しかし、上段3つ目のカラムにあるボタンだけはクリックの対象外にします。
以下が今回のCoffeeです。
$('#sample-tr').on 'click', (e)-> target = $(e.target) if target[0].nodeName == "BUTTON" return if $(@).hasClass('show') $(@).removeClass('show') $('#sample-hidden-tr').hide() else $(@).addClass('show') $('#sample-hidden-tr').show() retrun
詳細解説
HTMLは省略します。
$('#sample-tr').on 'click', (e)-> target = $(e.target)
まずは最初の2行です。
1行目は上段tr
へのクリックイベントで、引数e
がイベントオブジェクトです。
2行目はイベントが発生したjQueryオブジェクトを変数に入れています。
target
の中身は以下のようになっています。
target: jQuery.fn.init(1) 0: button accessKey: "" assignedSlot: null attributeStyleMap: StylePropertyMap {size: 0} attributes: NamedNodeMap {0: type, 1: name, type: type, name: name, length: 2} autocapitalize: "" . . . nextElementSibling: null nextSibling: null nodeName: "BUTTON" nodeType: 1 . . .
次の2行です。
if target[0].nodeName == "BUTTON" return
if文でイベントが発生した要素がボタンだったら何もしないで終了させています。
if文の内容と、先ほどのtarget
の中身を見比べてみてください。
target: jQuery.fn.init(1) 0: button accessKey: "" . . . nodeName: "BUTTON" . . .
target[0].nodeName == "BUTTON"
イベントオブジェクトのtarget
。
その中に入っているキー[0]でDOM要素を取得し、
さらにその中からnodeName
プロパティで対象となった要素名を取得します。
そして、要素名が"BUTTON"だったら何もせずreturn
というわけです。
ちなみに、最初にe.target
を変数targetに入れましたが、
今回のような単純なコードでしたら入れる必要もないと思います。
if $(e.target)[0].nodeName == "BUTTON"
でいけます。
個人的に見やすかっただけです、、、
まとめ
今まで苦手意識のあったイベントオブジェクトやjQueryオブジェクトでしたが、
一度じっくり眺めてみるとなんとなく解ってきました。
やはりぱっと見よくわからない!と思っても、
テンパることなく冷静に眺めていることって必要ですね。
余談ですが、今回のことで
なぜ$()
を使ってjQueryオブジェクトにするのか?
ということが今更ながら理解できました。
根本が解っていないと理解が遅くなる一方ですね。。。
まだまだ奥が深いと思うので、これを機にちゃんと勉強してみます。
【Git】ブランチ間違えてコミットしてた!?
皆さん明けましておめでとうございます。
なんとか1月終わる前に更新できました(^ ^;)
本年も地味に更新してまいりますので、
どうぞよろしくお願いいたします。
さて、今回は年明け早々やらかしたブランチ切り替え忘れ、
そしてそのまま作業した挙句コミットまでしちゃった!
その時の解決方法を載せておきます。
経緯
先日、仕事開始時にブランチを切り替え忘れ、
そのままずーっと作業し、コミットももちろん複数回行い、
作業終了時に初めて「ブランチ前回のままじゃん!!」と気づきました。
ひどい失敗で、誰かの役にたつのかわかりませんが・・・
その時行った、
間違えたブランチから本来のブランチへ変更部分を移してコミット。
という解決方法を記述します。
手順
間違えたブランチをコミットする前の状態に戻す。
変更部分を一度退避する。
ブランチを切り替える。
切り替えたブランチで退避した変更部分を復活。
コミットする。
詳細
間違えたブランチを、コミットする前の状態に戻す。
$git log $git reset --soft コミットのハッシュ値
まずはgit log
でどこまで戻せば良いか確認します。
次にgit reset --soft コミットのハッシュ値
でブランチを
コミット前の状態に戻します。
この時絶対に--soft
を使ってください!
このオプションで作業ディレクトリの変更内容は残したまま、
コミットだけを取り消すことができます。
ちなみに指定するコミットのハッシュ値は、
このコミットまで戻したい!というコミットのハッシュ値を指定します。
指定したコミットの次にコミットしたものまでが取り消されます。
これに限らず、どれを指定するとどこまで影響するのか?にいつも迷います。。。
変更部分を一時退避する
$git stash
このままではcheckoutしても変更部分を反映させられないので、
この変更部分は一時的に退避させます。
ちなみに、退避させるものが複数ある場合、
$git stash save "hogehoge"
のように名前をつけておくこともできます。
ブランチを切り替える
わざわざ紹介することもないと思いますが、
$git checkout ブランチ名
切り替えたブランチで退避した変更部分を復活
$git stash pop
このコマンドは、退避した部分を復活と同時に
退避リストから削除するものです。
もちろん復活と削除を別々に行うことも可能ですが、
今回は全変更部分を一括でやってしまったので。。。
あとは切り替えたブランチでコミットすれば作業終了です。
なお、git stash
の使い方については、こちらで詳しく説明してくださっています。
解決方法の参考にさせていただいたのはこちらです。
まとめ
今回は焦っていたので全変更部分を一括で移して1コミットで終わらせてしましました。
本来ならコミットごとに、
状態を一つ戻す→名前をつけて退避
を繰り返し、退避終了後
ブランチ切り替え→一つずつ復元→コミット
とすべきだったと思います。
初めてのことでパニクっていたのと、子供の迎え時間が迫っていたので
テンパって一気にどーん!とやってしまいました。
反省。。。。
しかしまずは作業前に確認しましょう。。。
本年もご覧いただき有難うございました。
こんにちは、マリンです。
2018年最後の投稿です。
いよいよ今年も残すところ12時間弱。
年々1年が短くなっている様に感じます〜(´༎ຶོρ༎ຶོ`)
来年は1日1日、1仕事1仕事、1コード1コード大事に、
毎日勉強していく!!!(つもりです…(≧∀≦))
では、本年も皆さま当ブログをご覧いただき、
誠にありがとうございました!
2019年も地味に更新して参る所存ですので、
どうぞよろしくお願い申し上げます。
皆さま良いお年をお迎えくださいm( )m
【Rails】Date型↔︎文字型変換
こんにちは、マリンです。
最近よく日付関係を扱うことがよくあるのですが、
Date(日付)型と文字列型の変換方法をよく忘れるので、
備忘録としてここに書かせていただきます。
Date型 → 文字列型
Date型から文字列型への変換方法。
strftime
today = Date.today # 2018-12-05 Date型の日付(変換前) today.strftime("%Y年 %m月 %d日") # "2018年 12月 05日" 文字列型の日付(変換後)
Date型のオブジェクトに対し、strftime
メソッドを使うことで文字列型に変換できます。
引数にフォーマットを指定することで、その指定通りの形に変換できます。
ちなみに、%Y
を%y
にすると年の下二桁だけを出せます。
フォーマット一覧は以下の通りです。
*文字は基本的に英語表記です。
フォーマット | 変換後の出力 |
---|---|
%A | 曜日の名称 |
%a | 曜日の省略名 |
%B | 月の名称 |
%b | 月の省略名 |
%c | 日付と時刻 |
%d | 日(01-31) |
%H | 24時間制の時(00-23) |
%I | 12時間制の時(01-12) |
%j | 年中の通算日 (001-366) |
%M | 分(00-59) |
%m | 月を表す数字(01-12) |
%p | 午前または午後(AM,PM) |
%S | 秒(00-60 *60はうるう秒) |
%U | 週を表す数。最初の日曜日が第1週の始まり(00-53) |
%W | 週を表す数。最初の月曜日が第1週の始まり(00-53) |
%w | 曜日を表す数。日曜日が0(0-6) |
%X | 時刻 |
%x | 日付 |
%Y | 西暦を表す数 |
%y | 西暦の下2桁(00-99) |
%Z | タイムゾーン |
%% | パーセント文字 |
文字列型 → Date型
文字列型からDate型への変換。
to_date
to_date
メソッドを使う。
str_today = "2018-12-05" # 文字列型の日付(変換前) str_today.to_date # Date型の日付(変換後) => Wed, 05 Dic 2018
to_date
は楽なのでよく使います。
ただ、西暦の下二桁のみには対応していません。
strptime
Date型のstrptimeを使う。
Date.strptime('2018-12-05', '%Y-%m-%d') # (文字列型の日付, 日付を表すフォーマット) => Wed, 05 Dic 2018
to_date
に比べたらちょっと複雑になりますが、
こちらは西暦下二桁のみにも対応可能です。
Date.strptime('18-12-05', '%y-%m-%d') => Wed, 05 Dic 2018
まとめ
日付についてはDateやらDateTimeやらいろいろあっていつも混乱します。
また取得したものがDateなのか文字列なのか?とか。
計算するときに型が違うとエラーになっちゃいますしね(汗)
日付に関する型の違いもいずれまとめられたらと思います。
【Git】git reset --hard HEADを取り消したい!!
こんにちは、マリンです。
今日Gitでやらかしました。
表題の通りなのですが、それにプラスしてDBのロールバックとかも関わってきて、
「ギャーーーー!!!」
ってなったので残しておきます。
概要
やらかした内容が多すぎるので、時系列で箇条書きします。
新規でDBのテーブルを作成するのに
rails g migration ~~
で作ってしまった。テーブルを作った後しばらく作業を進めてからModelが無いことに気づく。(この間何度かcommitしてる)
Modelだけ作れば良いところ、わざわざ
rake db:rollback
しようとした。だがロールバックする前に何を思ったかCommitをテーブル作る以前まで戻してしまった。
しかもGitの取り消しを
git reset --hard HEAD@{n}
でやってしまった。(ここが一番問題)
やはり一番のやらかしポイントは、commitのやり直しで
git reset --hard HEAD@{n}
を使ってしまったことでしょう。
--hard
オプションをつけると、ワーキングツリーまで変更されてします。
では、これに対する対処を次から書いていきます。
対処法
1、2、3まではおそらくModelファイルだけ作ってあげれば良かった話だと思うので省略します。
4、5、6について詳細と対処法を記載しようと思います。
そもそも何が起こったのか?
私が不用意に打ったgit reset --hard HEAD@{n}
これによって何が起こったのかを解説します。
飛ばしていただいて結構です。
$ git reset --hard HEAD^
git reset
:これは任意のcommitを取り消すコマンドです。--hard
:resetコマンドのオプションです。コミットだけでなく、ワーキングツリーまで元の状態に書き換えます。HEAD@{n}
:HEADの位置をどこまで戻すかを指示しています。@{n}
で遡ることn番目のcommitを表します。
問題は真ん中の--hard
オプションです。
これによりワーキングツリーまで元の状態に戻ってしまったため、
テーブル作成のために書いたマイグレーションファイルまで消えてしまいました。
(今回はテーブル作成をする一つ前のコミットまで戻ったので・・・)
そしてこれをrake db:rollback
を実行する前にやってしまいました。
該当のマイグレーションファイルが無いのにロールバックしたってできるわけがありません。
なのでこの取り消し(git reset)を取り消して、マイグレーションファイルを復活させる!
それが今回の目標です。
ちなみに問題のオプションですが、
--soft
にを指定すればコミットだけをなかったことにしてくれます。
これにしていればアワアワすることもなかったでしょう・・・
他にもコミットとインデックスを取り消す--mixed
もあります。
オプション無しのデフォルトもこれです。
こちらでより詳しく説明してくださっています。
[git reset (--hard/--soft)]ワーキングツリー、インデックス、HEADを使いこなす方法
コミット取り消しの取り消し
ここからが本題です。
消してしまった事実をなかったことにして、
マイグレーションファイルを復活させます。
$ git reflog $ git reset --hard HEAD@{n} $ git log
こちらが一連の流れです。
git reflog
:
まずどこまでコミットを戻すか履歴を見ます。
コマンドがgit log
でない理由は、
リセットされたコミットはgit log
の履歴に出てこないからです。
git reflog
は消されたコミットも履歴として見ることができます。
git reset --hard HEAD@{n}
:
ここで取り消しを無かったことにします。
今回は--hard
オプションで大丈夫です。
消えてしまったワーキングツリーのファイルを復活させたいので。
HEAD@{n}
のnにはログで確認した該当コミットが現在地から何番目にあたるかの番号を入れてください。
reflog
の時に番号入りで表示されるはずなのでわかりやすいと思います!
git log
:
最後に念のため確認をしましょう。
この場合はこちらの履歴で大丈夫です。
以上が解説になります。
なお、実例を交えたより詳しい説明をこちらでしてくださっていますので、
ぜひご覧ください。
git reset --hardした内容を取り消す (git reset --hard, reflog, HEAD@{x}, 取り消してしまったコミットを元に戻す) - いろいろ備忘録日記
まとめ
今までadd、commit、pushくらいしかやってこなかったGitです。
正直他のことはよくわからないから触りたく無かったし、
そもそも何ができるのかも曖昧でした。
しかし、今回初めて「履歴が残っている」ということの有り難みを感じました。
そしてむやみに手元まで変えてはならない!!ということも・・・
基本は--soft
でやるのが安全だし、一般的な様ですね。
大変勉強になりました!
【Bootstrap/Rails】popoverのdata-contentの中身をHelperに切り出してみた。
こんにちは、マリンです。
今回はBootstrapのpopoverです。
popoverはtitle
に表示するタイトル。data-content
に表示する内容を書きます。
でも長い内容をタグ内に書きたくないでしょ!
ってなわけでRailsのHelperにメソッド切って表示内容を切り出してみました。
注)HTML上ではベタ書きになっちゃいますけど。
概要
- 環境 -
Rails5
Bootstrap3
- 例に使うテーブル構造 -
Usersテーブル
id
name
Childrenテーブル
id
name
user_id
- 概要 -
Userの名前をクリックすると、
ポップオーバーでChildrenの名前が表示されるようにします。
この時data-content
の中身が複雑になるので、
Helperにメソッドを切ってそれをdata-content
に渡します。
詳細
そもそもなんでこんなことになるのか?ちょっと詳細を説明します。
まず前提として、対象のページはindex.html.erb
で、
Userの名前はUser.all
をeach
で回して表示しているとします。
さらにChildrenは複数いる可能性があります。
そこで問題となるのが、
どのUserの子供であるかを特定するために
user
を渡す必要があること。Childrenは
user.children
の配列になること。その配列から名前を取得して表示するには、ループを回す必要があること。
ポップオーバーの内容は複雑になる場合、別エリアに切り出すことも可能です。
しかし今回の場合、まず一番外側でUser.all
をループしています。
切り出すにはこのループの外になるでしょう。
となると1番のどのUserかを特定するuser
を渡すのが大変です。
Ajaxを駆使してコントローラに値を渡して〜・・・なんてことが予想されます。
2、3番は表示内容が複雑になる理由です。
てことでHelperにメソッドを切ってみてはどうか?となったわけです。
ちなみに子の名前は一人一人改行して表示します。
HTML上はベタ書きになってしまいますが、コードはすっきりします。
ソースコード
さて前置きが長くなりましたが、ここから本題です。
まぁやってることは真新しいことではないのですが・・・
ControllerとModelは特に特筆することはないので、コードだけで解説は省略します。
Controller
# controllers/users_controller.rb def index @users = User.all end
Model
# user.rb has_many :children # child.rb belongs_to :user
View
<!-- views/users/index.html.erb --> <% @users.each do |user| %> <button class="btn" data-html="true" data-toggle="popover" title="子ども" data-cotent="<%= children_popover(user) %>"> <%= user.name %> </button> <% end %>
まずbuttonタグの中にあるdata-html="true"
をご覧ください。
今回のメソッド切り出しとは直接関係はありませんが、
これを入れることでポップオーバーの中で改行<br>
を使うことができるようになります。
次に本題のdata-content="<%= children_popover(user) %>"
です。
このerb表記の中身が、後述のHelperに切り出すメソッド名です。
引数にuser
を渡していることにご注目ください。
別エリアへの切り出しではないため、大枠のループのuser
をそのまま使うことができます。
Helper
# helpers/users_helper.rb def children_popover(user) users_children = [] user.children.each do |child| users_children << child.name end users_children.join("<br>") end
まず最初に子どもの名前を入れる空の配列を用意します。
そしてuser.children
のループを回し、
その中で名前を先ほどの配列に格納していきます。
最後にループの外で出来上がった配列を、
区切り文字に<br>
改行を指定して返します。
これを使うために先ほどViewでdata-html="true"
を指定しました。
解説は以上になります。
まとめ
今回は値の取得などにたいした時間がかからないものでしたのでこの方法を使用しました。
しかし、表示する値の取得に時間がかかるようでしたら、
やはり別エリアに表示内容を切り出し、
値の取得にはAjaxを使って行うなどの方法をとった方が良いかと思います。
私も機会がありましたら挑戦してみようと思います。
ちなみに、今回の検証でpopoverを使用するためにclass="btn"
が必ず必要だったのですが、
これは仕様でしょうか?それとも私の設定ミスでしょうか?
どなたかわかる方いらっしゃいましたら是非教えてください。
よろしくお願い致します。
【jQuery】show/hide ~イベントによって表示・非表示を切り替える~
こんにちは、マリンです。
今回はボタンクリックなどのイベントによって
簡単に要素の表示・非表示を切り替えようと思います。
概要
任意の要素の表示・非表示をボタンのクリックで切り替えます。
ボタンを押すと要素を非表示に、もう一度押すと表示させます。
詳細
Rails環境で行っているため、JSの記述はcoffee scriptです。
View
<!-- app/views/samples/index.html.erb --> <div class="target-element" data-display="on"> <p>この部分を切り替えます。</p> </div> <button type="button" class="btn btn-md btn-default switch-display">Switch</button> <script> samples.switchDisplay(); </script>
上から順番に解説します。
<div class="target-element" data-display="on"> <p>この部分を切り替えます。</p> </div>
この部分が表示したり非表示にしたりする要素です。
target-element
はjQueryでこの部分を特定するためのセレクタです。
data-display="on"
は、現状が表示中かどうかを判定するためのものです。
<button type="button" class="btn btn-md btn-default switch-display">Switch</button>
表示・非表示の切り替えボタンです。
Bootstrapを使っているので、btn
などのクラスでスタイルを当てています。
switch-display
はイベントの対象となるセレクタです。
CoffeeScript
class SamplesController switchDisplay: -> $('.switch-display').on 'click', ()-> if $('.targe-element').data('display') == 'on' $('.switch-display').data('display', 'off') $('.switch-display').hide() else $('.switch-display').data('display', 'on') $('.switch-display').show() return this.samples = new SamplesController
上から順番に解説します。(class ~~
については省略します)
$('.switch-display').on 'click', ()-> if $('.targe-element').data('display') == 'on'
.switch-display
(ボタン)がクリックされたら、
まず切り替え対象の要素の持つdata-display
の値が
on
であるかそうでないか検証します。
$('.switch-display').data('display', 'off') $('.switch-display').hide()
値がon
の時、つまり表示状態の時には
data-display
の値をoff
にし、
切り替え対象の要素をhide()
で非表示にします。
else $('.switch-display').data('display', 'on') $('.switch-display').show()
値がoff
ので非表示状態の時には
data-display
の値をon
にし、
切り替え対象の要素をshow()
で表示にします。
まとめ
要点としては、
切り替えの着火剤となるイベント
hide
による非表示show
による表示
この3点です。
今回はイベントをクリックにしましたが、
hover
などで自作のポップオーバーに使ったりなど
イベントを変えればいろいろと応用が効くと思います。