PC版U-NEXTの動画視聴のストレスを減らすスクリプトを書いたメモ

ビギナーです（免罪符）。
U-NEXTにおいて動画画面クリックで再生/一時停止操作を可能にするスクリプトを書きました。
配布先は<a href="https://greasyfork.org/ja/scripts/384524-playpauseonscreen-unext">こちら</a>．

#はじめに
youtubeでは動画画面上をクリックで再生/一時停止が切り替えられます。U-NEXTはそれができず、ながら見しているときに動画を一時停止したいときは毎回画面左下にある2cm四方くらいのボックスにマウスカーソルをピタリと当てる必要があります。私はエイム練習がしたくて動画を見ているわけではないのです...これはストレスです。

#U-NEXTの仕様と思惑・失敗
　U-NEXTの動画再生ページでは多くのhtmlタグがネストされています。chromeのデベロッパーツールで探ってみたところ、UIレイヤーの一番上にくるタグはdivで、class="ezLrGS"ないしマウスホバー時は"feUiJR"を持っていることがわかりました。そこでそのdivに対しオンクリックイベントを仕掛け、再生/一時停止を可能にしようと試みました。
ところがそのdivは、シークバーや音量調整などの動画のコントロール全般のオンクリックを担っているようなのです。コントロールバーはボタンそれぞれ別個にdivで領域確保されていて上にレイヤードされているのに、それらのマウスクリックイベントが透過しているような感じです。現に、件のレイヤーのdivのクリックをCSSで透過させると、クリックでは何も操作できなくなりました。
　そこで、<a href="https://qiita.com/ryo2132/items/bac787725c983d0e3f4b">この記事</a>に着想を得ました。コントロールバーや、次の動画のホバーがあるタイトル付近を避けて新しくdivをマスクし、そこにオンクリックを付加するというアイデアです。この方向性でうまく動作させることが可能となりました。

#スクリプト本体・説明
```javascript
// ==UserScript==
// @name         PlayPauseOnScreen-UNEXT
// @description  Enable you to play or pause a movie with a click on the screen at U-NEXT
// @version      1.4
// @namespace    https://qiita.com/toten_s
// @match        https://video.unext.jp/*
// ==/UserScript==

function addGlobalStyle(css){
  var head, style;
  head = document.getElementsByTagName("head")[0];
  if (!head) { return }
  style = document.createElement("style");
  style.type = "text/css";
  style.innerHTML = css;
  head.appendChild(style);
}

addGlobalStyle(`
  #ctl{
  position: absolute;
  margin: auto;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  height: 80vh;
  width: 100vw;
  }
  .hideCursor{
  cursor: none !important;
  }
`);

function video_ctl(v){
  if(v.paused){
    v.play();
  }else{
    v.pause();
  }
}

var video_tag;
function mask_div(){
  video_tag = document.getElementsByTagName("video")[0];
  if(document.getElementById("ctl") == undefined){
    var div = document.createElement("div");
    div.id = "ctl";
    div.addEventListener("click", function(){video_ctl(video_tag)}, false);
    //カーソル消し
    var timer;
    div.addEventListener("mousemove", function(){
      div.className = "";
      clearTimeout(timer);
      timer = setTimeout(function() {
        div.className = "hideCursor";
      }, 1000);
    });
    var layered = document.getElementsByTagName("div")[2];
    layered.appendChild(div);
  }
  console.log("PPOS: loaded");
}

console.log("PPOS: activated");
var target = document.getElementById("app");
var observer = new MutationObserver(function(mutations){
    if(mutations[0].target.nodeName == "VIDEO"){mask_div();};
});
var options = {
  attributes: true,
  attributeFilter: ["src"],
  subtree: true
};
observer.observe(target, options);
```
##console.logなど
起動しているかどうかの確認。αテストでは各所に散りばめてユーザースクリプトの処理がどのタイミングで行われるかを確認していました。htmlを読み込んだあと動的にvideoタグが生成されるようなので、何か工夫をしないとvideoタグを引っ張ってくるコードがエラーを吐きます。

##Ovserver
前述の工夫というのがこれ。代案にスクリプト読み込んだ数秒後に開始するというタイマー処理も考えたが、廃止。理由は、ページ遷移時にスクリプトが再び読み込まれるということがないので、videoタグの参照先の変化を監視して動かそうという発想。

##main
###概要
手を加えていない時の最上位レイヤー（件のdiv）と同じ階層に新しくdivを付け加える。cssでabsoluteにしておけば，同じ階層だと後ろの行にあるdivが上にマスクされる．そこにonclickイベントを付けて再生制御．
###DOS属性操作
タグの属性にアクセスする方法はいろいろあるようだけれど、
<code>div.id = ‘abc’</code>
のようにインスタンス変数的にアクセスする方法がわかりやすくて短いと思う（javascriptだとオプションと呼ぶらしい？）。onclick属性もそのようにアクセスできるけれど、引数を取る関数をonclickにするときとか、無名関数で複数行の処理をするときどうすれば良いか不明なのでaddEventlistenerで対応。つまり
<code>div.addEventListener("click", function(){video_ctl(video_tag)}, false)</code>
でなく
<code>div.onclick = video_ctl</code>
みたいな感じでも書けるということ。video_ctlの引数をグローバル変数にしたらこれでも動く．
あと、動画視聴ページに移行して再生が始められるまでにvideoタグがコロコロ変わるみたいで、その度に前述の監視が発火する。なのでif文で個数制御しておかないと大量のdivがマスクされることになる。

###Timer
βテストをしてくれた母からの要望で書き加えた。これらの記述をすることで視聴中マウスカーソルが消えて、邪魔をしなくなる。

##video_ctl
videoタグに対するメソッドはいろいろあって、この.pausedは一時停止しているときTrue、再生中はfalseを返してくれる。それでif分岐させてplay,pauseさせるのがこの関数。

#おわりに
Unextユーザーは使うと便利だと，思う！配布先は<a href="https://greasyfork.org/ja/scripts/384524-playpauseonscreen-unext">こちら</a>．

#参考
[1]JavaScriptでclass属性値を取得、変更する方法 https://lab.syncer.jp/Web/JavaScript/Snippet/76/
[2]Twitterから「いいね」を消し去るChrome拡張を作る - Qiita https://qiita.com/hal1437/items/59d7a55124027d2ff492
[3]z-index の値を無視して背面要素を操作可能にするCSS - Qiita https://qiita.com/shouchida/items/83c48c7423ea0eb617b8
[4]position:relativeとposition:absoluteで画像や文字を重ねてみよう https://naifix.com/relative-absolute/
[5]JavaScriptでのグローバル変数の宣言方法 | UX MILK https://uxmilk.jp/11598
[6]【DOM基礎】ノードの取得／属性の取得・設定 - Qiita https://qiita.com/KDE_SPACE/items/e21bb31dd4d9c162c4a6
[7]ライブラリを使わない素のJavaScriptでDOM操作 - Qiita https://qiita.com/kouh/items/dfc14d25ccb4e50afe89
[8]videoタグの動画埋め込み時に、画面クリックで再生、ポーズを設定する方法 - Qiita https://qiita.com/ryo2132/items/bac787725c983d0e3f4b
[9]How To Edit CSS within TamperMonkey (Edit Sites CSS) https://sinister.ly/Thread-Tutorial-How-To-Edit-CSS-within-TamperMonkey-Edit-Sites-CSS
[10]MutationObserver - †MASAYOSHI†のオンラインメモ帳 https://masayoshi-9a7ee.hatenablog.com/entry/20150627/1435372089
[11]