Online IDE Support JS

Injects elements into a codepen IDE for demonstration purposes

Versión del día 21/06/2022. Echa un vistazo a la versión más reciente.

Este script no debería instalarse directamente. Es una biblioteca que utilizan otros scripts mediante la meta-directiva de inclusión // @require https://update.greasyfork.org/scripts/438329/1063208/Online%20IDE%20Support%20JS.js

let demo;
let initCounter = 500;
const deprecatedEvents = {
    dropdown: [`getValue`]
};

const pen = {
    actions: {
        log: (msg) => {
            const logEl = pen.elements.logContent;
            pen.elements.logLabel.classList.add(`highlight`);
            setTimeout(() => {
                pen.elements.logLabel.classList.remove(`highlight`);
            }, 500);
            logEl.innerText = `${msg}\n${logEl.innerText}`;
            if (msg) console.log(msg);
        },
        api: {
            addButton: (lText, lAction) => {
                if (typeof lText === `string`) {
                    const newButton = pen.utils.createElement(`button`, {
                        class: `dds__btn dds__btn-primary dds__btn-sm dds__button dds__button--mini dds__text-truncate`,
                        text: lText
                    });
                    newButton.addEventListener(`click`, (e) => {
                        let actionResponse;
                        if (lAction.length > 0) {
                            try {
                                actionResponse = lAction(0);
                            } catch (e) {
                                try {
                                    actionResponse = lAction("0");
                                } catch (e) {
                                    try {
                                        actionResponse = lAction(["0"]);
                                    } catch (e) {
                                        try {
                                            actionResponse = lAction([0]);
                                        } catch (e) {
                                            try {
                                                actionResponse = lAction(new Date());
                                            } catch (e) {
                                                try {
                                                    actionResponse = lAction({ "alignment": "end" });
                                                } catch (e) {
                                                    try {
                                                        actionResponse = lAction(document.querySelector(`.dds__side-nav__item`));
                                                    } catch (e) {
                                                        try {
                                                            actionResponse = lAction(0, `descending`);
                                                        } catch (e) {
                                                            try {
                                                                actionResponse = lAction("1");
                                                            } catch (e) {
                                                                console.error(e);
                                                                actionResponse = lAction();
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } else {
                            actionResponse = lAction();
                        }
                        if (actionResponse) pen.actions.log(actionResponse);
                    });
                    pen.elements.apiContent.appendChild(newButton);
                } else { // presume we are moving an existing element to the pen nav
                    pen.elements.apiContent.appendChild(lText);
                }
            }
        },
    },
    elements: {
        logId: `log`,
        apiId: `api`,
    },
    utils: {
        addStyle: (styles) => {
            /* Create style document */
            var css = document.createElement('style');
            css.type = 'text/css';
            if (css.styleSheet)
                css.styleSheet.cssText = styles;
            else
                css.appendChild(document.createTextNode(styles));
            /* Append style to the tag name */
            document.getElementsByTagName("head")[0].appendChild(css);
        },
        /**
         * converts kebab-case words into camelCase ones
         * @param {string} key - a string with some number of dashes
         * @return {string} a camelCase version of whatever string was entered
         */
        dashCamel: function (key) {
            return key.replace(/-[a-z]/g, (m) => m.toUpperCase().replace(/-/gi, ""));
        },
        capitalize: (what) => {
            return what.charAt(0).toUpperCase() + what.slice(1);
        },
        createElement: (nodeType, props) => {
            const domNode = document.createElement(nodeType);
            if (props && "object" === typeof props) {
                for (const prop in props) {
                    if (prop === "html") {
                        domNode.innerHTML = props[prop];
                    } else if (prop === "text") {
                        domNode.textContent = props[prop];
                    } else {
                        if (prop.slice(0, 5) === "aria_" || prop.slice(0, 4) === "data_") {
                            const attr = prop.slice(0, 4) + "-" + prop.slice(5);
                            domNode.setAttribute(attr, props[prop]);
                        } else {
                            domNode.setAttribute(prop, props[prop]);
                        }
                    }
                    // Set attributes on the element if passed
                    if (["role", "aria-label"].includes(prop)) domNode.setAttribute(prop, props[prop]);
                }
            }
            return domNode;
        }
    },
    initialize: () => {
        if (demo == null) {
            setTimeout(() => {
                initCounter--;
                if (initCounter > 0) {
                    pen.initialize();
                }
            }, 50);
            return;
        }
        Object.keys(pen.elements).forEach(key => {
            if (key.indexOf(`Id`) > 0) {
                const elString = key.replace(`Id`, ``);
                pen.elements[elString] = pen.utils.createElement(`div`, {
                    id: elString,
                });
                if (elString === 'log' && (demo.log == null || demo.log !== `open`)) {
                    pen.elements[elString].classList.add(`closed`);
                }
                if (elString === 'api' && (demo.api == null || demo.api !== `open`)) {
                    pen.elements[elString].classList.add(`closed`);
                }
                pen.elements[`${elString}Label`] = pen.utils.createElement(`div`, {
                    class: `label`
                });
                pen.elements[`${elString}Label`].innerText = elString;

                pen.elements[`${elString}Content`] = pen.utils.createElement(`div`, {
                    class: `content`
                });
            }
        });
        Object.keys(pen.elements).forEach(key => {
            if (!key.match(/(Id|Label|Content)/g)) {
                document.querySelector(`body`).appendChild(pen.elements[key]);
                pen.elements[key].appendChild(pen.elements[`${key}Label`]);
                pen.elements[key].appendChild(pen.elements[`${key}Content`]);
            }
            if (key.indexOf(`Label`) > 0) {
                pen.elements[key].addEventListener(`click`, () => {
                    pen.elements[key.replace(`Label`, ``)].classList.toggle(`closed`);
                });
            }
        });

        let hasDispose = false;
        Object.keys(demo.component).forEach(key => {
            const method = pen.utils.capitalize(pen.utils.dashCamel(demo.selector));
            const selectorScript = `document.querySelector('[data-dds="${demo.selector}"]').${method}`;
            if (typeof demo.component[key] === `function`) {
                if (key !== `dispose`) {
                    if (!deprecatedEvents[demo.selector] || !deprecatedEvents[demo.selector].includes(key)) {
                        const parameterCount = demo.component[key].length;
                        let comment = parameterCount > 0 ? ` // takes ${parameterCount} parameters` : ``;
                        pen.actions.api.addButton(key, demo.component[key]);
                        pen.actions.log(`${selectorScript}.${key}();${comment}`);
                    }
                } else {
                    hasDispose = true;
                    pen.actions.log(`${selectorScript}.dispose()`);
                }
            } else {
                pen.actions.log(`${selectorScript}.${key} = ${demo.component[key]}`);
            }
        });
        pen.actions.log(`\n\n${demo.selector} properties / methods:::::::::::::::::::::::\n`);

        hasDispose && (pen.actions.api.addButton(`dispose`, () => {
            demo.component[`dispose`]();
            pen.elements.api.querySelectorAll(`button`).forEach(b => b.disabled = `true`);
        }));


        demo.events.forEach((ev) => {
            pen.actions.log(`
document.addEventListener('${ev}', (event) => {
    console.log(event.detail);
})`);
            document.addEventListener(ev, (e) => {
                let output;
                pen.actions.log(`${ev} was fired with {event}.detail = ${JSON.stringify(e.detail)}`);
                try {
                    output = JSON.stringify(e);
                    pen.actions.log(output);
                } catch (error) {
                    output = e;
                    console.error(ev, output);
                }
            });
        });
        pen.actions.log(`\n${demo.selector} events:::::::::::::::::::::::`);
    },
    addLinks: () => {
        const version = `2.12.0`;
        const links = [
            `https://dds.dell.com/components/${version}/css/dds-reboot.min.css`,
            `https://dds.dell.com/components/${version}/css/dds-fonts.min.css`,
            `https://dds.dell.com/components/${version}/css/dds-icons.min.css`,
            `https://dds.dell.com/components/${version}/css/dds-helpers.min.css`,
            `https://dds.dell.com/components/${version}/css/dds-main.min.css`,
        ];
        links.forEach((href) => {
            let link = pen.utils.createElement(`link`, {
                rel: 'stylesheet',
                crossorigin: '',
                href: href
            });
            document.querySelector(`head`).appendChild(link);
        });
    },
    addCss: () => {
        pen.utils.addStyle(`
body {
  margin: 5rem 3rem !important;
}
#log,
#api {
    transition: all 0.5s ease-in-out;
    position: absolute;
    z-index: 9999;
    height: 49vh;
    width: 80%;
    top: 50%;
    margin-left: 5%;
    color: white;
    background: black;
    font-size: 0.7rem;
    font-family: monospace;
    line-height: 0.9rem;
    padding: 1rem;
}

#log .label,
#api .label {
    font-family: Roboto;
    background: black;
    color: white;
    position: relative;
    float: right;
    top: .7rem;
    left: 4rem;
    max-width: 6rem;
    min-width: 5.25rem;
    text-align: center;
    padding: 0.5rem 0.625rem;
    transform: rotate(-90deg);
    cursor: pointer;
    border-bottom-right-radius: 0.625rem;
    border-bottom-left-radius: 0.625rem;
    white-space: nowrap;
}
#log .content {
  position: relative;
  top: -2rem;
  width: 98%;
  max-height: 46vh;
  overflow: auto;
}

.highlight {
  background: rgb(2,0,36) !important;
  background: linear-gradient(180deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgba(0,212,255,1) 100%) !important;
}

#api {
    top: 0;
    height: unset;
    min-height: 4.55rem;
    background: aliceblue;
}

#api button {
  margin-left: 0.3rem;
  margin-bottom: 0.1rem;
}

#api .label {
    top: 0;
    background: aliceblue;
    color: black;
    font-weight: bold;
}

.closed {
    transform: translateX(-110%);
}
`);
    },
    addButton: (label, callback, target) => {
        const newBtn = document.createElement(`button`);
        newBtn.classList.add(`dds__button`);
        newBtn.addEventListener(`click`, callback);
        newBtn.innerText = label;
        newBtn.style.marginRight = `0.625rem`;
        if (target) {
            target.appendChild(newBtn);
        } else {
            document.querySelector(`body`).prepend(newBtn);
        }
    }
};

(() => {
    // pen.addLinks();
    pen.addCss();
    pen.initialize();
})();