擬似要素(:beforeとか:afterとか)のjsからの操作が地味に調べたのと応用できそうだったのでメモ
【ゆるゆる募】もっと簡単な方法あったのに的なつっこみ
やりたいこと
- グローバルメニュー設置
- サブメニューはブラウザ幅100%
- グローバルメニュー内の項目をマウスオーバーしたら該当の項目に向けて吹き出しを出す
- PCのみの表示だけ作ればおk
要するにこういうこと
課題
- 擬似要素は非DOMなのでjsから操作するのにstyleを追加しないといけない。
- 動的に位置を取得しないといけないのでcssのclass追加でごまかせない
- なるべくコードを短くしたい ← これ
実装
擬似要素の操作
下記を参考に
Change :hover CSS properties with JavaScript
マウスがグロナビ内のメニューに来たときにブラウザサイズから位置をとって、headにstyle要素をTextNodeで追加
マウスが離れた時にスタイル自体を削除
var nav, style;
nav = $('#global-nav ul li.outline a.menu');
style = document.createElement('style');
nav.on('mouseenter', function(e){// マウス乗っかった時
var target, clientRect, leftpx, css;
target = e.target;
clientRect = target.getBoundingClientRect() ;
// 座標とる。なんとなく真ん中あたりにくるように調整
leftpx = window.pageXOffset + clientRect.left + 70;
css = '#global-nav ul li.outline ul:after{ left: ' + leftpx +'px; }';
style.appendChild(document.createTextNode(css));
document.getElementsByTagName('head')[0].appendChild(style);
}).on('mouseleave', function(){// マウス離れた時
document.getElementsByTagName('head')[0].removeChild(style);
});
あれ?マウスエンターの範囲が狭いので位置取得失敗するよ
こういう悲しいことになったので、サブメニューからマウスが離れたらstyleを削除するように変更
var submenu, nav, style;
submenu = $('#global-nav ul li.outline ul');
style = document.createElement('style');
nav.on('mouseenter', function(e){// マウス乗っかった時
var target, clientRect, leftpx, css;
target = e.target;
clientRect = target.getBoundingClientRect() ;
// 座標とる。なんとなく真ん中あたりにくるように調整
leftpx = window.pageXOffset + clientRect.left + 70;
css = '#global-nav ul li.outline ul:after{ left: ' + leftpx +'px; }';
style.appendChild(document.createTextNode(css));
document.getElementsByTagName('head')[0].appendChild(style);
});
submenu.on('mouseleave', function(){
document.getElementsByTagName('head')[0].removeChild(style);
});