Copy Link Common Library

Copy Link for Common Library

Dit script moet niet direct worden geïnstalleerd - het is een bibliotheek voor andere scripts om op te nemen met de meta-richtlijn // @require https://update.greasyfork.org/scripts/451573/1095463/Copy%20Link%20Common%20Library.js

function updateClipboard(CopyData) {
    try {
        navigator.clipboard.writeText(CopyData).then(function() {
            console.log('navigator.clipboard - Copying to clipboard was successful!')
        })
    } catch {
        GM_setClipboard(CopyData)
        console.log('GM_setClipboard - Copying to clipboard was successful!')
    }
}

function MaxZIndexFromPoint(selector) {
    //console.log(selector, getAllElementsFromPoint(document.querySelector(selector)) + 1)
    return getAllElementsFromPoint(document.querySelector(selector))
}

function getMaxZIndex() {
    return Math.max(
        ...Array.from(document.querySelectorAll('body *'), el =>
            parseFloat(window.getComputedStyle(el).zIndex),
        ).filter(zIndex => !Number.isNaN(zIndex)),
        1,
    );
}

function getZIndex(el) {
    if (el && el !== document.body && el !== window && el !== document && el !== document.documentElement) {
        var z = window.document.defaultView.getComputedStyle(el).getPropertyValue('z-index');
        if (isNaN(z)) return getZIndex(el.parentNode);
    }
    return z;
};

function getPosition(element) {
    let rect = element.getBoundingClientRect()
    return {
        x: rect.x,
        y: rect.y
    };
}

function getAllElementsFromPoint(el) {
    let elements = [];
    let display = [];
    let zIndex = []
    let item = document.elementFromPoint(getPosition(el).x, getPosition(el).y)
    while (item && item !== document.body && item !== window && item !== document && item !== document.documentElement && el !== item) {
        //console.log(item)
        elements.push(item);
        display.push(item.style.display)
        if (!isNaN(getZIndex(item))) {
            let zI = getZIndex(item)
            console.log(zI)
            zIndex.push(zI)
        }
        item.style.display = "none";
        item = document.elementFromPoint(getPosition(el).x, getPosition(el).y);
    }
    // restore display property
    for (let i = 0; i < elements.length; i++) {
        elements[i].style.display = display[i];
    }
    return Math.max(...zIndex, 1);
}

function getElementOffset(el) {
    let rect = el.getBoundingClientRect()
    return {
        top: rect.top,
        bottom: rect.bottom,
        left: rect.left,
        right: rect.right,
        width: rect.width,
        height: rect.height,
    };
}

function getRelativeOffset(el) {
    return {
        top: el.offsetTop,
        bottom: el.offsetTop + el.offsetHeight,
        left: el.offsetLeft,
        right: el.offsetLeft + el.offsetWidth,
        width: el.offsetWidth,
        height: el.offsetHeight,
    };
}

function getNodeTextElementOffset(node) {
    let textNode = getTextNodesIn(node, false)
    let range = document.createRange();
    try {
        range.selectNode(textNode);
        let rect = range.getBoundingClientRect()
        return {
            top: rect.offsetTop,
            bottom: rect.offsetTop + rect.offsetHeight,
            left: rect.offsetLeft,
            right: rect.offsetLeft + rect.offsetWidth,
            width: rect.offsetWidth,
            height: rect.offsetHeight,
        }    
    } catch (error) {
        console.error(error)
        return {
            top: 0,
            bottom: 0,
            left: 0,
            right: 0,
            width: 0,
            height: 0,
        }   
    }    
}

function getTextNodesIn(node, includeWhitespaceNodes) {
    var textNodes = [], nonWhitespaceMatcher = /\S/;

    function getTextNodes(node) {
        if (node.nodeType == Node.TEXT_NODE) {
            if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
                textNodes.push(node);
            }
        } else {
            for (var i = 0, len = node.childNodes.length; i < len; ++i) {
                getTextNodes(node.childNodes[i]);
            }
        }
    }

    getTextNodes(node);
    //console.log(textNodes, textNodes?.length)
    return textNodes?.length ? textNodes.shift() : null;
}
function getDefaultFontSize() {
    const element = document.createElement('div');
    element.style.width = '1rem';
    element.style.display = 'none';
    document.body.append(element);

    const widthMatch = window
        .getComputedStyle(element)
        .getPropertyValue('width')
        .match(/\d+/);

    element.remove();

    if (!widthMatch || widthMatch.length < 1) {
        return null;
    }

    const result = Number(widthMatch[0]);
    return !isNaN(result) ? result : null;
}

//백그라운드 이미지 가져오기
function GetBackGroundUrl(Area) {
    let BackGroundUrl = ''
    try {
        let imgURL = window.document.defaultView.getComputedStyle(Area, null).getPropertyValue('background')
        BackGroundUrl = imgURL.replace(/.*\s?url\([\'\"]?/, '').replace(/[\'\"]?\).*/, '')
        return BackGroundUrl
    } catch (err) {
        console.log(err)
    }
}

//Match
function MatchRegex(Area, regex, attributeToSearch) {
    //console.log(Area, regex, attributeToSearch)
    const output = [];
    if (attributeToSearch) {
        for (let element of Area.querySelectorAll(`[${attributeToSearch}]`)) {
            //console.log(regex.test(element.getAttribute(attributeToSearch)), element)
            if (regex.test(element.getAttribute(attributeToSearch))) {
                //console.log(element)
                output.push(element);
            }
        }
    } else {
        for (let element of Area.querySelectorAll('*')) {
            for (let attribute of element.attributes) {
                if (regex.test(attribute.value)) {
                    //console.log(element)
                    output.push(element);
                }
            }
        }
    }
    return output;
}

// Not Match
function NotMatchRegex(Area, regex, attributeToSearch) {
    const output = [];
    if (attributeToSearch) {
        for (let element of Area.querySelectorAll(`[${attributeToSearch}]`)) {
            if (!regex.test(element.getAttribute(attributeToSearch))) {
                //console.log(element)
                output.push(element);
            }
        }
    } else {
        for (let element of Area.querySelectorAll('*')) {
            for (let attribute of element.attributes) {
                if (!regex.test(attribute.value)) {
                    //console.log(element)
                    output.push(element);
                }
            }
        }
    }
    return output;
}

function querySelectorAllRegex(Area, regex, attributeToSearch) {
    const output = [];
    if (attributeToSearch === 'href') {
        for (let element of Area.querySelectorAll('A')) {
            if (element.href && !regex.test(element.href)) {
                //console.log(element, regex)
                output.push(element);
            }
        }
    } else if (attributeToSearch) {
        for (let element of Area.querySelectorAll(`[${attributeToSearch}]`)) {
            if (!regex.test(element.getAttribute(attributeToSearch))) {
                console.log(element, regex)
                output.push(element);
            }
        }
    } else {
        for (let element of Area.querySelectorAll('*')) {
            for (let attribute of element.attributes) {
                if (!regex.test(attribute.value)) {
                    console.log(element)
                    output.push(element);
                }
            }
        }
    }
    return output;
}

function byteLengthOf(TitleText, maxByte) {
    //assuming the String is UCS-2(aka UTF-16) encoded
    let Result
    let CharByte = 0
    let LineByte = 0
    for (var i = 0, l = TitleText.length; i < l; i++) {
        var Code = TitleText.charCodeAt(i);
        if (Code < 0x0080) { //[0x0000, 0x007F]
            CharByte = 1
            LineByte += 1;
        } else if (Code < 0x0800) { //[0x0080, 0x07FF]
            CharByte = 2
            LineByte += 2;
        } else if (Code < 0xD800) { //[0x0800, 0xD7FF]
            CharByte = 3
            LineByte += 3;
        } else if (Code < 0xDC00) { //[0xD800, 0xDBFF]
            var lo = TitleText.charCodeAt(++i);
            if (i < l && lo >= 0xDC00 && lo <= 0xDFFF) { //followed by [0xDC00, 0xDFFF]
                CharByte = 4
                LineByte += 4;
            } else {
                CharByte = 0
                throw new Error("UCS-2 String malformed");
            }
        } else if (Code < 0xE000) { //[0xDC00, 0xDFFF]
            CharByte = 0
            throw new Error("UCS-2 String malformed");
        } else { //[0xE000, 0xFFFF]
            CharByte = 3
            LineByte += 3;
        }
        //console.log(TitleText[i], CharByte, LineByte)
        if (LineByte >= maxByte) {
            TitleText = TitleText.substr(0, i).replace(/(、|,)$/, '').trim()
            Result = TitleText + '…'
            break;
        }
    }
    return Result ? Result.trim() : TitleText
}

function byteLengthOfCheck(TitleText) {
    if (typeof TitleText === 'undefined') { return 0 }
    //assuming the String is UCS-2(aka UTF-16) encoded
    let LineByte = 0
    for (var i = 0, l = TitleText.length; i < l; i++) {
        var Code = TitleText.charCodeAt(i);
        if (Code < 0x0080) { //[0x0000, 0x007F]
            LineByte += 1;
        } else if (Code < 0x0800) { //[0x0080, 0x07FF]
            LineByte += 2;
        } else if (Code < 0xD800) { //[0x0800, 0xD7FF]
            LineByte += 3;
        } else if (Code < 0xDC00) { //[0xD800, 0xDBFF]
            var lo = TitleText.charCodeAt(++i);
            if (i < l && lo >= 0xDC00 && lo <= 0xDFFF) { //followed by [0xDC00, 0xDFFF]
                LineByte += 4;
            } else {
                throw new Error("UCS-2 String malformed");
            }
        } else if (Code < 0xE000) { //[0xDC00, 0xDFFF]
            throw new Error("UCS-2 String malformed");
        } else { //[0xE000, 0xFFFF]
            LineByte += 3;
        }
    }
    return LineByte
}

function SearchChar(Text, Char) {
    let result = ''
    let SearchEx = new RegExp(Char, 'g')
    if (Text.match(SearchEx)) {
        return Text.match(SearchEx).reverse()[0]
    } else return result
}

function getFlag(Text) {
    let Point = []
    let LastPoint = Text.length - 1
    for (let j = LastPoint; j > 0; j--) {
        let Code = Text.charCodeAt(j)
        if (Code > 65280 && Code < 65375 && Code != 65306) {
            console.log(j, Code, String.fromCodePoint(Code))
            Point.push(j + 1)
        }
    }
    return Point
}

//ingnore childNodes Text
function ingnoreChildNodesText(element) {
    let childNodes = element.childNodes;
    result = '';

    for (let i = 0; i < childNodes.length; i++) {
        if (childNodes[i].nodeType == 3) {
            result += childNodes[i].data;
        }
    }

    return result;
}

// innerText except A tag
function getDirectInnerText(element) {
    let childNodes = element.childNodes;
    let result = ''

    for (let i = 0; i < childNodes.length; i++) {
        //console.log('nodeType: ', childNodes[i], childNodes[i].nodeType, childNodes[i].tagName )
        if (childNodes[i].tagName === 'A' || childNodes[i].nodeType == 3) {
            result += childNodes[i].data ? childNodes[i].data : childNodes[i].textContent;
        }
    }

    return result;
}

//첫글자 대문자
function nameCorrection(str) {
    let strPerfect = str.replace(/\s+/g, " ").trim();
    let strSmall = strPerfect.toLowerCase();
    let arrSmall = strSmall.split(" ");
    let arrCapital = [];
    for (let x of arrSmall.values()) {
        arrCapital.push(x[0].toUpperCase() + x.slice(1));
    }

    return arrCapital.join(" ");
}

function capitalize(str) {
    //console.log('capitalize: ', str)
    let result = str[0].toUpperCase();

    for (let i = 1; i < str.length; i++) {
        if (str[i - 1] === ' ') {
            result += str[i].toUpperCase();
        } else {
            result += str[i];
        }
    }

    return result;
}

//파일명 사용불가 문자 전각문자로 변환
function FilenameConvert(text) {
    const ExcludeChar = /[<\/:>*?"|\\]/g
    let result = text.replace(ExcludeChar, function(elem) {
        return String.fromCharCode(parseInt(elem.charCodeAt(0)) + 65248)
    })
    return result
}

function getNumericMonth(monthAbbr) {
    monthAbbr = capitalize(monthAbbr)
    return (String(['January',
        'February',
        'March',
        'April',
        'May',
        'June',
        'July',
        'August',
        'September',
        'October',
        'November',
        'December'
    ].indexOf(monthAbbr) + 1).padStart(2, '0'))
}

/**
 * 해당 함수는
 * php의 mb_convert_kana의 Javascript 버전이다.
 * 히라가나는 반각이 없음.
 */

function mbConvertKana(text, option) {
    let katahan, kanazen, hirazen, mojilength, i, re;
    katahan = ["ガ", "ギ", "グ", "ゲ", "ゴ", "ザ", "ジ", "ズ", "ゼ", "ゾ", "ダ", "ヂ", "ヅ", "デ", "ド", "バ", "パ", "ビ", "ピ", "ブ", "プ", "ベ", "ペ", "ボ", "ポ", "ヴ", "ー", "ァ", "ア", "ィ", "イ", "ゥ", "ウ", "ェ", "エ", "ォ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ッ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ャ", "ヤ", "ュ", "ユ", "ョ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ヲ", "ン", "カ", "ケ", "ワ", "イ", "エ", "゙", "゚"];
    kanazen = ["ガ", "ギ", "グ", "ゲ", "ゴ", "ザ", "ジ", "ズ", "ゼ", "ゾ", "ダ", "ヂ", "ヅ", "デ", "ド", "バ", "パ", "ビ", "ピ", "ブ", "プ", "ベ", "ペ", "ボ", "ポ", "ヴ", "ー", "ァ", "ア", "ィ", "イ", "ゥ", "ウ", "ェ", "エ", "ォ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ッ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ャ", "ヤ", "ュ", "ユ", "ョ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ヲ", "ン", "ヵ", "ヶ", "ヮ", "ヰ", "ヱ", "゛", "゜"];
    hirazen = ["が", "ぎ", "ぐ", "げ", "ご", "ざ", "じ", "ず", "ぜ", "ぞ", "だ", "ぢ", "づ", "で", "ど", "ば", "ぱ", "び", "ぴ", "ぶ", "ぷ", "べ", "ぺ", "ぼ", "ぽ", "ヴ", "ー", "ぁ", "あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お", "か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "っ", "つ", "て", "と", "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ", "ま", "み", "む", "め", "も", "ゃ", "や", "ゅ", "ゆ", "ょ", "よ", "ら", "り", "る", "れ", "ろ", "わ", "を", "ん", "か", "け", "ゎ", "ゐ", "ゑ", "゛", "゜"];
    mojilength = katahan.length;
    // r: 전각문자를 반각으로 변환
    // a: 전각영문자를 반각으로 변환
    if (option.match(/[ra]/)) {
        text = text.replace(/[A-z]/g, function(elem) {
            return String.fromCharCode(parseInt(elem.charCodeAt(0)) - 65248);
        });
    }
    // R: 반각문자를 전각으로 변환
    // A: 반각영문자를 전각으로 변환
    if (option.match(/[RA]/)) {
        text = text.replace(/[A-z]/g, function(elem) {
            return String.fromCharCode(parseInt(elem.charCodeAt(0)) + 65248);
        });
    }
    // n: 전각숫자를 반각으로 변환
    // a: 전각 영숫자를 반각으로 변환
    if (option.match(/[na]/)) {
        text = text.replace(/[0-9]/g, function(elem) {
            return String.fromCharCode(parseInt(elem.charCodeAt(0)) - 65248);
        });
    }
    // N: 반각숫자를 전각으로 변환
    // A: 반각영숫자를 전각으로 변환
    if (option.match(/[NA]/)) {
        text = text.replace(/[0-9]/g, function(elem) {
            return String.fromCharCode(parseInt(elem.charCodeAt(0)) + 65248);
        });
    }
    // s: 전각스페이스를 반각으로 변환
    if (option.match(/s/)) {
        text = text.replace(/ /g, " ");
    }
    // S: 반각스페이스를 전각으로 변환
    if (option.match(/S/)) {
        text = text.replace(/ /g, " ");
    }
    // k: 전각카타카나를 반각 카타카타로 변환
    if (option.match(/k/)) {
        for (i = 0; i < mojilength; i++) {
            re = new RegExp(kanazen[i], "g");
            text = text.replace(re, katahan[i]);
        }
    }
    // K: 반각카타카타를 전각카타카타로 변환
    // V: 탁점사용중인 문자를 글자로 변환
    if (option.match(/K/)) {
        if (!option.match(/V/)) {
            text = text.replace(/゙/g, "゛");
            text = text.replace(/゚/g, "゜");
        }
        for (i = 0; i < mojilength; i++) {
            re = new RegExp(katahan[i], "g");
            text = text.replace(re, kanazen[i]);
        }
    }
    // h: 전각히라가나를 반각카타카나로 변환
    if (option.match(/h/)) {
        for (i = 0; i < mojilength; i++) {
            re = new RegExp(hirazen[i], "g");
            text = text.replace(re, katahan[i]);
        }
    }
    // H: 반각카타카나를 전각히라가라로 변환
    // V: 탁점사용중인 문자를 글자로 변환
    if (option.match(/H/)) {
        if (!option.match(/V/)) {
            text = text.replace(/゙/g, "゛");
            text = text.replace(/゚/g, "゜");
        }
        for (i = 0; i < mojilength; i++) {
            re = new RegExp(katahan[i], "g");
            text = text.replace(re, hirazen[i]);
        }
    }
    // c: 전각카타카나를 전각히라가나로 변환
    if (option.match(/c/)) {
        for (i = 0; i < mojilength; i++) {
            re = new RegExp(kanazen[i], "g");
            text = text.replace(re, hirazen[i]);
        }
    }
    // C: 전각히라가나를 전각카타카나로 변환
    if (option.match(/C/)) {
        for (i = 0; i < mojilength; i++) {
            re = new RegExp(hirazen[i], "g");
            text = text.replace(re, kanazen[i]);
        }
    }
    return text;
}