カテゴリーアーカイブ JavaScript

著者:杉浦

javascriptの真偽値

 javascriptは暗黙的な型変換をよくしてくれる言語です。javascriptで真偽値が入りそうな演算を真偽値でない値で実行した場合、真偽値でない値を真偽値に暗黙的に変換します。javascriptである値を引数として真偽値に変換をする関数は次の表に従って変換を行います。

Table 9: ToBoolean Conversions
Argument Type

Result

Undefined

Return false.

Null

Return false.

Boolean

Return argument.

Number

If argument is +0, -0, or NaN, return false; otherwise return true.

String

If argument is the empty String (its length is zero), return false; otherwise return true.

Symbol

Return true.

Object

Return true.

引用:ECMAScript® 2017 Language Specification 7.1.2 ToBoolean
この表の肝要なところは引数が存在している様な値(なにか適当な実体がある感じ)ならtrue、存在していない様な値(未定義、null、NaNなど)ならfalseを返してくれるところです。このためjavascriptは

if(hoge !== '' && hoge !== null){console.log('hogeはtrue';)}

とのようにしなくとも

if(hoge){console.log('hogeはtrue');}

とするだけで存在の判定を大体やってくれます。ただ、int型等の数値を同じ様に書くのは注意です。0ならばfalseという変換にひっかかります。C言語やら01の世界やらで0(int)は大概、偽とされており、おそらくこの考えを引き継いでいるためjavascriptでは0ならばfalseに変換されます。

  • この記事いいね! (0)
著者:杉浦

マテリアルデザインのさわり

Design – Material Design
マテリアル・デザインって何? Androidデザイン責任者にインタヴュー | ギズモード・ジャパン
 マテリアルデザインの思想が理想とするデザインは脳にスッと入ってくるデザインです。
マテリアルデザインは一貫性のある法則を持つ世界の上でデザインを行うことで、脳にスッと入ってくるデザインを実現しようとします。一貫性のある法則には実世界の一部を再現するような法則が用いられています。ここで一部、とあるのはマテリアルデザインの目的がユーザの理解の促進にあるからです。理解を妨げて、処理を重くするだけの余分な法則を再現する理由はありません。主な法則は、実世界において紙を重ねた時に起きる現象を再現する直感的な法則です。例えば、ページはhogehogeとかかれたカードの集まり(並べてもいいし、重ねてもいい)で構成される。これは実世界の紙を重ねた時の状態を再現する法則です。他には、カード内から画像や文字ははみ出さない、下の要素には上の要素の影が落ちる。これはそれぞれ、紙面からはみ出して宙に浮く画像や文字はない、下の物体には上のカードの影が落ちる、という実世界上の法則の再現です。
 マテリアルデザインの効果の一例が次です。
ヘッダに影がない

ヘッダに影がある

 影がついた場合ヘッダが下の記事欄から独立していることがわかるため、スクロールをしてもヘッダが固定されると連想しやすくなります。

  • この記事いいね! (1)
著者:杉浦

セレクタによる複数選択から個々の要素を操作する

 ここで扱うセレクタは複数の要素を選択できるjQueryの$()とjavascript備え付けのquerySelectorAllの二つです。$([“属性名=’value'”]),querySelectorAll([“属性名^=’value'”])で条件式に合った要素が返ってきます。このvalueの中で正規表現が使えます。比較演算子は次の表です。

|= valueか、-valueが属性名な要素を選択
*= 部分一致。valueを含む文字列が属性名な要素を選択
~= スペースで区切られた複数の属性名を持つ要素が主な対象。valueな属性名を含む要素を選択。
$= 後方一致。末尾にvalueを含む文字列が属性名な要素を選択
= 完全一致。valueが属性名な要素を選択
!= 否定。valueでない文字列が属性名な要素を選択。属性名がない要素も選択。
^= 前方一致。先頭にvalueを含む文字列が属性名な要素を選択

querySelectorAllの返り値はNodelist型のため配列に変換しないと煩雑です。変換には次のコードが使えます。

Array.prototype.slice.call(document.querySelectorAll("属性名=value"))

次のようなArray.from()ならさらに楽です。

Array.from(document.querySelectorAll("属性名=value"))

Array.from()はこれを書いている時点でブラウザによる対応が怪しいです。対応表は次になります。Can I useも次の対応表へ案内してくれます。
ECMAScript 6 compatibility table
well-known symbolsの行が完全対応なら大丈夫なはずです。Array.fromが使えないなら上のArray.prototype.slice.callです。
 配列を

arr.forEach(funcion(a){/*処理*/});

なコードの様に扱うと処理が短く色々書けます。jQueryのイベント付与処理なら$(“#”+a.id).click(function(){/*click時処理*/})の様な具合です。
次のコードな正規表現で各文字列の差分を取る(最初の属性選択時の共通部分以外を抜き出す)ことでさらに使う幅が広がります。

a.属性名.replace(/^value/g,”) 前方一致したvalue部分を空にする
a.属性名.replace(/value$/g,”) 後方一致したvalue部分を空にする
a.属性名.replace(/value/g,”) 部分一致したvalue部分を空にする

属性名の命名規則をかっちりしていれば正規表現で楽にコーディングできます。

  • この記事いいね! (0)
著者:杉浦

chrome開発者ツールのコンソールでDOM操作を行う

 これはjavascriptを用いた開発で特に役に立つと思います。”javascriptのソースコードでやりたいDOM操作のコーディングを行う→目的のページをリロード→チェック→コーディング再開”なんてことがめんどくさい時に使えます。 GoogleChromeなどの多くのブラウザにはショートカットキーF12で開ける開発者ツールが備わっています。この開発者ツールのコンソールからjQuery付javascriptとほぼ同じ言語でDOMの操作ができます。
 要素を対象にとる

$(selecter),$$(selecter)

 document.querySelector(),document.queryAllSelector()と同じです。jQueryのセレクタと同じ記法です。どちらも対象が一つのみでも配列扱いをするので操作に注意がいります。要素の展開から属性なりイベントなりの色々が読み取れます。

*.children,*.firstChild,*.parentNode,...

 ちゃんと説明書を読んだわけでないので断言できませんがjavascriptに入っている要素参照操作が備わっているようです。

*.innerHTML,*.outerHTML

 連鎖して何かを呼び出せませんが一括操作に有用です。
DOMを操作する

*.append(),*.removeChild(),insertBefore(),…

 ちゃんと説明書を読んだわけでないので断言できませんがjavascriptに入っているDOM操作が備わっているようです。
便利

* = *,if,while,for

 変数を持つことも分岐、繰り返しを行うこともできます。ほぼ対話的なjavascriptです。

clear()

 画面をきれいにします。

コンソール上のDOMの階層要素を右クリック→Expand recursivelyを実行

 DOMの要素を再帰的に展開、要は全部展開します。コンソール上の参照されたDOM要素はElementPanelのDOM要素に近い機能を備えています。

コンソール上の適当な隙間で右クリック→Save as...

 コンソール上の操作のログを保存します。直接Command Historyを開く命令がみあたらないのでこれで代用です。正直手間な感じはします。

  • この記事いいね! (0)
村上 著者:村上

【jQuery】FastClickライブラリを特定の要素のみ無効にする方法【iOS】

Cordova開発をしているとお世話になるライブラリが、この「FastClick」だと思います。
これを使うことで、モバイルでアプリを実行したときのクリックの反応速度がかなり改善されます。
が、ものによっては、この FastClick ライブラリと競合を起こすライブラリもあるようで、今日、まさにその現象に遭遇しました。

 

競合を起こしたライブラリは、OpenstreetMap を使用した地図を表示できる「MapBox」です。
地図の表示の全てに影響するわけではなく、地図に表示したマップピンをクリックして、吹き出しを表示するロジックに影響が出ており、iOS でのみ吹き出しが表示できない状態でした。
クリックの動作をする箇所でのエラーだったので、最初は Click イベントを取得できていないことを疑いましたが、エラーログを見たところ、FastClick との競合が原因でした。

 

解決方法ですが、こちらのサイトを参考にしました。

JS/jQueryでFastClick.jsを使ってスマホのclickイベントの300ms遅延をなくす|ITハット
http://ithat.me/2016/11/06/js-jquery-smartphone-click-event-300ms-delay-fastclick

サンプルに書くほどでもないのですが…対策方法は、FastClick を無効化したい aタグなどの要素に、needsclick というクラスを追加するだけです。

<a class="needsclick">FastClickを無効にしたい要素</a>

特定の要素のみに FastClick を適用する方法もありますが、現在開発中のシステムでは、無効化したい要素がここのみだったので、この方法を採用しました。
ちなみに、特定の要素のみに適用する方法は下記の通りです。

<div>
    <div class="fastclick">
        <!-- FastClickを適用する要素 -->
    </div>
    <div>
        <!-- FastClickを適用しない要素 -->
    </div>
</div>
$(function(){
    FastClick.attach($('.fastclick')[0]);
});

全てに FastClick を適用するときには、下記のように記述します。

$(function(){
    FastClick.attach(document.body);
});

対策としては以上です。

 

ということで、FastClick を一部無効化する方法でした。
ライブラリの競合はやはり厄介ですね。
最悪、FastClick を無効化しなければいけないのでは…と思ったので、解決策があって良かったです。

  • この記事いいね! (0)
著者:杉浦

documentFragmentをIEで使う方法

 DocumentFragmentは小型のdocumentの様なものを定義する関数です。DocumentFragmentで定義されたDOMは画面に反映されません。
DocumentFragment – Web API インターフェイス | MDN
 下の画像の表はDocumentFragmentの対応表です。

 見ての通りInternet Explorerは2018/05/22時点でBasic support、querySelector、querySelectorAllにのみしか対応していません。他にも内部にDocumentFragmentを作成するコンテンツテンプレート要素であるタグにも対応していません。このためgetElementIDのようなdocumentに対してよく使用する関数すらDocumentFragmentにかけようとするとエラーないし予期せぬ動作を招くことがあります。基本サポートの範囲がよくわからなかったので、実装していないのではないかと疑い同等の機能を他の記述で試すぐらいしか解決法がわかりませんでした(W3Cの仕様書なり技術書なりにあるはず)。querySelector、querySelectorAllには対応しているので要素探索は楽なので、対象の要素に対してappendChild等の基本的であろうコードを書くのがコーディングの方針になると思います。
 InternetExplorerはFirefox、chromeなどの他ブラウザよりも律義にレンダリングを頻繁にしてくれます。そのためDOMの追加が大量にあるような場合は一度DocumentFragmentなどの画面に影響しない部分でDOMをまとめて構成、一括してdocumentにつなげる方がとても良いです。以下はtable_masterというIDのついた親を持ち、hoge_tableというIDのついたtable内のtbody_topというIDのついたtbodyを、tbody内のHTMLコードを表す文字列hoge_strで置き換える例です。


var df = document.createDocumentFragment();
df.appendChild(document.getElementById("hoge_table"));
df.querySelector("#tbody_top").innerHTML = "";
var tbd = document.createElement("tbody")
hoge_str = "abc";
tbd.innerHTML = hoge_str;
while(tbd.firstChild){
	df.querySelector("#tbody_top").appendChild(tbd.firstChild);
}
document.getElementById("table_master").appendChild(df.firstChild);
  • この記事いいね! (0)
村上 著者:村上

【JavaScript】使用しているモバイル端末の種類を判定する方法

今回は、どの端末を使用しているかを判定する方法について。
ちなみに、AndroidiOS の判定しかしていません。

参考にさせていただいたサイトはこちらから。

使用してるブラウザを判定したい – Qiita
https://qiita.com/sakuraya/items/33f93e19438d0694a91d

コードはこちら。

var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("android") != -1){
    // Android の時の処理
}
if ((userAgent.indexOf("iphone") != -1)||(agent.indexOf("ipad") != -1)){
    // iOS(iPhone、iPad)の時の処理
}

navigator.userAgent でユーザーエージェントを取得します。
そして、取得できた結果は .toLowerCase() メソッドを使って全て小文字に変換します。
で、.indexOf() メソッドで、指定された値が最初に現れたインデックスを取得します。
なお .indexOf() メソッドは、指定した値がなかった場合、-1 を返します。

あとは、Android、iOSごとに行いたい処理を ifで分岐した先に記述すればOKです。
思っていたよりも簡単ですね!

 

以上、使用しているデバイス端末の種類を判定する方法でした。
ちなみに、私はこちらをアプリのアップデートを促す際の処理で使っています。
もし、インストールされているアプリが最新のバージョンよりも古かったら、端末を判定し、Google Play もしくは App Store のそれぞれのページに遷移させています。
使っているのはその箇所のみですね。
端末ごとに分けなければいけない処理は意外と少なく、この程度で済むようです。

なお、参考にさせていただいた記事では、ブラウザの判定も紹介されています。
今のところ、ブラウザで分け無ければいけない処理はありませんが、機会があったらこちらも参考にさせていただきたいと思います。

  • この記事いいね! (0)
著者:杉浦

javascriptのDOM操作の高速化に使える機能:DocumentFragment

 これはいくらかjavascriptを知っている人向けの記事で、javascriptの機能の一つDocumentFragmentの紹介です。
 DocumentFragmentはDOMツリーとほぼ同じ機能を持つ独立したノード、小型のdocumentの様なものを定義するインターフェースです。ルートであるdocumentのDOMツリーを操作した場合、レンダリングがしょっちゅう働きますが、DocumentFragmentに従って作成されたDOMツリー同然のノードを操作した場合はレンダリングが全く働きません。このためDocumentFragmentを用いてDOMツリーに連結する予定の木を作成、作成された木を連結、とすることで比較的高速にDOMツリーを操作できます。。
 DOMツリーとはHTMLドキュメントなどを木構造オブジェクトとして扱う際の木のことです。DOMツリー中のノードが削除、変更されたり、新たにノードが追加された場合、レンダリングが行われる場合があります。DOMの操作は重い動作である、という意見、記事がいくつも見られる理由の一つはおそらくこれでしょう。もっとも最近はブラウザも賢くなりレンダリング回数を少なくしようとしていますが、警戒するに越したことはないです。IEにおいてfor文中でappendChildを回す部分のあったプログラムを走らせたら、レンダリングの実行回数がえらいことになっていました。
 DocumentFragment – Web API インターフェイス | MDN
 使い方
var df = document.createDocumentFragment();
 このdfを好き勝手いじれます。dfをどこぞに連結する場合、DocumentFragmentの頂点ノードは削除され、一つの木として自然な形になります。
 レンダリングなどのブラウザの内部について述べられた記事:ブラウザのしくみ: 最新ウェブブラウザの内部構造 – HTML5 Rocks

  • この記事いいね! (0)
村上 著者:村上

【JavaScript】jQueryなしでappend()と同じことを実行する

DOM操作をするときに jQuery の append() を使うことが多いのですが、場合によっては jQuery が使用できないことがあるかと思います。
なので、今回はタイトル通り、jQueryなしで append() と同じことを行う方法についてです。

参考にさせていただいた記事はこちら。

innerHTML より insertAdjacentHTML を使う – Qiita
https://qiita.com/amamamaou/items/624c22adec32515e863b

 

実際のコードはこちら。
今回使うメソッドは、insertAdjacentHTML() というものです。

<div id="parent">
    <p>p要素 その1</p>
</div>
// id=parendの子要素の最下部に要素を追加 append()
var element = document.getElementById("parent");
element.insertAdjacentHTML("beforeend", "<p>p要素 その2</p>");

上記のコードを実行すると、ID が parent の要素の子要素の一番下に、指定したp要素が追加されます。
動作としては、jQuery の append() と全く一緒です。
ちなみに、insertAdjacentHTML() メソッドの第一引数を変更することで、append() 以外の動作を行わせることができます。

簡単に表でまとめてみました。

jQuery insertAdjacentHTML()
append() “beforeend”
prepend() “afterbegin”
before() “beforebegin”
after() “afterend”

jQuery で行えるDOM要素の挿入は、こちらの方法でも問題なくできるようです。

なお、もしHTML文字列ではなく、HTML要素を指定したい場合には、insertAdjacentElement() が利用できます。
第一引数は、insertAdjacentHTML() と全く同じで、追加したい要素を指定する第二引数のみが違います。
こちらは、実装しているコードで使い分けてください。

 

ということで、jQueryなしで append() などと同じことを実行する方法でした。
システムによっては、jQueryを使えないこともあるかと思うので、この方法は覚えておきたいと思います。

  • この記事いいね! (0)
村上 著者:村上

【JavaScript】長い文章の文末を省略して末尾に「…」を表示させる方法

昨日の記事とほぼ同じタイトルですが、今回はCSSではなくJavaScriptで文章の文末を省略して末尾に三点リーダーを追加する方法です。
こちらは範囲からはみ出たかどうかではなく、文字数で判断をしています。

ちなみに、昨日の記事はこちらから。

【CSS】長い文章の文末を省略して末尾に「…」を表示させる方法
https://cpoint-lab.co.jp/article/201805/【css】長い文章の文末を省略して末尾に「」を/

こちらの記事では、CSSで指定した範囲からはみ出した文章の文末を省略しています。
複数行の表示には対応しておらず、省略後は1行の表示になります。

 

コードはこちら。

<p id="text"></p>
var text = "春はあけぼの。やうやう白くなりゆく山際、少し明かりて、紫だちたる雲の細くたなびきたる。";
var slicetext = text.length > 20 ? (text).slice(0,20)+"…" : text;
document.getElementById('text').innerHTML = slicetext;

文字数をカウントし、20文字以上だったら、slice メソッドを使って21文字目からをカットして、三点リーダーを追加しています。
そして、pタグの中に、そのカット後の文章を表示しています。
行っている処理はこれだけです!

 

JavaScriptで文末を省略する方法でした。
好みにもよりますが、明確に○文字以下で表示することが決まっている場合や、表示する範囲が不変で、かつ複数行で表示したいときなどに使えそうです。
1行だけ表示するなら、表示範囲も可変が可能なCSSで指定する方がよさそう。
このあたりは実装する内容によって使い分けてください。

  • この記事いいね! (0)