badgeteam/Hatchery

View on GitHub
resources/assets/js/app.js

Summary

Maintainability
D
2 days
Test Coverage
/* global require */

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */
require('./bootstrap');

window.keymap = 'default';

const framebuffer = [];
let frames;
let currentFrame = 0;
let editor;

window.drawIcon = function () {
    let r = 0, p = 0;
    frames[currentFrame].forEach(function (pixel) {
        if (p > 7) {
            r++;
            p = 0;
        }
        if (r > 7) {
            console.warn('Image too big!');
        }
        framebuffer[r][p].style.backgroundColor = pixel.replace('0x', '#');
        p++;
    });
};

window.gotoFrame = function (num) {
    currentFrame = num;
    window.drawIcon();
    for (let child = document.getElementById('frames').firstChild; child !== null; child = child.nextSibling) {
        child.className = 'frames btn btn-default';
    }
    document.getElementById('frame' + num).className = 'frames btn btn-info';
};

window.addFrame = function () {
    const newFrame = frames.length;
    frames[newFrame] = [];
    for (let p = 0; p < 64; p++) {
        frames[newFrame][p] = '0x00000000';
    }
    window.addFrameButton(newFrame);
    window.framesToContent();
};

window.addFrameButton = function (index) {
    const framesDiv = document.getElementById('frames');
    if (index > 0) {
        if (index === 1) {
            let firstFrame = document.createElement('a');
            firstFrame.onclick = function () {
                window.gotoFrame(0); };
            firstFrame.innerText = '1';
            firstFrame.className = 'frames btn btn-info';
            firstFrame.id = 'frame0';
            framesDiv.appendChild(firstFrame);
        }
        let frameButton = document.createElement('a');
        frameButton.onclick = function () {
            window.gotoFrame(index); };
        frameButton.innerText = (index + 1).toString();
        frameButton.className = 'frames btn btn-default';
        frameButton.id = 'frame' + index;
        framesDiv.appendChild(frameButton);
    }
};

window.framesToContent = function () {
    let content = 'icon = (';
    let first = true;
    frames.forEach(function (frame) {
        if (!first) {
            content += ', ';
        } else {
            first = false;
        }
        content += '[';
        let firstPixel = true;
        frame.forEach(function (pixel) {
            if (!firstPixel) {
                content += ', ';
            } else {
                firstPixel = false;
            }
            content += pixel;
        });
        content += ']';
    });
    content += ', ' + frames.length + ')';
    editor.setValue(content);
};

window.pixelToHexA = function (rgba) {
    let remove = 5;
    if (rgba.indexOf('rgba') === -1) {
        remove = 4;
    }
    let sep = rgba.indexOf(',') > -1 ? ',' : ' ';
    rgba = rgba.substr(remove).split(')')[0].split(sep);
    if (rgba.indexOf('/') > -1) {
        rgba.splice(3,1);
    }
    for (let R in rgba) {
        let r = rgba[R];
        if (r.indexOf('%') > -1) {
            let p = r.substr(0,r.length - 1) / 100;
            if (R < 3) {
                rgba[R] = Math.round(p * 255);
            } else {
                rgba[R] = p;
            }
        }
    }
    if (isNaN(rgba[0])) {
        rgba[0] = 0;
    }
    if (isNaN(rgba[1])) {
        rgba[1] = 0;
    }
    if (isNaN(rgba[2])) {
        rgba[2] = 0;
    }
    if (isNaN(rgba[3])) {
        rgba[3] = 1;
    }
    let r = (+rgba[0]).toString(16),
        g = (+rgba[1]).toString(16),
        b = (+rgba[2]).toString(16),
        a = Math.round(+rgba[3] * 255).toString(16);
    if (r.length === 1) {
        r = '0' + r;
    }
    if (g.length === 1) {
        g = '0' + g;
    }
    if (b.length === 1) {
        b = '0' + b;
    }
    if (a.length === 1) {
        a = '0' + a;
    }
    return ('0x' + r + g + b + a);
};

window.lintFile = function () {
    const form = document.getElementById('content_form');
    const lintApi = form.getAttribute('action').replace('files', 'lint-content');
    window.$.post(lintApi, {
        file_content: editor.getValue(),
        _token: window.Laravel.csrfToken
    });
};

window.onload = function () {
    const ext = document.getElementById('extension');
    let langmode = 'python';
    if (ext) {
        if (ext.getAttribute('value') === 'json') {
            langmode = 'javascript';
        } else if (ext.getAttribute('value') === 'v') {
            langmode = 'verilog';
        } else if (ext.getAttribute('value') === 'md' || ext.getAttribute('value') === 'txt') {
            langmode = 'markdown';
        } else if (ext.getAttribute('value') === 'sh') {
            langmode = 'shell';
        }
    }

    [
        'content',
        'commands',
        'constraints'
    ].forEach(function (field) {
        if (document.getElementById(field)) {
            window.CodeMirror = require([
                '../../../node_modules/codemirror/lib/codemirror',
                '../../../node_modules/codemirror/mode/python/python',
                '../../../node_modules/codemirror/mode/javascript/javascript',
                '../../../node_modules/codemirror/mode/markdown/markdown',
                '../../../node_modules/codemirror/mode/verilog/verilog',
                '../../../node_modules/codemirror/mode/shell/shell',
                '../../../node_modules/codemirror/addon/dialog/dialog',
                '../../../node_modules/codemirror/addon/search/searchcursor',
                '../../../node_modules/codemirror/keymap/vim',
                '../../../node_modules/codemirror/keymap/sublime',
                '../../../node_modules/codemirror/keymap/emacs'
            ], function (CodeMirror) {
                editor = CodeMirror.fromTextArea(document.getElementById(field), {
                    lineNumbers: true,
                    mode: langmode,
                    showCursorWhenSelecting: true,
                    indentWithTabs: true,
                    keyMap: window.keymap,
                    json: true,
                    theme: (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'ambiance' : ''
                });
            });
            // Enable navigation prompt
            window.onbeforeunload = function () {
                return true;
            };
            const form = document.getElementById('content_form');
            if (form) {
                form.addEventListener('submit', function () {
                    window.onbeforeunload = null;
                });
            }
        }

        if (document.getElementById(field + '-readonly')) {
            window.CodeMirror = require([
                '../../../node_modules/codemirror/lib/codemirror',
                '../../../node_modules/codemirror/mode/python/python',
                '../../../node_modules/codemirror/mode/javascript/javascript',
                '../../../node_modules/codemirror/mode/markdown/markdown',
                '../../../node_modules/codemirror/mode/verilog/verilog',
                '../../../node_modules/codemirror/mode/shell/shell'
            ], function (CodeMirror) {
                CodeMirror.fromTextArea(document.getElementById(field + '-readonly'), {
                    lineNumbers: true,
                    mode: langmode,
                    readOnly: true,
                    theme: (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'ambiance' : ''
                });
            });
        }
    });
    if (document.getElementById('pixels')) {
        let icon;
        let readOnly = true;
        if (document.getElementById('content')) {
            icon = document.getElementById('content');
            readOnly = false;
        } else {
            icon = document.getElementById('content-readonly');
        }
        let data = icon.innerHTML.trim();
        if (data.startsWith('icon = ')) {
            data = data.replace('icon = (', '');
            data = data.replace(')','');
            let numFrames = parseInt(data.match(/[0-9]+?$/)[0], 10);
            data = data.replace(', ' + numFrames, '');
            if (numFrames > 0) {
                frames = data.split('],');
                frames.forEach(function (frame, index) {
                    frame = frame.trim();
                    frame = frame.replace('[', '');
                    frame = frame.replace(']', '');
                    frame = frame.trim();
                    frame = frame.split(',');
                    frame.forEach(function (pixel, index) {
                        frame[index] = pixel.trim();
                    });
                    frames[index] = frame;
                    currentFrame = index;
                    window.addFrameButton(index);
                });
            } else if (data.length === 0) {
                frames = [];
                for (let p = 0; p < 64; p++) {
                    frames[currentFrame][p] = '0x00000000';
                }
            }
            currentFrame = 0;
            if (frames.length !== numFrames) {
                console.warn('Data corrupted!');
            } else {
                for (let r = 0; r < 8; r++) {
                    framebuffer[r] = [];
                    for (let p = 0; p < 8; p++) {
                        framebuffer[r][p] = document.getElementById('row' + r + 'pixel' + p);
                        if (!readOnly) {
                            framebuffer[r][p].onclick = function () {
                                this.style.backgroundColor = document.getElementById('colour').style.backgroundColor;
                                let pos = this.id.match(/[0-9]+?/g);
                                let r = parseInt(pos[0], 10);
                                let p = parseInt(pos[1], 10);
                                frames[currentFrame][(r * 8) + p] = window.pixelToHexA(this.style.backgroundColor);
                                window.framesToContent();
                            };
                        }
                    }
                }
                window.drawIcon();
            }
            if (!readOnly) {
                const parentBasic = document.getElementById('colour'),
                    popupBasic = new window.Picker.default(parentBasic);
                popupBasic.onChange = function (color) {
                    parentBasic.style.backgroundColor = color.rgbaString;
                };
            }
        }
    }

    const lintButtons = document.getElementsByClassName('lint-button');
    for (let z = 0; z < lintButtons.length; z++) {
        const elem = lintButtons[z];
        elem.onclick = function () {
            window.lintFile();
            return false;
        };
    }

    if (window.UserId) {
        window.Echo.private('App.User.' + window.UserId)
            .listen('ProjectUpdated', (data) => {
                const messages = document.getElementById('messages');
                messages.innerHTML += '<div class="alert alert-' + data.type + ' alert-dismissible">\n' +
                    '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>\n' +
                    '<p>' + data.message + '</p>\n' +
                    '</div>';
            });
    }
};