<commit_before>"use strict";
var crc = require("../basic/crc");
var path = require("path");
var fs = require("fs");
var report = require("./report");
var setting = require("./setting");
var getArgs = require('./getArgs');
var strings = require("../basic/strings");
var r21 = "'()*+,-./0123456789:;"
var r29 = "?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[";
var r34 = "]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var memory = require("../efront/memery");
var codetemp = function (delta) {
    var temp = [];
    while (delta > 0) {
        var mode = delta % 84;
        if (mode < 21) {
            temp.push(r21[mode])
        }
        else if (mode < 50) {
            temp.push(r29[mode - 21]);
        }
        else {
            temp.push(r34[mode - 50]);
        }
        delta = delta / 84 | 0;
    }
    return temp;
}
var encrypt = function (text, efrontsign) {
    text = String(text);
    if (!encoded) return text;
    var start = parseInt(efrontsign, 36) % 128;
    var rest = [];
    for (var cx = 0, dx = text.length; cx < dx; cx++) {
        var code = text.charCodeAt(cx);
        var delta = code - start;
        if (delta < 0) {
            delta = -delta;
            if (delta < 5) {
                rest.push(r21[delta])
            } else if (delta < 34) {
                rest.push(r29[delta - 5]);
            } else {
                var temp = codetemp(delta - 33);
                rest.push(r21[10 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        else {
            if (delta < 6) {
                rest.push(r21[delta + 5]);
            }
            else if (delta < 40) {
                rest.push(r34[delta - 6]);
            } else {
                var temp = codetemp(delta - 39);
                rest.push(r21[15 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        start = code;
    }
    return rest.join("");
}
var encoded = memory.ENCRYPT;
var compress = memory.COMPRESS;
var ReleaseTime = new Date();
if (encoded) encoded = (Math.random() * ReleaseTime | 0).toString(36);

ReleaseTime = String(ReleaseTime);
var buildHtml = function (html, code) {
    var isZimoliDetected = false;
    var poweredByComment;
    var html = html.toString()
        .replace(/^\s*(<!doctype[^>]*?>\s*)?<!--([\s\S]*?)--!?>/i, function (_, doctype, message) {
            // `${doctype}<!--${message}\r\n${efrontReloadVersionAttribute}-->`
            poweredByComment = _;
            return "";
        })
        .replace(/<!--[\s\S]*?--!?>/g, "")
        .replace(/<title>(.*?)<\/title>/i, `<title>${memory.TITLE || "$1"}</title>`)
        .replace(/<script\b[\s\S]*?<\/script>\s*/ig, function (script) {
            if (/(["'`])post\1\s*,\s*(['`"])comm\/main\2/i.test(script)) {
                isZimoliDetected = true;
                return "";
            }
            if (/<script\s[^>]*?(type\s*=\s*)?(["']|)efront\-?(?:hook|main|host|script|loader)\1[^>]*?>/i.test(script)) {
                isZimoliDetected = true;
            }
            if (/\b((delete|ignore)oncompile|efrontworker)\b/i.test(script)) {
                return "";
            }
            return script;
        });

    if (isZimoliDetected)
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script compiledinfo${encoded ? '-' + encoded : ''}="${ReleaseTime} by efront ${require(path.join(__dirname, "../../package.json")).version}">\r\n<!--\r\n-function(){${code}}.call(this)\r\n-->\r\n</script>\r\n${head}`);
    if (memory.IN_WATCH_MODE) {
        let WATCH_PORT = memory.WATCH_PORT;
        let reloadVersion = memory.WATCH_PROJECT_VERSION;
        let efrontReloadVersionAttribute = "efront-reload-version";
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script ${efrontReloadVersionAttribute}=${reloadVersion}>
        -function(){
            "use strict";
            var load = function(url, onload, method){
                var xhr = new XMLHttpRequest;
                xhr.open(method, url);
                xhr.timeout = 0;
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4 && xhr.status === 200) onload(xhr);
                };
                xhr.send("${reloadVersion}");
            };
            var reloader = function(){
                load(location.pathname + "?time=" + +new Date(), function(xhr){
                    var version = xhr.responseText.match(/\\b${efrontReloadVersionAttribute}\\s*=\\s*(\\d+)\\b/);
                    console.info("当前版本:${reloadVersion},目标版本:" + targetVersion + "正在重新加载,..");
                    if( !version || +version[1] !== ${reloadVersion}) location.reload() | console.warn("reload..", new Date);
                    else setTimeout(reloader, 200);
                }, "get");
            };
            var targetVersion = ${reloadVersion};
            var checkUpdate = function(xhr){
                targetVersion = xhr.responseText||xhr.response;
                reloader();
            };
            load("http://localhost${WATCH_PORT ? ":" + WATCH_PORT : ""}/reload/${reloadVersion}", checkUpdate, "post");
        }();
        </script>\r\n${head}`);
    }
    if (poweredByComment) {
        html = html.replace(/^\s*(?:<!doctype[\s\S]*?>)?/i, poweredByComment);
    }
    return html;
};
function toApplication(responseTree) {
    var mainScript = responseTree.main || responseTree["main.js"] || null;
    var indexHtml = responseTree["/index.html"] || responseTree["@index.html"];
    if (!indexHtml) {
        var htmlPath = path.join(__dirname, "../../apps", "index.html");
        indexHtml = {
            time: 0,
            needed: true,
            fullpath: htmlPath,
            data: fs.readFileSync(htmlPath),
            realpath: htmlPath,
            version: fs.statSync(htmlPath).mtime,
            destpath: path.join("index.html"),
        };
        responseTree["/index.html"] = indexHtml;
    }
    if (mainScript) {
        Object.keys(responseTree).forEach(function (key) {
            if (/\.(jsp|php|html|asp)$/i.test(key)) {
                var response = responseTree[key];
                if (response && response.data) {
                    response.data = buildHtml(response.data, mainScript.data);
                }
            }
        });
    }
    delete responseTree["main"];
    delete responseTree["main.js"];
    return responseTree;
}
var rebuildData = function (responseTree) {
    var keys = Object.keys(responseTree).sort();
    var keysmap = Object.create(null);
    var renmap = Object.create(null);
    keys.forEach(function (k) {
        var o = responseTree[k];
        if (!o.data || !o.destpath || !o.realpath) {
            return;
        }
        var k0 = k.toLowerCase().replace(/\d+$/, '');
        if (k0 in keysmap) {
            keysmap[k0]++;
            k0 = k0 + keysmap[k0];
            if (k0 !== k) renmap[k] = k0;
        } else {
            keysmap[k0] = 1;
        }
    });
    Object.keys(renmap).forEach(k => {
        var o = responseTree[k];
        if (o.type !== '') {
            delete renmap[k];
            console.warn("发现可能被覆盖的路径", o.destpath);
            return;
        }

        var k1 = renmap[k];
        delete responseTree[k];
        responseTree[k1] = o;
        k1 = k1.replace(/^[\s\S]*?([^\/\\]*?)(\.[^\/\\\.]+)?$/, '$1');
        var m = /^([\s\S]*?)[^\/\\]*?(\.[^\/\\\.]+)?$/.exec(o.destpath);
        if (m[1]) {
            o.destpath = m[1] + k1 + m[2];
        }
    });

    Object.keys(responseTree).forEach(function (k) {
        var imageIndex = 0;
        var rep = function (e) {
            if (typeof e !== "string") return String(e);

            return strings.encode(e.replace(/(["`']|)data(\.\w+)\:([\w\+\/\=,;\-\.]+)\1/gi, function (_, quote, ext, data) {
                var match = /^([\w\-\.\/]+;base64)?,([\w\+\/\-\=]+)$/i.exec(data);
                if (!match) return _;
                do {
                    imageIndex++;
                    var name = k + "-" + imageIndex + ext;
                } while (name in responseTree);
                var destpath = response.destpath.replace(/\.[\w]+$/, '') + '-' + imageIndex + ext;
                responseTree[name] = { destpath, data: Buffer.from(match[2], "base64"), realpath: true, url: name };
                return quote + destpath.replace(/\\/g, '/') + quote;
            }));
        };
        var response = responseTree[k];
        if (!response.data) return;
        var data = String(response.data);

        var { argNames, args, required, dependenceNamesOffset, strs, strend } = getArgs(data);
        if (strs && strs.length > 0) {
            strs = `[${strs.map(rep)}]`;
            data = response.data = data.slice(0, dependenceNamesOffset) + (strs.length * 2).toString(36) + strs + data.slice(strend);
        }
        if (!dependenceNamesOffset) return;
        if (args) args = args.map(a => {
            if (!(a in renmap)) return a;
            return renmap[a];
        });
        var argstr = args.concat(argNames, !required ? [] : required.split(";").map(a => {
            return a.replace(/\.(\w+)$/g, '').replace(/\-(\w)/g, (_, a) => a.toUpperCase());
        }).join(";")).join(",");
        var arglen = (argstr.length << 1).toString(36);
        while (arglen.length < 3) {
            arglen = "0" + arglen;
        }
        response.data = arglen + argstr + data.slice(dependenceNamesOffset);
    });
};
module.exports = function (responseTree) {
    rebuildData(responseTree);
    report(responseTree);
    if (!responseTree["main"] && !responseTree["main.js"]) {
        console.warn("在您所编译的项目中没有发现主程序");
        return toApplication(responseTree);
    }
    var commbuilder = require("../efront/commbuilder");
    commbuilder.compress = false;
    var mainScript = responseTree.main || responseTree["main.js"];
    var mainScriptData = commbuilder(mainScript.data, "main.js", mainScript.realpath, []);
    commbuilder.compress = +compress;
    var versionTree = {};
    if (setting.is_file_target) {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(v.name) || !v.data) return;
            if (v.type === "@") return;
            if (v.name !== "main") {
                versionTree[v.name] = encrypt(v.data, encoded);
                delete responseTree[k];
            }
        });
    } else {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (!v) return;
            if (v.type === "@") return;
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(v.name) || !v.data) return;
            if (v.name !== "main") {
                v.data = encrypt(v.data, encoded);
                var responseVersion = crc([].map.call(v.data.toString(), e => e.charCodeAt(0))).toString(36) + (+v.data.length).toString(36);
                versionTree[v.name] = responseVersion;
            }
        });
    }

    return Promise.resolve(mainScriptData).then(function (mainScriptData) {
        if (setting.is_file_target) {
            var xTreeName = /(?:\bresponseTree\s*|\[\s*(["'])responseTree\1\s*\])\s*[\:\=]\s*(.+?)\b/m.exec(mainScriptData)[2];
            commbuilder.prepare = false;
        } else {
            var xTreeName = /(?:\bversionTree\s*|\[\s*(["'])versionTree\1\s*\])\s*[\:\=]\s*(.+?)\b/m.exec(mainScriptData)[2];
        }

        var code = "{\r\n" + Object.keys(versionTree).map(k => `["${k}"]:"${versionTree[k]}"`).join(",\r\n\t") + "\r\n}";
        var versionVariableName;
        code = mainScriptData.toString()
            .replace(/var\s+killCircle[\s\S]*?\}\);?\s*\}\s*\};/, 'var killCircle=function(){};')
            .replace(/(?:\.send|\[\s*(["'])send\1\s*\])\s*\((.*?)\)/g, (match, quote, data) => (versionVariableName = data || "", quote ? `[${quote}send${quote}]()` : ".send()"))
            .replace(/(['"])post\1\s*,(.*?)\s*\)/ig, `$1get$1,$2${versionVariableName && `+"${memory.EXTT}?"+` + versionVariableName})`)
            .replace(
                new RegExp(/\b/.source + xTreeName + /(\s*)=(\s*)\{.*?\}/.source),
                function (m, s1, s2) {
                    return xTreeName + `${s1}=${s2}${code}`;
                }
            );
        return commbuilder(code, "main.js", mainScript.realpath, []);
    }).then(function (mainScriptData) {
        mainScript.data = mainScriptData;
        return toApplication(responseTree);
    });
};<commit_msg>防止一些非编译的代码被破坏<commit_after>"use strict";
var crc = require("../basic/crc");
var path = require("path");
var fs = require("fs");
var report = require("./report");
var setting = require("./setting");
var getArgs = require('./getArgs');
var strings = require("../basic/strings");
var r21 = "'()*+,-./0123456789:;"
var r29 = "?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[";
var r34 = "]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var memory = require("../efront/memery");
var codetemp = function (delta) {
    var temp = [];
    while (delta > 0) {
        var mode = delta % 84;
        if (mode < 21) {
            temp.push(r21[mode])
        }
        else if (mode < 50) {
            temp.push(r29[mode - 21]);
        }
        else {
            temp.push(r34[mode - 50]);
        }
        delta = delta / 84 | 0;
    }
    return temp;
}
var encrypt = function (text, efrontsign) {
    text = String(text);
    if (!encoded) return text;
    var start = parseInt(efrontsign, 36) % 128;
    var rest = [];
    for (var cx = 0, dx = text.length; cx < dx; cx++) {
        var code = text.charCodeAt(cx);
        var delta = code - start;
        if (delta < 0) {
            delta = -delta;
            if (delta < 5) {
                rest.push(r21[delta])
            } else if (delta < 34) {
                rest.push(r29[delta - 5]);
            } else {
                var temp = codetemp(delta - 33);
                rest.push(r21[10 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        else {
            if (delta < 6) {
                rest.push(r21[delta + 5]);
            }
            else if (delta < 40) {
                rest.push(r34[delta - 6]);
            } else {
                var temp = codetemp(delta - 39);
                rest.push(r21[15 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        start = code;
    }
    return rest.join("");
}
var encoded = memory.ENCRYPT;
var compress = memory.COMPRESS;
var ReleaseTime = new Date();
if (encoded) encoded = (Math.random() * ReleaseTime | 0).toString(36);

ReleaseTime = String(ReleaseTime);
var buildHtml = function (html, code) {
    var isZimoliDetected = false;
    var poweredByComment;
    var html = html.toString()
        .replace(/^\s*(<!doctype[^>]*?>\s*)?<!--([\s\S]*?)--!?>/i, function (_, doctype, message) {
            // `${doctype}<!--${message}\r\n${efrontReloadVersionAttribute}-->`
            poweredByComment = _;
            return "";
        })
        .replace(/<!--[\s\S]*?--!?>/g, "")
        .replace(/<title>(.*?)<\/title>/i, `<title>${memory.TITLE || "$1"}</title>`)
        .replace(/<script\b[\s\S]*?<\/script>\s*/ig, function (script) {
            if (/(["'`])post\1\s*,\s*(['`"])comm\/main\2/i.test(script)) {
                isZimoliDetected = true;
                return "";
            }
            if (/<script\s[^>]*?(type\s*=\s*)?(["']|)efront\-?(?:hook|main|host|script|loader)\1[^>]*?>/i.test(script)) {
                isZimoliDetected = true;
            }
            if (/\b((delete|ignore)oncompile|efrontworker)\b/i.test(script)) {
                return "";
            }
            return script;
        });

    if (isZimoliDetected)
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script compiledinfo${encoded ? '-' + encoded : ''}="${ReleaseTime} by efront ${require(path.join(__dirname, "../../package.json")).version}">\r\n<!--\r\n-function(){${code}}.call(this)\r\n-->\r\n</script>\r\n${head}`);
    if (memory.IN_WATCH_MODE) {
        let WATCH_PORT = memory.WATCH_PORT;
        let reloadVersion = memory.WATCH_PROJECT_VERSION;
        let efrontReloadVersionAttribute = "efront-reload-version";
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script ${efrontReloadVersionAttribute}=${reloadVersion}>
        -function(){
            "use strict";
            var load = function(url, onload, method){
                var xhr = new XMLHttpRequest;
                xhr.open(method, url);
                xhr.timeout = 0;
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4 && xhr.status === 200) onload(xhr);
                };
                xhr.send("${reloadVersion}");
            };
            var reloader = function(){
                load(location.pathname + "?time=" + +new Date(), function(xhr){
                    var version = xhr.responseText.match(/\\b${efrontReloadVersionAttribute}\\s*=\\s*(\\d+)\\b/);
                    console.info("当前版本:${reloadVersion},目标版本:" + targetVersion + "正在重新加载,..");
                    if( !version || +version[1] !== ${reloadVersion}) location.reload() | console.warn("reload..", new Date);
                    else setTimeout(reloader, 200);
                }, "get");
            };
            var targetVersion = ${reloadVersion};
            var checkUpdate = function(xhr){
                targetVersion = xhr.responseText||xhr.response;
                reloader();
            };
            load("http://localhost${WATCH_PORT ? ":" + WATCH_PORT : ""}/reload/${reloadVersion}", checkUpdate, "post");
        }();
        </script>\r\n${head}`);
    }
    if (poweredByComment) {
        html = html.replace(/^\s*(?:<!doctype[\s\S]*?>)?/i, poweredByComment);
    }
    return html;
};
function toApplication(responseTree) {
    var mainScript = responseTree.main || responseTree["main.js"] || null;
    var indexHtml = responseTree["/index.html"] || responseTree["@index.html"];
    if (!indexHtml) {
        var htmlPath = path.join(__dirname, "../../apps", "index.html");
        indexHtml = {
            time: 0,
            needed: true,
            fullpath: htmlPath,
            data: fs.readFileSync(htmlPath),
            realpath: htmlPath,
            version: fs.statSync(htmlPath).mtime,
            destpath: path.join("index.html"),
        };
        responseTree["/index.html"] = indexHtml;
    }
    if (mainScript) {
        Object.keys(responseTree).forEach(function (key) {
            if (/\.(jsp|php|html|asp)$/i.test(key)) {
                var response = responseTree[key];
                if (response && response.data) {
                    response.data = buildHtml(response.data, mainScript.data);
                }
            }
        });
    }
    delete responseTree["main"];
    delete responseTree["main.js"];
    return responseTree;
}
var rebuildData = function (responseTree) {
    var keys = Object.keys(responseTree).sort();
    var keysmap = Object.create(null);
    var renmap = Object.create(null);
    keys.forEach(function (k) {
        var o = responseTree[k];
        if (!o.data || !o.destpath || !o.realpath) {
            return;
        }
        var k0 = k.toLowerCase().replace(/\d+$/, '');
        if (k0 in keysmap) {
            keysmap[k0]++;
            k0 = k0 + keysmap[k0];
            if (k0 !== k) renmap[k] = k0;
        } else {
            keysmap[k0] = 1;
        }
    });
    Object.keys(renmap).forEach(k => {
        var o = responseTree[k];
        if (o.type !== '') {
            delete renmap[k];
            console.warn("发现可能被覆盖的路径", o.destpath);
            return;
        }

        var k1 = renmap[k];
        delete responseTree[k];
        responseTree[k1] = o;
        k1 = k1.replace(/^[\s\S]*?([^\/\\]*?)(\.[^\/\\\.]+)?$/, '$1');
        var m = /^([\s\S]*?)[^\/\\]*?(\.[^\/\\\.]+)?$/.exec(o.destpath);
        if (m[1]) {
            o.destpath = m[1] + k1 + m[2];
        }
    });

    Object.keys(responseTree).forEach(function (k) {
        var imageIndex = 0;
        var rep = function (e) {
            if (typeof e !== "string") return String(e);

            return strings.encode(e.replace(/(["`']|)data(\.\w+)\:([\w\+\/\=,;\-\.]+)\1/gi, function (_, quote, ext, data) {
                var match = /^([\w\-\.\/]+;base64)?,([\w\+\/\-\=]+)$/i.exec(data);
                if (!match) return _;
                do {
                    imageIndex++;
                    var name = k + "-" + imageIndex + ext;
                } while (name in responseTree);
                var destpath = response.destpath.replace(/\.[\w]+$/, '') + '-' + imageIndex + ext;
                responseTree[name] = { destpath, data: Buffer.from(match[2], "base64"), realpath: true, url: name };
                return quote + destpath.replace(/\\/g, '/') + quote;
            }));
        };
        var response = responseTree[k];
        if (!isEfrontCode(response)) return;
        var data = String(response.data);

        var { argNames, args, required, dependenceNamesOffset, strs, strend } = getArgs(data);
        if (strs && strs.length > 0) {
            strs = `[${strs.map(rep)}]`;
            data = response.data = data.slice(0, dependenceNamesOffset) + (strs.length * 2).toString(36) + strs + data.slice(strend);
        }
        if (!dependenceNamesOffset) return;
        if (args) args = args.map(a => {
            if (!(a in renmap)) return a;
            return renmap[a];
        });
        var argstr = args.concat(argNames, !required ? [] : required.split(";").map(a => {
            return a.replace(/\.(\w+)$/g, '').replace(/\-(\w)/g, (_, a) => a.toUpperCase());
        }).join(";")).join(",");
        var arglen = (argstr.length << 1).toString(36);
        while (arglen.length < 3) {
            arglen = "0" + arglen;
        }
        response.data = arglen + argstr + data.slice(dependenceNamesOffset);
    });
};
var isEfrontCode = function (response) {
    if (!response) return;
    if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(response.name) || !response.data) return;
    if (response.type === "@") return;
    return true;
}
module.exports = function (responseTree) {
    rebuildData(responseTree);
    report(responseTree);
    if (!responseTree["main"] && !responseTree["main.js"]) {
        console.warn("在您所编译的项目中没有发现主程序");
        return toApplication(responseTree);
    }
    var commbuilder = require("../efront/commbuilder");
    commbuilder.compress = false;
    var mainScript = responseTree.main || responseTree["main.js"];
    var mainScriptData = commbuilder(mainScript.data, "main.js", mainScript.realpath, []);
    commbuilder.compress = +compress;
    var versionTree = {};
    if (setting.is_file_target) {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (!isEfrontCode(v)) return;
            if (v.name !== "main") {
                versionTree[v.name] = encrypt(v.data, encoded);
                delete responseTree[k];
            }
        });
    } else {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (!isEfrontCode(v)) return;
            if (v.name !== "main") {
                v.data = encrypt(v.data, encoded);
                var responseVersion = crc([].map.call(v.data.toString(), e => e.charCodeAt(0))).toString(36) + (+v.data.length).toString(36);
                versionTree[v.name] = responseVersion;
            }
        });
    }

    return Promise.resolve(mainScriptData).then(function (mainScriptData) {
        if (setting.is_file_target) {
            var xTreeName = /(?:\bresponseTree\s*|\[\s*(["'])responseTree\1\s*\])\s*[\:\=]\s*(.+?)\b/m.exec(mainScriptData)[2];
            commbuilder.prepare = false;
        } else {
            var xTreeName = /(?:\bversionTree\s*|\[\s*(["'])versionTree\1\s*\])\s*[\:\=]\s*(.+?)\b/m.exec(mainScriptData)[2];
        }

        var code = "{\r\n" + Object.keys(versionTree).map(k => `["${k}"]:"${versionTree[k]}"`).join(",\r\n\t") + "\r\n}";
        var versionVariableName;
        code = mainScriptData.toString()
            .replace(/var\s+killCircle[\s\S]*?\}\);?\s*\}\s*\};/, 'var killCircle=function(){};')
            .replace(/(?:\.send|\[\s*(["'])send\1\s*\])\s*\((.*?)\)/g, (match, quote, data) => (versionVariableName = data || "", quote ? `[${quote}send${quote}]()` : ".send()"))
            .replace(/(['"])post\1\s*,(.*?)\s*\)/ig, `$1get$1,$2${versionVariableName && `+"${memory.EXTT}?"+` + versionVariableName})`)
            .replace(
                new RegExp(/\b/.source + xTreeName + /(\s*)=(\s*)\{.*?\}/.source),
                function (m, s1, s2) {
                    return xTreeName + `${s1}=${s2}${code}`;
                }
            );
        return commbuilder(code, "main.js", mainScript.realpath, []);
    }).then(function (mainScriptData) {
        mainScript.data = mainScriptData;
        return toApplication(responseTree);
    });
};<|endoftext|>


<commit_before>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/fileLibrary.html'
], function ($, _, Backbone, FileLibraryTemplate) {
	'use strict';

	var FileLibraryView = Backbone.View.extend({

		tagName:  'div',

    el: '#fileLibraryView',

		template: _.template(FileLibraryTemplate),

		// The DOM events specific to an item.
		events: {
			//'click .toggle':	'toggleCompleted',
			//'dblclick label':	'edit',
			//'click .destroy':	'clear',
			//'keypress .edit':	'updateOnEnter',
			//'keydown .edit':	'revertOnEscape',
			//'blur .edit':		'close'
      'hidden.bs.modal #fileLibraryModal': 'refreshView'
		},

		// The TodoView listens for changes to its model, re-rendering. Since there's
		// a one-to-one correspondence between a **Todo** and a **TodoView** in this
		// app, we set a direct reference on the model for convenience.
		initialize: function () {
			//this.listenTo(this.model, 'change', this.render);
			//this.listenTo(this.model, 'destroy', this.remove);
			//this.listenTo(this.model, 'visible', this.toggleVisible);

		},

		// Re-render the titles of the todo item.

    render: function () {

      //debugger;
      this.$el.html(this.template);
      //global.pagesView.populateTable();
      this.populateTable();

      //debugger;

      //$('#dashboardView').hide();
      //$('#pagesView').show();

			//this.toggleVisible();
			//this.$input = this.$('.edit');
			return this;
		},

    populateTable: function() {
      //debugger;

      //Loop through each model in the collection.
      //global.postsCollection.forEach( function(model) {
      for( var i = 0; i < global.fileUploadCollection.length; i++ ) {

        try {
          //debugger;

          var model = global.fileUploadCollection.models[i];

          //Handle corner case of new install with empty DB
          if( (global.fileUploadCollection.models.length == 1) && (model.id == "") ) {
            return;
          }

          //Clone the example row provided in the template.
          var tempRow = global.fileLibraryView.$el.find('#fileRow').clone();

          //Clear the ID copied from the example row.
          tempRow.attr('id', '');

          //Populate the new row with data from the model.
          var fileName = model.get('fileName');
          tempRow.find('th').html(''+fileName+'');
          tempRow.find('th').find('a').attr('onclick', 'global.fileLibraryView.editPost('+i+')');

          //Add the on-click function to the Delete button.
          tempRow.find('.postCol4').find('button').attr('onclick', 'global.fileLibraryView.deleteFile(global.fileUploadCollection.models['+i+'].id)');

          //tempRow.find('.postAuthor').text(model.get('author'));
          //tempRow.find('.postCategories').text(model.get('categories').join(','));

          //var publishedDate = new Date(model.get('publishedDate'));
          //var datestr = (publishedDate.getMonth()+1)+'/'+publishedDate.getDate()+'/'+publishedDate.getFullYear();
          //tempRow.find('.postDate').text(datestr);

          //Remove the 'hidden' attribute copied from the example row.
          tempRow.show();

          //Append the new row to the DOM.
          global.fileLibraryView.$el.find('#filesTable').append(tempRow);
        } catch(err) {
          console.error('Error encountered in fileLibraryView.populateTable(). Error message:');
          console.error(err.message);

          log.push('Error encountered in fileLibraryView.populateTable(). Error message:')
          log.push(err.message)
          sendLog();
        }

      }
      //});

    },

    editPost: function(model_index) {
      debugger;

      //$('#pagesView').hide();
      //$('#pagesAddNewView').show();

      //$('#app-location').text('Pages : Edit Post');

      //Load the currently selected model into the TinyMCE state variable so that once
      //the TinyMCE editor has been loaded, it knows which model to load.
      //global.tinymce.currentModelIndex = model_index;

      //Render the Add New pages View view.
      //global.pagesAddNewView.render();

      //global.pagesAddNewView.loadPost(model_index);
    },

    uploadFile: function() {
      //debugger;
      /*
      var fileName = this.$el.find('#fileNameUpload').val();

      if( fileName == "" ) {
        this.$el.find('#successMsgUpload').text('Please enter a file name.');
        return;
      }
      */

      var selectedFile = this.$el.find('#file_upload').get(0).files[0];

      //Create the FormData data object and append the file to it.
      var newFile = new FormData();
      newFile.append('file_upload', selectedFile); //This is the raw file that was selected

      var opts = {
        url: 'http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/create',
        data: newFile,
        cache: false,
        contentType: false,
        processData: false,
        type: 'POST',
        success: function(data){
          //Dev Note: KeystoneAPI only allows file and image uploads with the file itself. Any extra metadata will have to
          //be uploaded/updated with a second call.

          //debugger;
          console.log('File upload succeeded! ID: ' + data.file_upload._id);
          log.push('File upload succeeded! ID: ' + data.file_upload._id);
          debugger;
          //Fill out the file information
          //data.file_upload.name = global.fileLibraryView.$el.find('#fileNameUpload').val();
          //data.file_upload.fileName = global.fileLibraryView.$el.find('#fileNameUpload').val();
          data.file_upload.name = data.file_upload.file.originalname;
          data.file_upload.fileName = data.file_upload.file.originalname;
          data.file_upload.url = 'http://'+global.serverIp+'/uploads/files/'+data.file_upload.file.filename;
          data.file_upload.fileType = data.file_upload.file.type;

          //Update the file with the information above.
          $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+data.file_upload._id+'/update', data.file_upload, function(data) {
            //debugger;
            log.push('File information updated.');

            //Refresh the Collection.
            //global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
            global.fileUploadCollection.fetch();

            //Notify successful upload via modal.
            global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
            global.fileLibraryView.$el.find('.modal-sm').find('#successMsg').show();
            //global.fileLibraryView.render();
          })
          //If the metadata update fails:
          .fail(function(data) {
            debugger;
          });
        },

        //This error function is called if the POST fails for submitting the file itself.
        error: function(err) {
          //debugger;

          global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').show();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').html(
            '
The file was not uploaded to the server. This is most likely because the server does not accept the selected file TYPE.

'+
            'Here is the error message from the server:
'+
            'Server status: '+err.status+'
'+
            'Server message: '+err.statusText+'

'
          );

        }
      };

      //Execute the AJAX operation.
      jQuery.ajax(opts);
    },

    fileSelected: function() {
      //debugger;

      //this.$el.find('#fileNameUploadDiv').show();
    },

    //This function is called when the modal has completed closing. It refreshes the View to make sure
    //any new uploaded files appear in the file table.
    refreshView: function() {
      //debugger;

      //Fixing bug where modal backdrop stays in place.
      $('.modal-backdrop').hide();

      this.render();
    },

    deleteFile: function(id) {
      //debugger;
      $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+id+'/remove', '', function(data) {
        //debugger;

        if( data.success == true ) {
          log.push('FileUpload object deleted successfully. ID: '+id);
          global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
          global.fileUploadCollection.fetch();
          //global.fileLibraryView.render();
        } else {
          console.error('FileUpload object no deleted! ID: '+id);
          log.push('FileUpload object no deleted! ID: '+id);
          sendLog();
        }
      })
    }

	});

  //debugger;
	return FileLibraryView;
});
<commit_msg>adding file extension to file name during upload.<commit_after>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/fileLibrary.html'
], function ($, _, Backbone, FileLibraryTemplate) {
	'use strict';

	var FileLibraryView = Backbone.View.extend({

		tagName:  'div',

    el: '#fileLibraryView',

		template: _.template(FileLibraryTemplate),

		// The DOM events specific to an item.
		events: {
			//'click .toggle':	'toggleCompleted',
			//'dblclick label':	'edit',
			//'click .destroy':	'clear',
			//'keypress .edit':	'updateOnEnter',
			//'keydown .edit':	'revertOnEscape',
			//'blur .edit':		'close'
      'hidden.bs.modal #fileLibraryModal': 'refreshView'
		},

		// The TodoView listens for changes to its model, re-rendering. Since there's
		// a one-to-one correspondence between a **Todo** and a **TodoView** in this
		// app, we set a direct reference on the model for convenience.
		initialize: function () {
			//this.listenTo(this.model, 'change', this.render);
			//this.listenTo(this.model, 'destroy', this.remove);
			//this.listenTo(this.model, 'visible', this.toggleVisible);

		},

		// Re-render the titles of the todo item.

    render: function () {

      //debugger;
      this.$el.html(this.template);
      //global.pagesView.populateTable();
      this.populateTable();

      //debugger;

      //$('#dashboardView').hide();
      //$('#pagesView').show();

			//this.toggleVisible();
			//this.$input = this.$('.edit');
			return this;
		},

    populateTable: function() {
      //debugger;

      //Loop through each model in the collection.
      //global.postsCollection.forEach( function(model) {
      for( var i = 0; i < global.fileUploadCollection.length; i++ ) {

        try {
          //debugger;

          var model = global.fileUploadCollection.models[i];

          //Handle corner case of new install with empty DB
          if( (global.fileUploadCollection.models.length == 1) && (model.id == "") ) {
            return;
          }

          //Clone the example row provided in the template.
          var tempRow = global.fileLibraryView.$el.find('#fileRow').clone();

          //Clear the ID copied from the example row.
          tempRow.attr('id', '');

          //Populate the new row with data from the model.
          var fileName = model.get('fileName');
          tempRow.find('th').html(''+fileName+'');
          tempRow.find('th').find('a').attr('onclick', 'global.fileLibraryView.editPost('+i+')');

          //Add the on-click function to the Delete button.
          tempRow.find('.postCol4').find('button').attr('onclick', 'global.fileLibraryView.deleteFile(global.fileUploadCollection.models['+i+'].id)');

          //tempRow.find('.postAuthor').text(model.get('author'));
          //tempRow.find('.postCategories').text(model.get('categories').join(','));

          //var publishedDate = new Date(model.get('publishedDate'));
          //var datestr = (publishedDate.getMonth()+1)+'/'+publishedDate.getDate()+'/'+publishedDate.getFullYear();
          //tempRow.find('.postDate').text(datestr);

          //Remove the 'hidden' attribute copied from the example row.
          tempRow.show();

          //Append the new row to the DOM.
          global.fileLibraryView.$el.find('#filesTable').append(tempRow);
        } catch(err) {
          console.error('Error encountered in fileLibraryView.populateTable(). Error message:');
          console.error(err.message);

          log.push('Error encountered in fileLibraryView.populateTable(). Error message:')
          log.push(err.message)
          sendLog();
        }

      }
      //});

    },

    editPost: function(model_index) {
      debugger;

      //$('#pagesView').hide();
      //$('#pagesAddNewView').show();

      //$('#app-location').text('Pages : Edit Post');

      //Load the currently selected model into the TinyMCE state variable so that once
      //the TinyMCE editor has been loaded, it knows which model to load.
      //global.tinymce.currentModelIndex = model_index;

      //Render the Add New pages View view.
      //global.pagesAddNewView.render();

      //global.pagesAddNewView.loadPost(model_index);
    },

    uploadFile: function() {
      //debugger;

      var selectedFile = this.$el.find('#file_upload').get(0).files[0];

      //Create the FormData data object and append the file to it.
      var newFile = new FormData();
      newFile.append('file_upload', selectedFile); //This is the raw file that was selected

      var opts = {
        url: 'http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/create',
        data: newFile,
        cache: false,
        contentType: false,
        processData: false,
        type: 'POST',
        success: function(data){
          //Dev Note: KeystoneAPI only allows file and image uploads with the file itself. Any extra metadata will have to
          //be uploaded/updated with a second call.

          //debugger;
          console.log('File upload succeeded! ID: ' + data.file_upload._id);
          log.push('File upload succeeded! ID: ' + data.file_upload._id);

          //Fill out the file information
          data.file_upload.name = data.file_upload.file.originalname;
          data.file_upload.fileName = data.file_upload.file.originalname;
          data.file_upload.url = 'http://'+global.serverIp+'/uploads/files/'+data.file_upload.file.filename;
          data.file_upload.fileType = data.file_upload.file.type;

          //Update the file with the information above.
          $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+data.file_upload._id+'/update', data.file_upload, function(data) {
            //debugger;
            log.push('File information updated.');

            //Refresh the Collection.
            //global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
            global.fileUploadCollection.fetch();

            //Notify successful upload via modal.
            global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
            global.fileLibraryView.$el.find('.modal-sm').find('#successMsg').show();
            //global.fileLibraryView.render();
          })
          //If the metadata update fails:
          .fail(function(data) {
            debugger;
          });
        },

        //This error function is called if the POST fails for submitting the file itself.
        error: function(err) {
          //debugger;

          global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').show();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').html(
            '
The file was not uploaded to the server. This is most likely because the server does not accept the selected file TYPE.

'+
            'Here is the error message from the server:
'+
            'Server status: '+err.status+'
'+
            'Server message: '+err.statusText+'

'
          );

        }
      };

      //Execute the AJAX operation.
      jQuery.ajax(opts);
    },

    fileSelected: function() {
      //debugger;

    },

    //This function is called when the modal has completed closing. It refreshes the View to make sure
    //any new uploaded files appear in the file table.
    refreshView: function() {
      //debugger;

      //Fixing bug where modal backdrop stays in place.
      $('.modal-backdrop').hide();

      this.render();
    },

    deleteFile: function(id) {
      //debugger;
      $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+id+'/remove', '', function(data) {
        //debugger;

        if( data.success == true ) {
          log.push('FileUpload object deleted successfully. ID: '+id);
          global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
          global.fileUploadCollection.fetch();
          //global.fileLibraryView.render();
        } else {
          console.error('FileUpload object no deleted! ID: '+id);
          log.push('FileUpload object no deleted! ID: '+id);
          sendLog();
        }
      })
    }

	});

  //debugger;
	return FileLibraryView;
});
<|endoftext|>


<commit_before>/* eslint react/forbid-prop-types: "off" */
import React from 'react';
import PropTypes from 'prop-types';
import Debug from 'debug';

import DEFAULT_COLORS from '../constants/DEFAULT_CHART_COLORS';
import googleChartLoader from './GoogleChartLoader';

const debug = new Debug('react-google-charts:Chart');

let uniqueID = 0;

const generateUniqueID = () => {
  uniqueID += 1;
  return `reactgooglegraph-${uniqueID}`;
};

export default class Chart extends React.Component {

  constructor(props) {
    debug('constructor', props);
    super(props);
    this.state = { graphID: props.graph_id || generateUniqueID() };
    this.chart = null;
    this.wrapper = null;
    this.hidden_columns = {};
    this.dataTable = [];

    this.debounce = this.debounce.bind(this);
    this.onResize = this.onResize.bind(this);
    this.drawChart = this.drawChart.bind(this);
    this.togglePoints = this.togglePoints.bind(this);
    this.buildDataTableFromProps = this.buildDataTableFromProps.bind(this);
    this.listenToChartEvents = this.listenToChartEvents.bind(this);
    this.addChartActions = this.addChartActions.bind(this);
    this.updateDataTable = this.updateDataTable.bind(this);
    this.onSelectToggle = this.onSelectToggle.bind(this);
    this.addSourceColumnTo = this.addSourceColumnTo.bind(this);
    this.restoreColorTo = this.restoreColorTo.bind(this);
    this.hideColumn = this.hideColumn.bind(this);
  }
  componentDidMount() {
    debug('componentDidMount');
    if (typeof window === 'undefined') {
      return;
    }
    if (this.props.loadCharts) {
      googleChartLoader.init(this.props.chartPackages, this.props.chartVersion).then(() => {
        this.drawChart();
      });
      this.onResize = this.debounce(this.onResize, 200);
      window.addEventListener('resize', this.onResize);
    } else {
      this.drawChart();
    }
  }

  componentDidUpdate() {
    debug('componentDidUpdate');
    if (!this.props.loadCharts) {
      this.drawChart();
    } else if (googleChartLoader.isLoading) {
      googleChartLoader.initPromise.then(() => {
        this.drawChart();
      });
    } else if (googleChartLoader.isLoaded) {
      this.drawChart();
    }
  }
  componentWillUnmount() {
    try {
      if (window) {
        if (window.google && window.google.visualization) {
          window.google.visualization.events.removeAllListeners(this.wrapper);
        }
        window.removeEventListener('resize', this.onResize);
      }
    } catch (err) {
      return;
    }
  }

  onResize() {
    debug('Chart::onResize');
    this.drawChart();
  }

  onSelectToggle() {
    debug('onSelectToggle');
    const selection = this.chart.getSelection();
    if (selection.length > 0) {
      if (selection[0].row == null) {
        const column = selection[0].column;
        this.togglePoints(column);
      }
    }
  }

  getColumnColor(columnIndex) {
    if (this.props.options.colors) {
      if (this.props.options.colors[columnIndex]) {
        return this.props.options.colors[columnIndex];
      }
    } else if (columnIndex in DEFAULT_COLORS) {
      return DEFAULT_COLORS[columnIndex];
    }
    return DEFAULT_COLORS[0];
  }

  buildDataTableFromProps() {
    debug('buildDataTableFromProps', this.props);

    if (this.props.diffdata) {
      const diffdata = this.props.diffdata;
      const oldData = window.google.visualization.arrayToDataTable(diffdata.old);
      const newData = window.google.visualization.arrayToDataTable(diffdata.new);
        // must take computeDiff from prototypes since not available with charts early in process
      const computeDiff = window.google.visualization[this.props.chartType].prototype.computeDiff;
      const chartDiff = computeDiff(oldData, newData);
      return chartDiff;
    }

    if (this.props.data === null && this.props.rows.length === 0 && !this.props.allowEmptyRows) {
      throw new Error("Can't build DataTable from rows and columns: rows array in props is empty");
    } else if (this.props.data === null && this.props.columns.length === 0) {
      throw new Error("Can't build DataTable from rows and columns: columns array in props is empty");
    }
    if (this.props.data !== null) {
      try {
        this.wrapper.setDataTable(this.props.data);
        const dataTable = this.wrapper.getDataTable();
        return dataTable;
      } catch (err) {
        // console.error('Failed to set DataTable from data props ! ', err);
        throw new Error('Failed to set DataTable from data props ! ', err);
      }
    }

    const dataTable = new window.google.visualization.DataTable();
    this.props.columns.forEach((column) => {
      dataTable.addColumn(column);
    });
    dataTable.addRows(this.props.rows);
    if (this.props.numberFormat) {
      const formatter = new window.google.visualization.NumberFormat(
        this.props.numberFormat.options
      );
      formatter.format(dataTable, this.props.numberFormat.column);
    }

    if (this.props.dateFormat) {
      const dateFormat = new window.google.visualization.DateFormat(
        this.props.dateFormat.options
      );
      this.props.dateFormat.columns.forEach((columnIdx) => {
        dateFormat.format(dataTable, columnIdx);
      });
    }

    return dataTable;
  }
  updateDataTable() {
    debug('updateDataTable');
    window.google.visualization.errors.removeAll(
      document.getElementById(this.wrapper.getContainerId())
    );
    this.dataTable.removeRows(0, this.dataTable.getNumberOfRows());
    this.dataTable.removeColumns(0, this.dataTable.getNumberOfColumns());
    this.dataTable = this.buildDataTableFromProps();
    return this.dataTable;
  }

  drawChart() {
    debug('drawChart', this);
    if (!this.wrapper) {
      const chartConfig = {
        chartType: this.props.chartType,
        options: this.props.options,
        containerId: this.state.graphID,
      };
      this.wrapper = new window.google.visualization.ChartWrapper(chartConfig);
      this.dataTable = this.buildDataTableFromProps();
      this.wrapper.setDataTable(this.dataTable);

      window.google.visualization.events.addOneTimeListener(this.wrapper, 'ready', () => {
        this.chart = this.wrapper.getChart();
        this.listenToChartEvents();
        this.addChartActions();
      });
    } else {
      this.updateDataTable();
      this.wrapper.setDataTable(this.dataTable);
       // this.wrapper.setChartType(this.props.chartType)
      this.wrapper.setOptions(this.props.options);
      if (this.wrapper.getChartType() !== this.props.chartType) {
        window.google.visualization.events.removeAllListeners(this.wrapper);
        this.wrapper.setChartType(this.props.chartType);
        const self = this;
        window.google.visualization.events.addOneTimeListener(this.wrapper, 'ready', () => {
          self.chart = self.wrapper.getChart();
          self.listenToChartEvents.call(self);
        });
      }
    }
    this.wrapper.draw();
  }

  addChartActions() {
    debug('addChartActions', this.props.chartActions);
    if (this.props.chartActions === null) {
      return;
    }
    this.props.chartActions.forEach((chartAction) => {
      this.chart.setAction({
        id: chartAction.id,
        text: chartAction.text,
        action: chartAction.action.bind(this, this.chart),
      });
    });
  }

  listenToChartEvents() {
    debug('listenToChartEvents', this.props.legend_toggle, this.props.chartEvents);
    if (this.props.legend_toggle) {
      window.google.visualization.events.addListener(
        this.wrapper,
        'select',
        this.onSelectToggle
      );
    }
    this.props.chartEvents.forEach((chartEvent) => {
      if (chartEvent.eventName === 'ready') {
        chartEvent.callback(this);
      } else {
        ((event) => {
          window.google.visualization.events.addListener(this.chart, event.eventName, (e) => {
            event.callback(this, e);
          });
        })(chartEvent);
      }
    });
  }

  buildColumnFromSourceData(columnIndex) {
    debug('buildColumnFromSourceData', columnIndex);
    return {
      label: this.dataTable.getColumnLabel(columnIndex),
      type: this.dataTable.getColumnType(columnIndex),
      sourceColumn: columnIndex,
      role: this.dataTable.getColumnRole(columnIndex) // addedBy minam.cho(devbada) cause of 'All series on a given axis must be of the same data type': July 10, 2017
    };
  }

  buildEmptyColumnFromSourceData(columnIndex) {
    debug('buildEmptyColumnFromSourceData', columnIndex);
    return {
      label: this.dataTable.getColumnLabel(columnIndex),
      type: this.dataTable.getColumnType(columnIndex),
      calc: () => null,
      role: this.dataTable.getColumnRole(columnIndex) // addedBy minam.cho(devbada) cause of 'All series on a given axis must be of the same data type': July 10, 2017
    };
  }
  addEmptyColumnTo(columns, columnIndex) {
    debug('addEmptyColumnTo', columns, columnIndex);
    const emptyColumn = this.buildEmptyColumnFromSourceData(columnIndex);
    columns.push(emptyColumn);
  }

  hideColumn(colors, columnIndex) {
    debug('hideColumn', colors, columnIndex);
    if (!this.isHidden(columnIndex)) {
      this.hidden_columns[columnIndex] = { color: this.getColumnColor(columnIndex - 1) };
    }
    colors.push('#CCCCCC');
  }
  addSourceColumnTo(columns, columnIndex) {
    debug('addSourceColumnTo', columns, columnIndex);
    const sourceColumn = this.buildColumnFromSourceData(columnIndex);
    columns.push(sourceColumn);
  }

  isHidden(columnIndex) {
    return this.hidden_columns[columnIndex] !== undefined;
  }
  restoreColorTo(colors, columnIndex) {
    debug('restoreColorTo', colors, columnIndex);
    debug('hidden_columns', this.hidden_columns);
    let previousColor;
    if (this.isHidden(columnIndex)) {
      previousColor = this.hidden_columns[columnIndex].color;
      delete this.hidden_columns[columnIndex];
    } else {
      previousColor = this.getColumnColor(columnIndex - 1);
    }
    if (columnIndex !== 0) {
      colors.push(previousColor);
    }
  }
  // eslint-disable-next-line class-methods-use-this
  debounce(func, wait) {
    let timeout;
    return function (...args) {
      const context = this;
      clearTimeout(timeout);
      timeout = setTimeout(() => func.apply(context, args), wait);
    };
  }
  togglePoints(column) {
    debug('togglePoints', column);
    const view = new window.google.visualization.DataView(this.wrapper.getDataTable());
    const columnCount = view.getNumberOfColumns();
    let colors = []; // eslint-disable-line prefer-const
    let columns = []; // eslint-disable-line prefer-const
    for (let i = 0; i < columnCount; i += 1) {
      // If user clicked on legend
      if (i === 0) {
        this.addSourceColumnTo(columns, i);
      } else if (i === column) {
        if (this.isHidden(i)) {
          this.addSourceColumnTo(columns, i);
          this.restoreColorTo(colors, i);
        } else {
          this.addEmptyColumnTo(columns, i);
          this.hideColumn(colors, i);
        }
      } else if (this.isHidden(i)) {
        this.addEmptyColumnTo(columns, i);
        this.hideColumn(colors, i);
      } else {
        this.addSourceColumnTo(columns, i);
        this.restoreColorTo(colors, i);
      }
    }
    view.setColumns(columns);
    this.props.options.colors = colors;
    this.chart.draw(view, this.props.options);
  }

  render() {
    debug('render', this.props, this.state);
    const divStyle = {
      height: this.props.height || this.props.options.height,
      width: this.props.width || this.props.options.width,
    };
    return (

        {this.props.loader ? this.props.loader : 'Rendering Chart...'}

    );
  }
}

Chart.propTypes = {
  graph_id: PropTypes.string,
  chartType: PropTypes.string,
  rows: PropTypes.arrayOf(PropTypes.array),
  columns: PropTypes.arrayOf(PropTypes.object),
  data: PropTypes.arrayOf(PropTypes.array),
  options: PropTypes.any,
  width: PropTypes.string,
  height: PropTypes.string,
  chartEvents: PropTypes.arrayOf(PropTypes.shape({
    // https://github.com/yannickcr/eslint-plugin-react/issues/819
    eventName: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    callback: PropTypes.func, // eslint-disable-line react/no-unused-prop-types
  })),
  chartActions: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    text: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    action: PropTypes.func, // eslint-disable-line react/no-unused-prop-types
  })),
  loadCharts: PropTypes.bool,
  loader: PropTypes.node,
  legend_toggle: PropTypes.bool,
  allowEmptyRows: PropTypes.bool,
  chartPackages: PropTypes.arrayOf(PropTypes.string),
  chartVersion: PropTypes.string,
  numberFormat: PropTypes.shape({
    column: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
    options: PropTypes.shape({
      decimalSymbol: PropTypes.string,  // eslint-disable-line react/no-unused-prop-types
      fractionDigits: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
      groupingSymbol: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      negativeColor: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      negativeParens: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types
      pattern: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      prefix: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      suffix: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    }),
  }),
  dateFormat: PropTypes.shape({
    // eslint-disable-next-line react/no-unused-prop-types
    columns: PropTypes.arrayOf(PropTypes.number),
    options: PropTypes.shape({
      formatType: PropTypes.string,  // eslint-disable-line react/no-unused-prop-types
      pattern: PropTypes.string,  // eslint-disable-line react/no-unused-prop-types
      timeZone: PropTypes.number,  // eslint-disable-line react/no-unused-prop-types
    }),
  }),
  diffdata: PropTypes.shape({
    on: PropTypes.array, // eslint-disable-line react/no-unused-prop-types
    off: PropTypes.array, // eslint-disable-line react/no-unused-prop-types
  }),
};

Chart.defaultProps = {
  chartType: 'LineChart',
  rows: [],
  columns: [],
  options: {
    chart: {
      title: 'Chart Title',
      subtitle: 'Subtitle',
    },
    hAxis: { title: 'X Label' },
    vAxis: { title: 'Y Label' },
    width: '400px',
    height: '300px',
  },
  width: '400px',
  height: '300px',
  chartEvents: [],
  chartActions: null,
  data: null,
  legend_toggle: false,
  allowEmptyRows: false,
  loadCharts: true,
  loader:
Rendering Chart
,
  chartPackages: ['corechart'],
  chartVersion: 'current',
  numberFormat: null,
  dateFormat: null,
  diffdata: null,
};
<commit_msg>fixed eslint errors (#163)<commit_after>/* eslint react/forbid-prop-types: "off" */
import React from 'react';
import PropTypes from 'prop-types';
import Debug from 'debug';

import DEFAULT_COLORS from '../constants/DEFAULT_CHART_COLORS';
import googleChartLoader from './GoogleChartLoader';

const debug = new Debug('react-google-charts:Chart');

let uniqueID = 0;

const generateUniqueID = () => {
  uniqueID += 1;
  return `reactgooglegraph-${uniqueID}`;
};

export default class Chart extends React.Component {

  constructor(props) {
    debug('constructor', props);
    super(props);
    this.state = { graphID: props.graph_id || generateUniqueID() };
    this.chart = null;
    this.wrapper = null;
    this.hidden_columns = {};
    this.dataTable = [];

    this.debounce = this.debounce.bind(this);
    this.onResize = this.onResize.bind(this);
    this.drawChart = this.drawChart.bind(this);
    this.togglePoints = this.togglePoints.bind(this);
    this.buildDataTableFromProps = this.buildDataTableFromProps.bind(this);
    this.listenToChartEvents = this.listenToChartEvents.bind(this);
    this.addChartActions = this.addChartActions.bind(this);
    this.updateDataTable = this.updateDataTable.bind(this);
    this.onSelectToggle = this.onSelectToggle.bind(this);
    this.addSourceColumnTo = this.addSourceColumnTo.bind(this);
    this.restoreColorTo = this.restoreColorTo.bind(this);
    this.hideColumn = this.hideColumn.bind(this);
  }
  componentDidMount() {
    debug('componentDidMount');
    if (typeof window === 'undefined') {
      return;
    }
    if (this.props.loadCharts) {
      googleChartLoader.init(this.props.chartPackages, this.props.chartVersion).then(() => {
        this.drawChart();
      });
      this.onResize = this.debounce(this.onResize, 200);
      window.addEventListener('resize', this.onResize);
    } else {
      this.drawChart();
    }
  }

  componentDidUpdate() {
    debug('componentDidUpdate');
    if (!this.props.loadCharts) {
      this.drawChart();
    } else if (googleChartLoader.isLoading) {
      googleChartLoader.initPromise.then(() => {
        this.drawChart();
      });
    } else if (googleChartLoader.isLoaded) {
      this.drawChart();
    }
  }
  componentWillUnmount() {
    try {
      if (window) {
        if (window.google && window.google.visualization) {
          window.google.visualization.events.removeAllListeners(this.wrapper);
        }
        window.removeEventListener('resize', this.onResize);
      }
    } catch (err) {
      return;
    }
  }

  onResize() {
    debug('Chart::onResize');
    this.drawChart();
  }

  onSelectToggle() {
    debug('onSelectToggle');
    const selection = this.chart.getSelection();
    if (selection.length > 0) {
      if (selection[0].row == null) {
        const column = selection[0].column;
        this.togglePoints(column);
      }
    }
  }

  getColumnColor(columnIndex) {
    if (this.props.options.colors) {
      if (this.props.options.colors[columnIndex]) {
        return this.props.options.colors[columnIndex];
      }
    } else if (columnIndex in DEFAULT_COLORS) {
      return DEFAULT_COLORS[columnIndex];
    }
    return DEFAULT_COLORS[0];
  }

  buildDataTableFromProps() {
    debug('buildDataTableFromProps', this.props);

    if (this.props.diffdata) {
      const diffdata = this.props.diffdata;
      const oldData = window.google.visualization.arrayToDataTable(diffdata.old);
      const newData = window.google.visualization.arrayToDataTable(diffdata.new);
        // must take computeDiff from prototypes since not available with charts early in process
      const computeDiff = window.google.visualization[this.props.chartType].prototype.computeDiff;
      const chartDiff = computeDiff(oldData, newData);
      return chartDiff;
    }

    if (this.props.data === null && this.props.rows.length === 0 && !this.props.allowEmptyRows) {
      throw new Error("Can't build DataTable from rows and columns: rows array in props is empty");
    } else if (this.props.data === null && this.props.columns.length === 0) {
      throw new Error("Can't build DataTable from rows and columns: columns array in props is empty");
    }
    if (this.props.data !== null) {
      try {
        this.wrapper.setDataTable(this.props.data);
        const dataTable = this.wrapper.getDataTable();
        return dataTable;
      } catch (err) {
        // console.error('Failed to set DataTable from data props ! ', err);
        throw new Error('Failed to set DataTable from data props ! ', err);
      }
    }

    const dataTable = new window.google.visualization.DataTable();
    this.props.columns.forEach((column) => {
      dataTable.addColumn(column);
    });
    dataTable.addRows(this.props.rows);
    if (this.props.numberFormat) {
      const formatter = new window.google.visualization.NumberFormat(
        this.props.numberFormat.options
      );
      formatter.format(dataTable, this.props.numberFormat.column);
    }

    if (this.props.dateFormat) {
      const dateFormat = new window.google.visualization.DateFormat(
        this.props.dateFormat.options
      );
      this.props.dateFormat.columns.forEach((columnIdx) => {
        dateFormat.format(dataTable, columnIdx);
      });
    }

    return dataTable;
  }
  updateDataTable() {
    debug('updateDataTable');
    window.google.visualization.errors.removeAll(
      document.getElementById(this.wrapper.getContainerId())
    );
    this.dataTable.removeRows(0, this.dataTable.getNumberOfRows());
    this.dataTable.removeColumns(0, this.dataTable.getNumberOfColumns());
    this.dataTable = this.buildDataTableFromProps();
    return this.dataTable;
  }

  drawChart() {
    debug('drawChart', this);
    if (!this.wrapper) {
      const chartConfig = {
        chartType: this.props.chartType,
        options: this.props.options,
        containerId: this.state.graphID,
      };
      this.wrapper = new window.google.visualization.ChartWrapper(chartConfig);
      this.dataTable = this.buildDataTableFromProps();
      this.wrapper.setDataTable(this.dataTable);

      window.google.visualization.events.addOneTimeListener(this.wrapper, 'ready', () => {
        this.chart = this.wrapper.getChart();
        this.listenToChartEvents();
        this.addChartActions();
      });
    } else {
      this.updateDataTable();
      this.wrapper.setDataTable(this.dataTable);
       // this.wrapper.setChartType(this.props.chartType)
      this.wrapper.setOptions(this.props.options);
      if (this.wrapper.getChartType() !== this.props.chartType) {
        window.google.visualization.events.removeAllListeners(this.wrapper);
        this.wrapper.setChartType(this.props.chartType);
        const self = this;
        window.google.visualization.events.addOneTimeListener(this.wrapper, 'ready', () => {
          self.chart = self.wrapper.getChart();
          self.listenToChartEvents.call(self);
        });
      }
    }
    this.wrapper.draw();
  }

  addChartActions() {
    debug('addChartActions', this.props.chartActions);
    if (this.props.chartActions === null) {
      return;
    }
    this.props.chartActions.forEach((chartAction) => {
      this.chart.setAction({
        id: chartAction.id,
        text: chartAction.text,
        action: chartAction.action.bind(this, this.chart),
      });
    });
  }

  listenToChartEvents() {
    debug('listenToChartEvents', this.props.legend_toggle, this.props.chartEvents);
    if (this.props.legend_toggle) {
      window.google.visualization.events.addListener(
        this.wrapper,
        'select',
        this.onSelectToggle
      );
    }
    this.props.chartEvents.forEach((chartEvent) => {
      if (chartEvent.eventName === 'ready') {
        chartEvent.callback(this);
      } else {
        ((event) => {
          window.google.visualization.events.addListener(this.chart, event.eventName, (e) => {
            event.callback(this, e);
          });
        })(chartEvent);
      }
    });
  }

  buildColumnFromSourceData(columnIndex) {
    debug('buildColumnFromSourceData', columnIndex);
    return {
      label: this.dataTable.getColumnLabel(columnIndex),
      type: this.dataTable.getColumnType(columnIndex),
      sourceColumn: columnIndex,
      role: this.dataTable.getColumnRole(columnIndex),
        // above addedBy minam.cho(devbada)
        // cause of 'All series on a given axis must be of the same data type'
        // July 10, 2017
    };
  }

  buildEmptyColumnFromSourceData(columnIndex) {
    debug('buildEmptyColumnFromSourceData', columnIndex);
    return {
      label: this.dataTable.getColumnLabel(columnIndex),
      type: this.dataTable.getColumnType(columnIndex),
      calc: () => null,
      role: this.dataTable.getColumnRole(columnIndex),
        // above addedBy minam.cho(devbada)
        // cause of 'All series on a given axis must be of the same data type'
        // July 10, 2017
    };
  }
  addEmptyColumnTo(columns, columnIndex) {
    debug('addEmptyColumnTo', columns, columnIndex);
    const emptyColumn = this.buildEmptyColumnFromSourceData(columnIndex);
    columns.push(emptyColumn);
  }

  hideColumn(colors, columnIndex) {
    debug('hideColumn', colors, columnIndex);
    if (!this.isHidden(columnIndex)) {
      this.hidden_columns[columnIndex] = { color: this.getColumnColor(columnIndex - 1) };
    }
    colors.push('#CCCCCC');
  }
  addSourceColumnTo(columns, columnIndex) {
    debug('addSourceColumnTo', columns, columnIndex);
    const sourceColumn = this.buildColumnFromSourceData(columnIndex);
    columns.push(sourceColumn);
  }

  isHidden(columnIndex) {
    return this.hidden_columns[columnIndex] !== undefined;
  }
  restoreColorTo(colors, columnIndex) {
    debug('restoreColorTo', colors, columnIndex);
    debug('hidden_columns', this.hidden_columns);
    let previousColor;
    if (this.isHidden(columnIndex)) {
      previousColor = this.hidden_columns[columnIndex].color;
      delete this.hidden_columns[columnIndex];
    } else {
      previousColor = this.getColumnColor(columnIndex - 1);
    }
    if (columnIndex !== 0) {
      colors.push(previousColor);
    }
  }
  // eslint-disable-next-line class-methods-use-this
  debounce(func, wait) {
    let timeout;
    return function (...args) {
      const context = this;
      clearTimeout(timeout);
      timeout = setTimeout(() => func.apply(context, args), wait);
    };
  }
  togglePoints(column) {
    debug('togglePoints', column);
    const view = new window.google.visualization.DataView(this.wrapper.getDataTable());
    const columnCount = view.getNumberOfColumns();
    let colors = []; // eslint-disable-line prefer-const
    let columns = []; // eslint-disable-line prefer-const
    for (let i = 0; i < columnCount; i += 1) {
      // If user clicked on legend
      if (i === 0) {
        this.addSourceColumnTo(columns, i);
      } else if (i === column) {
        if (this.isHidden(i)) {
          this.addSourceColumnTo(columns, i);
          this.restoreColorTo(colors, i);
        } else {
          this.addEmptyColumnTo(columns, i);
          this.hideColumn(colors, i);
        }
      } else if (this.isHidden(i)) {
        this.addEmptyColumnTo(columns, i);
        this.hideColumn(colors, i);
      } else {
        this.addSourceColumnTo(columns, i);
        this.restoreColorTo(colors, i);
      }
    }
    view.setColumns(columns);
    this.props.options.colors = colors;
    this.chart.draw(view, this.props.options);
  }

  render() {
    debug('render', this.props, this.state);
    const divStyle = {
      height: this.props.height || this.props.options.height,
      width: this.props.width || this.props.options.width,
    };
    return (

        {this.props.loader ? this.props.loader : 'Rendering Chart...'}

    );
  }
}

Chart.propTypes = {
  graph_id: PropTypes.string,
  chartType: PropTypes.string,
  rows: PropTypes.arrayOf(PropTypes.array),
  columns: PropTypes.arrayOf(PropTypes.object),
  data: PropTypes.arrayOf(PropTypes.array),
  options: PropTypes.any,
  width: PropTypes.string,
  height: PropTypes.string,
  chartEvents: PropTypes.arrayOf(PropTypes.shape({
    // https://github.com/yannickcr/eslint-plugin-react/issues/819
    eventName: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    callback: PropTypes.func, // eslint-disable-line react/no-unused-prop-types
  })),
  chartActions: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    text: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    action: PropTypes.func, // eslint-disable-line react/no-unused-prop-types
  })),
  loadCharts: PropTypes.bool,
  loader: PropTypes.node,
  legend_toggle: PropTypes.bool,
  allowEmptyRows: PropTypes.bool,
  chartPackages: PropTypes.arrayOf(PropTypes.string),
  chartVersion: PropTypes.string,
  numberFormat: PropTypes.shape({
    column: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
    options: PropTypes.shape({
      decimalSymbol: PropTypes.string,  // eslint-disable-line react/no-unused-prop-types
      fractionDigits: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
      groupingSymbol: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      negativeColor: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      negativeParens: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types
      pattern: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      prefix: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
      suffix: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
    }),
  }),
  dateFormat: PropTypes.shape({
    // eslint-disable-next-line react/no-unused-prop-types
    columns: PropTypes.arrayOf(PropTypes.number),
    options: PropTypes.shape({
      formatType: PropTypes.string,  // eslint-disable-line react/no-unused-prop-types
      pattern: PropTypes.string,  // eslint-disable-line react/no-unused-prop-types
      timeZone: PropTypes.number,  // eslint-disable-line react/no-unused-prop-types
    }),
  }),
  diffdata: PropTypes.shape({
    on: PropTypes.array, // eslint-disable-line react/no-unused-prop-types
    off: PropTypes.array, // eslint-disable-line react/no-unused-prop-types
  }),
};

Chart.defaultProps = {
  chartType: 'LineChart',
  rows: [],
  columns: [],
  options: {
    chart: {
      title: 'Chart Title',
      subtitle: 'Subtitle',
    },
    hAxis: { title: 'X Label' },
    vAxis: { title: 'Y Label' },
    width: '400px',
    height: '300px',
  },
  width: '400px',
  height: '300px',
  chartEvents: [],
  chartActions: null,
  data: null,
  legend_toggle: false,
  allowEmptyRows: false,
  loadCharts: true,
  loader:
Rendering Chart
,
  chartPackages: ['corechart'],
  chartVersion: 'current',
  numberFormat: null,
  dateFormat: null,
  diffdata: null,
};
<|endoftext|>


<commit_before>var globalModule = angular.module('globalModule', []);

globalModule.controller('globalController', ['$scope', '$location', function($scope, $location) {

	$scope.ipc = require('ipc');

	$scope.showMessageModal = function(message) {
		if (!message) return;
		$scope.message = message;
		$('#message-modal').modal('show');
	};

    $scope.connections = [];
    if (localStorage.getItem('connections')) {
    	$scope.connections = JSON.parse(localStorage.getItem('connections'));
    }

    $scope.setConnection = function(connection) {
        $scope.connections.push(connection);
        localStorage.setItem('connections', JSON.stringify($scope.connections));
    };

    $scope.removeConnection = function(id) {
        var _index;
        $scope.connections.forEach(function(item, index) {
            if (item.id === id) {
                _index = index;
            }
        });
        if (typeof _index !== 'undefined') {
            $scope.connections.splice(_index, 1);
        }

        localStorage.setItem('connections', JSON.stringify($scope.connections));
    };

    $scope.connectionExist = function(connection) {

    	for (var i = 0; i < $scope.connections.length; i++) {
    		var curr = $scope.connections[i];
    		if (curr.id === connection.id) {
    			return true;
    		}
    		if (curr.host === connection.host
    			&& curr.port === connection.port
    			&& curr.user === connection.user) {
    			return true;
    		}
    	}

    	return false;
    };

}]);
<commit_msg>added reset connections function<commit_after>var globalModule = angular.module('globalModule', []);

globalModule.controller('globalController', ['$scope', '$location', function($scope, $location) {

	$scope.ipc = require('ipc');

	$scope.showMessageModal = function(message) {
		if (!message) return;
		$scope.message = message;
		$('#message-modal').modal('show');
	};

    $scope.connections = [];
    if (localStorage.getItem('connections')) {
    	$scope.connections = JSON.parse(localStorage.getItem('connections'));
    }

    $scope.setConnection = function(connection) {
        $scope.connections.push(connection);
        localStorage.setItem('connections', JSON.stringify($scope.connections));
    };

    $scope.removeConnection = function(id) {
        var _index;
        $scope.connections.forEach(function(item, index) {
            if (item.id === id) {
                _index = index;
            }
        });
        if (typeof _index !== 'undefined') {
            $scope.connections.splice(_index, 1);
        }

        localStorage.setItem('connections', JSON.stringify($scope.connections));
    };

    $scope.connectionExist = function(connection) {

    	for (var i = 0; i < $scope.connections.length; i++) {
    		var curr = $scope.connections[i];
    		if (curr.id === connection.id) {
    			return true;
    		}
    		if (curr.host === connection.host
    			&& curr.port === connection.port
    			&& curr.user === connection.user) {
    			return true;
    		}
    	}

    	return false;
    };

    $scope.resetConnections = function() {
    	localStorage.removeItem('connections');
    };

}]);
<|endoftext|>


<commit_before>"use strict"

// TODO: Flip color based on major version
const sMajorVer = /Chrome\/([0-9]+)/.exec(navigator.userAgent)[1];
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.font = "12px Sans-Serif";
ctx.fillStyle = "blue";
ctx.strokeText(sMajorVer, 2, 10);
var imageData = ctx.getImageData(0, 0, 19, 19);
chrome.browserAction.setIcon({
  imageData: imageData
});
const sVer = /Chrome\/[0-9]+\.[0-9]+\.([0-9]+)/.exec(navigator.userAgent)[1];
try {
    chrome.browserAction.setBadgeText( {text: sVer} );
    chrome.browserAction.setTitle( { title: navigator.userAgent });
} catch (e) { alert("Error: " + e); }<commit_msg>Add colors<commit_after>"use strict"

const sMajorVer = /Chrome\/([0-9]+)/.exec(navigator.userAgent)[1];
const allColors = ["red", "blue", "green", "black"];

var myColor = allColors[sMajorVer % allColors.length];
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.font = "14px Verdana";
ctx.strokeStyle = myColor;
ctx.strokeText(sMajorVer, 1, 11);
var imageData = ctx.getImageData(0, 0, 19, 19);
chrome.browserAction.setIcon({
  imageData: imageData
});
const sVer = /Chrome\/[0-9]+\.[0-9]+\.([0-9]+)/.exec(navigator.userAgent)[1];
try {
    chrome.browserAction.setBadgeText( {text: sVer} );
    chrome.browserAction.setTitle( { title: navigator.userAgent });
    chrome.browserAction.setBadgeBackgroundColor({color: myColor});
} catch (e) { alert("Error: " + e); }<|endoftext|>


<commit_before>/* Chinese initialisation for the jQuery UI date picker plugin. */
/* Written by Ressol (ressol@gmail.com). */
( function( factory ) {
	if ( typeof define === "function" && define.amd ) {

		// AMD. Register as an anonymous module.
		define( [ "../widgets/datepicker" ], factory );
	} else {

		// Browser globals
		factory( jQuery.datepicker );
	}
}( function( datepicker ) {

datepicker.regional[ "zh-TW" ] = {
	closeText: "關閉",
	prevText: "<上月",
	nextText: "下月>",
	currentText: "今天",
	monthNames: [ "一月","二月","三月","四月","五月","六月",
	"七月","八月","九月","十月","十一月","十二月" ],
	monthNamesShort: [ "一月","二月","三月","四月","五月","六月",
	"七月","八月","九月","十月","十一月","十二月" ],
	dayNames: [ "星期日","星期一","星期二","星期三","星期四","星期五","星期六" ],
	dayNamesShort: [ "周日","周一","周二","周三","周四","周五","周六" ],
	dayNamesMin: [ "日","一","二","三","四","五","六" ],
	weekHeader: "周",
	dateFormat: "yy/mm/dd",
	firstDay: 1,
	isRTL: false,
	showMonthAfterYear: true,
	yearSuffix: "年" };
datepicker.setDefaults( datepicker.regional[ "zh-TW" ] );

return datepicker.regional[ "zh-TW" ];

} ) );
<commit_msg>Datepicker: Correct Traditional Chinese translation<commit_after>/* Chinese initialisation for the jQuery UI date picker plugin. */
/* Written by Ressol (ressol@gmail.com). */
( function( factory ) {
	if ( typeof define === "function" && define.amd ) {

		// AMD. Register as an anonymous module.
		define( [ "../widgets/datepicker" ], factory );
	} else {

		// Browser globals
		factory( jQuery.datepicker );
	}
}( function( datepicker ) {

datepicker.regional[ "zh-TW" ] = {
	closeText: "關閉",
	prevText: "<上個月",
	nextText: "下個月>",
	currentText: "今天",
	monthNames: [ "一月","二月","三月","四月","五月","六月",
	"七月","八月","九月","十月","十一月","十二月" ],
	monthNamesShort: [ "一月","二月","三月","四月","五月","六月",
	"七月","八月","九月","十月","十一月","十二月" ],
	dayNames: [ "星期日","星期一","星期二","星期三","星期四","星期五","星期六" ],
	dayNamesShort: [ "週日","週一","週二","週三","週四","週五","週六" ],
	dayNamesMin: [ "日","一","二","三","四","五","六" ],
	weekHeader: "週",
	dateFormat: "yy/mm/dd",
	firstDay: 1,
	isRTL: false,
	showMonthAfterYear: true,
	yearSuffix: "年" };
datepicker.setDefaults( datepicker.regional[ "zh-TW" ] );

return datepicker.regional[ "zh-TW" ];

} ) );
<|endoftext|>


<commit_before>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/fileLibrary.html'
], function ($, _, Backbone, FileLibraryTemplate) {
	'use strict';

	var FileLibraryView = Backbone.View.extend({

		tagName:  'div',

    el: '#fileLibraryView',

		template: _.template(FileLibraryTemplate),

		// The DOM events specific to an item.
		events: {
			//'click .toggle':	'toggleCompleted',
			//'dblclick label':	'edit',
			//'click .destroy':	'clear',
			//'keypress .edit':	'updateOnEnter',
			//'keydown .edit':	'revertOnEscape',
			//'blur .edit':		'close'
      'hidden.bs.modal #fileLibraryModal': 'refreshView'
		},

		// The TodoView listens for changes to its model, re-rendering. Since there's
		// a one-to-one correspondence between a **Todo** and a **TodoView** in this
		// app, we set a direct reference on the model for convenience.
		initialize: function () {
			//this.listenTo(this.model, 'change', this.render);
			//this.listenTo(this.model, 'destroy', this.remove);
			//this.listenTo(this.model, 'visible', this.toggleVisible);

		},

		// Re-render the titles of the todo item.

    render: function () {

      //debugger;
      this.$el.html(this.template);
      //global.pagesView.populateTable();
      this.populateTable();

      //debugger;

      //$('#dashboardView').hide();
      //$('#pagesView').show();

			//this.toggleVisible();
			//this.$input = this.$('.edit');
			return this;
		},

    populateTable: function() {
      //debugger;

      //Loop through each model in the collection.
      //global.postsCollection.forEach( function(model) {
      for( var i = 0; i < global.fileUploadCollection.length; i++ ) {

        try {
          //debugger;

          var model = global.fileUploadCollection.models[i];

          //Handle corner case of new install with empty DB
          if( (global.fileUploadCollection.models.length == 1) && (model.id == "") ) {
            return;
          }

          //Clone the example row provided in the template.
          var tempRow = global.fileLibraryView.$el.find('#fileRow').clone();

          //Clear the ID copied from the example row.
          tempRow.attr('id', '');

          //Populate the new row with data from the model.
          var fileName = model.get('fileName');
          tempRow.find('th').html(''+fileName+'');
          tempRow.find('th').find('a').attr('onclick', 'global.fileLibraryView.editPost('+i+')');

          //Add the on-click function to the Delete button.
          tempRow.find('.postCol4').find('button').attr('onclick', 'global.fileLibraryView.deleteFile(global.fileUploadCollection.models['+i+'].id)');

          //tempRow.find('.postAuthor').text(model.get('author'));
          //tempRow.find('.postCategories').text(model.get('categories').join(','));

          //var publishedDate = new Date(model.get('publishedDate'));
          //var datestr = (publishedDate.getMonth()+1)+'/'+publishedDate.getDate()+'/'+publishedDate.getFullYear();
          //tempRow.find('.postDate').text(datestr);

          //Remove the 'hidden' attribute copied from the example row.
          tempRow.show();

          //Append the new row to the DOM.
          global.fileLibraryView.$el.find('#filesTable').append(tempRow);
        } catch(err) {
          console.error('Error encountered in fileLibraryView.populateTable(). Error message:');
          console.error(err.message);

          log.push('Error encountered in fileLibraryView.populateTable(). Error message:')
          log.push(err.message)
          sendLog();
        }

      }
      //});

    },

    editPost: function(model_index) {
      debugger;

      //$('#pagesView').hide();
      //$('#pagesAddNewView').show();

      //$('#app-location').text('Pages : Edit Post');

      //Load the currently selected model into the TinyMCE state variable so that once
      //the TinyMCE editor has been loaded, it knows which model to load.
      //global.tinymce.currentModelIndex = model_index;

      //Render the Add New pages View view.
      //global.pagesAddNewView.render();

      //global.pagesAddNewView.loadPost(model_index);
    },

    uploadFile: function() {
      //debugger;

      var selectedFile = this.$el.find('#file_upload').get(0).files[0];

      //Create the FormData data object and append the file to it.
      var newFile = new FormData();
      newFile.append('file_upload', selectedFile); //This is the raw file that was selected

      var opts = {
        url: 'http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/create',
        data: newFile,
        cache: false,
        contentType: false,
        processData: false,
        type: 'POST',
        success: function(data){
          //Dev Note: KeystoneAPI only allows file and image uploads with the file itself. Any extra metadata will have to
          //be uploaded/updated with a second call.

          //debugger;
          console.log('File upload succeeded! ID: ' + data.file_upload._id);
          log.push('File upload succeeded! ID: ' + data.file_upload._id);

          //Fill out the file information
          data.file_upload.name = data.file_upload.file.originalname;
          data.file_upload.fileName = data.file_upload.file.originalname;
          data.file_upload.url = 'http://'+global.serverIp+'/uploads/files/'+data.file_upload.file.filename;
          data.file_upload.fileType = data.file_upload.file.type;

          //Update the file with the information above.
          $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+data.file_upload._id+'/update', data.file_upload, function(data) {
            //debugger;
            log.push('File information updated.');

            //Refresh the Collection.
            //global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
            global.fileUploadCollection.fetch();

            //Notify successful upload via modal.
            global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
            global.fileLibraryView.$el.find('.modal-sm').find('#successMsg').show();
            //global.fileLibraryView.render();
          })
          //If the metadata update fails:
          .fail(function(data) {
            debugger;
          });
        },

        //This error function is called if the POST fails for submitting the file itself.
        error: function(err) {
          //debugger;

          global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').show();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').html(
            '
The file was not uploaded to the server. This is most likely because the server does not accept the selected file TYPE.

'+
            'Here is the error message from the server:
'+
            'Server status: '+err.status+'
'+
            'Server message: '+err.statusText+'

'
          );

        }
      };

      //Execute the AJAX operation.
      jQuery.ajax(opts);
    },

    fileSelected: function() {
      //debugger;

    },

    //This function is called when the modal has completed closing. It refreshes the View to make sure
    //any new uploaded files appear in the file table.
    refreshView: function() {
      //debugger;

      //Fixing bug where modal backdrop stays in place.
      $('.modal-backdrop').hide();

      this.render();
    },

    deleteFile: function(id) {
      //debugger;
      $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+id+'/remove', '', function(data) {
        //debugger;

        if( data.success == true ) {
          log.push('FileUpload object deleted successfully. ID: '+id);
          global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
          global.fileUploadCollection.fetch();
          //global.fileLibraryView.render();
        } else {
          console.error('FileUpload object no deleted! ID: '+id);
          log.push('FileUpload object no deleted! ID: '+id);
          sendLog();
        }
      })
    }

	});

  //debugger;
	return FileLibraryView;
});
<commit_msg>added server port to file URL in fileLibraryView<commit_after>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/fileLibrary.html'
], function ($, _, Backbone, FileLibraryTemplate) {
	'use strict';

	var FileLibraryView = Backbone.View.extend({

		tagName:  'div',

    el: '#fileLibraryView',

		template: _.template(FileLibraryTemplate),

		// The DOM events specific to an item.
		events: {
			//'click .toggle':	'toggleCompleted',
			//'dblclick label':	'edit',
			//'click .destroy':	'clear',
			//'keypress .edit':	'updateOnEnter',
			//'keydown .edit':	'revertOnEscape',
			//'blur .edit':		'close'
      'hidden.bs.modal #fileLibraryModal': 'refreshView'
		},

		// The TodoView listens for changes to its model, re-rendering. Since there's
		// a one-to-one correspondence between a **Todo** and a **TodoView** in this
		// app, we set a direct reference on the model for convenience.
		initialize: function () {
			//this.listenTo(this.model, 'change', this.render);
			//this.listenTo(this.model, 'destroy', this.remove);
			//this.listenTo(this.model, 'visible', this.toggleVisible);

		},

		// Re-render the titles of the todo item.

    render: function () {

      //debugger;
      this.$el.html(this.template);
      //global.pagesView.populateTable();
      this.populateTable();

      //debugger;

      //$('#dashboardView').hide();
      //$('#pagesView').show();

			//this.toggleVisible();
			//this.$input = this.$('.edit');
			return this;
		},

    populateTable: function() {
      //debugger;

      //Loop through each model in the collection.
      //global.postsCollection.forEach( function(model) {
      for( var i = 0; i < global.fileUploadCollection.length; i++ ) {

        try {
          //debugger;

          var model = global.fileUploadCollection.models[i];

          //Handle corner case of new install with empty DB
          if( (global.fileUploadCollection.models.length == 1) && (model.id == "") ) {
            return;
          }

          //Clone the example row provided in the template.
          var tempRow = global.fileLibraryView.$el.find('#fileRow').clone();

          //Clear the ID copied from the example row.
          tempRow.attr('id', '');

          //Populate the new row with data from the model.
          var fileName = model.get('fileName');
          tempRow.find('th').html(''+fileName+'');
          tempRow.find('th').find('a').attr('onclick', 'global.fileLibraryView.editPost('+i+')');

          //Add the on-click function to the Delete button.
          tempRow.find('.postCol4').find('button').attr('onclick', 'global.fileLibraryView.deleteFile(global.fileUploadCollection.models['+i+'].id)');

          //tempRow.find('.postAuthor').text(model.get('author'));
          //tempRow.find('.postCategories').text(model.get('categories').join(','));

          //var publishedDate = new Date(model.get('publishedDate'));
          //var datestr = (publishedDate.getMonth()+1)+'/'+publishedDate.getDate()+'/'+publishedDate.getFullYear();
          //tempRow.find('.postDate').text(datestr);

          //Remove the 'hidden' attribute copied from the example row.
          tempRow.show();

          //Append the new row to the DOM.
          global.fileLibraryView.$el.find('#filesTable').append(tempRow);
        } catch(err) {
          console.error('Error encountered in fileLibraryView.populateTable(). Error message:');
          console.error(err.message);

          log.push('Error encountered in fileLibraryView.populateTable(). Error message:')
          log.push(err.message)
          sendLog();
        }

      }
      //});

    },

    editPost: function(model_index) {
      debugger;

      //$('#pagesView').hide();
      //$('#pagesAddNewView').show();

      //$('#app-location').text('Pages : Edit Post');

      //Load the currently selected model into the TinyMCE state variable so that once
      //the TinyMCE editor has been loaded, it knows which model to load.
      //global.tinymce.currentModelIndex = model_index;

      //Render the Add New pages View view.
      //global.pagesAddNewView.render();

      //global.pagesAddNewView.loadPost(model_index);
    },

    uploadFile: function() {
      //debugger;

      var selectedFile = this.$el.find('#file_upload').get(0).files[0];

      //Create the FormData data object and append the file to it.
      var newFile = new FormData();
      newFile.append('file_upload', selectedFile); //This is the raw file that was selected

      var opts = {
        url: 'http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/create',
        data: newFile,
        cache: false,
        contentType: false,
        processData: false,
        type: 'POST',
        success: function(data){
          //Dev Note: KeystoneAPI only allows file and image uploads with the file itself. Any extra metadata will have to
          //be uploaded/updated with a second call.

          //debugger;
          console.log('File upload succeeded! ID: ' + data.file_upload._id);
          log.push('File upload succeeded! ID: ' + data.file_upload._id);

          //Fill out the file information
          data.file_upload.name = data.file_upload.file.originalname;
          data.file_upload.fileName = data.file_upload.file.originalname;
          data.file_upload.url = 'http://'+global.serverIp+':'+global.serverPort+'/uploads/files/'+data.file_upload.file.filename;
          data.file_upload.fileType = data.file_upload.file.type;

          //Update the file with the information above.
          $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+data.file_upload._id+'/update', data.file_upload, function(data) {
            //debugger;
            log.push('File information updated.');

            //Refresh the Collection.
            //global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
            global.fileUploadCollection.fetch();

            //Notify successful upload via modal.
            global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
            global.fileLibraryView.$el.find('.modal-sm').find('#successMsg').show();
            //global.fileLibraryView.render();
          })
          //If the metadata update fails:
          .fail(function(data) {
            debugger;
          });
        },

        //This error function is called if the POST fails for submitting the file itself.
        error: function(err) {
          //debugger;

          global.fileLibraryView.$el.find('.modal-sm').find('#waitingGif').hide();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').show();
          global.fileLibraryView.$el.find('.modal-sm').find('#errorMsg').html(
            '
The file was not uploaded to the server. This is most likely because the server does not accept the selected file TYPE.

'+
            'Here is the error message from the server:
'+
            'Server status: '+err.status+'
'+
            'Server message: '+err.statusText+'

'
          );

        }
      };

      //Execute the AJAX operation.
      jQuery.ajax(opts);
    },

    fileSelected: function() {
      //debugger;

    },

    //This function is called when the modal has completed closing. It refreshes the View to make sure
    //any new uploaded files appear in the file table.
    refreshView: function() {
      //debugger;

      //Fixing bug where modal backdrop stays in place.
      $('.modal-backdrop').hide();

      this.render();
    },

    deleteFile: function(id) {
      //debugger;
      $.get('http://'+global.serverIp+':'+global.serverPort+'/api/fileupload/'+id+'/remove', '', function(data) {
        //debugger;

        if( data.success == true ) {
          log.push('FileUpload object deleted successfully. ID: '+id);
          global.fileUploadCollection.refreshView = true; //Set flag so view is refreshed after collection is updated.
          global.fileUploadCollection.fetch();
          //global.fileLibraryView.render();
        } else {
          console.error('FileUpload object no deleted! ID: '+id);
          log.push('FileUpload object no deleted! ID: '+id);
          sendLog();
        }
      })
    }

	});

  //debugger;
	return FileLibraryView;
});
<|endoftext|>