かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

JS 表示してるページのURLを取得したりするアレコレのメモ

URLを取得する方法のメモ (Chrome / Firefox / Safari で確認しています。)

例えばこんなURL

1. http://example.com/dir/
2. http://www.example.com/dir/
3. http://example.com/dir/index.html#section01
4. http://www.example.com/dir/index.html#section01
5. http://example.com/dir/index.html?s=foo
6. http://www.example.com/dir/index.html?s=foo

今のページのURLを取得する

window.location.href

又は

document.URL // 読み取り専用

👇

// 1. => "http://example.com/dir/"
// 2. => "http://www.example.com/dir/"
// 3. => "http://example.com/dir/index.html#section01"
// 4. => "http://www.example.com/dir/index.html#section01"
// 5. => "http://example.com/dir/index.html?s=foo"
// 6. => "http://www.example.com/dir/index.html?s=foo"

ドメイン名を取得

window.location.host
// 又は window.location.hostname

👇

// 1. 3. 5. => "example.com"
// 2. 4. 6. => "www.example.com"

プロトコルを取得

window.location.protocol

👇 1 ~ 4 共通

// "http"

サイトのトップページのURLを取得

プロトコルドメイン名から作成できる。

window.location.protocol + '//' + window.location.host

👇

// 1. 3. 5. => "http://example.com"
// 2. 4. 6. => "http://www.example.com"

ドメイン以下のパス

window.location.pathname

👇

// 1. 2. => "/dir/"
// 3. 4. 5. 6. => "/dir/index.html"

※ URLの末に/が無ければ無いまま取得されるっぽい

トップページ(http://example.com)の場合は/が取得される

window.location.pathname // => "/"

ハッシュを取得

window.location.hash

👇

// 1. 2. 5. 6. => ""
// 3. 4. => "#section01"

パラメーターを取得

window.location.search

👇

// 1. 2. 3. 4. => ""
// 5. 6. => "?s=foo"

※ ブラウザの場合locationwindowオブジェクトのプロパティなので、wondow.は省略可 (但しスコープ内にlocationって名前の変数を作っていない場合)


[参考]

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

iOS javascript clickイベントが効かないにはまる。

レスポンシブなサイトを作成していてモバイルの時によくある、メニューアイコンを押したら全画面にメニューが表示されてメニュー以外をクリックするとメニューが閉じる機能を作っていました。
Chromeの開発ツールでは意図したとおりに動作していたのですが、iPhone実機で確認した所メニュー以外の部分をタップしたらメニューを閉じる機能が動作していませんでした。

確認環境

clickイベントが効かないパターンがあるっぽい

動作しなかった例

$(document).on('click', 'div.hitarea', function(){ /*... 処理 */ });

※ 対象の要素を解りやすくするために敢えてdiv.hitareaと書いています

どうやら$(document).on$('body').on のようなイベントの登録のしかたで、イベント対象がaタグではない時にクリックイベントが無視されてしまうようです。

解決方法

1. クリック対象となる要素にcursor: pointerというスタイルを付ける

クリック対象の要素にcursor: pointerというスタイルがあれば、aタグでなくてもクリックイベントが効くようになるようです。(イベントがdocumentやbodyといったものに登録されている場合イベントターゲットがpointerな要素ならタップ可能な要素だとiOSが判定するような仕組みっぽいです。)

今回の例だと次のようにスタイルを加えるとクリックイベントが動作するようになりました。

div.hitarea {
  cursor: pointer;
}

ボタンのように使いたい機能だった場合はこの方法が簡単です。
しかし、今回のようなレスポンシブなサイトで、ボタンエリア以外をクリックしたらメニューを閉じたいというような場合、モバイルで見てる時は良いのですがPCで見るとモーダルのメニュー上どこにマウスを持っていってもカーソルがクリック可能なポインターになってしまうので、ちょっと問題がありました。

2. document, body にイベントを登録しなければOK

iOSでクリックイベントが動作しないのは、documentまたはbodyにイベントが登録されている かつ 対象の要素がaタグでない(pointerのスタイルがない) とき ですので、$(document).on$('body').onとしなければ問題なく動作します。

例えば次のようなHTML構造で

<body>
  <div class="container">
    <div class="hitarea"></div>
  </div>
</body>

単純に最初から画面にある該当要素だけでクリックイベントが効けば良いのであれば

$(document).on('click', 'div.hitarea', function(){ /*... 処理 */ });

ではなく

$('div.hitarea').on('click', function(){ /*... 処理 */ }); 

とすればOKです。

後から追加される要素にもクリックイベントが効く必要があるときは、

$('.container').on('click', 'div.hitarea', function(){ /*... 処理 */ }); 

上記のようにdocumentbodyではなく対象となる要素が追加される親要素にイベント登録をすれば、後から追加されるdiv.hitarea要素にもクリックイベントが効くようになります。

 
Chromeの開発ツールで見た目と動作問題ないなーと思っても実機だと挙動が異なることがあるってのを改めて実感しました。(iOSで見てたブラウザもデフォルトのSafariChromeとも異なりますからそりゃ違いもありますよねw)
モバイルサイト製作時はめんどくさがらずに、ケーブル繋いで実機のブラウザで見て確認・デバックをしなきゃなーって思いました。(でも、ちょっとめんどくさい...

過去にaタグだけどclickイベントが効かない事があったのですが、href属性を付けていなかったので、cursor: poinrerのスタイルが無い扱いになってたから、動作しなかったんじゃないかなって今回の件でナゾが判明した気がしました。


[参考]

Javascript Chromeでページトップに戻る(scrollTop)が効かなくなってた件。

Chromeで以前作ったサイトを見ていて、jQueryで実装していたページトップに戻るが効かなくなっているのに気づいてしまいました...

スペック

  • Mac OSX
  • Chrome v61.0.3163.91

$('body').scrollTop() が効かなくなっていた。

今までは、FireFoxIE系はhtmlタグで、webkit系はbodyタグでscrollTopが動作していたので、$('html, body') とするとコールバックが2回呼ばれてしまうのが嫌だったので👇 の様な感じでブラウザ判別してscrollTopを使用するタグを切り替えていました。

var scrollTag = ( window.chrome || 'WebkitAppearance' in document.documentElement.style )? 'body' : 'html';

$(scrollTag).animate({
  scrollTop: 0
}, 'fast', function() {
  console.log('callback');
});

Chromeでは上記の判定で scrollTagbodyになっているので、$('body').scrollTop() が効いているか調べてみると...

// Chrome
$('body').scrollTop(); // => 0 ※常に0が返る

Chromeのアップデートで仕様変更になったようで、Firefoxを同じでhtmlタグでscrollTopが動作するようになり、$('body').scrollTop() が常に0になってしまうようになっていた為に「ページトップに戻る」が動作しなくなっていたようです... (いつのアップデートで変更になってたんだろう???

ブラウザごとの scrollTop の効くタグを調べてみる。

改めて、どのブラウザがbodyで動作するのか、htmlで動作するのかを調べてみました。
IE系が手元に無いので、調べ次第追加します。

👇 codepen に簡単なHTMLとscriptを作成して、各ブラウザでチェックしてみて動作する方のタグを調べます。にちょっとしたチェック用のHTMLとかJSをcodepenに作っておくと緊急時に割りとお役立ちなのです!

See the Pen scroll test HTML or BODY? by KIKIKI (@chaika-design) on CodePen.

ブラウザ バージョン html body
Chrome 61.0.3163.91 ×
Safaei 10.1.2 ×
Firefox 55.0.3 ×
Vivaldi 1.12.955.36 ×
Opera 47.0.2631.83 ×
Safari (iPhone) 10.0 ×
Edge 41.16299 ×
IE 11.125 ×

以前調べた時と違って、ChromeVivaldi では body タグではscrollTopが効かなく、htmlタグで効くようになっていました。
追記 IE, Edgeを調べました。 IEhtmlでEdgeはbodyで動作するようです... MS君は何故自社ブラウザで挙動揃えないのよ....

scrollTopを使用するタグのブラウザ別判定を変更する。

使用していたscrollTopを使用するタグを決めるブラウザ判定のスクリプトを変更します。

IE・Edgeは調べてません 調べました。2018.04.06

var ua = navigator.userAgent;
var scrollTag = (( !window.chrome && 'WebkitAppearance' in document.documentElement.style ) || ( ua.indexOf('OPR') !== -1 || ua.indexOf('Edge') !== -1 ))? 'body' : 'html';

OperaとEdgeが少し厄介で。window.chrome オブジェクトを持っているけど、body タグにしなければならないので、OperaとEdgeの判定のためだけにユーザーエージェントを利用して (ua.indexOf('OPR') !== -1 || ua.indexOf('Edge') !== -1) で常にbodyになるようにしてあげる必要がありました。

OperaとEdgeの問題があるのでif文で書いてしまう方が見やすいような気がします。

var ua = navigator.userAgent;
var scrollTag;
if( ua.indexOf('OPR') !== -1 || ua.indexOf('Edge') !== -1 ) {
  scrollTag = 'body';
} else {
  scrollTag = ( !window.chrome && 'WebkitAppearance' in document.documentElement.style )? 'body' : 'html';
}

 
調べていると body, html {height: 100%}というCSSが原因?という記事も出てきたのですが、私の確認できる範囲ではこれを削除してもうまく動作せず、変更時のサイトへの影響範囲が大きいのでjavascriptの判定の方を変更する事にしました。

また、いつブラウザの仕様が変わってしまうか解りませんので、その時はまた調べて変更する必要がありそうです。(メンドー
昔作ったサイトでは色々と動かなくなってそう...


[参考]

トップをねらえ2! Blu-ray Box

トップをねらえ2! Blu-ray Box