IE の attachEvent では this が使えない?
mixi エコーの返信をポップアップ表示する Greasemonkeyを IE でも使えるようにしようと思って修正していたんですが、ちょっと attachEvent の辺りで若干ハマってしまったのでメモメモ。
とりあえず
変更前のソースはこんな感じ。
// ==UserScript== // @name Mixi Echo Popup // @namespace http://ohaco.jp/ // @include http://mixi.jp/recent_echo.pl* // @version 1.0.0 // ==/UserScript== (function() { var allAnchor = document.getElementsByTagName("a"); var overlay = document.getElementById('overlay').style; for (i = 0; i < allAnchor.length; i++ ) { if (allAnchor[i].getAttribute('href').match(/list_echo\.pl.*&post_time=/)) { allAnchor[i].addEventListener('mouseover', function(){popupDisplay(this)}, true) } } function popupDisplay(obj) { var popup, status, reply, trash, close; var url = obj.getAttribute('href').replace("list_echo", "view_echo"); var httpRequest = new XMLHttpRequest(); httpRequest.open('GET', url, true); httpRequest.send(''); httpRequest.onreadystatechange = function() { if (httpRequest.readyState == 4) { var res = httpRequest.responseText; var start = res.indexOf('<div class="echoStatus clearfix">'); var end = res.indexOf('<div class="echoQuestionnaire">'); if (start != -1) { res = res.slice(start,end); res = res.replace("echo_member_id_1", "echo_member_id_100"); res = res.replace("echo_post_time_1", "echo_post_time_100"); res = res.replace("echo_nickname_1", "echo_nickname_100"); res = res.replace("echo_body_1", "echo_body_100"); popup = document.createElement("div"); popup.innerHTML = res; popup.style.position = 'absolute'; popup.style.margin = '-118px 0 0 0'; popup.style.padding = '10px 0'; popup.style.height = '88px'; popup.style.overflow = 'hidden'; popup.style.zIndex = '1'; popup.style.background = '#fff'; popup.style.border = 'solid 1px #999'; popup.addEventListener('mouseover', function(){close = false;}, true); popup.addEventListener('mouseout', function(){close = true;}, true); var popupDiv = popup.getElementsByTagName('div'); for (i = 0; i < popupDiv.length; i++ ) { if (popupDiv[i].className == 'status') { status = popupDiv[i]; status.style.marginTop = '0'; status.style.fontSize = '12px'; status.getElementsByTagName('span')[0].style.fontSize = '11px'; } } var popupAnchor = popup.getElementsByTagName('a'); for (i = 0; i < popupAnchor.length; i++ ) { if (popupAnchor[i].className == 'reply') { reply = popupAnchor[i]; reply.removeAttribute('onclick'); reply.setAttribute('onclick', 'show_echo_reply_layer(event, 100)'); } if (popupAnchor[i].className == 'trash') { trash = popupAnchor[i]; trash.style.display = 'none'; } } overlay.display = 'block'; overlay.opacity = 0; close = true; obj.parentNode.insertBefore(popup, obj.parentNode.firstChild); document.addEventListener('click', function(){ if(close) { obj.parentNode.removeChild(popup); overlay.display = 'none'; } }, true) } else { alert('\u8A72\u5F53\u3059\u308B\u30A8\u30B3\u30FC\u304C\u3042\u308A\u307E\u305B\u3093\uFF1E\uFF1C'); } } } } })();
冒頭の for 文の部分で addEventListener を使ってアンカーのマウスオーバーイベントを追加していますが、 IE では addEventListener が使えないので、代わりに attachEvent を使うように書きかえなくてはいけません。
IE 等の addEventListener が使えないブラウザの場合は attachEvent を使うように変更
とりあえず、特に何も考えずに下のように変更してみましたが…(一部抜粋)
for (i = 0; i < allAnchor.length; i++ ) { if (allAnchor[i].href.match(/list_echo\.pl.*&post_time=/)) { if (document.addEventListener) { allAnchor[i].addEventListener('mouseover', function(){popupDisplay(this);}, true); } else if (document.attachEvent) { allAnchor[i].attachEvent('onmouseover', function(){popupDisplay(this);}); } } }
うーん、動きません><
addEventListener の方では this で、ちゃんとマウスオーバーイベントが発生したアンカーの要素が渡されるんですが attachEvent の方だと、どうも this では上手く渡せないみたいです。
いろいろ調べてみた結果
IE 様には event.srcElement というものがあるらしいので、それを使ってみました!
以下、テストスクリプト。
// ==UserScript== // @name Mixi Echo Popup // @namespace http://ohaco.jp/ // @include http://mixi.jp/recent_echo.pl* // ==/UserScript== (function() { var allAnchor = document.getElementsByTagName("a"); for (i = 0; i < allAnchor.length; i++ ) { if (allAnchor[i].href.match(/list_echo\.pl.*&post_time=/)) { if (document.addEventListener) { allAnchor[i].addEventListener('mouseover', function(){popupDisplay(this);}, true); } else if (document.attachEvent) { allAnchor[i].attachEvent('onmouseover', function(){popupDisplay(event.srcElement);}); } } } function popupDisplay(obj) { alert(obj.getAttribute('href')); // http://mixi.jp/list_echo.pl?id=自主規制&post_time=自主規制 } })();
おー、ちゃんと渡せてるっぽい!