7cc@はてなブログ

JavaScriptとかとか

You might not need jQuery は間違いだらけ

追記: 文面を修正しました。 2018-05-21

すこし話題になっている(いた?)ようだが、jQueryを(読むだけで自分では)使ったことの無い私が気付いただけで間違いが10個あった。

サイトはここ
GitHubにソースがある

見つけた間違い

60個あるうち10個
つまり全体の1/6, 16.6%

内容についてはレポジトリ参照(しかし、そこまでする利点は無いので見なくてよいです)

メソッド どうしたか
children 既にissueにあった
contains issue出した
empty issue出した
fadeIn issueで指摘されたのに確認されないまま閉じられたのでコメントした
trigger issue出した
offset PR(Pull Request)が間違っていたのでコメントした
outerWidth/Height PRを取り入れていたが、やはり間違っていたのでコメントした
AJAX グローバル変数になっている。onloadの中も変。面倒なので何もしない。
parseHTML childNodesを使うべきところでchildren。何もしない。

※表だと9だが、outerのところで2つなので10とカウント

trigger, offset, outerHeight は 2014/03/06現在 まだ修正されていない。
emptyは修正しないようだ。
さらに、formの部品になる要素のcloneNodeなど、本当は要修正がまだある(IEではコピーした要素のvalueが空になる)。

このレポジトリのオーナーは

  • jQueryのソースを全く読まず
  • まともにテストもせず

に書いている。断言できる。まだ間違いはありそうだけど、これ以上はやめにした。

見た時にはすでに修正されていたが、isArrayの方法がメチャクチャだった。これ一つだけでも、どれだけひどいかが十分に分かる。

isArray = Array.isArray || function(arr) {
  return arr.toString() == '[object Array]'
}

このレポジトリに対する反応

Github

3000スター以上付いている。どういうことなの・・・

jQuery作者のツイート

この返しが面白い

雑感

  • 素直にjQuery使うほうが良い。必要な部分だけコピーして使うこともできるわけで。
  • 前述の通り誤りがあるのでサイトのコードは使わないようにしよう。

デバッグ時だけconsole出力したい

var debug = true
if ( !window.console || !Function.bind ) {
  debug = false
}
var cl = debug?
  Function.prototype.bind.call(console.log, console) : function(){}

usage

cl(1, 2)

console.log.applyだと出力箇所が関数定義場所になってしまうのでbindを使う。

あるいは単純にdebug && console.log()でも良いと思う。

document.activeElement

概要

focusのある要素を返す。

  • 基本的にformの部品が対象
  • 他には<a>, <area>, <detail>, tabindex属性付き要素など、フォーカス可能な要素も返す
  • iframe内の要素にフォーカスがある時は、そのiframeが返る

仕様はここ。8 User interaction — HTML Standard.htm 8.4.2 Focus management


子要素があっても、activeElementはフォーカス可能な要素になる。
こういうhtmlのspanをクリックすると、

<p tabindex="0"><span>span</span></p>
event.target // span
document.activeElement // p

という具合になる。

フォームの部品以外の互換性

要素をクリックしたときのdocument.activeElementが、その要素になるか

要素 Chrome Firefox IE
a ☓*1
area ☓*1
tabindex

*1 tabキーや、element.focus()でフォーカスを移動している時は返す。そうでなければbodyになる

スクリプトでelement.focus()すれば同じ結果が得られる。
しかしChromeではフォーカスがあると水色の枠線で囲まれて若干気持ち悪い。

Chrome以外なら、document.activeElementを見ればリンクがクリックされたと分かる。

デモ

http://jsbin.com/fihop/4

IEとdocument.activeElement

次の要素もclickでactiveElementになる

  • widthCSSが指定されているdiv
  • fieldset
  • たぶん他にもいろいろ・・・

つまり最初に書いた通り、formの部品以外では注意が要る。

ownerDocument, document

createElementでつくった要素

var div = document.createElement("div")
div.ownerDocument === document // true

ownerDocumentは文書中に要素があるかは関係ない。

xhrで得た要素

var xhr = new XMLHttpRequest
xhr.open("GET", document.URL)
xhr.responseType = "document"
xhr.onload = function(e){
  var doc = e.target.response
    , a =doc.getElementsByTagName("a")[0]
  console.log(
    a.ownerDocument === document // false
  )
  document.body.appendChild(p)
  console.log(
    a.ownerDocument === document // true
  )
}
xhr.send(null)

親ノードになるドキュメント次第で変わる。

いつ使うのか

複数のwindowがある場合。例えば、<iframe>