HNEXTサポート

サムネイルポップアップ、タイトル全表示、表示条件保持

Version au 09/01/2024. Voir la dernière version.

// ==UserScript==
// @name         HNEXTサポート
// @namespace    https://greasyfork.org/morca
// @version      0.1
// @description  サムネイルポップアップ、タイトル全表示、表示条件保持
// @author       morca
// @match        https://video.hnext.jp/*
// ==/UserScript==

if (typeof jQuery == "undefined" || $().jquery < "1.8.0") {
    let script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
    script.onload = code;
    document.getElementsByTagName("head")[0].appendChild(script);
} else {
    code();
}
function code() {
    'use strict';
    function getCookie(name, dfl) {
        name += "=";
        let found = document.cookie.split("; ").find(c => c.indexOf(name) === 0);
        if (found) return decodeURIComponent(found.substr(name.length));
        return dfl;
    }
    function setCookie(name, value) {
        //TODO max-age
        document.cookie = name + "=" + encodeURIComponent(value) + "; path=/; max-age=5184000";
    }
    var href = location.href
    var base = href.replace(/^([^?]+)(?:\?(.*))?$/, "$1");
    var args = href.replace(/^([^?]+)(?:\?(.*))?$/, "$2").split('&');
    var changed = false;
    for (var filter = 0; filter < args.length; filter++) {
        if (/^filter=/.test(args[filter])) break;
    }
    if (filter == args.length) args.push("filter=");
    $("select.js-list-filter__sel").each((i, e) => {
        var sel = "filter=" + getCookie("filter", "");
        if (args[filter] != sel) {
            args[filter] = sel;
            changed = true;
        }
        $(e).change(function() {
            setCookie("filter", $(this).val());
        });
    });
    for (var order = 0; order < args.length; order++) {
        if (/^order=/.test(args[order])) break;
    }
    if (order == args.length) args.push("order=popular");
    $("select.js-list-sort__sel").each((i, e) => {
        var sel = "order=" + getCookie("order", "popular");
        if (args[order] != sel) {
            args[order] = sel;
            changed = true;
        }
        $(e).change(function() {
            setCookie("order", $(this).val());
        });
    });
    if (changed) window.top.location.replace(base + "?" + args.join("&"));
    function appendPreview() {
        $("div.ui-item-a__thumb, div.ui-item-a__thumb--list-collection, div.rnk-item__thumb").each((i, e) => {
            if (e.parentNode.hasAttribute("preview")) return;
            let src = $(e).attr("style");
            if (/^.*:url\(\/\/imgc\.nxtv\.jp\/.*_JK_F.*\.\w+\?.*$/.test(src)) {
                src = src.replace(/^.*:url\((\/\/imgc\.nxtv\.jp\/.*)_JK_F(.*\.\w+)\?.*$/, "https:$1_JK$2");
                $(e).parent().attr("src", src).attr("preview", "");
            }
            $(e).parent().parent().parent().find("a").attr("target", "_blank");
        });
        $("p.ui-item-a__catch, h2.rnk-item__text").each((i, e) => {
            $(e).attr("title", $(e).text());
        });
        $("div.ui-item-a__rate-wrap").each((i, e) => {
            $(e).attr("title", $(e).find("span.unx-ico-star").length);
        });
    }
    appendPreview();
    var imagePreviewSetEvents;
    (function(resolveSrc) {
        /*
         * Image preview script
         * original is written by Alen Grakalic (http://cssglobe.com)
         */
        var cursor;
        function move(ev) {
            if (!ev) ev = cursor; else cursor = ev;
            if (!ev) return;
            const margin = 10;
            const xOffset = 10;
            const yOffset = -30;
            let p = $("#preview");
            let x = ev.clientX + xOffset;
            let y = ev.clientY + yOffset;
            if (x + p.outerWidth(true) > $(window).width() - margin && x >= margin) x = $(window).width() - margin - p.outerWidth(true);
            if (y + p.outerHeight(true) > $(window).height() - margin && y >= margin) y = $(window).height() - margin - p.outerHeight(true);
            if (x < margin & x + p.outerWidth(true) <= $(window).width() - margin) x = margin;
            if (y < margin & y + p.outerHeight(true) <= $(window).height() - margin) y = margin;
            p.css("left", x + "px").css("top", y + "px");
        }
        var timer = setInterval(() => {
            $("#preview > img[srcs*=';']").each((i, e) => {
                if (!e.loaded) return;
                let src = e.getAttribute("src");
                let srcs = $(e).attr("srcs").split(";");
                if (srcs.length >= 2) {
                    if (e.second) {
                        e.loaded = false;
                        e.setAttribute("src", srcs[(srcs.indexOf(src) + 1) % srcs.length]);
                    } else {
                        e.second = true;//skip first trigger
                    }
                }
            });
        }, 2000);
        function create(ev, t) {
            if (!t.focus) return;//check focus still on
            let src = t.getAttribute("src");
            if (!src) {
                if (resolveSrc) resolveSrc(t, create, ev);
                return;
            }
            t.t = t.getAttribute("title");
            t.title = "";
            let style = "display: none;"//fadeIn
                + " position: fixed;"//clientX/Y
                + " z-index: 1000;"//foreground
                + " pointer-events: none;"//avoid hover flicker
                + " *width: auto;"//wrap
                + " line-height: 120%; box-sizing: content-box; padding: 2px; border: 1px solid #333; background: #444; color: #fff;";//design
            let c = (t.t) ? `<span style='font-size: 95%; font-family: 'メイリオ'; text-align: center;'>${t.t}</span>` : "";
            let srcs = src.split(";");
            let img = `<img src='${srcs[0]}' srcs='${src}' srcs0='${src}' style='display: none;' />`;
            let div = $(`<div id='preview' style='${style}''>${c}${img}</div>`);
            $("body").append(div);
            $(div).find("img:last")[0].addEventListener('load', function(e) {//last is to exclude emoji img
                if (this.width == 120 && /\/4\.jpg/.test(this.getAttribute("src"))) {//TODO geo spec 404 image
                    $(div).hide();
                    let src = this.getAttribute("src");
                    console.log("fail", src);
                    this.setAttribute("src", src.replace(/\/4\.jpg/, "/3.jpg"));
                    return;
                }
                if (this.width <= 1) {
                    $(div).hide();
                    let src = this.getAttribute("src");
                    console.log("fail", src);
                    let srcs = this.getAttribute("srcs").split(";");
                    let srcs2 = srcs.filter((e, i, a) => { return a[i] != src });//TODO remove it and after
                    this.setAttribute("srcs", srcs2.join(";"));
                    if (srcs2.length > 0) this.setAttribute("src", srcs2[0]);
                    return;
                }
                this.loaded = true;
                if (this.height > document.documentElement.clientHeight * 0.9) {
                    this.width *= document.documentElement.clientHeight / this.height * 0.9;
                }
                this.parentNode.style.width = this.width + "px";
                this.style.display = "block";
                move(null);
                $(div).fadeIn();//to show hidden img
            }, false);
            move(ev);//just save
            $(div).fadeIn();//to response hover
        }
        imagePreviewSetEvents = function(node, unbind) {
            if (!node.hasAttribute("preview")) return;
            if (unbind) {
                $(node).removeAttr("preview");
                $(node).unbind("mouseenter mouseleave mousemove");
                return;
            }
            let events = $(node).data("events");
            if (events && (events.mouseenter || events.mouseleave || events.mousemove)) return;
            $(node).hover(function(ev) {
                this.focus = true;
                create(ev, this);
            }, function() {
                this.focus = false;
                if (this.t) this.title = this.t;
                $("#preview > img[srcs0*=';']").each((i, e) => {//update shrunk srcs
                    let srcs = e.getAttribute("srcs");
                    let srcs0 = e.getAttribute("srcs0");
                    if (srcs != srcs0) $(`[preview][src="${srcs0}"]`).attr("src", srcs);
                });
                $("#preview").remove();
            }).mousemove(function(ev) {
                if (!$("#preview")[0]) {
                    create(ev, this);//for src added afterward
                    return;
                }
                move(ev);
            });
        }
    })(function(t, create, ev) {
        let href = t.getAttribute("href");
        let m = /&rp=([^&]+)/.exec(href);
        if (m) href = decodeURIComponent(m[1]);
        if (!/^(?:[^/]+:\/\/[^/]+)?(?:\/[^/]+)?\/detail-[0-9]+\.html(\?.+)?$/.test(href)) return;
        href = href.replace(/\.html(\?.+)?$/, ".html");
        if (t.creating) return;
        t.creating = true;
        let title = t.getAttribute("title");
        $.get(href, data => {
            let html = $.parseHTML(data);
            let img = $(html).find("img[itemprop='image']");
            let alt = img.attr("alt");
            let src = img.attr("src");
            if (!src) {
                console.log("not found");
                imagePreviewSetEvents(t, true);
                return;
            }
            if (/\/(.+\/)?cdn\/.+\/[1-4]\.jpg(\?.*)?$/.test(src)) {
                src = src.replace(/\/[1-4]\.jpg(\?.*)?$/, "/4.jpg");
            }
            if (!title) {
                let title = t.getAttribute("title");
                title = `${alt}` + (title && ` ${title}` || "");
                t.setAttribute("title", title);
            }
            t.setAttribute("src", src);
            create(ev, t);
            t.creating  = false;
        });
    });
    $("[preview]").each((i, e) => { imagePreviewSetEvents(e); });
    function watchAutoPager(holder, load) {
        $(holder).each((i, e) => {
            var countDefer = 0;
            var timerDefer;
            e.addEventListener('DOMNodeInserted', function(e) {
                countDefer = 0;
                if (!timerDefer) timerDefer = setInterval(() => {
                    if (countDefer < 2) {
                        countDefer++;
                        return;
                    }
                    clearInterval(timerDefer);
                    timerDefer = null;
                    if (load) load();
                }, 1000);
            });
        });
    }
    watchAutoPager("body", () => {
        appendPreview();
        $("[preview]").each((i, e) => { imagePreviewSetEvents(e); });
    });
}