Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IE8以下で、'{window} click'にバインドした時に、イベントハンドラの第2引数がwindowと===にならない #339

Closed
fukudayasuo opened this issue Jun 4, 2014 · 3 comments
Assignees
Labels
Milestone

Comments

@fukudayasuo
Copy link

コントローラでイベントハンドラをバインドした時、第2引数にはそのイベントハンドラのcurrentTargetのjQueryオブジェクトが渡される。

'{window} click'にバインドしたハンドラの第2引数には、$(window)が渡されるはずであるが、以下のようなコードで比較した時、$elの中身がwindowと===にならない。

h5.core.controller('body', {
  __name:'A',
  '{window} click': function(context, $el) {
    $el[0] === window; // falseになる。
  }
});

IE8でjQuery1.10.0で確認した。

@fukudayasuo
Copy link
Author

原因は、IE8-でwindowオブジェクトを比較するときの挙動に起因している。

コントローラはイベントハンドラのセレクタが'{window}'だった時には、そのコントローラのルートエレメントが属しているdocumentのparentWindow(IE8-の場合)にバインドしている。

$elは、イベントハンドラのthisをjQueryオブジェクトにしたものである。なので、$elは$(document.parentWindow)である。

IE9以上では、document.parentWindow === window であるが、IE8-では、document.parentWindow !=== windowである。

以下にIE8(IE10のdocmode8)で、windowオブジェクトの比較をテストした結果を示す。(7の結果以外は参考まで。)

var window1 = window;
window2 = window;
window.window3 = window;
var obj = {
        w: window
};
window.obj = obj;
window.obj.w2 = window;

window === window.window; // 1
window === window1;  // 2
window === window2; // 3
window !== window3; // 4
window === window.obj.w; // 5
window === window.obj.w2; // 6
document.parentWindow !== window; // 7
document.parentWindow !== window2; // 8
document.parentWindow === window3; // 9

本issueで問題となっているのは、7の比較が!==になることである。

!==ではあるものの、インスタンスは同一であるような挙動をし、例えばwindow.a = 1;とすると、document.parentWindow.a === 1になり、逆にdocument.parentWIndowにプロパティを追加した場合も同様である。

そのため、イベントハンドラの第2引数は、windowオブジェクトの操作を行う分には特に問題は発生しない。windowと比較して!==になってしまうことだけが問題である。

また、ポップアップウィンドウやiframeなど、別ウィンドウを参照する分にはparentWindowとwindowオブジェクトは===になる。

popupWindow = window.open();
// ポップアップが開いた後
popupWindow === popupWindow.document.parentWindow;

しかし、ポップアップウィンドウ内のスクリプトで、windowを比較した時には、同様の問題が発生する。

// ポップアップウィンドウ内のスクリプト
document.parentWindow !== window;
window.opener.popupWin !== window;
window.opener.popupWin === document.parentWindow;
window.opener === window.opener.document.parentWindow;

FWの対応としては以下の候補がある。

  • windowと"==="で比較してtrueになるように、windowにバインドするときは、document.parentWindowではなくwindowにバインドする(ただし、コントローラのルートエレメントが自window内の時のみ)
    (getWindowOfDocument(doc)を、window.document===docならwindowを返すようにする)
  • FWは対応しない。("==="で比較できないだけで、windowオブジェクトを使用する分には問題ないため。)
    テストケースでも"==="で比較することはできないので、テストケースでは何らかの対応を行う。

@fukudayasuo
Copy link
Author

バインドするターゲットを、window.document.parentWindowではなく、windowにバインドするようにして対応する。

'{window}'にバインドするとき、コントローラのルートエレメントからdocumentを取得して、取得したdocumentからwindowオブジェクトをgetWindowOfDocument(doc)を使って取得している。

このgetWindowOfDocument(doc)を修正する。今のコードだと、(doc.defaultView || doc.parentWIndow)を返しているが、window.document === docかどうかを比較してtrueならparentWindowではなくwindowを返すように修正する。

@simdy simdy added the bug label Jun 8, 2014
@simdy simdy added this to the v1.1.11 milestone Jun 8, 2014
@fukudayasuo
Copy link
Author

IE10のdocumode8,7ではなく、本物のIE8,IE7で確認したところ、
window.window !== windowでした。

コントローラのバインド先に'{window}'が指定されていた場合は、バインド先の取得にgetByPathを使用していてwindow.windowを取得しています。

そのため、getWindowOfDocumentを修正しても、'{window}'をバインドするときのバインドターゲットはwindowではなくwindow.windowになってしまいます。

getByPathも修正します。

具体的には、getByPath(namespace, rootObj)で、rootObj===window(またはrootObjの指定が無い)且つ、namespaceが"window."で始まっているなら、最初の"window."は無視するようにします。

fukudayasuo pushed a commit to hifive-labs/hifivemain that referenced this issue Jun 9, 2014
…ようにしました。

getByPathを、rootObjがwindowまたは指定無しなら、namespaceの最初の'window.'を無視するようにしました。

テストケース追加
'{window}'にバインドした時に第2引数に$(window)が来ることを確認するアサートのコメントアウトを外しました。
@simdy simdy closed this as completed Jun 9, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants