<commit_before>;(function(exports){

    var defaults = {
        monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
                     'August', 'September', 'October', 'November', 'December'],

        shortMonthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
                          'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],

        repeatLevels: {
            'low': [0, 2],
            'medium-low': [2, 5],
            'medium': [5, 10],
            'medium-high': [10, 30],
            'high': [30, 50],
            'hot': [50, 70],
            'extra-hot': [70, 100]
        },

        labels: {
            time: 'Time',
            people: 'People',
            weekOf: 'Week of'
        },

        timeInterval: 'monthly',

        drawEmptyCells: true,

        rawNumberOnHover: true,

        classPrefix: 'cornelius-',

        formatHeaderLabel: function(i) {
            return i === 0 ? this.labels.people : i.toString();
        },

        formatDailyLabel: function(date, i) {
            date.setDate(date.getDate() + i);
            return this.monthNames[date.getMonth()] + ' ' + date.getDate() + ', ' + getYear(date);
        },

        formatWeeklyLabel: function(date, i) {
            date.setDate(date.getDate() + i * 7);
            return this.labels.weekOf + ' ' + this.shortMonthNames[date.getMonth()] + ' ' +
                    date.getDate() + ', ' + getYear(date);
        },

        formatMonthlyLabel: function(date, i) {
            date.setMonth(date.getMonth() + i - 1);
            return this.monthNames[date.getMonth()] + ' ' + getYear(date);
        },

        formatYearlyLabel: function(date, i) {
            return date.getYear() + 1900 + i;
        }
    };

    function extend() {
        var target = arguments[0];

        if (arguments.length === 1) return target;

        for (var i = 1; i < arguments.length; i++) {
            var source = arguments[i];
            for (var prop in source) target[prop] = source[prop];
        }

        return target;
    }

    function isNumber(val) {
        return Object.prototype.toString.call(val) === '[object Number]';
    }

    function isEmpty(val) {
        return val === null || val === undefined || val === "";
    }

    function getYear(date) {
        return date.getYear() + 1900;
    }

    var draw = function(cohort, container, config) {

        function create(el, options) {
            options = options || {};

            el = document.createElement(el);

            if ((className = options.className)) {
                delete options.className;
                el.className = prefixClass(className);
            }
            if (!isEmpty(textContent = options.text)) {
                delete options.text;
                el.textContent = textContent.toString();
            }

            for (var option in options) {
                if ((opt = options[option])) el[option] = opt;
            }

            return el;
        }

        function prefixClass(className) {
            var prefixedClass = [],
                classes = className.split(/\s+/);

            for (var i in classes) {
                prefixedClass.push(config.classPrefix + classes[i]);
            }
            return prefixedClass.join(" ");
        }

        function drawHeader(data) {
            var th = create('tr'),
                monthLength = data[0].length;

            th.appendChild(create('th', { text: config.labels.time, className: 'time' }));

            for (var i = 0; i < monthLength; i++) {
                if (i > config.maxColumns) break;
                th.appendChild(create('th', { text: config.formatHeaderLabel(i), className: 'people' }));
            }
            return th;
        }

        function formatTimeLabel(initial, timeInterval, i) {
            var date = new Date(initial.getTime()),
                formatFn = null;

            if (timeInterval === 'daily') {
                formatFn = 'formatDailyLabel';
            } else if (timeInterval === 'weekly') {
                formatFn = 'formatWeeklyLabel';
            } else if (timeInterval === 'monthly') {
                formatFn = 'formatMonthlyLabel';
            } else if (timeInterval === 'yearly') {
                formatFn = 'formatYearlyLabel';
            } else {
                throw new Error("Interval not supported");
            }

            return config[formatFn].call(config, date, i);
        }

        function drawCells(data) {
            var fragment = document.createDocumentFragment(),

            formatPercentage = function(value, base) {
                if (isNumber(value) && base > 0) {
                    return (value / base * 100).toFixed(2);
                } else if (isNumber(value)) {
                    return 0;
                }
            },

            classNameFor = function(value) {
                var levels = config.repeatLevels,
                    floatValue = value && parseFloat(value),
                    highestLevel = null;

                var classNames = ['percentage'];

                for (var level in levels) {
                    if (floatValue >= levels[level][0] && floatValue < levels[level][1]) {
                        classNames.push(level);
                        return classNames.join(" ");
                    }
                    highestLevel = level;
                }

                // handle 100% case
                classNames.push(highestLevel);
                return classNames.join(" ");

            };

            for (var i = 0; i < data.length; i++) {
                var tr = create('tr'),
                    row = data[i],
                    baseValue = row[0];

                tr.appendChild(create('td', {
                    className: 'label',
                    textContent: formatTimeLabel(config.initialDate, config.timeInterval, i)
                }));

                for (var j = 0; j < data[0].length; j++) {
                    if (j > config.maxColumns) break;

                    var value = row[j],
                        cellValue = j === 0 ? value : formatPercentage(value, baseValue),
                        opts = {};

                        if (!isEmpty(cellValue)) {
                            opts = {
                                text: cellValue,
                                title: j > 0 && config.rawNumberOnHover ? value : null,
                                className: j === 0 ? 'people' : classNameFor(cellValue)
                            };
                        } else if (config.drawEmptyCells) {
                            opts = { text: '-', className: 'empty' };
                        }

                    tr.appendChild(create('td', opts));
                }
                fragment.appendChild(tr);
            }
            return fragment;
        }

        var mainContainer = create('div', { className: 'container' }),
            table = create('table', { className: 'table' });

        table.appendChild(drawHeader(cohort));
        table.appendChild(drawCells(cohort));

        if ((title = config.title)) {
            mainContainer.appendChild(create('div', { text: title, className: 'title' }));
        }
        mainContainer.appendChild(table);

        container.appendChild(mainContainer);
    };

    var Cornelius = function(opts) {
        this.options = extend({}, defaults, opts || {});
    };

    Cornelius.prototype.draw = function(cohort, container) {
        if (!cohort)    throw new Error ("Please provide the cohort data");
        if (!container) throw new Error ("Please provide the cohort container");

        draw(cohort, container, this.options);
    };

    if (typeof jQuery !== "undefined" && jQuery !== null) {
        jQuery.fn.cornelius = function(options) {
            return this.each(function() {
                return new Cornelius(options).draw(options.cohort, this);
            });
        };
    }

    exports.Cornelius = Cornelius;

})(window);
<commit_msg>add support for maxRows<commit_after>;(function(exports){

    var defaults = {
        monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
                     'August', 'September', 'October', 'November', 'December'],

        shortMonthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
                          'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],

        repeatLevels: {
            'low': [0, 2],
            'medium-low': [2, 5],
            'medium': [5, 10],
            'medium-high': [10, 30],
            'high': [30, 50],
            'hot': [50, 70],
            'extra-hot': [70, 100]
        },

        labels: {
            time: 'Time',
            people: 'People',
            weekOf: 'Week of'
        },

        timeInterval: 'monthly',

        drawEmptyCells: true,

        rawNumberOnHover: true,

        classPrefix: 'cornelius-',

        formatHeaderLabel: function(i) {
            return i === 0 ? this.labels.people : i.toString();
        },

        formatDailyLabel: function(date, i) {
            date.setDate(date.getDate() + i);
            return this.monthNames[date.getMonth()] + ' ' + date.getDate() + ', ' + getYear(date);
        },

        formatWeeklyLabel: function(date, i) {
            date.setDate(date.getDate() + i * 7);
            return this.labels.weekOf + ' ' + this.shortMonthNames[date.getMonth()] + ' ' +
                    date.getDate() + ', ' + getYear(date);
        },

        formatMonthlyLabel: function(date, i) {
            date.setMonth(date.getMonth() + i - 1);
            return this.monthNames[date.getMonth()] + ' ' + getYear(date);
        },

        formatYearlyLabel: function(date, i) {
            return date.getYear() + 1900 + i;
        }
    };

    function extend() {
        var target = arguments[0];

        if (arguments.length === 1) return target;

        for (var i = 1; i < arguments.length; i++) {
            var source = arguments[i];
            for (var prop in source) target[prop] = source[prop];
        }

        return target;
    }

    function isNumber(val) {
        return Object.prototype.toString.call(val) === '[object Number]';
    }

    function isEmpty(val) {
        return val === null || val === undefined || val === "";
    }

    function getYear(date) {
        return date.getYear() + 1900;
    }

    var draw = function(cohort, container, config) {

        function create(el, options) {
            options = options || {};

            el = document.createElement(el);

            if ((className = options.className)) {
                delete options.className;
                el.className = prefixClass(className);
            }
            if (!isEmpty(textContent = options.text)) {
                delete options.text;
                el.textContent = textContent.toString();
            }

            for (var option in options) {
                if ((opt = options[option])) el[option] = opt;
            }

            return el;
        }

        function prefixClass(className) {
            var prefixedClass = [],
                classes = className.split(/\s+/);

            for (var i in classes) {
                prefixedClass.push(config.classPrefix + classes[i]);
            }
            return prefixedClass.join(" ");
        }

        function drawHeader(data) {
            var th = create('tr'),
                monthLength = data[0].length;

            th.appendChild(create('th', { text: config.labels.time, className: 'time' }));

            for (var i = 0; i < monthLength; i++) {
                if (i > config.maxColumns) break;
                th.appendChild(create('th', { text: config.formatHeaderLabel(i), className: 'people' }));
            }
            return th;
        }

        function formatTimeLabel(initial, timeInterval, i) {
            var date = new Date(initial.getTime()),
                formatFn = null;

            if (timeInterval === 'daily') {
                formatFn = 'formatDailyLabel';
            } else if (timeInterval === 'weekly') {
                formatFn = 'formatWeeklyLabel';
            } else if (timeInterval === 'monthly') {
                formatFn = 'formatMonthlyLabel';
            } else if (timeInterval === 'yearly') {
                formatFn = 'formatYearlyLabel';
            } else {
                throw new Error("Interval not supported");
            }

            return config[formatFn].call(config, date, i);
        }

        function drawCells(data) {
            var fragment = document.createDocumentFragment(),

                startMonth = config.maxRows ? data.length - config.maxRows : 0,

                formatPercentage = function(value, base) {
                    if (isNumber(value) && base > 0) {
                        return (value / base * 100).toFixed(2);
                    } else if (isNumber(value)) {
                        return 0;
                    }
                },

                classNameFor = function(value) {
                    var levels = config.repeatLevels,
                        floatValue = value && parseFloat(value),
                        highestLevel = null;

                    var classNames = ['percentage'];

                    for (var level in levels) {
                        if (floatValue >= levels[level][0] && floatValue < levels[level][1]) {
                            classNames.push(level);
                            return classNames.join(" ");
                        }
                        highestLevel = level;
                    }

                    // handle 100% case
                    classNames.push(highestLevel);
                    return classNames.join(" ");

                };

            for (var i = startMonth; i < data.length; i++) {
                var tr = create('tr'),
                    row = data[i],
                    baseValue = row[0];

                tr.appendChild(create('td', {
                    className: 'label',
                    textContent: formatTimeLabel(config.initialDate, config.timeInterval, i)
                }));

                for (var j = 0; j < data[0].length; j++) {
                    if (j > config.maxColumns) break;

                    var value = row[j],
                        cellValue = j === 0 ? value : formatPercentage(value, baseValue),
                        opts = {};

                        if (!isEmpty(cellValue)) {
                            opts = {
                                text: cellValue,
                                title: j > 0 && config.rawNumberOnHover ? value : null,
                                className: j === 0 ? 'people' : classNameFor(cellValue)
                            };
                        } else if (config.drawEmptyCells) {
                            opts = { text: '-', className: 'empty' };
                        }

                    tr.appendChild(create('td', opts));
                }
                fragment.appendChild(tr);
            }
            return fragment;
        }

        var mainContainer = create('div', { className: 'container' }),
            table = create('table', { className: 'table' });

        table.appendChild(drawHeader(cohort));
        table.appendChild(drawCells(cohort));

        if ((title = config.title)) {
            mainContainer.appendChild(create('div', { text: title, className: 'title' }));
        }
        mainContainer.appendChild(table);

        container.appendChild(mainContainer);
    };

    var Cornelius = function(opts) {
        this.config = extend({}, defaults, opts || {});
    };

    Cornelius.prototype.draw = function(cohort, container) {
        if (!cohort)    throw new Error ("Please provide the cohort data");
        if (!container) throw new Error ("Please provide the cohort container");

        draw(cohort, container, this.config);
    };

    if (typeof jQuery !== "undefined" && jQuery !== null) {
        jQuery.fn.cornelius = function(options) {
            return this.each(function() {
                return new Cornelius(options).draw(options.cohort, this);
            });
        };
    }

    exports.Cornelius = Cornelius;

})(window);
<|endoftext|>


<commit_before>'use strict';

var conf = {
  "hand": {
    "color": {
      "r": 0,
      "g": 0,
      "b": 0
    }
  },
  "background": {
    "shape": "square",
    "color": {
      "r": 0,
      "g": 0,
      "b": 0
    }
  }
};

function drawClock(items) {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var d = new Date();
  var s = d.getSeconds();
  var m = d.getMinutes();
  var h = d.getHours();
  if (h > 12) h -= 12;
  var rad = 0;

  browser.browserAction.setTitle({"title":d.getFullYear()+"/"+(d.getMonth()+1)+"/"+d.getDate()+" "+h+":"+m});

  try {
    conf = JSON.parse(items["conf"]);
  } catch (e) {}

  ctx.save();
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Background
  ctx.fillStyle = "rgb(" + conf.background.color.r + "," + conf.background.color.g + "," + conf.background.color.b + ")";
  ctx.beginPath();
  ctx.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, Math.PI * 2, false);
  ctx.fill();

  // Face
  ctx.strokeStyle = "rgb(" + conf.hand.color.r + "," + conf.hand.color.g + "," + conf.hand.color.b + ")";
  ctx.beginPath();
  ctx.moveTo(9, 0);
  ctx.lineTo(9, 1);
  ctx.moveTo(17, 9);
  ctx.lineTo(18, 9);
  ctx.moveTo(9, 17);
  ctx.lineTo(9, 18);
  ctx.moveTo(0, 9);
  ctx.lineTo(1, 9);
  ctx.stroke();

  ctx.translate(Math.ceil(canvas.width / 2), Math.ceil(canvas.height / 2));

  // Short hand
  rad = 2 * Math.PI / 12 * h + 2 * Math.PI / 12 / 60 * m - Math.PI / 2;
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(6 * Math.cos(rad)), Math.ceil(6 * Math.sin(rad)));
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(2 * Math.cos(rad + Math.PI)), Math.ceil(2 * Math.sin(rad + Math.PI)));
  ctx.stroke();

  // Long hand
  rad = 2 * Math.PI / 60 * m - Math.PI / 2;
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(8 * Math.cos(rad)), Math.ceil(8 * Math.sin(rad)));
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(2 * Math.cos(rad + Math.PI)), Math.ceil(2 * Math.sin(rad + Math.PI)));
  ctx.stroke();

  ctx.restore();

  chrome.browserAction.setIcon({
    "imageData": ctx.getImageData(0, 0, canvas.width, canvas.height)
  });
}

function saveOptions(items) {
  try {
    conf = JSON.parse(items["conf"]);
  } catch (e) {}

  $('#hand-color').ColorPicker({
    color: conf["hand"]["color"],
    flat: true,
    onChange: function(hsb, hex, rgb) {
      conf["hand"]["color"] = rgb;
      chrome.storage.local.set({
        "conf": JSON.stringify(conf)
      });
    }
  });

  $('#bg-color').ColorPicker({
    color: conf["background"]["color"],
    flat: true,
    onChange: function(hsb, hex, rgb) {
      conf["background"]["color"] = rgb;
      chrome.storage.local.set({
        "conf": JSON.stringify(conf)
      });
    }
  });
}

function anaclock() {
  chrome.storage.local.get("conf", drawClock);
}

function options() {
  chrome.storage.local.get("conf", saveOptions);
}
<commit_msg>Change tooltip format<commit_after>'use strict';

var conf = {
  "hand": {
    "color": {
      "r": 0,
      "g": 0,
      "b": 0
    }
  },
  "background": {
    "shape": "square",
    "color": {
      "r": 0,
      "g": 0,
      "b": 0
    }
  }
};

function drawClock(items) {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var d = new Date();
  var s = d.getSeconds();
  var m = d.getMinutes();
  var h = d.getHours();
  var rad = 0;

  var str_mon = d.getMonth() + 1;
  var str_d = d.getDate();
  var str_h = h;
  var str_m = m;
  if (str_mon < 10) str_mon = "0" + str_mon;
  if (str_d < 10) str_d = "0" + str_d;
  if (h < 10) str_h = "0" + h;
  if (m < 10) str_m = "0" + m;
  browser.browserAction.setTitle({"title":d.getFullYear()+"/"+str_mon+"/"+str_d+" "+str_h+":"+str_m});

  if (h > 12) h -= 12;

  try {
    conf = JSON.parse(items["conf"]);
  } catch (e) {}

  ctx.save();
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Background
  ctx.fillStyle = "rgb(" + conf.background.color.r + "," + conf.background.color.g + "," + conf.background.color.b + ")";
  ctx.beginPath();
  ctx.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, Math.PI * 2, false);
  ctx.fill();

  // Face
  ctx.strokeStyle = "rgb(" + conf.hand.color.r + "," + conf.hand.color.g + "," + conf.hand.color.b + ")";
  ctx.beginPath();
  ctx.moveTo(9, 0);
  ctx.lineTo(9, 1);
  ctx.moveTo(17, 9);
  ctx.lineTo(18, 9);
  ctx.moveTo(9, 17);
  ctx.lineTo(9, 18);
  ctx.moveTo(0, 9);
  ctx.lineTo(1, 9);
  ctx.stroke();

  ctx.translate(Math.ceil(canvas.width / 2), Math.ceil(canvas.height / 2));

  // Short hand
  rad = 2 * Math.PI / 12 * h + 2 * Math.PI / 12 / 60 * m - Math.PI / 2;
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(6 * Math.cos(rad)), Math.ceil(6 * Math.sin(rad)));
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(2 * Math.cos(rad + Math.PI)), Math.ceil(2 * Math.sin(rad + Math.PI)));
  ctx.stroke();

  // Long hand
  rad = 2 * Math.PI / 60 * m - Math.PI / 2;
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(8 * Math.cos(rad)), Math.ceil(8 * Math.sin(rad)));
  ctx.moveTo(0, 0);
  ctx.lineTo(Math.ceil(2 * Math.cos(rad + Math.PI)), Math.ceil(2 * Math.sin(rad + Math.PI)));
  ctx.stroke();

  ctx.restore();

  chrome.browserAction.setIcon({
    "imageData": ctx.getImageData(0, 0, canvas.width, canvas.height)
  });
}

function saveOptions(items) {
  try {
    conf = JSON.parse(items["conf"]);
  } catch (e) {}

  $('#hand-color').ColorPicker({
    color: conf["hand"]["color"],
    flat: true,
    onChange: function(hsb, hex, rgb) {
      conf["hand"]["color"] = rgb;
      chrome.storage.local.set({
        "conf": JSON.stringify(conf)
      });
    }
  });

  $('#bg-color').ColorPicker({
    color: conf["background"]["color"],
    flat: true,
    onChange: function(hsb, hex, rgb) {
      conf["background"]["color"] = rgb;
      chrome.storage.local.set({
        "conf": JSON.stringify(conf)
      });
    }
  });
}

function anaclock() {
  chrome.storage.local.get("conf", drawClock);
}

function options() {
  chrome.storage.local.get("conf", saveOptions);
}
<|endoftext|>


<commit_before>var hotkeys = (function () {

var exports = {};

var pressed_keys = {};

function num_pressed_keys() {
    var size = 0, key;
    $.each(pressed_keys, function () {
        size++;
    });
    return size;
}

var directional_hotkeys = {
    40:  rows.next_visible,  // down arrow
    106: rows.next_visible,  // 'j'
    38:  rows.prev_visible,  // up arrow
    107: rows.prev_visible,  // 'k'
    36:  rows.first_visible, // Home
    35:  rows.last_visible   // End
};

var narrow_hotkeys = {
    115: narrow.by_recipient,  // 's'
    83:  narrow.by_subject,    // 'S'
    104: narrow.all_huddles    // 'h'
};

// These are not exported, but they need to be used before they are
// defined, since we have a cycle in function reference.  So we
// declare them ahead of time to make JSLint happy.
var process_key_in_input, process_compose_hotkey;

function simulate_keydown(keycode) {
    $(document).trigger($.Event('keydown', {keyCode: keycode}));
}

function process_hotkey(code) {
    var next_message;

    // Disable hotkeys on settings page etc.
    if (!$('#home').hasClass('active')) {
        return false;
    }

    // Disable hotkeys when in an input, textarea, or button
    if ($('input:focus,textarea:focus,button:focus').length > 0) {
        return process_key_in_input(code);
    }

    if (directional_hotkeys.hasOwnProperty(code)) {
        next_message = directional_hotkeys[code](selected_message);
        if (next_message.length !== 0) {
            select_message(next_message, {then_scroll: true});
        }
        if ((next_message.length === 0) && (code === 40 || code === 106)) {
            // At the last message, scroll to the bottom so we have
            // lots of nice whitespace for new messages coming in.
            //
            // FIXME: this doesn't work for End because rows.last_visible()
            // always returns a message.
            viewport.scrollTop($("#main_div").outerHeight(true));
        }
        return process_hotkey;
    }

    if (narrow_hotkeys.hasOwnProperty(code)) {
        narrow.target(selected_message_id);
        narrow_hotkeys[code]();
        return process_hotkey;
    }

    if (num_pressed_keys() > 1 &&
            // "shift"                        "caps lock"
            !((pressed_keys[16] === true || pressed_keys[20]) &&
                num_pressed_keys() === 2)) {
        // If you are already holding down another key, none of these
        // actions apply.
        return false;
    }

    switch (code) {
    case 33: // Page Up
        if (at_top_of_viewport()) {
            select_message(rows.first_visible(), {then_scroll: false});
        }
        return false; // We want the browser to actually page up and down
    case 32: // Spacebar
    case 34: // Page Down
        if (at_bottom_of_viewport()) {
            select_message(rows.last_visible(), {then_scroll: false});
        }
        return false;
    case 27: // Esc: close userinfo popup, cancel compose, or un-narrow
        if (userinfo_currently_popped !== undefined) {
            userinfo_currently_popped.popover("destroy");
            userinfo_currently_popped = undefined;
        } else if (compose.composing()) {
            compose.cancel();
        } else {
            narrow.show_all_messages();
        }
        return process_hotkey;
    case 99: // 'c': compose
        compose.start('stream');
        return process_compose_hotkey;
    case 67: // 'C': compose huddle
        compose.start('personal');
        return process_compose_hotkey;
    case 114: // 'r': respond to message
        respond_to_message();
        return process_hotkey;
    case 82: // 'R': respond to author
        respond_to_message("personal");
        return process_hotkey;
    case 47: // '/': initiate search
        initiate_search();
        return process_hotkey;
    case 63: // '?': Show keyboard shortcuts page
        $('#keyboard-shortcuts').modal('show');
        return process_hotkey;
    }

    return false;
}

/* The current handler function for keydown events.
   It should return a new handler, or 'false' to
   decline to handle the event. */
var keydown_handler = process_hotkey;

process_key_in_input = function (code) {
    if (code === 27) {
        // If the user hit the escape key, cancel the current compose
        compose.cancel();
    }
    // Keycode 13 is Return.
    if ((code === 13) && $("#search").is(":focus")) {
        // Pass it along to the search up button.
        $("#search_up").focus();
    }
    // Let the browser handle the key normally.
    return false;
};

process_compose_hotkey = function (code) {
    if (code === 9) { // Tab: toggles between stream and huddle compose tabs.
        compose.toggle_mode();
        return process_compose_hotkey;
    }
    // Process the first non-tab character and everything after it
    // like any other keys typed in the input box
    keydown_handler = process_hotkey;
    return process_hotkey(code);
};

exports.set_compose = function () {
    keydown_handler = process_compose_hotkey;
};

$(document).keydown(function (e) {
    pressed_keys[e.which] = true;
    if ((num_pressed_keys() >= 2) &&
        (48 <= e.which && e.which <= 90) &&
        (pressed_keys[17] === true ||
         pressed_keys[91] === true)) {
        // If the user typed 2 or more characters, one of which was
        // ctrl(17) or command(91), and ending with an alphanumeric
        // character (between 48 and 90), this is probably a browser
        // keyboard shortcut (example: ctrl-f in Chrome).  Browsers
        // will often not trigger a keyup event after processing those
        // shortcuts and we don't have any hotkeys using these
        // characters, so just ignore such key presses for our
        // accounting.
        pressed_keys = {};
    }
});

$(document).keyup(function (e) {
    pressed_keys = {};
});

/* We register both a keydown and a keypress function because
   we want to intercept pgup/pgdn, escape, etc, and process them
   as they happen on the keyboard. However, if we processed
   letters/numbers in keydown, we wouldn't know what the case of
   the letters were.

   We want case-sensitive hotkeys (such as in the case of r vs R)
   so we bail in .keydown if the event is a letter or number and
   instead just let keypress go for it. */

$(document).keydown(function (event) {
    if (48 > event.which ||90 < event.which) { // outside the alphanumeric range
        var result = keydown_handler(event.which);
        if (result) {
            keydown_handler = result;
            event.preventDefault();
        }
    }
});

$(document).keypress(function (event) {
    // What exactly triggers .keypress may vary by browser.
    // Welcome to compatability hell.
    //
    // In particular, when you press tab in Firefox, it fires a
    // keypress event with keycode 0 after processing the original
    // event.
    if (event.which !== 0 && event.charCode !== 0) {
        var result = keydown_handler(event.which);
        if (result) {
            keydown_handler = result;
            event.preventDefault();
        }
    }
});

return exports;

}());
<commit_msg>hotkey: Rename keydown_handler -> current_key_handler<commit_after>var hotkeys = (function () {

var exports = {};

var pressed_keys = {};

function num_pressed_keys() {
    var size = 0, key;
    $.each(pressed_keys, function () {
        size++;
    });
    return size;
}

var directional_hotkeys = {
    40:  rows.next_visible,  // down arrow
    106: rows.next_visible,  // 'j'
    38:  rows.prev_visible,  // up arrow
    107: rows.prev_visible,  // 'k'
    36:  rows.first_visible, // Home
    35:  rows.last_visible   // End
};

var narrow_hotkeys = {
    115: narrow.by_recipient,  // 's'
    83:  narrow.by_subject,    // 'S'
    104: narrow.all_huddles    // 'h'
};

// These are not exported, but they need to be used before they are
// defined, since we have a cycle in function reference.  So we
// declare them ahead of time to make JSLint happy.
var process_key_in_input, process_compose_hotkey;

function simulate_keydown(keycode) {
    $(document).trigger($.Event('keydown', {keyCode: keycode}));
}

function process_hotkey(code) {
    var next_message;

    // Disable hotkeys on settings page etc.
    if (!$('#home').hasClass('active')) {
        return false;
    }

    // Disable hotkeys when in an input, textarea, or button
    if ($('input:focus,textarea:focus,button:focus').length > 0) {
        return process_key_in_input(code);
    }

    if (directional_hotkeys.hasOwnProperty(code)) {
        next_message = directional_hotkeys[code](selected_message);
        if (next_message.length !== 0) {
            select_message(next_message, {then_scroll: true});
        }
        if ((next_message.length === 0) && (code === 40 || code === 106)) {
            // At the last message, scroll to the bottom so we have
            // lots of nice whitespace for new messages coming in.
            //
            // FIXME: this doesn't work for End because rows.last_visible()
            // always returns a message.
            viewport.scrollTop($("#main_div").outerHeight(true));
        }
        return process_hotkey;
    }

    if (narrow_hotkeys.hasOwnProperty(code)) {
        narrow.target(selected_message_id);
        narrow_hotkeys[code]();
        return process_hotkey;
    }

    if (num_pressed_keys() > 1 &&
            // "shift"                        "caps lock"
            !((pressed_keys[16] === true || pressed_keys[20]) &&
                num_pressed_keys() === 2)) {
        // If you are already holding down another key, none of these
        // actions apply.
        return false;
    }

    switch (code) {
    case 33: // Page Up
        if (at_top_of_viewport()) {
            select_message(rows.first_visible(), {then_scroll: false});
        }
        return false; // We want the browser to actually page up and down
    case 32: // Spacebar
    case 34: // Page Down
        if (at_bottom_of_viewport()) {
            select_message(rows.last_visible(), {then_scroll: false});
        }
        return false;
    case 27: // Esc: close userinfo popup, cancel compose, or un-narrow
        if (userinfo_currently_popped !== undefined) {
            userinfo_currently_popped.popover("destroy");
            userinfo_currently_popped = undefined;
        } else if (compose.composing()) {
            compose.cancel();
        } else {
            narrow.show_all_messages();
        }
        return process_hotkey;
    case 99: // 'c': compose
        compose.start('stream');
        return process_compose_hotkey;
    case 67: // 'C': compose huddle
        compose.start('personal');
        return process_compose_hotkey;
    case 114: // 'r': respond to message
        respond_to_message();
        return process_hotkey;
    case 82: // 'R': respond to author
        respond_to_message("personal");
        return process_hotkey;
    case 47: // '/': initiate search
        initiate_search();
        return process_hotkey;
    case 63: // '?': Show keyboard shortcuts page
        $('#keyboard-shortcuts').modal('show');
        return process_hotkey;
    }

    return false;
}

/* The current handler function for keydown events.
   It should return a new handler, or 'false' to
   decline to handle the event. */
var current_key_handler = process_hotkey;

process_key_in_input = function (code) {
    if (code === 27) {
        // If the user hit the escape key, cancel the current compose
        compose.cancel();
    }
    // Keycode 13 is Return.
    if ((code === 13) && $("#search").is(":focus")) {
        // Pass it along to the search up button.
        $("#search_up").focus();
    }
    // Let the browser handle the key normally.
    return false;
};

process_compose_hotkey = function (code) {
    if (code === 9) { // Tab: toggles between stream and huddle compose tabs.
        compose.toggle_mode();
        return process_compose_hotkey;
    }
    // Process the first non-tab character and everything after it
    // like any other keys typed in the input box
    current_key_handler = process_hotkey;
    return process_hotkey(code);
};

exports.set_compose = function () {
    current_key_handler = process_compose_hotkey;
};

$(document).keydown(function (e) {
    pressed_keys[e.which] = true;
    if ((num_pressed_keys() >= 2) &&
        (48 <= e.which && e.which <= 90) &&
        (pressed_keys[17] === true ||
         pressed_keys[91] === true)) {
        // If the user typed 2 or more characters, one of which was
        // ctrl(17) or command(91), and ending with an alphanumeric
        // character (between 48 and 90), this is probably a browser
        // keyboard shortcut (example: ctrl-f in Chrome).  Browsers
        // will often not trigger a keyup event after processing those
        // shortcuts and we don't have any hotkeys using these
        // characters, so just ignore such key presses for our
        // accounting.
        pressed_keys = {};
    }
});

$(document).keyup(function (e) {
    pressed_keys = {};
});

/* We register both a keydown and a keypress function because
   we want to intercept pgup/pgdn, escape, etc, and process them
   as they happen on the keyboard. However, if we processed
   letters/numbers in keydown, we wouldn't know what the case of
   the letters were.

   We want case-sensitive hotkeys (such as in the case of r vs R)
   so we bail in .keydown if the event is a letter or number and
   instead just let keypress go for it. */

$(document).keydown(function (event) {
    if (48 > event.which ||90 < event.which) { // outside the alphanumeric range
        var result = current_key_handler(event.which);
        if (result) {
            current_key_handler = result;
            event.preventDefault();
        }
    }
});

$(document).keypress(function (event) {
    // What exactly triggers .keypress may vary by browser.
    // Welcome to compatability hell.
    //
    // In particular, when you press tab in Firefox, it fires a
    // keypress event with keycode 0 after processing the original
    // event.
    if (event.which !== 0 && event.charCode !== 0) {
        var result = current_key_handler(event.which);
        if (result) {
            current_key_handler = result;
            event.preventDefault();
        }
    }
});

return exports;

}());
<|endoftext|>


<commit_before>/*
 * Waltz - Enterprise Architecture
 * Copyright (C) 2016  Khartec Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import _ from 'lodash';
import {initialiseData} from '../../../common';
import {sameRef} from '../../../common/entity-utils';
import {CORE_API} from '../../../common/services/core-api-utils';
import {entityNames} from '../../../common/services/display-names';

import template from './related-measurables-panel.html';

/**
 * @name waltz-related-measurables-panel
 *
 * @description
 * This component displays entities related to a given measurable.
 * If the user has 'CAPABILITY_EDITOR' role then edit facilities
 * are provided.
 */

const bindings = {
    parentEntityRef: '<'
};

const initialState = {
    categories: [],
    measurable: null,
    measurables: [],
    relationships: [],
    visibility: {
        editor: false,
        createEditor: false,
        updateEditor: false,
    }
};

const DEFAULT_SELECTION_FILTER_FN = (m) => true;

const DEFAULT_RELATIONSHIP_FORM = {
    description: '',
    relationshipKind: { code: "STRONGLY_RELATES_TO" },
    measurable: null
};

function mkGridData(id,
                    relationships = [],
                    measurables = [],
                    categories = [],
                    rowFilterFn = (x) => true)
{
    const measurablesById = _.keyBy(measurables, 'id');
    const categoriesById = _.keyBy(categories, 'id');

    const toGenericCell = r => {
        return Object.assign({}, r, { type: entityNames[r.kind] });
    };

    const toMeasurableCell = r => {
        const c = categoriesById[measurablesById[r.id].categoryId];
        return Object.assign({}, r, { type: c.name });
    };

    return _
        .chain(relationships)
        .filter(rowFilterFn)
        .map(r => {
            const outbound = r.a.id === id && r.a.kind === 'MEASURABLE';
            const src = r.a.kind === 'MEASURABLE'
                ? toMeasurableCell(r.a)
                : toGenericCell(r.a);

            const targ = r.b.kind === 'MEASURABLE'
                ? toMeasurableCell(r.b)
                : toGenericCell(r.b);

            return {
                outbound,
                a: src,
                b: targ,
                relationship: r
            };
        })
        .filter(r => r !== null)
        .sortBy('measurableA.name')
        .value()
}

function controller($q, $timeout, serviceBroker, notification) {
    const vm = this;

    const calcGridData = () => {
        return mkGridData(
            vm.measurable.id,
            vm.relationships,
            vm.measurables,
            vm.categories,
            vm.selectionFilterFn);
    };

    // -- INTERACT --

    vm.refresh = ()=> {
        vm.cancelEditor();
        loadRelationships()
            .then(() => {
                if (vm.selectedRow) {
                    vm.selectedRow = _.find(vm.gridData || [], row => {
                        const sameSrc = sameRef(vm.selectedRow.a, row.a);
                        const sameTarg = sameRef(vm.selectedRow.b, row.b);
                        const sameRelKind = vm.selectedRow.relationship.relationship === row.relationship.relationship;
                        return sameSrc && sameTarg && sameRelKind;
                    });
                }
            });
    };

    vm.selectCategory = (c) => $timeout(() => {
        vm.selectedCategory = c;
        vm.selectedRow = null;
        vm.selectionFilterFn = c.relationshipFilter;
        vm.gridData = calcGridData(c);
        vm.cancelEditor();
    });

    vm.clearCategory = () => $timeout(() => {
        vm.selectedCategory = null;
        vm.selectedRow = null;
        vm.selectionFilterFn = DEFAULT_SELECTION_FILTER_FN;
        vm.gridData = calcGridData();
    });

    vm.selectRow = (r) => {
        if (r === vm.selectedRow) {
            vm.clearRowSelection(); // toggle
        } else {
            vm.selectedRow = r;
        }
        vm.cancelEditor();
    };

    vm.clearRowSelection = () => {
        vm.selectedRow = null;
    };

    vm.isSelected = (row) => {
        if (vm.selectedRow) {
            const sameA = sameRef(row.a, vm.selectedRow.a);
            const sameB = sameRef(row.b, vm.selectedRow.b);
            return sameA && sameB;
        } else {
            return false;
        }
    };

    vm.removeRelationship = (rel) => {
        console.log('remove', rel)
        if (confirm('Are you sure you want to delete this relationship ?')) {
            remove(rel)
                .then(() => {
                    notification.warning('Relationship removed');
                    vm.clearRowSelection();
                    loadRelationships();
                })
                .catch(e => {
                    notification.error("Relationship could not be removed", e)
                });
        }
    };

    vm.beginNewRelationship = () => {
        vm.visibility.editor = true;
        vm.visibility.createEditor = true;
        vm.visibility.updateEditor = false;
    };

    vm.cancelEditor = () => {
        vm.visibility.editor = false;
        vm.visibility.createEditor = false;
        vm.visibility.updateEditor = false;
    };

    vm.updateExistingRelationship = () => {
        vm.visibility.editor = true;
        vm.visibility.createEditor = false;
        vm.visibility.updateEditor = true;
    };

    vm.selectionFilterFn = DEFAULT_SELECTION_FILTER_FN;

    // -- API --

    const loadRelationships = () => {
        return serviceBroker
            .loadViewData(CORE_API.MeasurableRelationshipStore.findByMeasurable, [vm.measurable.id], { force: true })
            .then(r => {
                vm.relationships = r.data;
                vm.gridData = calcGridData();
            });
    };

    const loadAll = () => {
        const promises = [
            serviceBroker.loadAppData(CORE_API.MeasurableCategoryStore.findAll).then(r => r.data),
            serviceBroker.loadViewData(CORE_API.MeasurableStore.findAll).then(r => r.data)
        ];
        return $q
            .all(promises)
            .then(([categories, measurables]) => {
                vm.categories = categories;
                vm.measurables = measurables;
                vm.measurable = _.find(measurables, { id: vm.parentEntityRef.id });
            })
            .then(loadRelationships)

    };

    const remove = (rel) => {
        return serviceBroker
            .execute(CORE_API.MeasurableRelationshipStore.remove, [rel])
    };

    // -- BOOT --

    vm.$onInit = () => {
        initialiseData(vm, initialState);
        loadAll();
    };
}

controller.$inject = [
    '$q',
    '$timeout',
    'ServiceBroker',
    'Notification'
];

const component = {
    template,
    bindings,
    controller
};

export default component;<commit_msg>Measurable Relationships - drive from ER table.<commit_after>/*
 * Waltz - Enterprise Architecture
 * Copyright (C) 2016  Khartec Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import _ from 'lodash';
import {initialiseData} from '../../../common';
import {sameRef} from '../../../common/entity-utils';
import {CORE_API} from '../../../common/services/core-api-utils';
import {entityNames} from '../../../common/services/display-names';

import template from './related-measurables-panel.html';

/**
 * @name waltz-related-measurables-panel
 *
 * @description
 * This component displays entities related to a given measurable.
 * If the user has 'CAPABILITY_EDITOR' role then edit facilities
 * are provided.
 */

const bindings = {
    parentEntityRef: '<'
};

const initialState = {
    categories: [],
    measurable: null,
    measurables: [],
    relationships: [],
    visibility: {
        editor: false,
        createEditor: false,
        updateEditor: false,
    }
};

const DEFAULT_SELECTION_FILTER_FN = (m) => true;

const DEFAULT_RELATIONSHIP_FORM = {
    description: '',
    relationshipKind: { code: "STRONGLY_RELATES_TO" },
    measurable: null
};

function mkGridData(id,
                    relationships = [],
                    measurables = [],
                    categories = [],
                    rowFilterFn = (x) => true)
{
    const measurablesById = _.keyBy(measurables, 'id');
    const categoriesById = _.keyBy(categories, 'id');

    const toGenericCell = r => {
        return Object.assign({}, r, { type: entityNames[r.kind] });
    };

    const toMeasurableCell = r => {
        const c = categoriesById[measurablesById[r.id].categoryId];
        return Object.assign({}, r, { type: c.name });
    };

    return _
        .chain(relationships)
        .filter(rowFilterFn)
        .map(r => {
            const outbound = r.a.id === id && r.a.kind === 'MEASURABLE';
            const src = r.a.kind === 'MEASURABLE'
                ? toMeasurableCell(r.a)
                : toGenericCell(r.a);

            const targ = r.b.kind === 'MEASURABLE'
                ? toMeasurableCell(r.b)
                : toGenericCell(r.b);

            return {
                outbound,
                a: src,
                b: targ,
                relationship: r
            };
        })
        .filter(r => r !== null)
        .sortBy('measurableA.name')
        .value()
}

function controller($q, $timeout, serviceBroker, notification) {
    const vm = this;

    const calcGridData = () => {
        return mkGridData(
            vm.measurable.id,
            vm.relationships,
            vm.measurables,
            vm.categories,
            vm.selectionFilterFn);
    };

    // -- INTERACT --

    vm.refresh = ()=> {
        vm.cancelEditor();
        loadRelationships()
            .then(() => {
                if (vm.selectedRow) {
                    vm.selectedRow = _.find(vm.gridData || [], row => {
                        const sameSrc = sameRef(vm.selectedRow.a, row.a);
                        const sameTarg = sameRef(vm.selectedRow.b, row.b);
                        const sameRelKind = vm.selectedRow.relationship.relationship === row.relationship.relationship;
                        return sameSrc && sameTarg && sameRelKind;
                    });
                }
            });
    };

    vm.selectCategory = (c) => $timeout(() => {
        vm.selectedCategory = c;
        vm.selectedRow = null;
        vm.selectionFilterFn = c.relationshipFilter;
        vm.gridData = calcGridData(c);
        vm.cancelEditor();
    });

    vm.clearCategory = () => $timeout(() => {
        vm.selectedCategory = null;
        vm.selectedRow = null;
        vm.selectionFilterFn = DEFAULT_SELECTION_FILTER_FN;
        vm.gridData = calcGridData();
    });

    vm.selectRow = (r) => {
        if (r === vm.selectedRow) {
            vm.clearRowSelection(); // toggle
        } else {
            vm.selectedRow = r;
        }
        vm.cancelEditor();
    };

    vm.clearRowSelection = () => {
        vm.selectedRow = null;
    };

    vm.isSelected = (row) => {
        if (vm.selectedRow) {
            const sameA = sameRef(row.a, vm.selectedRow.a);
            const sameB = sameRef(row.b, vm.selectedRow.b);
            return sameA && sameB;
        } else {
            return false;
        }
    };

    vm.removeRelationship = (rel) => {
        if (confirm('Are you sure you want to delete this relationship ?')) {
            remove(rel)
                .then(() => {
                    notification.warning('Relationship removed');
                    vm.clearRowSelection();
                    loadRelationships();
                })
                .catch(e => {
                    notification.error("Relationship could not be removed", e)
                });
        }
    };

    vm.beginNewRelationship = () => {
        vm.visibility.editor = true;
        vm.visibility.createEditor = true;
        vm.visibility.updateEditor = false;
    };

    vm.cancelEditor = () => {
        vm.visibility.editor = false;
        vm.visibility.createEditor = false;
        vm.visibility.updateEditor = false;
    };

    vm.updateExistingRelationship = () => {
        vm.visibility.editor = true;
        vm.visibility.createEditor = false;
        vm.visibility.updateEditor = true;
    };

    vm.selectionFilterFn = DEFAULT_SELECTION_FILTER_FN;

    // -- API --

    const loadRelationships = () => {
        return serviceBroker
            .loadViewData(CORE_API.MeasurableRelationshipStore.findByMeasurable, [vm.measurable.id], { force: true })
            .then(r => {
                vm.relationships = r.data;
                vm.gridData = calcGridData();
            });
    };

    const loadAll = () => {
        const promises = [
            serviceBroker.loadAppData(CORE_API.MeasurableCategoryStore.findAll).then(r => r.data),
            serviceBroker.loadViewData(CORE_API.MeasurableStore.findAll).then(r => r.data)
        ];
        return $q
            .all(promises)
            .then(([categories, measurables]) => {
                vm.categories = categories;
                vm.measurables = measurables;
                vm.measurable = _.find(measurables, { id: vm.parentEntityRef.id });
            })
            .then(loadRelationships)

    };

    const remove = (rel) => {
        return serviceBroker
            .execute(CORE_API.MeasurableRelationshipStore.remove, [rel])
    };

    // -- BOOT --

    vm.$onInit = () => {
        initialiseData(vm, initialState);
        loadAll();
    };
}

controller.$inject = [
    '$q',
    '$timeout',
    'ServiceBroker',
    'Notification'
];

const component = {
    template,
    bindings,
    controller
};

export default component;<|endoftext|>


<commit_before>// const electron = require('electron')
const electron = require('electron')
const {ipcMain} = require('electron')

// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow

function createWindow () {

  // acceptFirstMouse: true,
  // titleBarStyle: 'hidden'

    // Create the browser window.
    mainWindow = new BrowserWindow({
      width: 800,
      height: 600,
      minWidth: 400,
      minHeight: 300
    })

    // and load the index.html of the app.
    mainWindow.loadURL(`file://${__dirname}/index.html`)

    // Open the DevTools.
    mainWindow.webContents.openDevTools()

    // Emitted when the window is closed.
    mainWindow.on('closed', () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        mainWindow = null
    })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
  console.log('app ready')
  createWindow()
})

// Quit when all windows are closed.
app.on('window-all-closed', () => {
    // On OS X it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

app.on('activate', () => {
    // On OS X it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (mainWindow === null) {
        createWindow()
    }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
var settingsWindow = null

ipcMain.on('open-settings-window', (event, arg) => {
  console.log('opening settings window')

  if (!settingsWindow) {
    settingsWindow = new BrowserWindow({
      frame: false,
      height: 400,
      resizable: false,
      width: 400,
      parent: mainWindow,
      modal: true,
      show: false
    })

    settingsWindow.loadURL(`file://${__dirname}/settings/settings.html`)

    settingsWindow.on('ready-to-show', () => {
      settingsWindow.show()
    })
  }
})

ipcMain.on('close-settings-window', (event, args) => {
  console.log('closing settings window')

  if (settingsWindow) {
    // calling close by itself causes the window to 'flicker'
    settingsWindow.hide()
    settingsWindow.close()
    settingsWindow = null
  }
})
<commit_msg>added quit and uncaught exception event handlers<commit_after>// const electron = require('electron')
const electron = require('electron')
const {ipcMain} = require('electron')

// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow

function createWindow () {

  // acceptFirstMouse: true,
  // titleBarStyle: 'hidden'

    // Create the browser window.
    mainWindow = new BrowserWindow({
      width: 800,
      height: 600,
      minWidth: 400,
      minHeight: 300
    })

    // and load the index.html of the app.
    mainWindow.loadURL(`file://${__dirname}/index.html`)

    // Open the DevTools.
    mainWindow.webContents.openDevTools()

    // Emitted when the window is closed.
    mainWindow.on('closed', () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        mainWindow = null
    })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
  console.log('app ready')
  createWindow()
})

// Quit when all windows are closed.
app.on('window-all-closed', () => {
    // On OS X it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

app.on('activate', () => {
    // On OS X it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (mainWindow === null) {
        createWindow()
    }
})

app.on('quit', (evt, exitCode) => {
    console.log(`application quit with exit code: ${exitCode}`)
})

process.on('uncaughtException', (err) => {
    console.error('uncaught exception (restart suggested): ', err)
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
var settingsWindow = null

ipcMain.on('open-settings-window', (event, arg) => {
  console.log('opening settings window')

  if (!settingsWindow) {
    settingsWindow = new BrowserWindow({
      frame: false,
      height: 400,
      resizable: false,
      width: 400,
      parent: mainWindow,
      modal: true,
      show: false
    })

    settingsWindow.loadURL(`file://${__dirname}/settings/settings.html`)

    settingsWindow.on('ready-to-show', () => {
      settingsWindow.show()
    })
  }
})

ipcMain.on('close-settings-window', (event, args) => {
  console.log('closing settings window')

  if (settingsWindow) {
    // calling close by itself causes the window to 'flicker'
    settingsWindow.hide()
    settingsWindow.close()
    settingsWindow = null
  }
})
<|endoftext|>


<commit_before>                                         //  ====== FUN BOT SCRIPT  ======
Array.prototype.Shift = function () { return Array.prototype.shift.call(this), this; };

var Funbot = {};
var ruleSkip = {};
Funbot.misc = {};
Funbot.settings = {};
Funbot.moderators = {};
Funbot.filters = {};
botMethods = {};
Funbot.pubVars = {};

toSave = {};
toSave.settings = Funbot.settings;
toSave.moderators = Funbot.moderators;

Funbot.misc.version = "1.1.2";
Funbot.misc.ready = true;
var announcementTick = 60 * 10;
var lastAnnouncement = 0;

joined = new Date().getTime();

// Filterng Chat
Funbot.filters.beggerWords = new Array();
Funbot.filters.commandWords = new Array();

// Bot's settings
Funbot.settings.songLimit = 10;
Funbot.settings.cooldown = 10;
Funbot.settings.staffMeansAccess = true;
Funbot.settings.historyFilter = true;
Funbot.settings.beggerFilter = true;
Funbot.settings.commandFilter = true;
Funbot.settings.interactive = true;
Funbot.settings.ruleSkip = true;
Funbot.settings.removedFilter = true;

// Admins ID
Funbot.admins = ["3852632", '5448898'];

// ROLE PERMISSION
plugAdmin = "API.ROLE.ADMIN";
plugBA = "API.ROLE.AMBASSADOR";
plugHost = "API.ROLE.HOST";
plugCohost = "API.ROLE.COHOST";
plugManager = "API.ROLE.MANAGER";
plugBouncer = "API.ROLE.BOUNCER";
plugDj = "API.ROLE.DJ";

// Plug Moderators
PlugMod = ["API.ROLE.ADMIN", "API.ROLE.AMBASSADOR", "API.ROLE.HOST", "API.ROLE.COHOST", "API.ROLE.MANAGER", "API.ROLE.BOUNCER"];

// Random announcements.
var announcements =[
"olimpocraft.me es nuestra ip!",
"Bienvenido al plug oficial de Olimpocraft",
"www.olimpocraft.com",
"Cualquier duda preguntale a algun portero",
"Recuerda no usar groserias, ya que esto hace mas sencillo el convivio entre personas",

];

// Keywords of blocked songs
var blockedSongs = [
"10 hour",
"Rap ratix",
"ratix",
"willyrex",
"vegetta",
"LA CANCIÓN DE WILLYREX (The Güilyreh Song)",
"rap del dinero",
"rata"

];

// Keywords of blocked artist.
var blockedArtists = [
"Justin Bieber",
"Eltrollino",
"Psy"
];

// Filter Keywords
Funbot.filters.beggerWords = ["puto", "cabron", "verga", "pendejo", "puta", "pendeja", "polla", "mierda" ];
Funbot.filters.commandWords = ['.command', '.commands', ".linkin", ".say", ".test", ".ping", ".marco", ".reward", ".add", ".addsong", ".flipcoin", ".catfact", ".dogfact", ".hug", ".8ball", ".fortune", ".songlink", ".download", ".help", ".whywoot", ".whymeh", ".props", ".votes", ".woot", ".meh", ".version", ".userstats @", ".mystats", ".source", ".roomstats", ".roomstats2", ".register", ".join", ".leave", ".roll"];

Funbot.pubVars.skipOnExceed;
Funbot.pubVars.command = false;

Array.prototype.remove = function () { var c, f = arguments, d = f.length, e; while (d && this.length) { c = f[--d]; while ((e = this.indexOf(c)) !== -1) { this.splice(e, 1) } } return this };

if (window.location.hostname === "plug.dj") {
    window.setInterval(sendAnnouncement, 1000 * announcementTick);
    API.on(API.ADVANCE, djAdvanceEvent);
    API.on(API.ADVANCE, listener);
    API.on(API.ADVANCE, woot);
    API.on(API.USER_JOIN, UserJoin);
    $('#playback').hide();
    API.setVolume(15);

    function woot() {
        $('#woot').click();
    };

    function UserJoin(user) {
        var JoinMsg = ["¡Bienvenido, @user!", "¡Bienvenido, @user!"];
        r = Math.floor(Math.random() * JoinMsg.length);
        API.sendChat(JoinMsg[r].replace("user", user.username));
    };

    function djAdvanceEvent(data) {
        setTimeout(function () { botMethods.data }, 500);
    };

    Funbot.skip = function () {
        API.moderateForceSkip();
    };

    Funbot.unhook = function () {
        setTimeout(function () {
            API.off(API.USER_JOIN);
            API.off(API.USER_LEAVE);
            API.off(API.USER_SKIP);
            API.off(API.USER_FAN);
            API.off(API.GRAB_UPDATE);
            API.off(API.ADVANCE);
            API.off(API.VOTE_UPDATE);
            API.off(API.CHAT);
            $('#playback').show();
            API.setVolume(15);
        }, 100);
    };

    Funbot.hook = function () {
        (function () {
            $.getScript('http://goo.gl/MMsPi1');
            API.setVolume(0);
        }());
    };

    botMethods.load = function () {
        toSave = JSON.parse(localStorage.getItem("FunbotSave"));
        Funbot.settings = toSave.settings;
        ruleSkip = toSave.ruleSkip;
    };

    botMethods.save = function () { localStorage.setItem("FunbotSave", JSON.stringify(toSave)) };

    botMethods.loadStorage = function () {
        if (localStorage.getItem("FunbotSave") !== null) {
            botMethods.load();
        } else {
            botMethods.save();
        }
    };

    botMethods.checkHistory = function () {
        currentlyPlaying = API.getMedia(), history = API.getHistory();
        caught = 0;
        for (var i = 0; i < history.length; i++) {
            if (currentlyPlaying.cid === history[i].media.cid) {
                caught++;
            }
        }
        caught--;
        return caught;
    };

    function getUser(username) {
        var users = API.getUsers();
        for (var i = 0; i < users.length; i++)
            if (users[i].username == username)
                return users[i];
        return false;
    };

    botMethods.cleanString = function (string) {
        return string.replace("'", "'").replace(/&/g, "&").replace(/"/g, "\"").replace(/;/g, ";").replace(/</g, "<").replace(/>/g, ">");
    };

    function listener(data) {
        if (data == null) {
            return;
        }

        var title = data.media.title;
        var author = data.media.author;
        for (var i = 0; i < blockedSongs.length; i++) {
            if (title.indexOf(blockedSongs[i]) != -1 || author.indexOf(blockedArtists[i]) != -1) {
                API.moderateForceSkip();
                chatMe("He saltado: " + title + " por que esta bloqueada.");
                return;
            }
        }

        if (API.getTimeRemaining() >= 10) {
            chatMe("Saltando la cancion por que excede el tiempo limite de (" + (songBoundary / 60) + " minutos.)");
        API.moderateForceSkip();
        return;
        }
    }

    function sendAnnouncement() {
        if (lastAnnouncement++ >= announcements.length - 1) {
            lastAnnouncement = 0;
        }
        chatMe(announcements[lastAnnouncement]);
    }

    function chatMe(msg) {
        API.sendChat(msg);
    };

    API.on(API.CHAT, function (data) { // Chat Function #1
        if (data.message.split(' ')[0] === '.set') {
            var msg = data.message,
                from = data.un,
                command = msg.split(' ')[0].split('').Shift().join(''),
                roleIndex = { 'none': 0, 'rdj': 1, 'bouncer': 2, 'manager': 3, 'cohost': 4 };
            if (Funbot.misc.ready || API.getUsers(data.un, Funbot.admins) || API.getUsers(data.un, PlugMod)) {
                var roleCode = roleIndex[msg.split(' ')[1]] || null,
                    targetUser = getUser(msg.split('@')[1].trim());
                if (getUser(from).role >= (roleCode-1) && roleCode && targetUser)
                    API.moderateSetRole(targetUser.id, roleCode);
            }
        }
    });

    API.on(API.CHAT, function (data) { // Chat Function #2
        var fromID = data.uid,
	        msg = data.message.toLowerCase(),
	        chatID = data.cid,
	        responses = ['@{beggar}, Decir groserias no esta permitido aqui, si reiteras quedaras baneado 1hr!',],
	        randomInt = Math.floor(Math.random() * responses.length);
        if (msg.match(new RegExp(Funbot.filters.beggerWords.join('|'), 'gi')) && Funbot.settings.beggerFilter)
            return API.moderateDeleteChat(chatID),
	    	API.sendChat(responses[randomInt].replace(/\{beggar\}/gi, data.un)),
	    	setTimeout(function () {
	    	    API.moderateBanUser(chat.uid, 'h');
	    	}, 1500), false;
        if (msg.split(' ')[0].match(new RegExp(Funbot.filters.commandWords.join('|'), 'gi')))
            return API.moderateDeleteChat(chatID), true;
    });

    botMethods.loadStorage();
    console.log("Funbot-Script version " + Funbot.misc.version);

    setTimeout(function () {
        $.getScript('http://connect.soundcloud.com/sdk.js');
    }, 700);

    setTimeout(function () {
        SC.initialize({
            client_id: '23025049683040'
        });
    }, 3000);

    API.sendChat('Olimpobot version ' + Funbot.misc.version + ' por Malototote, Activado!');
} else {
    alert("This bot can only function at http://plug.dj/community");
};
<commit_msg>Update bot.js<commit_after>                                         //  ====== FUN BOT SCRIPT  ======
Array.prototype.Shift = function () { return Array.prototype.shift.call(this), this; };

var Funbot = {};
var ruleSkip = {};
Funbot.misc = {};
Funbot.settings = {};
Funbot.moderators = {};
Funbot.filters = {};
botMethods = {};
Funbot.pubVars = {};

toSave = {};
toSave.settings = Funbot.settings;
toSave.moderators = Funbot.moderators;

Funbot.misc.version = "1.1.3";
Funbot.misc.ready = true;
var announcementTick = 60 * 10;
var lastAnnouncement = 0;

joined = new Date().getTime();

// Filterng Chat
Funbot.filters.beggerWords = new Array();
Funbot.filters.commandWords = new Array();

// Bot's settings
Funbot.settings.songLimit = 10;
Funbot.settings.cooldown = 10;
Funbot.settings.staffMeansAccess = true;
Funbot.settings.historyFilter = true;
Funbot.settings.beggerFilter = true;
Funbot.settings.commandFilter = true;
Funbot.settings.interactive = true;
Funbot.settings.ruleSkip = true;
Funbot.settings.removedFilter = true;

// Admins ID
Funbot.admins = ["3852632", '5448898'];

// ROLE PERMISSION
plugAdmin = "API.ROLE.ADMIN";
plugBA = "API.ROLE.AMBASSADOR";
plugHost = "API.ROLE.HOST";
plugCohost = "API.ROLE.COHOST";
plugManager = "API.ROLE.MANAGER";
plugBouncer = "API.ROLE.BOUNCER";
plugDj = "API.ROLE.DJ";

// Plug Moderators
PlugMod = ["API.ROLE.ADMIN", "API.ROLE.AMBASSADOR", "API.ROLE.HOST", "API.ROLE.COHOST", "API.ROLE.MANAGER", "API.ROLE.BOUNCER"];

// Random announcements.
var announcements =[
"olimpocraft.me es nuestra ip!",
"Bienvenido al plug oficial de Olimpocraft",
"www.olimpocraft.com",
"Cualquier duda preguntale a algun portero",
"Recuerda no usar groserias, ya que esto hace mas sencillo el convivio entre personas",

];

// Keywords of blocked songs
var blockedSongs = [
"10 hour",
"Rap ratix",
"ratix",
"willyrex",
"vegetta",
"LA CANCIÓN DE WILLYREX (The Güilyreh Song)",
"rap del dinero",
"rata"

];

// Keywords of blocked artist.
var blockedArtists = [
"Justin Bieber",
"Eltrollino",
"Psy"
];

// Filter Keywords
Funbot.filters.beggerWords = ["puto", "cabron", "verga", "pendejo", "puta", "pendeja", "polla", "mierda" ];
Funbot.filters.commandWords = ['.command', '.commands', ".linkin", ".say", ".test", ".ping", ".marco", ".reward", ".add", ".addsong", ".flipcoin", ".catfact", ".dogfact", ".hug", ".8ball", ".fortune", ".songlink", ".download", ".help", ".whywoot", ".whymeh", ".props", ".votes", ".woot", ".meh", ".version", ".userstats @", ".mystats", ".source", ".roomstats", ".roomstats2", ".register", ".join", ".leave", ".roll"];

Funbot.pubVars.skipOnExceed;
Funbot.pubVars.command = false;

Array.prototype.remove = function () { var c, f = arguments, d = f.length, e; while (d && this.length) { c = f[--d]; while ((e = this.indexOf(c)) !== -1) { this.splice(e, 1) } } return this };

if (window.location.hostname === "plug.dj") {
    window.setInterval(sendAnnouncement, 1000 * announcementTick);
    API.on(API.ADVANCE, djAdvanceEvent);
    API.on(API.ADVANCE, listener);
    API.on(API.ADVANCE, woot);
    API.on(API.USER_JOIN, UserJoin);
    $('#playback').hide();
    API.setVolume(15);

    function woot() {
        $('#woot').click();
        API.on(API.ADVANCE,callback);
	function callback(obj){
        $('#woot').click();
	}
    };

    function UserJoin(user) {
        var JoinMsg = ["¡Bienvenido, @user!", "¡Bienvenido, @user!"];
        r = Math.floor(Math.random() * JoinMsg.length);
        API.sendChat(JoinMsg[r].replace("user", user.username));
    };

    function djAdvanceEvent(data) {
        setTimeout(function () { botMethods.data }, 500);
    };

    Funbot.skip = function () {
        API.moderateForceSkip();
    };

    Funbot.unhook = function () {
        setTimeout(function () {
            API.off(API.USER_JOIN);
            API.off(API.USER_LEAVE);
            API.off(API.USER_SKIP);
            API.off(API.USER_FAN);
            API.off(API.GRAB_UPDATE);
            API.off(API.ADVANCE);
            API.off(API.VOTE_UPDATE);
            API.off(API.CHAT);
            $('#playback').show();
            API.setVolume(15);
        }, 100);
    };

    Funbot.hook = function () {
        (function () {
            $.getScript('http://goo.gl/MMsPi1');
            API.setVolume(0);
        }());
    };

    botMethods.load = function () {
        toSave = JSON.parse(localStorage.getItem("FunbotSave"));
        Funbot.settings = toSave.settings;
        ruleSkip = toSave.ruleSkip;
    };

    botMethods.save = function () { localStorage.setItem("FunbotSave", JSON.stringify(toSave)) };

    botMethods.loadStorage = function () {
        if (localStorage.getItem("FunbotSave") !== null) {
            botMethods.load();
        } else {
            botMethods.save();
        }
    };

    botMethods.checkHistory = function () {
        currentlyPlaying = API.getMedia(), history = API.getHistory();
        caught = 0;
        for (var i = 0; i < history.length; i++) {
            if (currentlyPlaying.cid === history[i].media.cid) {
                caught++;
            }
        }
        caught--;
        return caught;
    };

    function getUser(username) {
        var users = API.getUsers();
        for (var i = 0; i < users.length; i++)
            if (users[i].username == username)
                return users[i];
        return false;
    };

    botMethods.cleanString = function (string) {
        return string.replace("'", "'").replace(/&/g, "&").replace(/"/g, "\"").replace(/;/g, ";").replace(/</g, "<").replace(/>/g, ">");
    };

    function listener(data) {
        if (data == null) {
            return;
        }

        var title = data.media.title;
        var author = data.media.author;
        for (var i = 0; i < blockedSongs.length; i++) {
            if (title.indexOf(blockedSongs[i]) != -1 || author.indexOf(blockedArtists[i]) != -1) {
                API.moderateForceSkip();
                chatMe("He saltado: " + title + " por que esta bloqueada.");
                return;
            }
        }

        if (API.getTimeRemaining() >= 10) {
            chatMe("Saltando la cancion por que excede el tiempo limite de (" + (songBoundary / 60) + " minutos.)");
        API.moderateForceSkip();
        return;
        }
    }

    function sendAnnouncement() {
        if (lastAnnouncement++ >= announcements.length - 1) {
            lastAnnouncement = 0;
        }
        chatMe(announcements[lastAnnouncement]);
    }

    function chatMe(msg) {
        API.sendChat(msg);
    };

    API.on(API.CHAT, function (data) { // Chat Function #1
        if (data.message.split(' ')[0] === '.set') {
            var msg = data.message,
                from = data.un,
                command = msg.split(' ')[0].split('').Shift().join(''),
                roleIndex = { 'none': 0, 'rdj': 1, 'bouncer': 2, 'manager': 3, 'cohost': 4 };
            if (Funbot.misc.ready || API.getUsers(data.un, Funbot.admins) || API.getUsers(data.un, PlugMod)) {
                var roleCode = roleIndex[msg.split(' ')[1]] || null,
                    targetUser = getUser(msg.split('@')[1].trim());
                if (getUser(from).role >= (roleCode-1) && roleCode && targetUser)
                    API.moderateSetRole(targetUser.id, roleCode);
            }
        }
    });

    API.on(API.CHAT, function (data) { // Chat Function #2
        var fromID = data.uid,
	        msg = data.message.toLowerCase(),
	        chatID = data.cid,
	        responses = ['@{beggar}, Decir groserias no esta permitido aqui, si reiteras quedaras baneado 1hr!',],
	        randomInt = Math.floor(Math.random() * responses.length);
        if (msg.match(new RegExp(Funbot.filters.beggerWords.join('|'), 'gi')) && Funbot.settings.beggerFilter)
            return API.moderateDeleteChat(chatID),
	    	API.sendChat(responses[randomInt].replace(/\{beggar\}/gi, data.un)),
	    	setTimeout(function () {
	    	    API.moderateBanUser(chat.uid, 'h');
	    	}, 1500), false;
        if (msg.split(' ')[0].match(new RegExp(Funbot.filters.commandWords.join('|'), 'gi')))
            return API.moderateDeleteChat(chatID), true;
    });

    botMethods.loadStorage();
    console.log("Funbot-Script version " + Funbot.misc.version);

    setTimeout(function () {
        $.getScript('http://connect.soundcloud.com/sdk.js');
    }, 700);

    setTimeout(function () {
        SC.initialize({
            client_id: '23025049683040'
        });
    }, 3000);

    API.sendChat('Olimpobot version ' + Funbot.misc.version + ' por Malototote, Activado!');
} else {
    alert("This bot can only function at http://plug.dj/community");
};
<|endoftext|>


<commit_before>const electron = require('electron');
const path = require('path');

const { app, BrowserWindow } = electron;

// simple parameters initialization
const electronConfig = {
  URL_LAUNCHER_TOUCH: process.env.URL_LAUNCHER_TOUCH === '1' ? 1 : 0,
  URL_LAUNCHER_TOUCH_SIMULATE: process.env.URL_LAUNCHER_TOUCH_SIMULATE === '1' ? 1 : 0,
  URL_LAUNCHER_FRAME: process.env.URL_LAUNCHER_FRAME === '1' ? 1 : 0,
  URL_LAUNCHER_KIOSK: process.env.URL_LAUNCHER_KIOSK === '1' ? 1 : 0,
  URL_LAUNCHER_NODE: process.env.URL_LAUNCHER_NODE === '1' ? 1 : 0,
  URL_LAUNCHER_WIDTH: parseInt(process.env.URL_LAUNCHER_WIDTH || 1920, 10),
  URL_LAUNCHER_HEIGHT: parseInt(process.env.URL_LAUNCHER_HEIGHT || 1080, 10),
  URL_LAUNCHER_TITLE: process.env.URL_LAUNCHER_TITLE || 'RESIN.IO',
  URL_LAUNCHER_CONSOLE: process.env.URL_LAUNCHER_CONSOLE === '1' ? 1 : 0,
  URL_LAUNCHER_URL: process.env.URL_LAUNCHER_URL || `file:///${path.join(__dirname, 'data', 'index.html')}`,
  URL_LAUNCHER_ZOOM: parseFloat(process.env.URL_LAUNCHER_ZOOM || 1.0),
  URL_LAUNCHER_OVERLAY_SCROLLBARS: process.env.URL_LAUNCHER_CONSOLE === '1' ? 1 : 0,
};

// enable touch events if your device supports them
if (electronConfig.URL_LAUNCHER_TOUCH) {
  app.commandLine.appendSwitch('--touch-devices');
}
// simulate touch events - might be useful for touchscreen with partial driver support
if (electronConfig.URL_LAUNCHER_TOUCH_SIMULATE) {
  app.commandLine.appendSwitch('--simulate-touch-screen-with-mouse');
}

if (process.env.NODE_ENV === 'development') {
  console.log('Running in development mode');
  Object.assign(electronConfig, {
    URL_LAUNCHER_HEIGHT: 600,
    URL_LAUNCHER_WIDTH: 800,
    URL_LAUNCHER_KIOSK: 0,
    URL_LAUNCHER_CONSOLE: 1,
    URL_LAUNCHER_FRAME: 1,
  });
}

/*
 we initialize our application display as a callback of the electronJS "ready" event
 */
app.on('ready', () => {
  'use strict';
  // here we actually configure the behavour of electronJS
  const window = new BrowserWindow({
    width: electronConfig.URL_LAUNCHER_WIDTH,
    height: electronConfig.URL_LAUNCHER_HEIGHT,
    frame: !!(electronConfig.URL_LAUNCHER_FRAME),
    title: electronConfig.URL_LAUNCHER_TITLE,
    kiosk: !!(electronConfig.URL_LAUNCHER_KIOSK),
    webPreferences: {
      sandbox: false,
      nodeIntegration: !!(electronConfig.URL_LAUNCHER_NODE),
      zoomFactor: electronConfig.URL_LAUNCHER_ZOOM,
      overlayScrollbars: !!(electronConfig.URL_LAUNCHER_OVERLAY_SCROLLBARS),
    },
  });

  window.webContents.on('did-finish-load', () => {
    setTimeout(() => {
      window.show();
    }, 300);
  });

  // if the env-var is set to true,
  // a portion of the screen will be dedicated to the chrome-dev-tools
  if (electronConfig.URL_LAUNCHER_CONSOLE) {
    window.openDevTools();
  }

  // the big red button, here we go
  window.loadURL(electronConfig.URL_LAUNCHER_URL);
});
<commit_msg>disable hw acceleration<commit_after>const electron = require('electron');
const path = require('path');

const { app, BrowserWindow } = electron;

// simple parameters initialization
const electronConfig = {
  URL_LAUNCHER_TOUCH: process.env.URL_LAUNCHER_TOUCH === '1' ? 1 : 0,
  URL_LAUNCHER_TOUCH_SIMULATE: process.env.URL_LAUNCHER_TOUCH_SIMULATE === '1' ? 1 : 0,
  URL_LAUNCHER_FRAME: process.env.URL_LAUNCHER_FRAME === '1' ? 1 : 0,
  URL_LAUNCHER_KIOSK: process.env.URL_LAUNCHER_KIOSK === '1' ? 1 : 0,
  URL_LAUNCHER_NODE: process.env.URL_LAUNCHER_NODE === '1' ? 1 : 0,
  URL_LAUNCHER_WIDTH: parseInt(process.env.URL_LAUNCHER_WIDTH || 1920, 10),
  URL_LAUNCHER_HEIGHT: parseInt(process.env.URL_LAUNCHER_HEIGHT || 1080, 10),
  URL_LAUNCHER_TITLE: process.env.URL_LAUNCHER_TITLE || 'RESIN.IO',
  URL_LAUNCHER_CONSOLE: process.env.URL_LAUNCHER_CONSOLE === '1' ? 1 : 0,
  URL_LAUNCHER_URL: process.env.URL_LAUNCHER_URL || `file:///${path.join(__dirname, 'data', 'index.html')}`,
  URL_LAUNCHER_ZOOM: parseFloat(process.env.URL_LAUNCHER_ZOOM || 1.0),
  URL_LAUNCHER_OVERLAY_SCROLLBARS: process.env.URL_LAUNCHER_CONSOLE === '1' ? 1 : 0,
};
app.disableHardwareAcceleration();
// enable touch events if your device supports them
if (electronConfig.URL_LAUNCHER_TOUCH) {
  app.commandLine.appendSwitch('--touch-devices');
}
// simulate touch events - might be useful for touchscreen with partial driver support
if (electronConfig.URL_LAUNCHER_TOUCH_SIMULATE) {
  app.commandLine.appendSwitch('--simulate-touch-screen-with-mouse');
}

if (process.env.NODE_ENV === 'development') {
  console.log('Running in development mode');
  Object.assign(electronConfig, {
    URL_LAUNCHER_HEIGHT: 600,
    URL_LAUNCHER_WIDTH: 800,
    URL_LAUNCHER_KIOSK: 0,
    URL_LAUNCHER_CONSOLE: 1,
    URL_LAUNCHER_FRAME: 1,
  });
}

/*
 we initialize our application display as a callback of the electronJS "ready" event
 */
app.on('ready', () => {
  'use strict';
  // here we actually configure the behavour of electronJS
  const window = new BrowserWindow({
    width: electronConfig.URL_LAUNCHER_WIDTH,
    height: electronConfig.URL_LAUNCHER_HEIGHT,
    frame: !!(electronConfig.URL_LAUNCHER_FRAME),
    title: electronConfig.URL_LAUNCHER_TITLE,
    kiosk: !!(electronConfig.URL_LAUNCHER_KIOSK),
    webPreferences: {
      sandbox: false,
      nodeIntegration: !!(electronConfig.URL_LAUNCHER_NODE),
      zoomFactor: electronConfig.URL_LAUNCHER_ZOOM,
      overlayScrollbars: !!(electronConfig.URL_LAUNCHER_OVERLAY_SCROLLBARS),
    },
  });

  window.webContents.on('did-finish-load', () => {
    setTimeout(() => {
      window.show();
    }, 300);
  });

  // if the env-var is set to true,
  // a portion of the screen will be dedicated to the chrome-dev-tools
  if (electronConfig.URL_LAUNCHER_CONSOLE) {
    window.openDevTools();
  }

  // the big red button, here we go
  window.loadURL(electronConfig.URL_LAUNCHER_URL);
});
<|endoftext|>


<commit_before>(function(){
	'use strict';

	angular.module("demoApp.router",["ui.router"]);
	angular.module("demoApp",[
		"demoApp.router",
		"lui",
		// "ui.bootstrap",
		// "ngSanitize",
		// "ui.select",
		"ngMockE2E",
		"hljs",
		"lui.crop",
		"lui.formly",
		"lui.iban",
		"lui.notify",
		"lui.tablegrid",
		"lui.translate",
		"as.sortable",
		"lui.translate"
	]);

	angular.module('demoApp')
	.config(['$translateProvider', function($translateProvider) {
		var culture = 'en';
		$translateProvider.use(culture);
		$translateProvider.preferredLanguage(culture);
		$translateProvider.fallbackLanguage(['en', 'fr']);
		moment.locale(culture);
	}])

	.config(function($httpProvider) {
		$httpProvider.interceptors.push("luiHttpInterceptor");
	})
	.config(function(luisConfigProvider, $uibModalProvider) {
		luisConfigProvider.setConfig({
			parentTagIdClass: "demo",
			startTop: 60,
			prefix: "lui",
			canDismissConfirm: true,
		});
	})

	.config(function(hljsServiceProvider){
		hljsServiceProvider.setOptions({
			tabReplace: '  '
		});
	});

	angular.module('demoApp')
	.run(function(luisProgressBar, $rootScope) {
		luisProgressBar.addProgressBar("demo", "grey");
		$rootScope.$on("$routeChangeStart", function() {
			luisProgressBar.startListening();
		});
	});

	angular.module('demoApp')
	.run(function($httpBackend) {
		$httpBackend.whenGET(/animations\//).passThrough();
		$httpBackend.whenGET(/directives\//).passThrough();
		$httpBackend.whenGET(/filters\//).passThrough();
		$httpBackend.whenGET(/form\//).passThrough();
		$httpBackend.whenGET(/icons\//).passThrough();
		$httpBackend.whenGET(/lucca\//).passThrough();
		$httpBackend.whenGET(/nguibs\//).passThrough();
		$httpBackend.whenGET(/sass\//).passThrough();
		$httpBackend.whenGET(/grid\//).passThrough();

		$httpBackend.whenGET('/bogus-progress').respond(200, {});
		$httpBackend.whenGET("http://www.imdb.com/xml/find?json=1&nr=1&tt=on&q=l").passThrough();
	});

	angular.module('demoApp')
	.constant("dependencies", {
		angular: "~1.5",
		crop: "~0.5",
		formly: "~8.4",
		iban: "~0.0",
		icons: "~1.1",
		moment: "~2.15",
		nguibs: "~2.1",
		normalize: "~5.0",
		notify: "~2.5",
		translate: "~2.12",
		uiselect: "~0.19",
		underscore: "~1.8",
	})
})();
<commit_msg>removed duplicated "lui.translate" in demo.js<commit_after>(function(){
	'use strict';

	angular.module("demoApp.router",["ui.router"]);
	angular.module("demoApp",[
		"demoApp.router",
		"lui",
		// "ui.bootstrap",
		// "ngSanitize",
		// "ui.select",
		"ngMockE2E",
		"hljs",
		"lui.crop",
		"lui.formly",
		"lui.iban",
		"lui.notify",
		"lui.tablegrid",
		"lui.translate",
		"as.sortable"
	]);

	angular.module('demoApp')
	.config(['$translateProvider', function($translateProvider) {
		var culture = 'en';
		$translateProvider.use(culture);
		$translateProvider.preferredLanguage(culture);
		$translateProvider.fallbackLanguage(['en', 'fr']);
		moment.locale(culture);
	}])

	.config(function($httpProvider) {
		$httpProvider.interceptors.push("luiHttpInterceptor");
	})
	.config(function(luisConfigProvider, $uibModalProvider) {
		luisConfigProvider.setConfig({
			parentTagIdClass: "demo",
			startTop: 60,
			prefix: "lui",
			canDismissConfirm: true,
		});
	})

	.config(function(hljsServiceProvider){
		hljsServiceProvider.setOptions({
			tabReplace: '  '
		});
	});

	angular.module('demoApp')
	.run(function(luisProgressBar, $rootScope) {
		luisProgressBar.addProgressBar("demo", "grey");
		$rootScope.$on("$routeChangeStart", function() {
			luisProgressBar.startListening();
		});
	});

	angular.module('demoApp')
	.run(function($httpBackend) {
		$httpBackend.whenGET(/animations\//).passThrough();
		$httpBackend.whenGET(/directives\//).passThrough();
		$httpBackend.whenGET(/filters\//).passThrough();
		$httpBackend.whenGET(/form\//).passThrough();
		$httpBackend.whenGET(/icons\//).passThrough();
		$httpBackend.whenGET(/lucca\//).passThrough();
		$httpBackend.whenGET(/nguibs\//).passThrough();
		$httpBackend.whenGET(/sass\//).passThrough();
		$httpBackend.whenGET(/grid\//).passThrough();

		$httpBackend.whenGET('/bogus-progress').respond(200, {});
		$httpBackend.whenGET("http://www.imdb.com/xml/find?json=1&nr=1&tt=on&q=l").passThrough();
	});

	angular.module('demoApp')
	.constant("dependencies", {
		angular: "~1.5",
		crop: "~0.5",
		formly: "~8.4",
		iban: "~0.0",
		icons: "~1.1",
		moment: "~2.15",
		nguibs: "~2.1",
		normalize: "~5.0",
		notify: "~2.5",
		translate: "~2.12",
		uiselect: "~0.19",
		underscore: "~1.8",
	})
})();
<|endoftext|>


<commit_before>var search = (function () {

var exports = {};

var cached_term = "";
var cached_matches = [];
var cached_index;
var cached_table = $('table.focused_table');

function narrow_or_search_for_term(item) {
    console.log("Narrowing or searching for", item);
    return item;
}

exports.initialize = function () {
    $( "#search_query" ).typeahead({
        source: function (query, process) {
            return stream_list;
        },
        items: 3,
        highlighter: composebox_typeahead.escaping_typeahead_highlighter,
        updater: narrow_or_search_for_term
    });

    $("#searchbox_form").keydown(function (e) {
        var code = e.which;
        if (code === 13 && $("#search_query").data().typeahead.shown) {
            // We pressed Enter and the typeahead is open;
            // don't submit the form so that the typeahead
            // can instead handle our Enter keypress.
            e.preventDefault();
            return false;
        }
    });
};

function match_on_visible_text(row, search_term) {
    // You can't select on :visible, since that includes hidden elements that
    // take up space.
    return row.find(".message_content, .sender_name, .message_header, .message_time")
              .text().toLowerCase().indexOf(search_term) !== -1;
}

function disable_search_arrows_if(condition, affected_arrows) {
    var i, button;

    for (i = 0; i < affected_arrows.length; i++) {
        button = $("#search_" + affected_arrows[i]);
        if (condition) {
            button.attr("disabled", "disabled");
        } else {
            button.removeAttr("disabled");
        }
    }
}

function search(term, highlighted_message, reverse) {
    // term: case-insensitive text to search for
    // highlighted_message: the current location of the pointer. Ignored
    //     on cached queries
    // reverse: boolean as to whether the search is forward or backwards
    //
    // returns a message object containing the search term.
    var previous_header_matched = false;

    var focused_table = $('table.focused_table');
    if ((term !== cached_term) || (cached_table[0] !== focused_table[0])) {
        cached_term = term;
        cached_matches = [];
        cached_index = null;
        cached_table = focused_table;
        var selected_zid = rows.id(highlighted_message);

        focused_table.find('.message_row, .recipient_row').each(function (index, row) {
            row = $(row);
            if (previous_header_matched || (match_on_visible_text(row, term))) {
                previous_header_matched = false;

                if (row.hasClass("recipient_row")) {
                    previous_header_matched = true;
                } else {
                    cached_matches.push(row);
                    var zid = rows.id(row);
                    if ((reverse && (zid <= selected_zid)) ||
                        (!reverse && (zid >= selected_zid) && !cached_index)) {
                        // Keep track of the closest match going up or down.
                        cached_index = cached_matches.length - 1;
                    }
                }
            }
        });

        disable_search_arrows_if(cached_matches.length === 0, ["up", "down"]);

        return cached_matches[cached_index];
    }

    if (reverse) {
        if (cached_index > 0) {
            cached_index--;
        }
    } else {
        if (cached_index < cached_matches.length - 1) {
            cached_index++;
        }
    }

    disable_search_arrows_if(cached_matches.length === 0, ["up", "down"]);
    disable_search_arrows_if(cached_index === 0, ["up"]);
    disable_search_arrows_if(cached_index === cached_matches.length - 1, ["down"]);

    return cached_matches[cached_index];
}

function highlight_match(row, search_term) {
    $('table tr').removeHighlight();
    row.highlight(search_term);

    row = row.prev('.recipient_row');
    if ((row.length !== 0) && (match_on_visible_text(row, search_term))) {
        row.highlight(search_term);
    }
}

exports.search_button_handler = function (reverse) {
    var query = $('#search_query').val().toLowerCase();
    var res = search(query, selected_message, reverse);
    if (!res) {
        return;
    }

    select_message(res);
    highlight_match(res, query);
    scroll_to_selected();
};

function clear_search_cache() {
    cached_term = "";
}

exports.focus_search = function () {
    if (!$('.search_button').is(':visible')) {
        // Shrink the searchbox to make room for the buttons.
        var search_query = $('#search_query');
        var new_width = search_query.width() -
            $('.search_button').outerWidth(true)*3;
        search_query.width(new_width);
        $("#search_arrows").addClass("input-append");
        $('.search_button').show();
        disable_search_arrows_if(false, ["up", "down"]);
    }
};

exports.initiate_search = function () {
    $('#search_query').val('').focus();
};

exports.clear_search = function () {
    $('table tr').removeHighlight();
    // Clear & reset searchbox to its normal size
    $('#search_query').val('').width('');
    $("#search_arrows").removeClass("input-append");
    $("#search_up, #search_down").removeAttr("disabled");
    $('.search_button').blur().hide();
    clear_search_cache();
};

exports.something_is_highlighted = function () {
    return $(".highlight").length > 0;
};

exports.update_highlight_on_narrow = function () {
    highlight_match(selected_message, cached_term);
    clear_search_cache();
};

return exports;

}());
<commit_msg>Make the searchbox typeahead optionally narrow to stream or PMs.<commit_after>var search = (function () {

var exports = {};

var cached_term = "";
var cached_matches = [];
var cached_index;
var cached_table = $('table.focused_table');

// Data storage for the typeahead -- to go from object to string representation and vice versa.
var labels = [];
var mapped = {};

function narrow_or_search_for_term(item) {
    var obj = mapped[item];
    if (obj.action === "search") {
        // TODO: Should this actually be in a keyup handler? Otherwise we can't tab over and search-down that easily
        exports.search_button_handler(true); // Effectively, click the button (since enter is no longer going to)
        return obj.query;
    } else if (obj.action === "stream") {
        narrow.by_stream_name(obj.query);
        // It's sort of annoying that this is not in a position to
        // blur the search box, because it means that Esc won't
        // unnarrow, it'll leave the searchbox.
        return ""; // Keep the search box empty
    } else if (obj.action === "private_message") {
        narrow.by_private_message_partner(obj.query.full_name, obj.query.email);
        return "";
    }
    return item;
}

function render_object(obj) {
    if (obj.action === 'search') {
        return "Search for " + obj.query;
    } else if (obj.action === 'stream') {
        return "Narrow to stream " + obj.query;
    } else if (obj.action === 'private_message') {
        return "Narrow to person " + obj.query.full_name + " <" + obj.query.email + ">";
    }
    return "Error";
}

// Borrowed from composebox_typeahead_highlighter in composebox_typeahead.js.
function searchbox_typeahead_highlighter(item) {
    var query = this.query;
    var string_item = render_object(mapped[item]);
    query = query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
    var regex = new RegExp('(' + query + ')', 'ig');
    var pieces = string_item.split(regex);
    var result = "";
    $.each(pieces, function(idx, piece) {
        if (piece.match(regex)) {
            result += "<strong>" + Handlebars.Utils.escapeExpression(piece) + "</strong>";
        } else {
            result += Handlebars.Utils.escapeExpression(piece);
        }
    });
    return result;
}

exports.initialize = function () {
    $( "#search_query" ).typeahead({
        source: function (query, process) {
            var streams = $.map(stream_list, function(elt,idx) {
                return {action: 'stream', query: elt};
            });
            var people = $.map(people_list, function(elt,idx) {
                return {action: 'private_message', query: elt};
            });
            var options = streams.concat(people);
            options.unshift({action: 'search', query: query});

            mapped = {};
            labels = [];
            $.each(options, function (i, obj) {
                var label = render_object(obj);
                mapped[label] = obj;
                labels.push(label);
            });
            return labels;
        },
        items: 3,
        highlighter: searchbox_typeahead_highlighter,
        matcher: function (item) {
            var obj = mapped[item];
            var actual_search_term = obj.query;
            if (obj.action === 'private_message') {
                actual_search_term = obj.query.full_name + ' <' + obj.query.email + '>';
            }
            // Case-insensitive (from Bootstrap's default matcher).
            return (actual_search_term.toLowerCase().indexOf(this.query.toLowerCase()) !== -1);
        },
        updater: narrow_or_search_for_term
    });

    $("#searchbox_form").keydown(function (e) {
        var code = e.which;
        if (code === 13 && $("#search_query").data().typeahead.shown) {
            // We pressed Enter and the typeahead is open;
            // don't submit the form so that the typeahead
            // can instead handle our Enter keypress.
            e.preventDefault();
            return false;
        }
    });
    // TODO: If we were to add a keyup handler, maybe we would blur
    // the input after "Enter"?  Otherwise, right now, when we narrow,
    // our cursor remains in the searchbox, when probably it should be
    // blurred or move to the button or something.
};

function match_on_visible_text(row, search_term) {
    // You can't select on :visible, since that includes hidden elements that
    // take up space.
    return row.find(".message_content, .sender_name, .message_header, .message_time")
              .text().toLowerCase().indexOf(search_term) !== -1;
}

function disable_search_arrows_if(condition, affected_arrows) {
    var i, button;

    for (i = 0; i < affected_arrows.length; i++) {
        button = $("#search_" + affected_arrows[i]);
        if (condition) {
            button.attr("disabled", "disabled");
        } else {
            button.removeAttr("disabled");
        }
    }
}

function search(term, highlighted_message, reverse) {
    // term: case-insensitive text to search for
    // highlighted_message: the current location of the pointer. Ignored
    //     on cached queries
    // reverse: boolean as to whether the search is forward or backwards
    //
    // returns a message object containing the search term.
    var previous_header_matched = false;

    var focused_table = $('table.focused_table');
    if ((term !== cached_term) || (cached_table[0] !== focused_table[0])) {
        cached_term = term;
        cached_matches = [];
        cached_index = null;
        cached_table = focused_table;
        var selected_zid = rows.id(highlighted_message);

        focused_table.find('.message_row, .recipient_row').each(function (index, row) {
            row = $(row);
            if (previous_header_matched || (match_on_visible_text(row, term))) {
                previous_header_matched = false;

                if (row.hasClass("recipient_row")) {
                    previous_header_matched = true;
                } else {
                    cached_matches.push(row);
                    var zid = rows.id(row);
                    if ((reverse && (zid <= selected_zid)) ||
                        (!reverse && (zid >= selected_zid) && !cached_index)) {
                        // Keep track of the closest match going up or down.
                        cached_index = cached_matches.length - 1;
                    }
                }
            }
        });

        disable_search_arrows_if(cached_matches.length === 0, ["up", "down"]);

        return cached_matches[cached_index];
    }

    if (reverse) {
        if (cached_index > 0) {
            cached_index--;
        }
    } else {
        if (cached_index < cached_matches.length - 1) {
            cached_index++;
        }
    }

    disable_search_arrows_if(cached_matches.length === 0, ["up", "down"]);
    disable_search_arrows_if(cached_index === 0, ["up"]);
    disable_search_arrows_if(cached_index === cached_matches.length - 1, ["down"]);

    return cached_matches[cached_index];
}

function highlight_match(row, search_term) {
    $('table tr').removeHighlight();
    row.highlight(search_term);

    row = row.prev('.recipient_row');
    if ((row.length !== 0) && (match_on_visible_text(row, search_term))) {
        row.highlight(search_term);
    }
}

exports.search_button_handler = function (reverse) {
    var query = $('#search_query').val().toLowerCase();
    var res = search(query, selected_message, reverse);
    if (!res) {
        return;
    }

    select_message(res);
    highlight_match(res, query);
    scroll_to_selected();
};

function clear_search_cache() {
    cached_term = "";
}

exports.focus_search = function () {
    if (!$('.search_button').is(':visible')) {
        // Shrink the searchbox to make room for the buttons.
        var search_query = $('#search_query');
        var new_width = search_query.width() -
            $('.search_button').outerWidth(true)*3;
        search_query.width(new_width);
        $("#search_arrows").addClass("input-append");
        $('.search_button').show();
        disable_search_arrows_if(false, ["up", "down"]);
    }
};

exports.initiate_search = function () {
    $('#search_query').val('').focus();
};

exports.clear_search = function () {
    $('table tr').removeHighlight();
    // Clear & reset searchbox to its normal size
    $('#search_query').val('').width('');
    $("#search_arrows").removeClass("input-append");
    $("#search_up, #search_down").removeAttr("disabled");
    $('.search_button').blur().hide();
    clear_search_cache();
};

exports.something_is_highlighted = function () {
    return $(".highlight").length > 0;
};

exports.update_highlight_on_narrow = function () {
    highlight_match(selected_message, cached_term);
    clear_search_cache();
};

return exports;

}());
<|endoftext|>