Common Utilities

Some common utilities

このスクリプトは単体で利用できません。右のようなメタデータを含むスクリプトから、ライブラリとして読み込まれます: // @require https://update.greasyfork.org/scripts/558741/1712360/Common%20Utilities.js

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Common Utilities
// @description  Some common utilities
// @namespace    https://github.com/dzist
// @version      0.0.1
// @author       Dylan Zhang
// @grant        GM_info
// ==/UserScript==

const utils = {
    log(...args) {
        console.log(
            `%c${GM_info.script.name}`,
            'padding: 0 4px; background: cyan; color: #000;',
            ...args
        )
    },
    ensureCondition(condition, maxAttempts = 600 /* 10s */, failureMessage) {
        const raf = window.requestAnimationFrame

        return new Promise((resolve, reject) => {
            let attempts = 0
            const detect = () => {
                const result = condition()
                if (result) {
                    resolve(result)
                } else if (attempts < maxAttempts) {
                    attempts++
                    raf(detect)
                } else {
                    reject(new Error(failureMessage))
                }
            }
            raf(detect)
        })
    },
    ensureElement(selector, maxAttempts = 600) {
        return utils.ensureCondition(
            () => document.querySelector(selector),
            maxAttempts,
            `Could not detect ${selector} after ${maxAttempts} attempts`
        )
    },
    getProperty(obj, ...props) {
        const stack = [obj]
        let current = obj

        for(let i = 0, len = props.length; i < len; i++) {
            const key = props[i]
            // check for undefined or null
            if (current == null) {
                return [, stack]
            }

            const isArraySearch = Array.isArray(current) && isNaN(Number(key))
            if (isArraySearch) {
                // if the `current` value is an array and the key is not a number,
                // find the first item with the key inside it.
                const foundItem = current.find(item => item && item[key])
                if (foundItem) {
                    stack.push(foundItem)
                    current = foundItem[key]
                } else {
                    return [, stack]
                }
            } else {
                current = current[key]
                if (i < len - 1 && current) {
                    stack.push(current)
                }
            }
        }

        return [current, stack]
    }
}