※追記
コメントでこの記事よりも断然質の良い記事を教えてもらいました。
@kabochaさんありがとうございます。
You Don't Need jQuery
https://github.com/oneuijs/You-Dont-Need-jQuery
追記の追記。
日本語訳のお手伝いをさせていただきました。
github
https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README-ja.md[Qiita]もうjQueryは必要ない
http://qiita.com/tatesuke/items/b9548dd484b01b139b74
jQueryが使える環境でコーディングした後、jQueryが使えない環境でコーディングしようとすると、「どう書くんだっけ?」となることが多いです。ということで分かる範囲でチートシートを作りました。
当然ですが、サンプルコードは「似たような動作をする」「代替になりうる」という意味なので厳密に同じではありません。
また、JavaScriptやECMAScriptの仕様を意識していないため、古い書き方や新しい書き方など混在していると思います。
Selectors
エレメントを選択
伝統的なやり方ならば
// idで取得
var elem = document.getElementById("id");
// クラス名で取得
elem = document.getElementsByClassName("className");
// タグ名で取得
elem = document.getElementsByTagName("div");
最近のブラウザならquerySelectorAll/querySelectorのほうが便利。jqueryのセレクタを流用できる。
// セレクタに合致するエレメントを取得
var elem = document.querySelectorAll("#id");
// セレクタに合致する最初のエレメントを取得
elem = document.querySelector(".query");
ただし、jQueryのオブジェクトじゃないのでeach関数は使えない。自作するか、素直にfor文で回す。
Attributes
attr/removeAttr
// 属性を設定
element.setAttribute("name", "value");
// 属性を取得
var attr = element.getAttribute("name");
// 属性を削除
element.removeAttribute();
// 属性が存在するか
var hasAttr = element.hasAttribute("name");
addClass/removeClass/toggleClass
// クラスを追加
element.classList.add("className");
// クラスを切り替え
element.classList.toggle("className");
// クラスを削除
element.classList.remove("className");
// クラスが存在するか
var contains = element.classList.contains("className");
一応className
属性で文字列を取得することも可能
var classNames = element.className;
html
// htmlを取得
var html = element.innerHTML;
// htmlを設定
element.innerHTML = html;
text
// テキストを取得
var text = element.innerText;
// テキストを設定
element.innerText = text;
firefoxではinnerText
が使えないのでtextContent
を使う。
var text = element.textContent;
当然、ブラウザによって処理を振り分けるのは面倒なので次のようにするとよい。
引用元:『TM Life』 Firefox で innerText を使えるようにする方法
http://tmlife.net/programming/javascript/firefox-can-use-innertext.html
(function(){
var temp = document.createElement("div");
if (temp.innerText == undefined) {
Object.defineProperty(HTMLElement.prototype, "innerText", {
get: function() { return this.textContent },
set: function(v) { this.textContent = v; }
});
}
})();
val
// valueを取得
var val = element.value;
// valueを設定
element.value = val;
Traversing
hasClass
var hasClass = element.classList.contains(className);
children
var chldren = element.children;
こちらもjQueryオブジェクトではないのでeach関数は使えない。
closest
// 親エレメントを取得
var closet = element.parentNode;
セレクタがある場合はゴリゴリ書くしかない。
たとえば、タグ名を指定したければwhile
文で遡る。
var parent = element.parentNode;
while (parent.tagName != "BODY") {
parent = parent.parentNode;
}
find
エレメント自体にもquerySelectorAll
/querySelector
があるので、それで代用可能。
// findの代用
var elements = element.querySelectorAll(query);
next
// 次の要素を得る
var next = element.nextElementSibling;
nextAll
var nexts = [];
var current = element.nextElementSibling;
while (current != null) {
nexts.push(current);
current = current.nextElementSibling;
}
parent
// 親エレメントを取得
var parent = element.parentNode;
parents
element.parentNode
とwhile
文、if
文を組み合わせてゴリゴリ書く。
prev
// 前の要素を得る
var prev = element.previousElementSibling;
prevAll
var prevs = [];
var current= element.parentNode.firstElementChild;
while (current != element) {
prevs.push(current);
current = current.nextElementSibling;
}
siblings
var siblings = [];
var children = element.parentNode.children;
for (var i = 0; i < children.length; i++) {
if (children[i] != element) {
siblings.push(children[i]);
}
}
Manipulation
エレメント作成
エレメント作成の基本はdocument.createElement
。
var newElement = document.createElement("div");
createElement
ではjQueryのよう文字列からエレメントを簡単に作成することはできない。
その場合、以下のように、ダミーのエレメントを使うことで実現可能。
// ダミーのdiv作成
var dummy = document.createElement("div");
// ダミーのinnerHTMLを書き換える
dummy.innerHTML = "<div>hoge</div>";
// 作成したエレメントを取り出す。
var newElement = dummy.childNodes[0];
delete dummy;
append
parent.appendChild(element);
prepend
parent.insertBefore(element, parent.childNodes[0]);
after
var parent = element.parentNode;
var prev = element.nextSibling;
parent.insertBefore(insertElement, prev);
before
var parent = element.parentNode;
parent.insertBefore(insertElement, element);
insertAfter
$(A).insertAfter(B)
↓
var parent = B.parentNode;
var prev = B.nextSibling;
parent.insertBefore(A, prev);
insertBefore
$(A).insertBefore(B)
↓
var parent = B.parentNode;
parent.insertBefore(A, B);
wrap
$(A).wrap(B);
↓
var next = A.nextSibling;
var parent = A.parentNode;
parent.removeChild(A);
parent.insertBefore(B, next);
B.appendChild(A);
empty
element.innerHTML = "";
remove
element.parentNode.removeChild(element);
clone
element.cloneNode(true);
CSS
css
element.style
配下のプロパティをいじる。
element.style.border = "1px solid gray";
どんなプロパティがあるかはその都度調べる。たとえば↓とか。
http://javascriptist.net/docs/samples_element_style.html
offset/position
簡単に代替になるものがない(多分)。
一応、下記を使うと、起点となる要素からの相対距離が得られる。
var offsetTop = element.offsetTop;
var offsetLeft = element.offsetLeft;
起点となるエレメントに要注意。必ずしも画面の左上が起点ではない。親要素がposition:relative
なら親要素が起点になる。
画面左上を起点としたいならDOM構造に注意して、各要素のoffsetTopやoffsetLeftを足し合わせるという作業が必要になることがある。
scrollTop, scrollLeft
// スクロール量を得る
var scrollTop = element.scrollTop;
var scrollLeft = element.scrollLeft;
// スクロール量を設定
element.scrollTop = scrollTop;
element.scrollLeft = scrollLeft;
width/height
// 横幅、縦幅を得る(padding,border含む)
var width = element.offsetWidth;
var height = element.offsetHeight;
// 横幅、縦幅を設定する
// 普通はpadding, borderを含まない box-sizing:border-boxならpadding, bordeerを含む。
element.style.width = "100px";
element.style.heigth = "100px";
offsetWidth
やoffsetHeight
はReadOnlyです。
Events
on, off(イベント)
addEventListener
/removeEventListener
一択(attachEvent?何それ?)。
element.addEventListener("eventName", callback);
element.removeEventListener("eventName", callback);
jQuery.on(element, "eventName", callback)
のように、将来的に追加されるエレメントにも対応させる方法は調べてません。
ready
単純なところではwindow.onload
。
window.onload = function() {
// コード
}
これだとひとつしかイベントを登録できないし、''$(document).ready''とも厳密にはタイミングが違う。
最近のブラウザでは以下のほうが無難かも。
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded');
});
trigger
- イベントオブジェクトの生成
- イベントオブジェクトを初期化
- イベントをディスパッチ
の流れ。
// クリックイベントを発生させる
// イベント作成
var event = document.createEvent("MouseEvent");
// イベントオブジェクトを初期化
event.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,0,null);
// イベントをディスパッチ
targetElement.dispatchEvent(event);
MouseEvent以外にもKeyboardEventとか色々あってブラウザごとにバリエーションは違うらしい。Mozillaだと↓にいっぱい載ってる。
クリックイベントとかを自前で発火させることはあまりないとは思うけど・・・
カスタムイベントを発火させるには
var event= document.createEvent("Event");
event.initEvent("eventName",false,false);
targetElement.dispatchEvent(event);
各引数の意味とかはこの辺が詳しい↓
Effects
show/hide/toggle
display:none
するcssクラスを準備しておいて、styleList
を通してクラスをつけたり外したりするのが一番楽。
.hide{
display:none !important;
}
// 非表示にする
element.classList.remove("hide");
// 表示する
element.classList.add("hide");
// toggle
element.classList.toggle("hide");
もちろん、
// 直接styleをいじって非表示にする
element.style.display = "none";
として非表示にすることも可能。しかし、どうやって表示するか決めかねる。
// 表示するとき
// displayはblockか?inlineか?はたまたinline-blockか?それ以外?
element.style.display = "??";
jQueryはこのあたりをhide前にキャッシュしたり、見えないiframeにエレメントを追加したりしてうまいこと実装しているようだけど、ゼロから実装しなおすのは面倒くさい。可能なら上の例のようにcssのクラスを準備しておくのが一番手っ取り早い。
ajax
詳しくない&Web上にたくさん情報があるので割愛。
気が向いたら書くかも。