はじめに
ありとあらゆる所で使用されている超有名なJavaScriptライブラリといえば jQuery ですが、ちょっとした処理を行いたいがために使っているようであれば無駄な気もします。
最近のJavaScriptはjQueryなしでも割といろんな処理を行うことができます。
というのも、jQueryの動作を模倣してみようとゼロから書いた拙作のライブラリ queries.js を通してどのような処理を行っているのか理解が深まったからです。
宣伝になってしまいますが、ほぼjQueryみたいな事ができるJavaScriptライブラリの queries.js へのリンクを貼っておきます。
jQueryライクなJavaScriptライブラリ queries.js
ちなみに、Internet Explorer 11未満は考慮していません。
便利メソッド系
$.each()
や $.grep()
といったメソッドの代替となる記述です。
よく使いそうなものだけ取り上げています。
$.each()
$.each()
は、配列やオブジェクトを簡単にループ処理できるメソッドです。
var decoRations = ['諸星きらり', '城ヶ崎莉嘉', '赤城みりあ'];
var kbyd = {
kawaii: '輿水幸子',
yakyu: '姫川友紀',
dosue: '小早川紗枝',
};
/* 配列 */
$.each(engine, function (i, value) {
console.log(i + ': ' + value);
});
// "0: 諸星きらり"
// "1: 城ヶ崎莉嘉"
// "2: 赤城みりあ"
/* オブジェクト */
$.each(kbyd, function (key, value) {
console.log(key + ': ' + value);
});
// "kawaii: 輿水幸子"
// "yakyu: 姫川友紀"
// "dosue: 小早川紗枝"
これらは以下のように書き直すことができます。(変数は同じ)
/* 配列 */
// Array.prototype.forEach
decoRations.forEach(function (value, i) {
console.log(i + ': ' + value);
});
/* オブジェクト */
// for...in 文
for (var key in kbyd) {
console.log(key + ': ' + kbyd[key]);
}
// Object.keys() を使った方法
Object.keys(kbyd).forEach(function (key) {
console.log(key + ': ' + kbyd[key]);
});
配列の場合は、Array.prototype.forEach
を使った方法、オブジェクトの場合は for...in
文や Object.keys
を利用した方法です。。
$.each()
との違いは、コールバック関数の引数の順番や直接オブジェクトを使えない事、return false;
でもループが止まらないことでしょうか。
Array.prototype.forEach
は関数を利用した方法なので、break
や continue
は使えませんが、continue
に関しては return
で代用できます。返り値を指定しても意味ありません。
ループを止める処理を行いたい場合、本来の使い方ではなくなってしまいますが、Array.prototype.some
で似たような事を行えます。
var kawaii142s = ['輿水幸子', '白坂小梅', 'あの子', '星輝子'];
/* jQuery */
$.each(kawaii142s, function (i, value) {
console.log(value);
if (value === 'あの子') {
console.log('フギャー!?');
return false;
}
});
// "輿水幸子"
// "白坂小梅"
// "あの子"
// "フギャー!?"
/* Array.prototype.some */
kawaii142s.some(function (value) {
console.log(value);
if (value === 'あの子') {
console.log('フギャー!?');
// return true; なので注意
return true;
}
});
// "輿水幸子"
// "白坂小梅"
// "あの子"
// "フギャー!?"
うーん、これはちょっとおすすめできないですね……
ちなみに、ECMAScript 2015 では for...of
文が使えるので、break
や continue
も使えます。(変数は同じ)
for (let value of kawaii142s) {
console.log(value);
if (value === 'あの子') {
console.log('フギャー!?');
break;
}
}
// "輿水幸子"
// "白坂小梅"
// "あの子"
// "フギャー!?"
はやく標準になってほしいですね。
$.grep()
配列をフィルタリングするためのメソッドです。
var kawaii142s = ['輿水幸子', '白坂小梅', 'あの子', '星輝子'];
kawaii142s = $.grep(kawaii142s, function (value) {
return value !== 'あの子';
});
console.log(kawaii142s);
// ["輿水幸子", "白坂小梅", "星輝子"]
Array.prototype.filter
で同じことができます。
var kawaii142s = ['輿水幸子', '白坂小梅', 'あの子', '星輝子'];
kawaii142s = kawaii142s.filter(function (value) {
return value !== 'あの子';
});
console.log(kawaii142s);
// ["輿水幸子", "白坂小梅", "星輝子"]
$.map()
配列の値を関数を通して新しい配列として出力するメソッドです。
var result = $.map([0, 1, 2, 3, 4], function (value) {
return value * 2;
});
console.log(result);
// [0, 2, 4, 6, 8]
Array.prototype.map
で同じことができます。
var result = [0, 1, 2, 3, 4].map(function (value) {
return value * 2;
});
console.log(result);
// [0, 2, 4, 6, 8]
$.merge()
配列をマージする時に使うメソッドです。
var
asterisk = ['前川みく', '多田李衣菜'],
natsunana = ['木村夏樹', '安部菜々'];
$.merge(asterisk, natsunana);
console.log(asterisk);
// ["前川みく", "多田李衣菜", "木村夏樹", "安部菜々"]
これも簡単に書き直せます。(変数は同じ)
// Array.prototype.push.apply
asterisk.push.apply(asterisk, natsunana);
console.log(asterisk);
// ["前川みく", "多田李衣菜", "木村夏樹", "安部菜々"]
ECMAScript 2015 なら更にこのように書けます。
// Array.prototype.push
asterisk.push(...natsunana);
console.log(asterisk);
// ["前川みく", "多田李衣菜", "木村夏樹", "安部菜々"]
$.type()
指定したオブジェクトの型(クラス)を判定します。
$.type([]); // "array"
$.type(''); // "string"
$.type(function () {}); // "function"
Object.prototype.toString.call()
で同じことができます。
var toString = Object.prototype.toString;
function typeOf(obj) {
return toString.call(obj).slice(8, -1).toLowerCase();
}
typeOf([]); // "array"
typeOf(''); // "string"
typeOf(function () {}); // "function"
DOM操作系メソッド
jQueryといえばやはりこちらがメインですよね。よく使いそうなものだけ取り上げています。
$(function () {}), $(document).ready(function () {})
DOM構築が完了した後に実行します。これをやらないとうまく要素が取得できない原因になります。
// 通常
$(function () {
// do something
});
// 非推奨
$(document).ready(function () {
// do something
});
document.addEventListener('DOMContentLoaded', function () {
// do something
});
$('<tag>'), $('<tag attribute="value">content</tag>')
新しいHTML要素を生成します。
配列に似たjQueryオブジェクトが返ります。
// span要素の生成
$('<span>');
$('<span/>');
$('<span></span>');
// 中にテキストを含めたp要素の生成
$('<p>よぉこそぉ↑ジャパリカフェへ〜!</p>');
$('<p>').text('よぉこそぉ↑ジャパリカフェへ〜!');
// img要素の生成
$('<img src="./japaripark.jpg" alt="ジャパリパーク">');
$('<img>').attr({
src: './japaripark.jpg',
alt: 'ジャパリパーク',
});
// 生成した要素を #appendBlock に追加
$('<div>どうぞどうぞ! ゆっぐりしていってぇ!</div>').appendTo('#appendBlock');
// span要素の生成
var span = document.createElement('span');
// 中にテキストを含めたspan要素の生成
var paragraph = document.createElement('p');
paragraph.textContent = 'よぉこそぉ↑ジャパリカフェへ〜!';
// img要素の生成(パターン1)
var img01 = document.createElement('img');
img01.src = './japaripark.jpg';
img01.alt = 'ジャパリパーク';
// img要素の生成(パターン2)
var img02 = new Image();
img02.src = './japaripark.jpg';
img02.alt = 'ジャパリパーク';
// 生成した要素を #appendBlock に追加
var div = document.createElement('div');
div.textContent = 'どうぞどうぞ! ゆっぐりしていってぇ!';
document.getElementById('appendBlock').appendChild(div);
$('selector')
HTML要素を取得する方法です。CSSセレクタのように書けるので非常に便利ですよね。
配列に似たjQueryオブジェクトが返ります。
// idが "mainFooter" の要素を取得
$('#mainFooter');
// class名が "entries" の要素を取得
$('.entries');
// div要素を取得
$('div');
// article要素の子要素であるp要素を取得
$('article p');
$('article').find('p');
// ul要素とol要素の取得
$('ul, ol');
// チェックが付いたinput要素の取得
$('input:checked');
$('input').filter(':checked');
// target属性のないa要素を取得
$('a:not([target])');
$('a').not('[target]');
JavaScriptでは様々な取得方法があります。
document.getElementById
と document.querySelector
はHTML要素が、それ以外は配列に似た HTMLCollection
や NodeList
が返ります。
// idが "mainFooter" の要素を取得
document.getElementById('mainFooter'); // 処理が速い
document.querySelector('#mainFooter');
// class名が "entries" の要素を取得
document.getElementsByClassName('entries'); // 処理が速い
document.querySelectorAll('.entries');
// div要素を取得
document.getElementsByTagName('div'); // 処理が速い
document.querySelectorAll('div');
// article要素の子要素であるp要素を取得
document.querySelectorAll('article p');
// ul要素とol要素の取得
document.querySelectorAll('ul, ol');
// チェックが付いたinput要素の取得
document.querySelectorAll('input:checked');
// target属性のないa要素を取得
document.querySelectorAll('a:not([target])');
document.querySelectorAll
がほぼ同じ働きをしてくれています。
document.getElementsByTagName
や document.getElementsByClassName
が返す HTMLCollection
は動的な要素のリストで、document.querySelectorAll
が返す NodeList
は静的な要素のリストです。
何が違うのかというと、操作している途中で要素が追加されたりすると HTMLCollection
の中身と length
が変化するのに対して、NodeList
は取得した当時の値を保持したままです。なので、扱いに注意が必要です。
また、NodeList
は配列の Array.prototype.forEach()
と同じように NodeList.forEach()
が使用可能です。
以降、複数パターンを書くと煩雑になるので、基本的に単体のHTML要素の取得には document.querySelector
を、複数のHTML要素の取得には document.querySelectorAll
を使用する方法で解説します。
(実際には状況によって document.getElementById
, document.getElementsByTagName
, document.getElementsByClassName
なども使い分けるなどしましょう)
.each()
取得した要素のループ処理を行うメソッドです。
// '.article p' のループ処理
$('.article p').each(function (i, element) {
// do something
});
// '.article p' のループ処理
document.querySelectorAll('.article p').forEach(function (element, i) {
// do something
});
.find()
子要素(孫要素、ひ孫要素なども含む)を取得します。
// #mainNavigation の li を取得
$('#mainNavigation').find('li');
// .entries の h2 と h3 を取得
$('.entries').find('h2, h3');
/* 本来ならばこのように書く方がわかりやすい */
// #mainNavigation の li を取得
$('#mainNavigation li');
// .entries の h2 と h3 を取得
$('.entries h2, .entries h3');
/* あえて複雑な書き方をする場合 */
// #mainNavigation の li を取得(4通り)
document.getElementById('mainNavigation').getElementsByTagName('li'); // 処理が速い
document.getElementById('mainNavigation').querySelectorAll('li');
document.querySelector('#mainNavigation').getElementsByTagName('li');
document.querySelector('#mainNavigation').querySelectorAll('li');
// .entries の h2 と h3 を取得(配列にHTML要素を入れる方法)
var elements = [];
document.querySelectorAll('.entries').forEach(function (element) {
elements.push.apply(elements02, element.querySelectorAll('h2, h3'));
});
/// elements に h2 と h3 が入る
/* 本来ならばこのように書く方がわかりやすい */
// #mainNavigation の li を取得
document.querySelectorAll('#mainNavigation li');
// .entries の h2 と h3 を取得
document.querySelectorAll('.entries h2, .entries h3');
.html(), .text(), .empty()
指定した要素内のHTMLやテキストを取得・変更・空にします。
var $welcome = $('.welcome');
// .welcome 内のHTMLを取得
$welcome.html(); // 例えば "<b>ようこそ!</b>"
// .welcome 内のテキストを取得
$welcome.text(); // 例えば "ようこそ!"
// .welcome 内のHTMLを変更
$welcome.html('<b>いらっしゃぁい!</b>');
// .welcome 内のテキストを変更
$welcome.text('よぉこそぉ↑ジャパリカフェへ〜!');
// .welcome 内を空にする
$welcome.empty();
var welcome = document.querySelectorAll('.welcome');
// .welcome 内のHTMLを取得
welcome.innerHTML; // 例えば "<b>ようこそ!</b>"
// .welcome 内のテキストを取得
welcome.textContent; // 例えば "ようこそ!"
// .welcome 内のHTMLを変更
welcome.innerHTML = '<b>いらっしゃぁい!</b>';
// .welcome 内のテキストを変更
welcome.textContent = 'よぉこそぉ↑ジャパリカフェへ〜!';
// .welcome 内を空にする
welcome.textContent = '';
.attr(), .removeAttr()
要素の属性の値を取得、属性の追加・変更・削除を行います。
// #mainImage のalt属性を取得
$('#mainImage').attr('alt'); // 例えば "けものフレンズ"
// .targetLink にtarget属性を追加する
$('.targetLink').attr('target', '_blank');
$('.targetLink').attr({target: '_blank'});
// .targetLink のtarget属性を取り除く
$('.targetLink').removeAttr('target');
// #mainImage のalt属性を取得
document.querySelector('#mainImage').getAttribute('alt'); // 例えば "けものフレンズ"
// .targetLink にtarget属性を追加する
document.querySelectorAll('.targetLink').forEach(function (element) {
element.setAttribute('target', '_blank');
});
// .targetLink のtarget属性を取り除く
document.querySelectorAll('.targetLink').forEach(function (element) {
element.removeAttribute('target');
});
.addClass(), .removeClass(), .toggleClass()
要素のクラス名を操作するします。
var $elements = $('li a');
// 'li a' にクラス 'listLink' を追加
$elements.addClass('listLink');
// 'li a' のクラス 'listLink' を削除
$elements.removeClass('listLink');
// 'li a' のクラス 'listLink' がない場合は追加し、ある場合は削除する
$elements.toggleClass('listLink');
var elements = document.querySelectorAll('li a');
// 'li a' にクラス 'listLink' を追加
elements.forEach(function (element) {
element.classList.add('listLink');
});
// 'li a' のクラス 'listLink' を削除
elements.forEach(function (element) {
element.classList.remove('listLink');
});
// 'li a' のクラス 'listLink' がない場合は追加し、ある場合は削除する
elements.forEach(function (element) {
element.classList.toggle('listLink');
});
.css()
要素のスタイルを取得したり、スタイルを適用します。
// 最初に取得できる .redBox のスタイルを取得
$('.redBox').css('background-color'); // 例えば "rgb(255, 0, 0)"
$('.redBox').css('backgroundColor'); // 例えば "rgb(255, 0, 0)"
// .targetBox にスタイルを適用
$('.targetBox').css('margin-bottom', 50);
$('.targetBox').css('marginBottom', 50);
$('.targetBox').css({'margin-bottom': 50});
$('.targetBox').css({marginBottom: 50});
// 最初に取得できる .redBox のスタイルを取得
var
redBox = document.querySelector('.redBox'),
redBoxStyle = window.getComputedStyle(redBox); // getComputedStyle を使う
redBoxStyle.backgroundColor; // 例えば "rgb(255, 0, 0)"
redBoxStyle.getPropertyValue('background-color'); // 例えば "rgb(255, 0, 0)"
// .targetBox にスタイルを適用
document.querySelectorAll('.targetBox').forEach(function (element) {
element.style.marginBottom = '50px';
// チェインケースの場合
// element.style.setProperty('margin-bottom', '50px');
});
window.getComputedStyle()
については、自分が前に書いたものを見てもらうと分かると思います。
window.getComputedStyle() で要素のスタイルを取得する
.prop()
要素のプロパティを取得・変更します。
// 取得した要素の nodeName を取得する
$('.mainArticle').prop('nodeName'); // 例えば "ARTICLE"
// 2番目のチェックボックスにチェックを入れる
$('input[type="checkbox"]').eq(1).prop('checked', true);
$('input[type="checkbox"]').eq(1).prop({checked: true});
// 複数のテキストフォームを空にして disabled にする
$('input[type="text"]').prop({
value: '',
disabled: true,
});
// 取得した要素の nodeName を取得する
var mainArticle = document.querySelector('.mainArticle');
mainArticle.nodeName; // 例えば "ARTICLE"
// 2番目のチェックボックスにチェックを入れる
var checkbox = document.querySelectorAll('input[type="checkbox"]');
checkbox[1].checked = true;
// 複数のテキストフォームを空にして disabled にする
var inputText = document.querySelectorAll('input[type="text"]');
inputText.forEach(function (element) {
element.value = '';
element.disabled = true;
});
.eq()
n番目の要素を取り出します。
var $lists = $('#linkList li');
// '#linkList li' の4つ目を取り出す
$lists.eq(3);
// '#linkList li' の後ろから2つ目を取り出す
$lists.eq(-2);
var lists = document.querySelectorAll('#linkList li');
// '#linkList li' の4つ目を取り出す
lists[3];
// '#linkList li' の後ろから2つ目を取り出す
lists[lists.length - 2];
.first(), .last()
取得した要素リストの最初・最後の要素を取り出します。
var $lists = $('#linkList li');
// '#linkList li' の最初の要素を取り出す
$lists.first();
// '#linkList li' の最後の要素を取り出す
$lists.last();
var lists = document.querySelectorAll('#linkList li');
// '#linkList li' の最初の要素を取り出す
lists[0];
// '#linkList li' の最後の要素を取り出す
lists[lists.length - 1];
.filter(), .not()
取得した要素リストを特定の条件に当てはまる・当てはまらないかでフィルタリングします。
var $variousElement = $('.variousElement');
// .variousElement で span のみを取得
$('.variousElement').filter('span');
// .variousElement で span 以外を取得
$('.variousElement').not('span');
var $input = $('input');
// input属性の :checked のみを取得
$('input').filter(':checked');
// input属性の :disabled 以外を取得
$('input').not(':disabled');
/* 本来ならばこのように書く方がわかりやすい */
// input属性の :checked のみを取得
$('input:checked');
// input属性の :disabled 以外を取得
$('input:not(:disabled)');
// .variousElement で span のみを取得
document.querySelectorAll('span.variousElement');
// .variousElement で span 以外を取得
document.querySelectorAll('.variousElement:not(span)');
// input属性の :checked のみを取得
document.querySelectorAll('input:checked');
// input属性の :disabled 以外を取得
document.querySelectorAll('input:not(:disabled)');
.children()
要素の直下にある子要素を取得します。
// .entries 直下の子要素を取得
$('.entries').children();
// .entries 直下の div を取得
$('.entries').children('div');
/* 本来ならばこのように書く方がわかりやすい */
// .entries 直下の子要素を取得
$('.entries > *');
// .entries 直下の div を取得
$('.entries > div');
// .entries 直下の子要素を取得
document.querySelectorAll('.entries > *');
// .entries 直下の div を取得
document.querySelectorAll('.entries > div');
.parent()
要素の親要素を取得します。
// .children の親要素の取得
$('.children').parent();
// .children の親要素の取得
var parents = [];
document.querySelectorAll('.children').forEach(function (element) {
parents.push(element.parentNode);
});
/// 重複しているかもしれないので filter を使う
parents = parents.filter(function (element, i) {
return parents.indexOf(element) === i;
});
.next(), .prev()
要素の前後にある要素を取得します。
// .target の後にある要素の取得
$('.target').next();
// .target の前にある要素の取得
$('.target').prev();
// .target の後にある要素の取得
document.querySelectorAll('.target + *');
// .target の後にある要素の取得その2(nextElements に入る)
var nextElements = [];
document.querySelectorAll('.target').forEach(function (element) {
if (element.nextElementSibling) {
nextElements.push(element.nextElementSibling);
}
});
// .target の前にある要素の取得(prevElements に入る)
var prevElements = [];
document.querySelectorAll('.target').forEach(function (element) {
if (element.previousElementSibling) {
prevElements.push(element.previousElementSibling);
}
});
.clone()
要素を複製します。
// .sampleElement を複製
$('.sampleElement').clone();
// .sampleElement を複製(cloneElements に入る)
var cloneElements = [];
document.querySelectorAll('.sampleElement').forEach(function (element) {
cloneElements.push(element.cloneNode(true));
});
// .sampleElement(単体)を複製
document.querySelector('.sampleElement').cloneNode(true);
.remove()
要素をDOMから取り除きます。(削除ではない)
// .ignore を取り除く
$('.ignore').remove();
// .ignore を取り除く
document.querySelectorAll('.ignore').forEach(function (element) {
element.parentNode.removeChild(element);
// IE以外のブラウザではこの方法も使える
// element.remove();
});
.before(), .prepend(), .append(), .after()
指定した要素にHTMLや要素を挿入します。
こんな感じのHTMLがあったとします。
<p id="naninomu">ねえなんにぃのんむぅ</p>
<div id="targetBlock">
<p>ゆっぐりしてってぇ!</p>
</div>
var $targetBlock = $('#targetBlock');
// #targetBlock の前にHTMLを挿入
$targetBlock.before('<p id="p01">ふわああぁ!</p>');
// #targetBlock 内の先頭にHTMLを挿入
$targetBlock.prepend('<p id="p02">どうぞどうぞ!</p>');
// #targetBlock 内の一番後ろにHTMLを挿入
$targetBlock.append('<p id="p03">いやま゛っ↓てたよぉ!</p>');
// #targetBlock の後ろにHTMLを挿入
$targetBlock.after('<p id="p04">色々あるよぉ</p>');
// #targetBlock の前に、生成した要素を挿入
var $paragraph01 = $('<p id="p05">いらっしゃぁい!</p>');
$targetBlock.before($paragraph01);
// #targetBlock 内の先頭に、生成した要素を挿入
var $paragraph02 = $('<p id="p06">よぉこそぉ↑ジャパリカフェへ〜!</p>');
$targetBlock.prepend($paragraph02);
// #targetBlock 内の一番後ろに、生成した要素を挿入
var $paragraph03 = $('<p id="p07">やっとお客さんが来てくれたゆぉ!</p>');
$targetBlock.append($paragraph03);
// #targetBlock の後ろに、生成した要素を挿入
var $paragraph04 = $('<p id="p08">嬉しいなあ!</p>');
$targetBlock.after($paragraph04);
// #p08 の後ろに、#naninomu を挿入(移動)
$('#p08').after($('#naninomu'));
var targetBlock = document.querySelector('#targetBlock');
// #targetBlock の前にHTMLを挿入
targetBlock.insertAdjacentHTML('beforebegin', '<p id="p01">ふわああぁ!</p>');
// #targetBlock 内の先頭にHTMLを挿入
targetBlock.insertAdjacentHTML('afterbegin', '<p id="p02">どうぞどうぞ!</p>');
// #targetBlock 内の一番後ろにHTMLを挿入
targetBlock.insertAdjacentHTML('beforeend', '<p id="p03">いやま゛っ↓てたよぉ!</p>');
// #targetBlock の後ろにHTMLを挿入
targetBlock.insertAdjacentHTML('afterend', '<p id="p04">色々あるよぉ</p>');
// #targetBlock の前に、生成した要素を挿入
var paragraph01 = document.createElement('p');
paragraph01.id = 'p05';
paragraph01.textContent = 'いらっしゃぁい!';
targetBlock.parentNode.insertBefore(paragraph01, targetBlock);
/// 「#targetBlock の親要素」内にある子要素の #targetBlock の前に paragraph01 を挿入、ということ
// #targetBlock 内のの先頭に、生成した要素を挿入
var paragraph02 = document.createElement('p');
paragraph02.id = 'p06';
paragraph02.textContent = 'よぉこそぉ↑ジャパリカフェへ〜!';
targetBlock.insertBefore(paragraph02, targetBlock.firstChild);
/// #targetBlock 内にある最初の子要素の前に paragraph01 を挿入、ということ
// #targetBlock 内の一番後ろに、生成した要素を挿入
var paragraph03 = document.createElement('p');
paragraph03.id = 'p07';
paragraph03.textContent = 'やっとお客さんが来てくれたゆぉ!';
targetBlock.appendChild(paragraph03);
// #targetBlock の後ろに、生成した要素を挿入
var paragraph04 = document.createElement('p');
paragraph04.id = 'p08';
paragraph04.textContent = '嬉しいなあ!';
targetBlock.parentNode.insertBefore(paragraph04, targetBlock.nextSibling);
/// 「#targetBlock の親要素」内にある子要素の #targetBlock の
/// 次にあるノード(テキストや要素など)の前に挿入、ということ
// #p08 の後ろに、#naninomu を挿入(移動)
var p08 = document.querySelector('#p08');
p08.parentNode.insertBefore(document.querySelector('#naninomu'), p08.nextSibling);
最終的にHTMLはこのような感じになります。
<p id="p01">ふわああぁ!</p>
<p id="p05">いらっしゃぁい!</p>
<div id="targetBlock">
<p id="p06">よぉこそぉ↑ジャパリカフェへ〜!</p>
<p id="p02">どうぞどうぞ!</p>
<p>ゆっぐりしてってぇ!</p>
<p id="p03">いやま゛っ↓てたよぉ!</p>
<p id="p07">やっとお客さんが来てくれたゆぉ!</p>
</div>
<p id="p08">嬉しいなあ!</p>
<p id="naninomu">ねえなんにぃのんむぅ</p>
<p id="p04">色々あるよぉ</p>
このサンプルでは生成した要素を挿入していますが、既にDOM上にある要素も同じように扱えます。
.insertBefore(), .prependTo(), .appendTo(), .insertAfter()
要素を指定した要素に挿入します。
こんな感じのHTMLがあったとします。
<p id="yukkuri">ゆっぐりしてってぇ!</p>
<div id="targetBlock">
<p>よぉこそぉ↑ジャパリカフェへ〜!</p>
</div>
// 生成した要素を #targetBlock の前に挿入
$('<p id="p01">ふわああぁ!</p>').insertBefore('#targetBlock');
// 生成した要素を #targetBlock 内の先頭に挿入
$('<p id="p02">いらっしゃぁい!</p>').prependTo('#targetBlock');
// 生成した要素を #targetBlock 内の一番後ろに挿入
$('<p id="p03">どうぞどうぞ!</p>').appendTo('#targetBlock');
// 生成した要素を #targetBlock の後ろに挿入
$('<p id="p04">いやま゛っ↓てたよぉ!</p>').insertAfter('#targetBlock');
var targetBlock = document.querySelector('#targetBlock');
/* 考えは .before(), .prepend(), .append(), .after() と同じ*/
// 生成した要素を #targetBlock の前に挿入
var paragraph01 = document.createElement('p');
paragraph01.id = 'p01';
paragraph01.textContent = 'ふわああぁ!';
targetBlock.parentNode.insertBefore(paragraph01, targetBlock);
// 生成した要素を #targetBlock 内の先頭に挿入
var paragraph02 = document.createElement('p');
paragraph02.id = 'p02';
paragraph02.textContent = 'いらっしゃぁい!';
targetBlock.insertBefore(paragraph02, targetBlock.firstChild);
// 生成した要素を #targetBlock 内の一番後ろに挿入
var paragraph03 = document.createElement('p');
paragraph03.id = 'p03';
paragraph03.textContent = 'どうぞどうぞ!';
targetBlock.appendChild(paragraph03);
// 生成した要素を #targetBlock の後ろに挿入
var paragraph04 = document.createElement('p');
paragraph04.id = 'p04';
paragraph04.textContent = 'いやま゛っ↓てたよぉ!';
targetBlock.parentNode.insertBefore(paragraph04, targetBlock.nextSibling);
// #p04 の前に、#yukkuri を挿入(移動)
var p04 = document.querySelector('#p04');
p04.parentNode.insertBefore(document.querySelector('#yukkuri'), p04);
<p id="p01">ふわああぁ!</p>
<div id="targetBlock">
<p id="p02">いらっしゃぁい!</p>
<p>よぉこそぉ↑ジャパリカフェへ〜!</p>
<p id="p03">どうぞどうぞ!</p>
</div>
<p id="yukkuri">ゆっぐりしてってぇ!</p>
<p id="p04">いやま゛っ↓てたよぉ!</p>
.offset(), .position()
ドキュメントルートからみた要素の座標(絶対座標)、親要素から見た要素の座標を取得します。
var $absoluteBlock = $('#absoluteBlock');
// のドキュメントルートからみた #absoluteBlock の座標の取得
var offset = $absoluteBlock.offset();
offset.left; // X座標
offset.top; // Y座標
// 親要素から見た #absoluteBlock の座標の取得
var position = $absoluteBlock.position();
position.left; // X座標
position.top; // Y座標
var absoluteBlock = document.querySelector('#absoluteBlock');
// のドキュメントルートからみた #absoluteBlock の座標の取得
function getOffset(element) {
var rect = element.getClientRects().length > 0 ? element.getBoundingClientRect() : {top: 0, left: 0};
return {
top: rect.top + window.pageYOffset - document.documentElement.clientTop,
left: rect.left + window.pageXOffset - document.documentElement.clientLeft,
};
}
var offset = getOffset(absoluteBlock);
offset.left; // X座標
offset.top; // Y座標
// 親要素から見た #absoluteBlock の座標の取得
function getPosition(element) {
var
offset, offsetParent,
parent = {top: 0, left: 0},
style = window.getComputedStyle(element);
if (style.position === 'fixed') {
offset = element.getBoundingClientRect();
} else {
offset = getOffset(element);
offsetParent = element.offsetParent || document.documentElement;
if (offsetParent.nodeName !== 'HTML') {
parent = getOffset(offsetParent);
}
parent.top += parseFloat(style.borderTopWidth);
parent.left += parseFloat(style.borderLeftWidth);
}
return {
top: offset.top - parent.top - parseFloat(style.marginTop),
left: offset.left - parent.left - parseFloat(style.marginLeft),
};
}
var position = getPosition(absoluteBlock);
position.left; // X座標
position.top; // Y座標
これはちょっとめんどくさいかも……
.show(), .hide()
要素を表示・非表示にします。
// #hiddenContent を表示
$('#hiddenContent').show();
// #visibleContent を非表示
$('#visibleContent').hide();
/* 表示するときすべて display: block; でいい場合 */
// #hiddenContent を表示
document.querySelector('#hiddenContent').style.display = 'block';
// #visibleContent を非表示
document.querySelector('#visibleContent').style.display = 'none';
/* 表示するときに要素の display の初期値にしたい場合 */
var defaultDisplay = {DIV: 'block', SPAN: 'inline'};
function getDefaultDisplay(element) {
var nodeName = element.nodeName;
if (!defaultDisplay[nodeName]) {
element = createElement(nodeName, document.body);
defaultDisplay[nodeName] = window.getComputedStyle(element).display;
document.body.removeChild(element);
}
return defaultDisplay[nodeName];
}
// #hiddenContent を表示
var hiddenContent = document.querySelector('#hiddenContent');
hiddenContent.style.display = getDefaultDisplay(hiddenContent);
.on(), .off(), .click()等
要素のイベントを追加・削除します。
var $clickHere = $('#clickHere');
// #clickHere にクリックイベントを追加
$clickHere.on('click', function (ev) {
// do something
});
// または
// $clickHere.click(function (ev) {
// // do something
// });
// #clickHere からクリックイベントの削除
$clickHere.off('click');
var clickHere = document.querySelector('#clickHere');
// クリックイベント関数
function clickEvent(ev) {
// do something
};
// #clickHere にクリックイベントを追加
clickHere.addEventListener('click', clickEvent);
// #clickHere からクリックイベントの削除
clickHere.removeEventListener('click', clickEvent);
.one()
イベントを一度だけ実行します
// #clickHere に一度だけ有効なクリックイベントを追加
$('#clickHere').one('click', function (ev) {
// do something
});
var clickHere = document.querySelector('#clickHere');
// #clickHere に一度だけ有効なクリックイベントを追加
clickHere.addEventListener('click', function clickEvent(ev) {
clickHere.removeEventListener('click', clickEvent);
// do something
});
.hover()
マウスのホバーイベントを追加します。
// #hoverHere にホバーイベントを追加
$('#hoverHere').hover(function (ev) {
// mouseenter
// do something
}, function (ev) {
// mouseleave
// do something
});
var clickHere = document.querySelector('#clickHere');
// #hoverHere にホバーイベントを追加
clickHere.addEventListener('mouseenter', function (ev) {
// do something
});
clickHere.addEventListener('mouseleave', function (ev) {
// do something
});
mouseover
と mouseout
ではないんですね。
アニメーション
jQueryはアニメーションが簡単に設定できて便利ですが、CSSでもアニメーションを行えるのでそれで代わりに書いてみようという感じです。
フェードイン・フェードアウト
ボタンをクリックすると画像がフェードイン・フェードアウトを繰り返す動作をやってみます。
<div id="fadeEffectTarget"><img src="./serval-chan.jpg" width="100" height="200" alt="サーバルちゃん"></div>
<button id="fadeEffect">Click Here</button>
jQueryを使った例
$('#fadeEffect').click(function () {
$('#fadeEffectTarget').fadeToggle(300);
});
jQueryを使わない例
#fadeEffectTarget {
transition: opacity 300ms ease;
}
.fadeOut {
opacity: 0;
}
ただ単にフェードするアニメーションの場合
var target = document.querySelector('#fadeEffectTarget');
document.querySelector('#fadeEffect').addEventListener('click', function () {
target.classList.toggle('fadeOut');
});
フェードアウト時に display: none; にする必要がある場合
var target = document.querySelector('#fadeEffectTarget');
document.querySelector('#fadeEffect').addEventListener('click', function () {
var transitionEnd = function () {
target.removeEventListener('transitionend', transitionEnd);
target.style.display = 'none';
};
if (target.classList.contains('fadeOut')) {
target.removeEventListener('transitionend', transitionEnd);
target.style.display = 'block';
setTimeout(function () {
target.classList.remove('fadeOut');
});
} else {
target.classList.add('fadeOut');
target.addEventListener('transitionend', transitionEnd);
}
});
他のアニメーションに関しては後日追加する、かも?
おわりに
DOM関係の操作ってやっぱり面倒ですね。jQueryはやはり便利……
しかし、こういった事を行っていくことで、更にJavaScriptでのDOM関係の操作について理解が深まるのではないかと思います。