<div
    id="dmm-rotation-widget"
    class="dmm-rotation-widget"
    data-api="https://g-topic.com/dmm/dmm_rotation.php"
>
    <div class="drw-head">
        <span class="drw-pr">PR</span>
        <span class="drw-title"></span>
    </div>

    <div class="drw-grid"></div>

    <div class="drw-status">
        読み込み中...
    </div>
</div>


<style>

/* ==========================================
DMM ウィジェット全体
========================================== */

.dmm-rotation-widget {
     width: 100%;
    max-width: 760px;
    box-sizing: border-box;

    margin-top: 0;
    margin-right: auto;
    margin-bottom: 0;
    margin-left: auto;

    padding-top: 4px;
    padding-right: 4px;
    padding-bottom: 4px;
    padding-left: 4px;

    background: #ffffff;

    font-family:
        -apple-system,
        BlinkMacSystemFont,
        "Helvetica Neue",
        "Yu Gothic",
        Meiryo,
        sans-serif;
}

.dmm-rotation-widget * {
    box-sizing: border-box;
}


/* ==========================================
PR
========================================== */

.drw-head {
    display: inline-flex;
    align-items: center;

    margin-top: 0;
    margin-right: 0;
    margin-bottom: 2px;
    margin-left: 0;
}

.drw-pr {
    display: inline-block;

    padding-top: 2px;
    padding-right: 6px;
    padding-bottom: 2px;
    padding-left: 6px;

    border: 1px solid #cccccc;
    border-radius: 4px;

    background: #ffffff;
    color: #555555;

    font-size: 11px;
    font-weight: normal;
    line-height: 1.4;
}


/* ==========================================
商品表示エリア
========================================== */

.drw-grid {
    display: grid;

    grid-template-columns:
        repeat(3, minmax(0, 1fr));

    gap: 8px;
}


/* ==========================================
商品カード

上下左右を個別に変更可能
========================================== */

.drw-card {
    min-width: 0;

    padding-top: 2px;
    padding-right: 4px;
    padding-bottom: 2px;
    padding-left: 4px;

    border: 1px solid #eeeeee;
    border-radius: 7px;

    background: #ffffff;
    text-align: center;
}


/* ==========================================
商品画像
========================================== */

.drw-image-link {
    display: block;

    width: fit-content;
    max-width: 100%;

    margin-top: 0;
    margin-right: auto;
    margin-bottom: 0;
    margin-left: auto;

    text-decoration: none;
}

.drw-image {
    display: block;

    width: 180px;
    max-width: 100%;
    height: auto;

    margin: 0 auto;
}


/* ==========================================
商品名リンク
========================================== */

.drw-name {
    display: -webkit-box;

    overflow: hidden;

    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;

    /* 短い商品名の下に余白を作らない */
    min-height: 0;

    margin-top: 0;
    margin-right: 0;
    margin-bottom: 0;
    margin-left: 0;

    color: #0066CC !important;

    font-size: 13px;
    line-height: 1.45;

    text-align: left;
    text-decoration: none !important;
}

.drw-name:hover {
    text-decoration: underline !important;
}


/* ==========================================
読み込み中
========================================== */

.drw-status {
    padding: 10px 0;

    color: #777777;

    font-size: 13px;
    text-align: center;
}


/* ==========================================
スマートフォン
========================================== */

@media screen and (max-width: 600px) {

    .dmm-rotation-widget {
        padding-top: 0;
        padding-right: 4px;
        padding-bottom: 0;
        padding-left: 4px;
    }

    .drw-grid {
        grid-template-columns: 1fr;
        gap: 4px;
    }

    .drw-card {
        padding-top: 2px;
        padding-right: 4px;
        padding-bottom: 2px;
        padding-left: 4px;
    }

    .drw-image {
        width: 220px;
        max-width: 100%;
        height: auto;
    }

    .drw-name {
        min-height: 0;
        margin: 0;

        font-size: 14px;
    }

}

</style>


<script>

(function () {

    'use strict';


    var root =
        document.getElementById(
            'dmm-rotation-widget'
        );


    if (!root) {
        return;
    }


    var apiUrl =
        root.getAttribute(
            'data-api'
        );


    var grid =
        root.querySelector(
            '.drw-grid'
        );


    var status =
        root.querySelector(
            '.drw-status'
        );


    var title =
        root.querySelector(
            '.drw-title'
        );


    /*
     * ページを開いた瞬間に
     *
     * 1〜3位
     * 4〜6位
     * 7〜9位
     *
     * のいずれかをランダム選択。
     *
     * 時間による変化はなし。
     */
    var rankStarts =
        [
            0,
            3,
            6
        ];


    var selectedRankStart =
        rankStarts[
            Math.floor(
                Math.random()
                *
                rankStarts.length
            )
        ];


    /*
     * スマホでは、
     * 選択された3商品の中から
     * 1商品をランダム表示。
     *
     * この抽選もページを開いた時に
     * 1回だけ行う。
     */
    var mobileIndex =
        Math.floor(
            Math.random() * 3
        );


    var selectedItems = [];


    function escapeHtml(value) {

        return String(
            value == null
                ? ''
                : value
        )

        .replace(
            /&/g,
            '&amp;'
        )

        .replace(
            /</g,
            '&lt;'
        )

        .replace(
            />/g,
            '&gt;'
        )

        .replace(
            /"/g,
            '&quot;'
        )

        .replace(
            /'/g,
            '&#039;'
        );
    }


    function safeUrl(value) {

        value =
            String(
                value || ''
            );


        return value.indexOf(
            'https://'
        ) === 0
            ? value
            : '#';
    }


    function cardHtml(item) {

        var url =
            safeUrl(
                item.url
            );


        var image =
            safeUrl(
                item.image
            );


        var name =
            escapeHtml(
                item.title
            );


        return (

            '<div class="drw-card">'

            +

            '<a'
            +
            ' class="drw-image-link"'
            +
            ' href="' + url + '"'
            +
            ' target="_blank"'
            +
            ' rel="nofollow sponsored noopener"'
            +
            '>'

            +

            '<img'
            +
            ' class="drw-image"'
            +
            ' src="' + image + '"'
            +
            ' alt="' + name + '"'
            +
            ' loading="lazy"'
            +
            ' style="max-width: 100%; height: auto;"'
            +
            '>'

            +

            '</a>'

            +

            '<a'
            +
            ' class="drw-name"'
            +
            ' href="' + url + '"'
            +
            ' target="_blank"'
            +
            ' rel="nofollow sponsored noopener"'
            +
            '>'

            +

            name

            +

            '</a>'

            +

            '</div>'
        );
    }


    function render() {

        if (!selectedItems.length) {
            return;
        }


        var mobile =
            window.matchMedia(
                '(max-width: 600px)'
            ).matches;


        var itemsToShow;


        if (mobile) {

            var index =
                Math.min(
                    mobileIndex,
                    selectedItems.length - 1
                );


            itemsToShow =
                [
                    selectedItems[index]
                ];

        } else {

            itemsToShow =
                selectedItems;
        }


        var html = [];


        itemsToShow.forEach(
            function (item) {

                html.push(
                    cardHtml(
                        item
                    )
                );
            }
        );


        grid.innerHTML =
            html.join('');
    }


    fetch(
        apiUrl,
        {
            method: 'GET',
            mode: 'cors',
            cache: 'no-store'
        }
    )

    .then(
        function (response) {

            if (!response.ok) {

                throw new Error(
                    'HTTP '
                    +
                    response.status
                );
            }


            return response.json();
        }
    )

    .then(
        function (json) {


            if (
                !json.sources
                ||
                !Array.isArray(
                    json.rotation
                )
            ) {

                throw new Error(
                    'データ形式が不正です'
                );
            }


            /*
             * PHP側の
             *
             * s1
             * s1
             * s1
             * s2
             * s3
             *
             * をそのまま利用。
             */
            var rotation =
                json.rotation.filter(
                    function (key) {

                        return (
                            json.sources[key]
                            &&
                            Array.isArray(
                                json.sources[key]
                                    .items
                            )
                            &&
                            json.sources[key]
                                .items
                                .length > 0
                        );
                    }
                );


            if (!rotation.length) {

                throw new Error(
                    '表示できる商品がありません'
                );
            }


            /*
             * s1 / s2 / s3 も
             * ページを開いた瞬間に
             * ランダム選択。
             */
            var sourceKey =
                rotation[
                    Math.floor(
                        Math.random()
                        *
                        rotation.length
                    )
                ];


            var source =
                json.sources[
                    sourceKey
                ];


            var items =
                source.items
                ||
                [];


            /*
             * 1〜3位
             * 4〜6位
             * 7〜9位
             *
             * のいずれかを取得。
             */
            selectedItems =
                items.slice(
                    selectedRankStart,
                    selectedRankStart + 3
                );


            /*
             * 該当順位の商品が存在しない場合だけ
             * 1〜3番目へ戻す。
             */
            if (!selectedItems.length) {

                selectedItems =
                    items.slice(
                        0,
                        3
                    );
            }


            if (!selectedItems.length) {

                throw new Error(
                    '表示できる商品がありません'
                );
            }


            title.textContent =
                source.label;


            status.style.display =
                'none';


            render();
        }
    )

    .catch(
        function (err) {

            console.error(
                err
            );


            status.textContent =
                '商品を取得できませんでした。';
        }
    );


    /*
     * PC⇔スマホの画面幅変更時だけ再描画。
     *
     * 商品や順位は再抽選しない。
     */
    window.addEventListener(
        'resize',
        render
    );


})();

</script>