HTML・CSS・Javascriptなどのメモブログ│CODE-LIFE

WEB製作の仕事を始めたMaruのhtml・CSS・jsメモブログ。たまにExcelVBAの話もでます。

【脱jQuery?】jQueryみたいなセレクタが使えるdocument.querySelectorが便利

この記事でできるようになること

ちょっとしたjavascriptを書くだけなのにCSSっぽいセレクタを使って楽したいがためにjQueryライブラリを読ませるのは面倒。

document.getElementById('aaa').getElementsByClassName('bbb')[0]

なんて書くの長すぎ。

jQuery使わずにもっと短い書き方無いんかい!

と思って調べたところありました。

 

document.querySelector

概要

与えられた CSS セレクタにマッチする文書中の最初の要素(※深さ優先の先行順走査によるもの)を返します。

構文

element = document.querySelector( selectors );

引用元:document.querySelector - Web API インターフェイス | MDN

つまり、jQuery読み込まずにjQueryと同じセレクタが使える。これです。探していたやつ。

 

使用例

See the Pen querySelector by maru (@maru0014) on CodePen.

 

複雑なセレクタじゃないならgetElementsByClassNameの方が早い?

MDNの例を見てみるとクラス名で単一の要素を取得する場合は.getElementsByClassNameの方が処理速度が早いとあります。 document.querySelectorでクラス名指定する場合は複雑なセレクタになるときだけ使うのが良さそうです。2階層以上指定のときとかでしょうか

element = document.getElementsByClassName('aaa')[0].getElementsByClassName('bbb')[0]

element = document.querySelector('.aaa > .bbb');

これくらい差があればquerySelectorの方がいいですね。状況に応じて使い分けるか、速度はそこまで求めないから全部querySelectorでやっちゃうかってとこです。

 

一発で配列化できるdocument.querySelectorAll

document.querySelectorはクラス名で指定した時も最初にマッチした単一の要素を取ってきます。

対してdocument.querySelectorAllセレクタにマッチした要素を全て配列として格納してくれる。

.getElementsByClassName('bbb')と同じ挙動ですね。

これもおそらく.querySelectorAllよりも.getElementsByClassNameが速度的には早いのかもしれませんが、セレクタが複雑な場合は.querySelectorAllを使うことになるでしょう。

 

使用例

See the Pen querySelectorAll by maru (@maru0014) on CodePen.

上記.collection > .collection-item > spanというセレクタで配列にしています。 もし.getElementsByClassNameなどを用いて書くなら

//CLASSでセレクトして配列に格納
var list = document.getElementsByClassName('collection')[0].getElementsByClassName('collection-item');

//listの数だけ繰り返し
for(var i = 0; i < list.length; i++) { 
  //連番を付ける
  list[i].getElementsByTagName('span')[0].textContent = [i+1] + '.' + list[i].getElementsByTagName('span')[0].innerText;
}

となります。長いいいいい。 いや、まぁ連番付けるのjavascriptでやんなよって話は置いといて。

とにかく短く、簡単に書ける。 でもjQuery使っていい状況ならjQuery使ったほうが結局楽なんですがね。ちょっとしたプログラムのためにjQuery読ませるの重すぎてやだってときにquerySelectorを使うことにします。

  getElementの使い方はこちら code-life.hatenablog.com

HTML要素を超簡単に横並びにできるCSSの書き方 Flexbox

この記事でできるようになること

  • divやliの表示をキレイに簡単に横並びにできる

去年(2016年)くらいまでは未だ使うのは早いかなというような状況だったFlexible Box Layout(フレキシブルボックスレイアウト)。通称flexbox。 そろそろ使っても良いんじゃないでしょうか。

Flexboxのブラウザ対応状況

f:id:maru0014:20171119175621p:plain

参考: Can I use... Support tables for HTML5, CSS3, etc

 

(例)Flexboxで要素を横並びに

See the Pen flexbox by maru (@maru0014) on CodePen.

キレイにdiv要素が横並びになってますね。6つの子要素が横並びになっていますが、width(幅)指定は100%です。 width:calc(100%/6);でもなく、width:16.666667%;でもありません。これもFlexboxのすごいところ。 display:flex;が指定された親要素を持つ子要素は6等分のサイズを指定しなくてもいいかんじに等分してくれます。

7つ目の子要素を足そうが、8つ目を足そうが、改行されることなく横並びに。 そしてfloat:left;と違ってclearfix不要です。素晴らしい。

 

使い方は親要素に一行追記するだけ

.row {
  display: flex;/*これを入れるだけで横並び*/
  background: #ccc;
}

前述した実装例でもdisplay: flex;CSSに追記してあります。 超絶楽です。

 

3つごとに改行(3等分)にしたい場合はflex-wrap:wrap;を追記

flexbox化した親要素の属性にflex-wrap:wrap;を追記すると回り込み(改行)が有効化されます。

.row {
  display: flex;
  flex-wrap:wrap;/*回り込み有効化*/
  background: #ccc;
}

そしてfloat:left;の時のように子要素のサイズを指定

.col {
  width: calc(100% / 3);/*3等分*/
}

(例)子要素をキレイに3列で表示

See the Pen flexbox-wrap by maru (@maru0014) on CodePen.

いかがでしょうか。 今までfloat:left;で横並びにして、サイズ指定して、clearfixして、という作り方だったものが3つのプロパティだけで実装できてしまいました。

【2017年最新】clearfix一番短い書き方は親要素にdisplay:flow-root;を書き加えるだけ

clearfixが適用されていない状態

See the Pen flow-root by maru (@maru0014) on CodePen.

float:left;でdiv要素を横並びにしましたが、clearfixを行っていないため外枠の.rowが上の方でちっちゃくなってしまいました。 現状で最もスマートな、短いclearfixとしては以下のような書き方でしょうか。

.row:after {
    content: "";
    display: table;
    clear: both;
}

Googleが作り上げたフレームワーク「マテリアライズDocumentation - Materialize)」においても上記のような記述となっていたため、これが現時点での最も正解に近い書き方なのかもしれません。 しかし、今後は新しい属性値flow-rootによって更に簡単に実装できそうです。

参考: CSS Display Module Level 3

display:flow-root;を書き加えた

See the Pen flow-root-on by maru (@maru0014) on CodePen.

変更点は一行のみ親要素div.rowdisplay:flow-root;を追記しただけです。 これは超簡単!

ただし、Safari未対応

f:id:maru0014:20171119160554p:plain 参考: Can I use... Support tables for HTML5, CSS3, etc

ChromeFirefoxoperaは対応しているようですが、Edgeやsafariは未対応。 AndroidはOK、iPhoneは✕という状況です。(IEは知らん)

結局まだclearfixは必要かな

ゆくゆくはsafariも対応するでしょうが、それまでは前述したafter要素によるclearfixが最適かと思います。 対応するまではこれを使いましょう。

.row:after {
    content: "";
    display: table;
    clear: both;
}

他の手段としてはflexboxを使うという方法もありますね。

code-life.hatenablog.com

jQueryを使わないjavascriptでの要素取得方法とテキストの書き換え

今までなんとなーくで書いて、動くからまぁいいか。でやってきてたjavascriptをきちんと勉強しようと思うので、少しずつメモ書きをためていきます。 今回はhtmlドキュメントツリー内の「id」、「class」、「name」を指定して要素取得します。

IDでテキストを取得

getElementById

var test = document.getElementById('aaa').textContent;

idを指定して単一の要素を取得.textContentで要素内のテキストを抽出しています。

テキストを書き換え

document.getElementById('aaa').textContent = '書き換えしました';

=の左右を入れ替えることで要素内のテキストを書き換えることができます。

 

CLASSでテキストを取得

getElementsByClassName

var test = document.getElementsByClassName('bbb')[0].textContent;

classを指定して要素のコレクションを取得し、[0]で何番目の要素かを指定し、.textContentで要素内のテキストを抽出しています。 getElementsというふうに複数形になっているため、何番目の要素を取ってくるのかを指定する必要があるわけです。 プログラミングにおいては[0]から順にカウントしていくので、[0]で上から1番目の要素となり、[1]なら上から2番目の要素となります。

テキストを書き換え

document.getElementsByClassName('bbb')[0].textContent = '書き換えしました';

 

タグの名前を指定してテキストを取得

getElementsByTagName

var test = document.getElementsByTagName('a')[0].textContent;

タグ名で取得する場合もClassNameと同様にコレクションを取得するので、[0]で何番目かを指定します。

テキストを書き換え

document.getElementById('ccc').getElementsByTagName('a')[0].textContent = '書き換えしました';

 

親要素を指定して子要素のテキストを取得

getElementById.getElementsByTagName

var test = document.getElementById('ccc').getElementsByTagName('a')[0].textContent;

まず親要素を指定、さらにその中に含まれている子要素を取得します。

テキストを書き換え

document.getElementById('ccc').getElementsByTagName('a')[0].textContent = '書き換えしました';

 

nameでテキストを取得

getElementsByName

document.getElementsByName("ddd")[0].textContent;

テキストを書き換え

document.getElementsByName("ddd")[0].textContent = '書き換えしました';
↓この本で勉強中!

確かな力が身につくJavaScript「超」入門 (確かな力が身につく「超」入門シリーズ)

確かな力が身につくJavaScript「超」入門 (確かな力が身につく「超」入門シリーズ)

あくまで自分用のメモ書きのつもりですが、使えそうだったらコピペで使ってやってください。 なにか間違ってたりもっと良い方法があったら教えてくださいな。

シートの最終行番号を取得するユーザー定義関数 - VBA(エクセルマクロ)

最近仕事で受注・発注業務のオートメーション化をするにあたって、VBAで良く使う「シート内で利用している最終行番号を取得する」「特定のセルを基準に一番下のセルの行番号を取得する」ユーザー定義関数をメモとして残しておきます。

シート名を引数にユーザー定義関数を記述

Function maxRow(ByVal sheetName As String) As Integer 
    maxRow = Sheets(sheetName).UsedRange.Rows.Count
End Function

これで関数の定義はできました。

シートの名前を指定して関数を呼び出す

    Debug.Print maxRow("sheet1") 

定義した関数を呼び出すにはmaxRow()のカッコ内に最終行番号を取得したいシート名を入れる。

使用例

下記のようなワークシートで先程の関数を呼び出すと「5」が返されます。

f:id:maru0014:20170203220506p:plain

最終行まで間が空いていてもカウントされる

下記のような場合、6~8行目まで空白になっていますが9行目にデータが入力されているので戻り値は「9」となります。

f:id:maru0014:20170203221937p:plain

特定のセルを基準に一番下のセルの行番号を取得したい場合

先程のユーザー定義関数で最終行を取得する場合は行の途中で空白があっても飛び越えて一番下の行を取得します。 しかし、下記のようにA列の最終行番号を取得したいといった場合には別の方法を使いましょう。

f:id:maru0014:20170203222529p:plain

  今度はmaxRowCellという名前の関数を作ってみました。 シート名を指定した後ろが.range(rangeName).End(xlDown).Rowに変わっています。 こう記述すると指定したセルの列における最終行番号を返します。

Function maxRowCell(ByVal sheetName As String, ByVal rangeName As String) As Integer
    maxRowCell = Sheets(sheetName).range(rangeName).End(xlDown).Row
End Function

シートの名前とセル名を指定して関数を呼び出す

    Debug.Print maxRowCell("sheet1", "A1")

このように呼び出すとイミディエイトウィンドウには「5」と表示されます。

概ねこれらの2パターンで最終行の取得は可能なので、for文の繰り返し回数の指定などに応用すればかなり使い勝手のいい関数かと思います。

ついでなので、For文での繰り返し処理のやり方も書いておきます。

最終行まで繰り返し処理を行うFor文の書き方

下記のようなシートがあったとして、A列のアルファベットに応じてB列に1から順番に数字を入力していきたい場合。

f:id:maru0014:20170203224228p:plain

まずはA列の最終行番号を取得してB列の何行目まで入力すれば良いのかを計算します。

A列の最終行番号を取得したいのでmaxRowCellを使うことにします。

    For i = 1 To maxRowCell("sheet1", "A1")
        range("B" & i).Value = i
    Next

こんな感じですね。 For文の「i」は繰り返すごとに1づつカウントアップされていくのでrange("B" & i)と記述すれば繰り返すごとに B1→B2→B3 となっていくわけです。 そしてそのセルの中身に今回は数字を入れるだけなのでvalue = iで 1→2→3 と入力されていきます。

実行結果

f:id:maru0014:20170203225706p:plain

無事にB列に1~5の数字が入りましたね。

このようにシートや列の最終行番号を取得することでいろいろな繰り返し処理の変数へ当てはめることができるので、自動でデータの入力や数式の入力を行うマクロを作る際にはとても重宝しています。 ただ、もしこれよりも良い書き方などがあればコメントなどで教えてもらえると助かります。

 

↓これで勉強してます

たった1秒で仕事が片づく Excel自動化の教科書

たった1秒で仕事が片づく Excel自動化の教科書

Google Analytics の文字化けしたURLを日本語に変換するブックマークレット

f:id:maru0014:20170130225128j:plain

Google Analyticsの画面では日本語URLは文字化けしてしまう

参考画像はこのブログのアクセス解析結果ですが、3番目のページはURLが文字化けしていますね。 これはURLに日本語などのマルチバイト文字のURLが使用されているためです。

この状態ではどのページなのか全くわかりませんね・・・。超不便。 そこで、ボタン一つでこの文字化けしたURLを日本語に変換して書き換えるブックマークレットを作ってみました。

 

変換ブックマークレットの実行結果サンプル

f:id:maru0014:20170130225652j:plain

実行するとこのようにテキストを書き換えます。 これで何のページなのか一発でわかるようになりました!

 

変換ブックマークレット利用方法

  1. このリンクをブックマークへ登録 → [日本語URL化]
  2. Google Analyticsのページで登録したブックマークを実行

これだけで変換されます。 ただし、思いつきでテキトーに作ったのでバグとかあると思います。 もし変なところや、こうした方が・・・という事があればコメントください。

 

変換ブックマークレットのソース

中身はこんなかんじ

$.each($('td'), function() {
    if ($(this).text().match(/\%/) && $(this).text().match(/\//)){
        var strUrl = decodeURI($(this).text());
        $(this).text(strUrl);
    }
});

処理の流れとしては、

  1. ページの中からtdタグを探す
  2. タグ内に「%」と「/」が含まれるかチェック
  3. trueの場合は変換を実行
  4. 変換したテキストに書き換え

の1-4を各td要素に対して繰り返し実行しています。

 

以上、「文字化けしたURLを日本語に変換するブックマークレット」でした。 javascriptはまだまだ勉強中。 というか基礎も抑えず雰囲気で書いてみて動いたらラッキーみたいな感じでやってるので、そのうち本でも読んでマスターしたいですね。

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

楽天市場RMSページでscriptタグ(禁止タグ)を有効にする方法(スマートフォン限定)

この記事でできるようになること

  • スマートフォンページ(トップページ・商品ページ・カテゴリーページ)などで任意のscriptを実行

楽天GOLDで実行したscriptのhtmlをフレーム読込するとか茶地なものではありません。)

楽天市場RMSで管理しているページ(商品ページ・カテゴリーページなど)は scriptタグが使用禁止となっており

<script src="aaa.js"></script>

などと記述しても編集確認画面へ移行できずエラーとなります。

スマートフォンページ限定ではありますが、このエラーを回避しscriptの実行を可能にする方法をご紹介します。

楽天市場ではセキュリティ面での保安のため禁止タグが指定されています。 ※禁止タグ利用は自己責任でお願いします。    

scriptタグのエラーを回避する記述方法

1.まず読み込ませたいjsファイルをGOLDにアップロード

2.商品ページページ設定の商品ページ共通説明文などに以下のタグを挿入

<script src="http://www.rakuten.ne.jp/gold/●●●/□□.js" type="text/javascript" =""=""></script                   >

3.エラーを回避して実際のページでscriptが正常に実行されます。

  ※再度言いますが、禁止タグ利用は自己責任でお願いします。

売れるネットショップ開業・運営 eコマース担当者・店長が身につけておくべき新・100の法則。

売れるネットショップ開業・運営 eコマース担当者・店長が身につけておくべき新・100の法則。

成功する ネットショップ集客と運営の教科書

成功する ネットショップ集客と運営の教科書