「サブウインドウ表示」から元に戻れない その2

「サブウインドウ表示」は動画プレーヤー以外の表示を排斥しているので、下手をするとユーザーが抜け出せなくなります。 前ページでプレミアムの「案内画面」の対策をしましたが、もうひとつの問題に気付きました。

 

 

戻れないプロセスの例 

これは、シリーズの最後の動画コンテンツや単一の動画コンテンツが終了した時のプロセスで生じます。

 

下は、シリーズになった動画コンテンツの一番最後の動画を聴取中の状態です。 これは「動画閲覧画面」である事を覚えておいてください。

 

 

この画面で「サブウインドウ表示」を選択して、下の様に動画の最後まで進んだとします。

 

 

シリーズの次の動画が無いので、この動画が終了した時は下の様な「他のコンテンツ」を選択する表示になります。

 

 

この状態では、「デフォルト表示」に戻るボタンがあるので問題はありません。

 

しかし、上の「他のコンテンツ」をクリックした場合、表示されるのは選択したコンテンツの「タイトル画面」です。 問題は、この画面でも「サブウインドウ表示」のデザインが適用されているため、上方へのスクロールが制限され、この画面の動画コンテンツを選択するしか出来なくなるという事です。 選択した動画が「有料動画」のみの場合には、出口がなくて困るかも知れません。

 

 

上のデフォルト画面は以下です。 もちろん、この状態なら行く先に困りません。

 

 

 

 コンテンツの「タイトル画面」

この様な問題になる理由を調べると、上の画面がコンテンツの「タイトル画面」だと気付きました。 通常の「動画閲覧画面」は以下の様なアドレスです。

 

https://abema.tv/video/episode/~~~~
https://abema.tv/channels/~~~~

 

しかし、上記の問題が生じる「タイトル画面」のアドレスは以下の形です。

 

https://abema.tv/video/title/~~~~

 

「動画閲覧画面」の手前に、括りとして必ずこの「タイトル画面」がある様です。 この画面は「動画閲覧画面」に似ていますが、「動画プレーヤー」が無く、右列の他のコンテンツのリンクもありません。

 

この画面には「動画プレーヤー」が無いので「サブウインドウ表示」をリセットするボタンが作れず、出られずに困る事が起こり得ます。

 

今回の事で、私はようやく「AbemaTV」のサイト構成が見えて来ました。

 

 

 

対策が優れた更新になる 

今回の「タイトル画面」に対する対策で、最初に考えたのは、動画プレーヤーの無い画面に入った時も、「案内画面」が表示された時と同様に「サブウインドウ表示」をリセットする事でした。

 

 

「動画プレーヤーの生成」のチェックプログラムは、ページの切換えごとに実行されます。 動画プレーヤーは、コンテンツの変更で作り直されるので、「サブウインドウ」ボタンをその度に生成するために、このチェックが必要です。

 

上の  が本来の処理ですが、それに の処理を追加すれば今回の問題の対策になります。 で、実際にコードを試すとリセットが働くのですが、少し問題がありました。 動画プレーヤーの生成の遅れに対処するため  の判定に 2sec必要で、リセットはその後になるのです。

 

ここから、もっと上手い方法を考えました。 これまで「サブウインドウ表示」の元になる「styleタグ」を「body」の末尾に置いていたのですが、置き場所を動画プレーヤー内にする方法です。

 

これなら、動画プレーヤーが生成されないページでは「サブウインドウ表示」のスタイルが適用される事は確実に防げます。 未確認の他の問題が生じる場合があっても、その可能性を一気に減らせ、今後のシステム変更にも強くなるはずです。

 

その代わり、動画プレーヤーが生成されるごとに「styleタグ」を埋め込む必要がありますが、テストしてみるとそん色を感じません。 シリーズの動画コンテンツの「サブウインドウ表示」は、コンテンツ間の移動で「サブウインドウ表示」がリセットされず、これは快適です。

 

上のダイアグラムの  の部分は全く不要になり、「AmbTV Comfy」の全体のコード構成をかなり変更しました。

 

 

 

 「ワイド表示」ボタンの操作性

「サブウインドウ表示」の実装で、デフォルトの「ワイド表示」ボタンの意味は薄れます。 ただ、使い方は人それぞれで、「ワイド表示」のデザインが必要という使い方もあり得ます。「ワイド表示」ボタンを非表示に出来ますが、多様性を減らさない方が良いと判断しています。

 

ただ、「サブウインドウ表示」の状態では「ワイド表示」のボタンは全く無効になります。「ワイド表示」が非表示にするツールは既に非表示にしてしまっているからです。 下は、「サブウインドウ表示」下の「ワイド表示」ボタンです。

 

 

実際の効果は無いのですが、このボタンをクリックすると「ワイド表示」が設定され、下の様にアイコンが変わります。

 

 

この状態で「サブウインドウ」を解除すると、「ワイド表示」になります。 しかし「サブウインドウ表示」の解除は、たいてい「デフォルト表示」に戻す事が目的で、「ワイド表示」にする事ではないと思います。

 

「サブウインドウ表示」で、アイコン以外は変化しない「ワイド表示」を設定するのは無意味です。 また間違って押していた場合は、「サブウインドウ表示」から復帰するつもりが「ワイド表示」に戻り、もういちど「ワイド表示」ボタンを押す必要があります。

 

このあたりの操作性を考えると、「サブウインドウ表示」の場合は「ワイド表示」ボタンを非表示にするのが一番良いと考えました。 要するに押せなくするだけです。

 

 

先に「ワイド表示」を押して「ワイド表示」にした場合は、「サブウインドウ表示」「ワイド表示」の両方のボタンがあり、つまり「サブウインドウ表示」に移行できます。 この場合「サブウインドウ表示」をリセットすると「ワイド表示」に戻ります。

 

「ワイド表示」で「サブウインドウ表示」ボタンを非表示に出来ると思いますが、効果のわりにコードが複雑になるので却下です。

 

 

 

「AmbTV Comfy」を利用するには

このツールは Chrome / Edge / Firefox版の拡張機能「Tampermonkey」上で動作します。 以下に、このツールの導入手順を簡単に説明します。

 

❶「Tampermonkey」を導入します

◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。

既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。 

拡張機能の導入については、以下のページに簡単な説明があるので参照ください。

 

 

❷「Tampermonkey」にスクリプトを登録します

◎「Tampermonkey」の「」マークの「新規スクリプト」タブを開きます。

 

 

 

◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。

 

〔コピー方法〕 軽量シンプルなツール「PreBox Button   」を使うと

  コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」

  の操作で、掲載コードのコピーが可能になります。

 

◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。

 

 

〔 AmbTV Comfy 〕 ver. 0.6

 

// ==UserScript==
// @name         AmbTV Comfy
// @namespace    http://tampermonkey.net/
// @version      0.6
// @description  AbemaTV ユーティリティ
// @author       Ameba User
// @match        https://abema.tv/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=abema.tv
// @grant        none
// ==/UserScript==



main();

let target=document.querySelector('head > title');
let monitor=new MutationObserver(main);
monitor.observe(target, { childList: true });

function main(){

    let retry=0;
    let interval=setInterval(wait_target, 20);
    function wait_target(){
        retry++;
        if(retry>100){ // リトライ制限 100回 2secまで
            clearInterval(interval); }
        let player=document.querySelector(
            '.com-vod-VODRecommendedContentsContainerView__player');
        if(player){
            clearInterval(interval);
            set_player(player); }}


    function set_player(player){
        let style=
            '<style class="atv_style">'+
            '.c-common-HeaderContainer-header, '+
            '.c-application-SideNavigation, '+
            '.c-application-SideNavigation--collapsed, '+
            '.com-vod-VODRecommendedContentsContainerView__player-aside-recommended '+
            '{ display: none; } '+
            '.c-video-EpisodeContainerView-breadcrumb, '+
            '.com-vod-VODRecommendedContentsContainerView__details, '+
            '.com-vod-VODRecommendedContentsContainerView__episode-list, '+
            '.com-feature-area-FeatureRecommendedArea__section, '+
            '.c-video-EpisodeContainerView__page-bottom, '+
            '.c-application-FooterContainer '+
            '{ display: none; } '+
            '.c-application-DesktopAppContainer__content-container '+
            '{ align-items: center; height: 100vh; } '+
            '.com-vod-VODResponsiveMainContent '+
            '{ margin: 0 !important; padding: 0 !important; } '+
            '.com-vod-VODRecommendedContentsContainerView__player-and-details '+
            '{ margin-right: 0 !important; } '+
            '.com-vod-VODRecommendedContentsContainerView__player '+
            '{ margin: 0 6px !important; } '+
            '.c-application-DesktopAppContainer__content '+
            '{ min-width: 400px !important; } '+
            '.com-vod-VODResponsiveMainContent '+
            '{ --com-vod-VODResponsiveMainContent--content-min-width: 400 !important; } '+
            '.com-vod-VODResponsiveMainContent__container { overflow: hidden; } '+
            '.com-vod-FullscreenInBrowserButton__screen-controller { display: none !important; } '+
            '</style>'+
            '<style class="atv_style_basic">'+
            '.com-vod-VODScreen-container { background: #000 !important; }'+
            '</style>';

        if(!player.querySelector('.atv_style')){
            player.insertAdjacentHTML('beforeend', style);

            let atv_style=player.querySelector('.atv_style');
            if(atv_style){
                atv_style.disabled=true; }}



        let wrap=player.querySelector('.c-vod-EpisodePlayerContainer-wrapper');
        if(wrap){
            let monitor1=new MutationObserver(play);
            monitor1.observe(wrap, { childList: true }); }

        setTimeout(()=>{
            let wrap_tv=player.querySelector('.c-tv-TimeshiftPlayerContainerView');
            if(wrap_tv){
                let monitor2=new MutationObserver(play);
                monitor2.observe(wrap_tv, { childList: true }); }
        }, 1000);


        setTimeout(()=>{
            let ec_thumbnail=
                document.querySelector('.c-vod-EpisodePlayerContainer-thumbnail');
            if(ec_thumbnail){
                reset_subw(); } // プレミアムAD表示時に「サブウインドウ表示」をリセット
        }, 200);

    } // set_player()



    function play(){
        let nav_b=document.querySelector(
            '.com-vod-VideoControlBar__playback-rate');
        if(nav_b){
            let sw=
                '<button type="button" class="atv_sw com-vod-FullscreenButton">'+
                '<div class="com-vod-FullscreenButton__tooltip">'+
                '<div class="atv_tp com-a-Tooltip com-a-Tooltip--arrow-position-center">'+
                '</div></div>'+
                '<span class="atv_icon">🔳</span></button>'+
                '<style>.atv_icon { padding: 0 0 2px; '+
                'filter: drop-shadow(2px 2px 0 #fff); } '+
                ':fullscreen .atv_sw { display: none; }</style>';

            if(!document.querySelector('.atv_sw')){
                nav_b.insertAdjacentHTML('afterend', sw); }

            let atv_sw=document.querySelector('.atv_sw');
            let atv_style=document.querySelector('.atv_style');
            let atv_tp=document.querySelector('.atv_tp');
            if(atv_sw && atv_style && atv_tp){
                if(atv_style.disabled==false){
                    atv_tp.textContent='デフォルト表示'; }
                else{
                    atv_tp.textContent='サブウインドウ表示'; }

                atv_sw.onclick=function(e){
                    e.preventDefault();
                    if(atv_style.disabled==false){
                        atv_style.disabled=true;
                        atv_tp.textContent='サブウインドウ表示'; }
                    else{
                        atv_style.disabled=false;
                        atv_tp.textContent='デフォルト表示'; }

                }}}} // play()



    function reset_subw(){
        let atv_style=document.querySelector('.atv_style');
        if(atv_style){
            if(atv_style.disabled==false){
                atv_style.disabled=true; }}}

} // main()




catch_click();

function catch_click(){ // 動画のサムネイルの暗転拡大表示
    let html_=document.querySelector('html');

    box_env();

    document.addEventListener('contextmenu', function(event){
        if(!event.shiftKey && !event.ctrlKey){
            event.preventDefault();
            let elem=document.elementFromPoint(event.clientX, event.clientY);
            let link_elem=elem.closest('a');

            if(link_elem){
                set_link(link_elem);
                set_img(link_elem);
                close(); }}});


    function box_env(){
        let lightbox=
            '<div id="lightbox">'+
            '<div id="photo_sw"><a id="photo_link">🎦 Movie Page</a></div>'+
            '<img id="box_img">'+
            '<style>'+
            '@keyframes fadeIn { 0% {opacity: 0} 100% {opacity: 1}} '+
            '.fin { animation: fadeIn .5s ease 0s 1 normal; animation-fill-mode: both; } '+
            '@keyframes fadeOut { 0% {opacity: 1} 100% {opacity: 0}} '+
            '.fout { animation: fadeOut .2s ease 0s 1 normal; animation-fill-mode: both; } '+
            '#lightbox { position: fixed; top: 0; left: 0; z-index: 3000; visibility: hidden; '+
            'background: black; width: 100vw; height: 100vh; text-align: center; } '+
            '#photo_sw { position: absolute; width: 100%; height: 15%; } '+
            '#photo_sw:hover #photo_link { opacity: 1; } '+
            '#photo_link { font: bold 21px Meiryo; position: absolute; top: 20px; left: 30px; '+
            'padding: 4px 12px 2px 10px; color: #000; background: #fff; cursor: pointer; '+
            'border: 2px solid #000; border-radius: 6px; text-decoration: none; opacity: 0; } '+
            '#box_img { width: 100vw; height: 100vh; padding: 2vh 2vw; '+
            'object-fit: contain; } '+
            '</style></div>';

        if(!document.querySelector('#lightbox')){
            document.body.insertAdjacentHTML('beforeend', lightbox); }}


    function set_link(target){
        let photo_link=document.querySelector('#photo_link');
        if(photo_link){
            let url=target.getAttribute('href');
            if(url){
                photo_link.setAttribute('href', url); }

            photo_link.onclick=function(event){
                event.stopImmediatePropagation(); }}}


    function set_img(target){
        let lightbox=document.querySelector('#lightbox');
        let box_img=lightbox.querySelector('#box_img');
        let img=target.querySelector('img');
        if(lightbox && box_img && img){
            let img_url=img.getAttribute('src').replace(/%3Fversion%.*$/,"");
            if(img_url){
                box_img.src=img_url;
                html_.style.overflow='hidden';
                lightbox.style.visibility='visible';
                lightbox.classList.remove('fout');
                lightbox.classList.add('fin'); }}}


    function close(){
        let html_=document.querySelector('html');
        let lightbox=document.querySelector('#lightbox');
        let box_img=lightbox.querySelector('#box_img');
        if(lightbox){
            lightbox.onclick=function(event){
                event.preventDefault();
                html_.style.overflow='inherit';
                lightbox.classList.remove('fin');
                lightbox.classList.add('fout');
                setTimeout(()=>{
                    lightbox.style.visibility='hidden';
                    box_img.src='';
                }, 200); }}}

} // catch_click()

 

 

 

「AmbTV Comfy」最新版について 

旧いバージョンの JavaScriptツールは、Abemaサイトのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。

 

●「AmbTV Comfy」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。