ニコニコ動画の動画の比率を固定するGreasemonkeyスクリプト

動画のサイズによって4:3、16:9と自動で変わってしまい
固定できないので作ってみた。
一つ前のスクリプトの副産物。

// ==UserScript==
// @name           Nicovideo Set Aspect Ratio
// @namespace      http://d.hatena.ne.jp/kiyo_hoge/
// @include        http://www.nicovideo.jp/watch/*
// ==/UserScript==

(function() {
    const VIDEO_SIZE_WIDE = true;
    var flvplayer = document.getElementById('flvplayer');
    
    function refreshVideo() {
        flvplayer.style.display = 'none';
        setTimeout(function() {
            flvplayer.style.display = '';
        }, 0);
    }
    
    if (!flvplayer) {
        return;
    }
    
    var flashvars = flvplayer.getAttribute('flashvars');
    var isWide = (flashvars.indexOf('isWide=1') >= 0);
    
    if (VIDEO_SIZE_WIDE && !isWide) {
        flvplayer.setAttribute('flashvars', flashvars + '&isWide=1');
        refreshVideo();
    }
    
    if (!VIDEO_SIZE_WIDE && isWide) {
        flvplayer.setAttribute('flashvars', flashvars.replace(/(?:^|&)isWide=[^&]+/g, ''));
        refreshVideo();
    }
})();

VIDEO_SIZE_WIDE = falseにすれば4:3固定。

ニコニコ動画の動画再生ページのレイアウトが変わった

ニコニコ動画の動画再生ページのレイアウトが変わったので
いつも通りスタイルシートを更新。
ニコニコ動画(9) 動画説明文を動画の横に


ただ更新したのはいい物のこのスタイルシートは16:9に対応していないのが
気に入っていなかったのでGreasemonkey辺りでどうにかできないかと思案。


前にニコニコ動画のプレーヤーからJavaScript経由で得られる情報を調べてみたが
そこからは動画の比率の情報は得られなかったので別の方法を検討。


動画の比率は何かしらの方法でプレーヤーに伝えられているだろうから
それを横からのぞき込んむことで初期の動画の比率を取得できないかと試してみた。


最初のサイズさえ取得できれば後は動画プレーヤーのクリック時にその位置から
比率が変更されたかどうかは分かる、


探してみたところ動画プレーヤーの属性から簡単に取得できた。

// ==UserScript==
// @name           ニコニコ動画(9) 動画説明文を動画の横に
// @namespace      http://d.hatena.ne.jp/kiyo_hoge/
// @description    「http://userstyles.org/styles/16521」の補助
// @include        http://www.nicovideo.jp/watch/*
// ==/UserScript==

location.href = 'javascript:(' + (function() {
  var flvplayer = document.getElementById('flvplayer');
  var watchHeader = document.getElementById('WATCHHEADER');
  
  if (!flvplayer) {
    return;
  }
  
  var flashvars = flvplayer.getAttribute('flashvars');
  var isWide;
  var loaded = false;
  
  if (flashvars.indexOf('isWide=1') >= 0) {
    isWide = true;
    addClass('video-size-wide', flvplayer);
    addClass('video-size-wide', watchHeader);
  }
  else {
    isWide = false;
  }
  
  flvplayer.addEventListener('click', function(e) {
    if (isVideoLoaded() && (flvplayer.ext_getVideoSize() == 'normal')) {
      if (isWide &&
        (632 <= e.layerX) && (e.layerX <= 652) &&
        (453 <= e.layerY) && (e.layerY <= 473)) {
        isWide = false;
        removeClass('video-size-wide', flvplayer);
        removeClass('video-size-wide', watchHeader);
      }
      else if (!isWide &&
        (502 <= e.layerX) && (e.layerX <= 522) && 
        (453 <= e.layerY) && (e.layerY <= 473)) {
        isWide = true;
        addClass('video-size-wide', flvplayer);
        addClass('video-size-wide', watchHeader);
      }
    }
  }, false);
  
  function addClass(className, elm) {
    var classList = elm.className.split(/\s+/);
    for (var i = classList.length; 0 <= i; i--) {
      if ((classList[i] == '') || (classList[i] == className)) {
        classList.splice(i, 1);
      }
    }
    classList.push(className);
    elm.className = classList.join(' ');
  }
  
  function removeClass(className, elm) {
    var classList = elm.className.split(/\s+/);
    for (var i = classList.length; 0 <= i; i--) {
      if ((classList[i] == '') || (classList[i] == className)) {
        classList.splice(i, 1);
      }
    }
    
    if (classList.length == 0) {
      elm.removeAttribute('class');
    }
    else {
      elm.className = classList.join(' ');
    }
  }
  
  function isVideoLoaded() {
    var status;
    if (loaded) {
      return true;
    }
    else {
      try {
        status = flvplayer.ext_getStatus();
      }
      catch (e) {
        status = 'stopped';
      }
      
      if (status != 'stopped') {
        loaded = true;
        return true;
      }
      
      return false;
    }
  }
}).toString() + ')();';

これと併用すれば上記のスタイルシートもプレーヤーサイズの比率変更に
対応することができるようになる。

Chrome版のAutoPagerizeはユーザースクリプトからAutoPagerizeのAPIを操作できない

Chromeの拡張の仕組みを知らないがwindow.AutoPagerizeを取得できなさそう。
GM_AutoPagerizeLoadedイベントを監視しても、ページ読み込み後に
setTimeoutでいくら粘ろうが取得できなかった
GM_AutoPagerizeLoadedイベント自体起きていない)。
少し前から無理そうだと感じていて改めて確かめてみたけどやっぱり無理だった。


addFilterはDOMNodeInsertedイベントを監視して追加される要素を取得すれば同じような事はできるが、それ以外のaddDocumentFilterやaddRequestFilterは多分無理。

jQuery UIのdialogを使い捨てで使う場合


$('<div />').dialog({
close: function(event) {
$(this).dialog('destroy');
$(event.target).remove();
});
今日初めて使った。
ダイアログ表示させる時、その要素がDOMツリーに入ってないとちゃんと
bodyの最後に追加してからdialogとして表示してくれる。
だがそのままではダイアログを閉じてもDOMツリーに追加されたままなので
閉じた際に削除する必要がある。


closeイベント時に「$(this).dialog('destroy');」を飛び出せば
ダイアログは消えるがダイアログ内に表示させた要素はbodyの最後に残ったままだ。


なのでダイアログとその中身を消すためには上のように
$(event.target).remove();」などとしてダイアログの中身も消す必要がある。


何も考えず使い捨て感覚で使ってたらidとかかぶってイベントがおかしくなった。