<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2008-2011  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// CodeCell
//============================================================================
/**
 * An extendable module that provide base functionnality to create cell for notebook.
 * @module IPython
 * @namespace IPython
 * @submodule CodeCell
 */

/* local util for codemirror */
var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;}

/**
 *
 * function to delete until previous non blanking space character
 * or first multiple of 4 tabstop.
 * @private
 */
CodeMirror.commands.delSpaceToPrevTabStop = function(cm){
    var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
    if (!posEq(from, to)) {cm.replaceRange("", from, to); return}
    var cur = cm.getCursor(), line = cm.getLine(cur.line);
    var tabsize = cm.getOption('tabSize');
    var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize;
    var from = {ch:cur.ch-chToPrevTabStop,line:cur.line}
    var select = cm.getRange(from,cur)
    if( select.match(/^\ +$/) != null){
        cm.replaceRange("",from,cur)
    } else {
        cm.deleteH(-1,"char")
    }
};

var IPython = (function (IPython) {
    "use strict";

    var utils = IPython.utils;
    var key   = IPython.utils.keycodes;
    CodeMirror.modeURL = "/static/components/codemirror/mode/%N/%N.js";

    /**
     * A Cell conceived to write code.
     *
     * The kernel doesn't have to be set at creation time, in that case
     * it will be null and set_kernel has to be called later.
     * @class CodeCell
     * @extends IPython.Cell
     *
     * @constructor
     * @param {Object|null} kernel
     * @param {object|undefined} [options]
     *      @param [options.cm_config] {object} config to pass to CodeMirror
     */
    var CodeCell = function (kernel, options) {
        this.kernel = kernel || null;
        this.code_mirror = null;
        this.input_prompt_number = null;
        this.collapsed = false;
        this.default_mode = 'python';

        var cm_overwrite_options  = {
            onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
        };

        options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options});

        IPython.Cell.apply(this,[options]);

        var that = this;
        this.element.focusout(
            function() { that.auto_highlight(); }
        );
    };

    CodeCell.options_default = {
        cm_config : {
            extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"},
            mode: 'python',
            theme: 'ipython',
            matchBrackets: true
        }
    };

    CodeCell.prototype = new IPython.Cell();

    /**
     * @method auto_highlight
     */
    CodeCell.prototype.auto_highlight = function () {
        this._auto_highlight(IPython.config.cell_magic_highlight)
    };

    /** @method create_element */
    CodeCell.prototype.create_element = function () {
        IPython.Cell.prototype.create_element.apply(this, arguments);

        var cell =  $('

').addClass('cell border-box-sizing code_cell');
        cell.attr('tabindex','2');

        this.celltoolbar = new IPython.CellToolbar(this);

        var input = $('

').addClass('input');
        var vbox = $('
').addClass('vbox box-flex1')
        input.append($('
').addClass('prompt input_prompt'));
        vbox.append(this.celltoolbar.element);
        var input_area = $('
').addClass('input_area');
        this.code_mirror = CodeMirror(input_area.get(0), this.cm_config);
        $(this.code_mirror.getInputField()).attr("spellcheck", "false");
        vbox.append(input_area);
        input.append(vbox);
        var output = $('

');
        cell.append(input).append(output);
        this.element = cell;
        this.output_area = new IPython.OutputArea(output, true);

        // construct a completer only if class exist
        // otherwise no print view
        if (IPython.Completer !== undefined)
        {
            this.completer = new IPython.Completer(this);
        }
    };

    /**
     *  This method gets called in CodeMirror's onKeyDown/onKeyPress
     *  handlers and is used to provide custom key handling. Its return
     *  value is used to determine if CodeMirror should ignore the event:
     *  true = ignore, false = don't ignore.
     *  @method handle_codemirror_keyevent
     */
    CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {

        if (this.read_only){
            return false;
        }

        var that = this;
        // whatever key is pressed, first, cancel the tooltip request before
        // they are sent, and remove tooltip if any, except for tab again
        if (event.type === 'keydown' && event.which != key.TAB ) {
            IPython.tooltip.remove_and_cancel_tooltip();
        };

        var cur = editor.getCursor();
        if (event.keyCode === key.ENTER){
            this.auto_highlight();
        }

        if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
            // Always ignore shift-enter in CodeMirror as we handle it.
            return true;
        } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
            // triger on keypress (!) otherwise inconsistent event.which depending on plateform
            // browser and keyboard layout !
            // Pressing '(' , request tooltip, don't forget to reappend it
            IPython.tooltip.pending(that);
        } else if (event.which === key.UPARROW && event.type === 'keydown') {
            // If we are not at the top, let CM handle the up arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_top()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        } else if (event.which === key.ESC) {
            IPython.tooltip.remove_and_cancel_tooltip(true);
            return true;
        } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
            // If we are not at the bottom, let CM handle the down arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_bottom()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
                if (editor.somethingSelected()){
                    var anchor = editor.getCursor("anchor");
                    var head = editor.getCursor("head");
                    if( anchor.line != head.line){
                        return false;
                    }
                }
                IPython.tooltip.request(that);
                event.stop();
                return true;
        } else if (event.keyCode === key.TAB && event.type == 'keydown') {
            // Tab completion.
            //Do not trim here because of tooltip
            if (editor.somethingSelected()){return false}
            var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
            if (pre_cursor.trim() === "") {
                // Don't autocomplete if the part of the line before the cursor
                // is empty.  In this case, let CodeMirror handle indentation.
                return false;
            } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) {
                IPython.tooltip.request(that);
                // Prevent the event from bubbling up.
                event.stop();
                // Prevent CodeMirror from handling the tab.
                return true;
            } else {
                event.stop();
                this.completer.startCompletion();
                return true;
            };
        } else {
            // keypress/keyup also trigger on TAB press, and we don't want to
            // use those to disable tab completion.
            return false;
        };
        return false;
    };

    // Kernel related calls.

    CodeCell.prototype.set_kernel = function (kernel) {
        this.kernel = kernel;
    }

    /**
     * Execute current code cell to the kernel
     * @method execute
     */
    CodeCell.prototype.execute = function () {
        this.output_area.clear_output(true, true, true);
        this.set_input_prompt('*');
        this.element.addClass("running");
        var callbacks = {
            'execute_reply': $.proxy(this._handle_execute_reply, this),
            'output': $.proxy(this.output_area.handle_output, this.output_area),
            'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
            'set_next_input': $.proxy(this._handle_set_next_input, this),
            'input_request': $.proxy(this._handle_input_request, this)
        };
        var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
    };

    /**
     * @method _handle_execute_reply
     * @private
     */
    CodeCell.prototype._handle_execute_reply = function (content) {
        this.set_input_prompt(content.execution_count);
        this.element.removeClass("running");
        $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
    }

    /**
     * @method _handle_set_next_input
     * @private
     */
    CodeCell.prototype._handle_set_next_input = function (text) {
        var data = {'cell': this, 'text': text}
        $([IPython.events]).trigger('set_next_input.Notebook', data);
    }

    /**
     * @method _handle_input_request
     * @private
     */
    CodeCell.prototype._handle_input_request = function (content) {
        this.output_area.append_raw_input(content);
    }

    // Basic cell manipulation.

    CodeCell.prototype.select = function () {
        IPython.Cell.prototype.select.apply(this);
        this.code_mirror.refresh();
        this.code_mirror.focus();
        this.auto_highlight();
        // We used to need an additional refresh() after the focus, but
        // it appears that this has been fixed in CM. This bug would show
        // up on FF when a newly loaded markdown cell was edited.
    };

    CodeCell.prototype.select_all = function () {
        var start = {line: 0, ch: 0};
        var nlines = this.code_mirror.lineCount();
        var last_line = this.code_mirror.getLine(nlines-1);
        var end = {line: nlines-1, ch: last_line.length};
        this.code_mirror.setSelection(start, end);
    };

    CodeCell.prototype.collapse = function () {
        this.collapsed = true;
        this.output_area.collapse();
    };

    CodeCell.prototype.expand = function () {
        this.collapsed = false;
        this.output_area.expand();
    };

    CodeCell.prototype.toggle_output = function () {
        this.collapsed = Boolean(1 - this.collapsed);
        this.output_area.toggle_output();
    };

    CodeCell.prototype.toggle_output_scroll = function () {
    this.output_area.toggle_scroll();
    };

    CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
        var ns = prompt_value || " ";
        return 'In [' + ns + ']:'
    };

    CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
        var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
        for(var i=1; i < lines_number; i++){html.push(['...:'])};
        return html.join('
')
    };

    CodeCell.input_prompt_function = CodeCell.input_prompt_classical;

    CodeCell.prototype.set_input_prompt = function (number) {
        var nline = 1
        if( this.code_mirror != undefined) {
           nline = this.code_mirror.lineCount();
        }
        this.input_prompt_number = number;
        var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
        this.element.find('div.input_prompt').html(prompt_html);
    };

    CodeCell.prototype.clear_input = function () {
        this.code_mirror.setValue('');
    };

    CodeCell.prototype.get_text = function () {
        return this.code_mirror.getValue();
    };

    CodeCell.prototype.set_text = function (code) {
        return this.code_mirror.setValue(code);
    };

    CodeCell.prototype.at_top = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === 0 && cursor.ch === 0) {
            return true;
        } else {
            return false;
        }
    };

    CodeCell.prototype.at_bottom = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
            return true;
        } else {
            return false;
        }
    };

    CodeCell.prototype.clear_output = function (stdout, stderr, other) {
        this.output_area.clear_output(stdout, stderr, other);
    };

    // JSON serialization

    CodeCell.prototype.fromJSON = function (data) {
        IPython.Cell.prototype.fromJSON.apply(this, arguments);
        if (data.cell_type === 'code') {
            if (data.input !== undefined) {
                this.set_text(data.input);
                // make this value the starting point, so that we can only undo
                // to this state, instead of a blank cell
                this.code_mirror.clearHistory();
                this.auto_highlight();
            }
            if (data.prompt_number !== undefined) {
                this.set_input_prompt(data.prompt_number);
            } else {
                this.set_input_prompt();
            };
            this.output_area.fromJSON(data.outputs);
            if (data.collapsed !== undefined) {
                if (data.collapsed) {
                    this.collapse();
                } else {
                    this.expand();
                };
            };
        };
    };

    CodeCell.prototype.toJSON = function () {
        var data = IPython.Cell.prototype.toJSON.apply(this);
        data.input = this.get_text();
        data.cell_type = 'code';
        if (this.input_prompt_number) {
            data.prompt_number = this.input_prompt_number;
        };
        var outputs = this.output_area.toJSON();
        data.outputs = outputs;
        data.language = 'python';
        data.collapsed = this.collapsed;
        return data;
    };

    IPython.CodeCell = CodeCell;

    return IPython;
}(IPython));
<commit_msg>Changing mode name from python -> ipython.<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2008-2011  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// CodeCell
//============================================================================
/**
 * An extendable module that provide base functionnality to create cell for notebook.
 * @module IPython
 * @namespace IPython
 * @submodule CodeCell
 */

/* local util for codemirror */
var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;}

/**
 *
 * function to delete until previous non blanking space character
 * or first multiple of 4 tabstop.
 * @private
 */
CodeMirror.commands.delSpaceToPrevTabStop = function(cm){
    var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
    if (!posEq(from, to)) {cm.replaceRange("", from, to); return}
    var cur = cm.getCursor(), line = cm.getLine(cur.line);
    var tabsize = cm.getOption('tabSize');
    var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize;
    var from = {ch:cur.ch-chToPrevTabStop,line:cur.line}
    var select = cm.getRange(from,cur)
    if( select.match(/^\ +$/) != null){
        cm.replaceRange("",from,cur)
    } else {
        cm.deleteH(-1,"char")
    }
};

var IPython = (function (IPython) {
    "use strict";

    var utils = IPython.utils;
    var key   = IPython.utils.keycodes;
    CodeMirror.modeURL = "/static/components/codemirror/mode/%N/%N.js";

    /**
     * A Cell conceived to write code.
     *
     * The kernel doesn't have to be set at creation time, in that case
     * it will be null and set_kernel has to be called later.
     * @class CodeCell
     * @extends IPython.Cell
     *
     * @constructor
     * @param {Object|null} kernel
     * @param {object|undefined} [options]
     *      @param [options.cm_config] {object} config to pass to CodeMirror
     */
    var CodeCell = function (kernel, options) {
        this.kernel = kernel || null;
        this.code_mirror = null;
        this.input_prompt_number = null;
        this.collapsed = false;
        this.default_mode = 'ipython';

        var cm_overwrite_options  = {
            onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
        };

        options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options});

        IPython.Cell.apply(this,[options]);

        var that = this;
        this.element.focusout(
            function() { that.auto_highlight(); }
        );
    };

    CodeCell.options_default = {
        cm_config : {
            extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"},
            mode: 'ipython',
            theme: 'ipython',
            matchBrackets: true
        }
    };

    CodeCell.prototype = new IPython.Cell();

    /**
     * @method auto_highlight
     */
    CodeCell.prototype.auto_highlight = function () {
        this._auto_highlight(IPython.config.cell_magic_highlight)
    };

    /** @method create_element */
    CodeCell.prototype.create_element = function () {
        IPython.Cell.prototype.create_element.apply(this, arguments);

        var cell =  $('

').addClass('cell border-box-sizing code_cell');
        cell.attr('tabindex','2');

        this.celltoolbar = new IPython.CellToolbar(this);

        var input = $('

').addClass('input');
        var vbox = $('
').addClass('vbox box-flex1')
        input.append($('
').addClass('prompt input_prompt'));
        vbox.append(this.celltoolbar.element);
        var input_area = $('
').addClass('input_area');
        this.code_mirror = CodeMirror(input_area.get(0), this.cm_config);
        $(this.code_mirror.getInputField()).attr("spellcheck", "false");
        vbox.append(input_area);
        input.append(vbox);
        var output = $('

');
        cell.append(input).append(output);
        this.element = cell;
        this.output_area = new IPython.OutputArea(output, true);

        // construct a completer only if class exist
        // otherwise no print view
        if (IPython.Completer !== undefined)
        {
            this.completer = new IPython.Completer(this);
        }
    };

    /**
     *  This method gets called in CodeMirror's onKeyDown/onKeyPress
     *  handlers and is used to provide custom key handling. Its return
     *  value is used to determine if CodeMirror should ignore the event:
     *  true = ignore, false = don't ignore.
     *  @method handle_codemirror_keyevent
     */
    CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {

        if (this.read_only){
            return false;
        }

        var that = this;
        // whatever key is pressed, first, cancel the tooltip request before
        // they are sent, and remove tooltip if any, except for tab again
        if (event.type === 'keydown' && event.which != key.TAB ) {
            IPython.tooltip.remove_and_cancel_tooltip();
        };

        var cur = editor.getCursor();
        if (event.keyCode === key.ENTER){
            this.auto_highlight();
        }

        if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
            // Always ignore shift-enter in CodeMirror as we handle it.
            return true;
        } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
            // triger on keypress (!) otherwise inconsistent event.which depending on plateform
            // browser and keyboard layout !
            // Pressing '(' , request tooltip, don't forget to reappend it
            IPython.tooltip.pending(that);
        } else if (event.which === key.UPARROW && event.type === 'keydown') {
            // If we are not at the top, let CM handle the up arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_top()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        } else if (event.which === key.ESC) {
            IPython.tooltip.remove_and_cancel_tooltip(true);
            return true;
        } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
            // If we are not at the bottom, let CM handle the down arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_bottom()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
                if (editor.somethingSelected()){
                    var anchor = editor.getCursor("anchor");
                    var head = editor.getCursor("head");
                    if( anchor.line != head.line){
                        return false;
                    }
                }
                IPython.tooltip.request(that);
                event.stop();
                return true;
        } else if (event.keyCode === key.TAB && event.type == 'keydown') {
            // Tab completion.
            //Do not trim here because of tooltip
            if (editor.somethingSelected()){return false}
            var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
            if (pre_cursor.trim() === "") {
                // Don't autocomplete if the part of the line before the cursor
                // is empty.  In this case, let CodeMirror handle indentation.
                return false;
            } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) {
                IPython.tooltip.request(that);
                // Prevent the event from bubbling up.
                event.stop();
                // Prevent CodeMirror from handling the tab.
                return true;
            } else {
                event.stop();
                this.completer.startCompletion();
                return true;
            };
        } else {
            // keypress/keyup also trigger on TAB press, and we don't want to
            // use those to disable tab completion.
            return false;
        };
        return false;
    };

    // Kernel related calls.

    CodeCell.prototype.set_kernel = function (kernel) {
        this.kernel = kernel;
    }

    /**
     * Execute current code cell to the kernel
     * @method execute
     */
    CodeCell.prototype.execute = function () {
        this.output_area.clear_output(true, true, true);
        this.set_input_prompt('*');
        this.element.addClass("running");
        var callbacks = {
            'execute_reply': $.proxy(this._handle_execute_reply, this),
            'output': $.proxy(this.output_area.handle_output, this.output_area),
            'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
            'set_next_input': $.proxy(this._handle_set_next_input, this),
            'input_request': $.proxy(this._handle_input_request, this)
        };
        var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
    };

    /**
     * @method _handle_execute_reply
     * @private
     */
    CodeCell.prototype._handle_execute_reply = function (content) {
        this.set_input_prompt(content.execution_count);
        this.element.removeClass("running");
        $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
    }

    /**
     * @method _handle_set_next_input
     * @private
     */
    CodeCell.prototype._handle_set_next_input = function (text) {
        var data = {'cell': this, 'text': text}
        $([IPython.events]).trigger('set_next_input.Notebook', data);
    }

    /**
     * @method _handle_input_request
     * @private
     */
    CodeCell.prototype._handle_input_request = function (content) {
        this.output_area.append_raw_input(content);
    }

    // Basic cell manipulation.

    CodeCell.prototype.select = function () {
        IPython.Cell.prototype.select.apply(this);
        this.code_mirror.refresh();
        this.code_mirror.focus();
        this.auto_highlight();
        // We used to need an additional refresh() after the focus, but
        // it appears that this has been fixed in CM. This bug would show
        // up on FF when a newly loaded markdown cell was edited.
    };

    CodeCell.prototype.select_all = function () {
        var start = {line: 0, ch: 0};
        var nlines = this.code_mirror.lineCount();
        var last_line = this.code_mirror.getLine(nlines-1);
        var end = {line: nlines-1, ch: last_line.length};
        this.code_mirror.setSelection(start, end);
    };

    CodeCell.prototype.collapse = function () {
        this.collapsed = true;
        this.output_area.collapse();
    };

    CodeCell.prototype.expand = function () {
        this.collapsed = false;
        this.output_area.expand();
    };

    CodeCell.prototype.toggle_output = function () {
        this.collapsed = Boolean(1 - this.collapsed);
        this.output_area.toggle_output();
    };

    CodeCell.prototype.toggle_output_scroll = function () {
    this.output_area.toggle_scroll();
    };

    CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
        var ns = prompt_value || " ";
        return 'In [' + ns + ']:'
    };

    CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
        var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
        for(var i=1; i < lines_number; i++){html.push(['...:'])};
        return html.join('
')
    };

    CodeCell.input_prompt_function = CodeCell.input_prompt_classical;

    CodeCell.prototype.set_input_prompt = function (number) {
        var nline = 1
        if( this.code_mirror != undefined) {
           nline = this.code_mirror.lineCount();
        }
        this.input_prompt_number = number;
        var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
        this.element.find('div.input_prompt').html(prompt_html);
    };

    CodeCell.prototype.clear_input = function () {
        this.code_mirror.setValue('');
    };

    CodeCell.prototype.get_text = function () {
        return this.code_mirror.getValue();
    };

    CodeCell.prototype.set_text = function (code) {
        return this.code_mirror.setValue(code);
    };

    CodeCell.prototype.at_top = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === 0 && cursor.ch === 0) {
            return true;
        } else {
            return false;
        }
    };

    CodeCell.prototype.at_bottom = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
            return true;
        } else {
            return false;
        }
    };

    CodeCell.prototype.clear_output = function (stdout, stderr, other) {
        this.output_area.clear_output(stdout, stderr, other);
    };

    // JSON serialization

    CodeCell.prototype.fromJSON = function (data) {
        IPython.Cell.prototype.fromJSON.apply(this, arguments);
        if (data.cell_type === 'code') {
            if (data.input !== undefined) {
                this.set_text(data.input);
                // make this value the starting point, so that we can only undo
                // to this state, instead of a blank cell
                this.code_mirror.clearHistory();
                this.auto_highlight();
            }
            if (data.prompt_number !== undefined) {
                this.set_input_prompt(data.prompt_number);
            } else {
                this.set_input_prompt();
            };
            this.output_area.fromJSON(data.outputs);
            if (data.collapsed !== undefined) {
                if (data.collapsed) {
                    this.collapse();
                } else {
                    this.expand();
                };
            };
        };
    };

    CodeCell.prototype.toJSON = function () {
        var data = IPython.Cell.prototype.toJSON.apply(this);
        data.input = this.get_text();
        data.cell_type = 'code';
        if (this.input_prompt_number) {
            data.prompt_number = this.input_prompt_number;
        };
        var outputs = this.output_area.toJSON();
        data.outputs = outputs;
        data.language = 'python';
        data.collapsed = this.collapsed;
        return data;
    };

    IPython.CodeCell = CodeCell;

    return IPython;
}(IPython));
<|endoftext|>


<commit_before>/* Stock API functions
 * Requires api.js to be loaded first
 */

function getStockList(filters={}, options={}) {
    return inventreeGet('/api/stock/', filters, options);
}

function getStockDetail(pk, options={}) {
    return inventreeGet('/api/stock/' + pk + '/', {}, options)
}

function getStockLocations(filters={}, options={}) {
    return inventreeGet('/api/stock/location/', filters, options)
}

/* Functions for interacting with stock management forms
 */

function removeStockRow(e) {
    // Remove a selected row from a stock modal form

    e = e || window.event;
    var src = e.target || e.srcElement;

    var row = $(src).attr('row');

    $('#' + row).remove();
}

function loadStockTable(table, options) {
    /* Load data into a stock table with adjustable options.
     * Fetches data (via AJAX) and loads into a bootstrap table.
     * Also links in default button callbacks.
     *
     * Options:
     *  url - URL for the stock query
     *  params - query params for augmenting stock data request
     *  groupByField - Column for grouping stock items
     *  buttons - Which buttons to link to stock selection callbacks
     *  filterList -
 element where filters are displayed
     */

    // List of user-params which override the default filters
    var params = options.params || {};

    var filterListElement = options.filterList || "#filter-list-stock";

    var filters = loadTableFilters("stock");

    var original = {};

    for (var key in params) {
        original[key] = params[key];
    }

    setupFilterList("stock", table, filterListElement);

    // Override the default values, or add new ones
    for (var key in params) {
        filters[key] = params[key];
    }

    table.inventreeTable({
        method: 'get',
        formatNoMatches: function() {
            return 'No stock items matching query';
        },
        url: options.url,
        queryParams: filters,
        customSort: customGroupSorter,
        groupBy: true,
        original: original,
        groupByField: options.groupByField || 'part',
        groupByFormatter: function(field, id, data) {

            var row = data[0];

            if (field == 'part__name') {

                var name = row.part__IPN;

                if (name) {
                    name += ' | ';
                }

                name += row.part__name;

                return imageHoverIcon(row.part__thumbnail) + name + ' (' + data.length + ' items)';
            }
            else if (field == 'part__description') {
                return row.part__description;
            }
            else if (field == 'quantity') {
                var stock = 0;
                var items = 0;

                data.forEach(function(item) {
                    stock += item.quantity;
                    items += 1;
                });

                stock = +stock.toFixed(5);

                return stock + " (" + items + " items)";
            } else if (field == 'status') {
                var statii = [];

                data.forEach(function(item) {
                    var status = String(item.status);

                    if (!status || status == '') {
                        status = '-';
                    }

                    if (!statii.includes(status)) {
                        statii.push(status);
                    }
                });

                // Multiple status codes
                if (statii.length > 1) {
                    return "-";
                } else if (statii.length == 1) {
                    return stockStatusDisplay(statii[0]);
                } else {
                    return "-";
                }
            } else if (field == 'batch') {
                var batches = [];

                data.forEach(function(item) {
                    var batch = item.batch;

                    if (!batch || batch == '') {
                        batch = '-';
                    }

                    if (!batches.includes(batch)) {
                        batches.push(batch);
                    }
                });

                if (batches.length > 1) {
                    return "" + batches.length + " batches";
                } else if (batches.length == 1) {
                    if (batches[0]) {
                        return batches[0];
                    } else {
                        return '-';
                    }
                } else {
                    return '-';
                }
            } else if (field == 'location__path') {
                /* Determine how many locations */
                var locations = [];

                data.forEach(function(item) {
                    var loc = item.location;

                    if (!locations.includes(loc)) {
                        locations.push(loc);
                    }
                });

                if (locations.length > 1) {
                    return "In " + locations.length + " locations";
                } else {
                    // A single location!
                    return renderLink(row.location__path, '/stock/location/' + row.location + '/')
                }
            } else if (field == 'notes') {
                var notes = [];

                data.forEach(function(item) {
                    var note = item.notes;

                    if (!note || note == '') {
                        note = '-';
                    }

                    if (!notes.includes(note)) {
                        notes.push(note);
                    }
                });

                if (notes.length > 1) {
                    return '...';
                } else if (notes.length == 1) {
                    return notes[0] || '-';
                } else {
                    return '-';
                }
            }
            else {
                return '';
            }
        },
        columns: [
            {
                checkbox: true,
                title: 'Select',
                searchable: false,
            },
            {
                field: 'pk',
                title: 'ID',
                visible: false,
            },
            {
                field: 'part__name',
                title: 'Part',
                sortable: true,
                formatter: function(value, row, index, field) {

                    var name = row.part__IPN;

                    if (name) {
                        name += ' | ';
                    }

                    name += row.part__name;

                    if (row.part__revision) {
                        name += " | ";
                        name += row.part__revision;
                    }

                    var url = '';

                    if (row.supplier_part) {
                        url = `/supplier-part/${row.supplier_part}/`;
                    } else {
                        url = `/part/${row.part}/`;
                    }

                    return imageHoverIcon(row.part__thumbnail) + renderLink(name, url);
                }
            },
            {
                field: 'part__description',
                title: 'Description',
                sortable: true,
            },
            {
                field: 'quantity',
                title: 'Stock',
                sortable: true,
                formatter: function(value, row, index, field) {

                    var val = value;

                    // If there is a single unit with a serial number, use the serial number
                    if (row.serial && row.quantity == 1) {
                        val = '# ' + row.serial;
                    }

                    var text = renderLink(val, '/stock/item/' + row.pk + '/');

                    return text;
                }
            },
            {
                field: 'status',
                title: 'Status',
                sortable: 'true',
                formatter: function(value, row, index, field) {
                    return stockStatusDisplay(value);
                },
            },
            {
                field: 'batch',
                title: 'Batch',
                sortable: true,
            },
            {
                field: 'location__path',
                title: 'Location',
                sortable: true,
                formatter: function(value, row, index, field) {
                    if (value) {
                        return renderLink(value, '/stock/location/' + row.location + '/');
                    }
                    else {
                        return 'No stock location set';
                    }
                }
            },
            {
                field: 'notes',
                title: 'Notes',
            }
        ],
    });

    if (options.buttons) {
        linkButtonsToSelection(table, options.buttons);
    }

    function stockAdjustment(action) {
        var items = $("#stock-table").bootstrapTable("getSelections");

        var stock = [];

        items.forEach(function(item) {
            stock.push(item.pk);
        });

        // Buttons for launching secondary modals
        var secondary = [];

        if (action == 'move') {
            secondary.push({
                field: 'destination',
                label: 'New Location',
                title: 'Create new location',
                url: "/stock/location/new/",
            });
        }

        launchModalForm("/stock/adjust/",
            {
                data: {
                    action: action,
                    stock: stock,
                },
                success: function() {
                    $("#stock-table").bootstrapTable('refresh');
                },
                secondary: secondary,
            }
        );
    }

    // Automatically link button callbacks
    $('#multi-item-stocktake').click(function() {
        stockAdjustment('count');
    });

    $('#multi-item-remove').click(function() {
        stockAdjustment('take');
    });

    $('#multi-item-add').click(function() {
        stockAdjustment('add');
    });

    $("#multi-item-move").click(function() {
        stockAdjustment('move');
    });

    $("#multi-item-order").click(function() {
        var selections = $("#stock-table").bootstrapTable("getSelections");

        var stock = [];

        selections.forEach(function(item) {
            stock.push(item.pk);
        });

        launchModalForm("/order/purchase-order/order-parts/", {
            data: {
                stock: stock,
            },
        });
    });

    $("#multi-item-delete").click(function() {
        var selections = $("#stock-table").bootstrapTable("getSelections");

        var stock = [];

        selections.forEach(function(item) {
            stock.push(item.pk);
        });

        stockAdjustment('delete');
    });
}

function loadStockTrackingTable(table, options) {

    var cols = [
        {
            field: 'pk',
            visible: false,
        },
        {
            field: 'date',
            title: 'Date',
            sortable: true,
            formatter: function(value, row, index, field) {
                var m = moment(value);
                if (m.isValid()) {
                    var html = m.format('dddd MMMM Do YYYY'); // + '
' + m.format('h:mm a');
                    return html;
                }

                return 'N/A';
            }
        },
    ];

    // If enabled, provide a link to the referenced StockItem
    if (options.partColumn) {
        cols.push({
            field: 'item',
            title: 'Stock Item',
            sortable: true,
            formatter: function(value, row, index, field) {
                return renderLink(value.part_name, value.url);
            }
        });
    }

    // Stock transaction description
    cols.push({
        field: 'title',
        title: 'Description',
        sortable: true,
        formatter: function(value, row, index, field) {
            var html = "" + value + "";

            if (row.notes) {
                html += "
" + row.notes + "";
            }

            if (row.link) {
                html += "
" + row.link + "";
            }

            return html;
        }
    });

    cols.push({
        field: 'quantity',
        title: 'Quantity',
        formatter: function(value, row, index, field) {
            return parseFloat(value);
        },
    });

    cols.push({
        sortable: true,
        field: 'user',
        title: 'User',
        formatter: function(value, row, index, field) {
            if (value)
            {
                // TODO - Format the user's first and last names
                return value.username;
            }
            else
            {
                return "No user information";
            }
        }
    });

    cols.push({
        sortable: false,
        formatter: function(value, row, index, field) {
            // Manually created entries can be edited or deleted
            if (!row.system) {
                var bEdit = "<button title='Edit tracking entry' class='btn btn-entry-edit btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/edit/'></button>";
                var bDel = "<button title='Delete tracking entry' class='btn btn-entry-delete btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/delete/'></button>";

                return "
" + bEdit + bDel + "
";
            } else {
                return "";
            }
        }
    });

    table.inventreeTable({
        method: 'get',
        queryParams: options.params,
        columns: cols,
        url: options.url,
    });

    if (options.buttons) {
        linkButtonsToSelection(table, options.buttons);
    }

    table.on('click', '.btn-entry-edit', function() {
        var button = $(this);

        launchModalForm(button.attr('url'), {
            reload: true,
        });
    });

    table.on('click', '.btn-entry-delete', function() {
        var button = $(this);

        launchModalForm(button.attr('url'), {
            reload: true,
        });
    });
}<commit_msg>Add same optio for stock table<commit_after>/* Stock API functions
 * Requires api.js to be loaded first
 */

function getStockList(filters={}, options={}) {
    return inventreeGet('/api/stock/', filters, options);
}

function getStockDetail(pk, options={}) {
    return inventreeGet('/api/stock/' + pk + '/', {}, options)
}

function getStockLocations(filters={}, options={}) {
    return inventreeGet('/api/stock/location/', filters, options)
}

/* Functions for interacting with stock management forms
 */

function removeStockRow(e) {
    // Remove a selected row from a stock modal form

    e = e || window.event;
    var src = e.target || e.srcElement;

    var row = $(src).attr('row');

    $('#' + row).remove();
}

function loadStockTable(table, options) {
    /* Load data into a stock table with adjustable options.
     * Fetches data (via AJAX) and loads into a bootstrap table.
     * Also links in default button callbacks.
     *
     * Options:
     *  url - URL for the stock query
     *  params - query params for augmenting stock data request
     *  groupByField - Column for grouping stock items
     *  buttons - Which buttons to link to stock selection callbacks
     *  filterList -
 element where filters are displayed
     *  disableFilters: If true, disable custom filters
     */

    // List of user-params which override the default filters
    var params = options.params || {};

    var filterListElement = options.filterList || "#filter-list-stock";

    var filters = {};

    if (!options.disableFilters) {
        filters = loadTableFilters("stock");
    }

    var original = {};

    for (var key in params) {
        original[key] = params[key];
    }

    setupFilterList("stock", table, filterListElement);

    // Override the default values, or add new ones
    for (var key in params) {
        filters[key] = params[key];
    }

    table.inventreeTable({
        method: 'get',
        formatNoMatches: function() {
            return 'No stock items matching query';
        },
        url: options.url,
        queryParams: filters,
        customSort: customGroupSorter,
        groupBy: true,
        original: original,
        groupByField: options.groupByField || 'part',
        groupByFormatter: function(field, id, data) {

            var row = data[0];

            if (field == 'part__name') {

                var name = row.part__IPN;

                if (name) {
                    name += ' | ';
                }

                name += row.part__name;

                return imageHoverIcon(row.part__thumbnail) + name + ' (' + data.length + ' items)';
            }
            else if (field == 'part__description') {
                return row.part__description;
            }
            else if (field == 'quantity') {
                var stock = 0;
                var items = 0;

                data.forEach(function(item) {
                    stock += item.quantity;
                    items += 1;
                });

                stock = +stock.toFixed(5);

                return stock + " (" + items + " items)";
            } else if (field == 'status') {
                var statii = [];

                data.forEach(function(item) {
                    var status = String(item.status);

                    if (!status || status == '') {
                        status = '-';
                    }

                    if (!statii.includes(status)) {
                        statii.push(status);
                    }
                });

                // Multiple status codes
                if (statii.length > 1) {
                    return "-";
                } else if (statii.length == 1) {
                    return stockStatusDisplay(statii[0]);
                } else {
                    return "-";
                }
            } else if (field == 'batch') {
                var batches = [];

                data.forEach(function(item) {
                    var batch = item.batch;

                    if (!batch || batch == '') {
                        batch = '-';
                    }

                    if (!batches.includes(batch)) {
                        batches.push(batch);
                    }
                });

                if (batches.length > 1) {
                    return "" + batches.length + " batches";
                } else if (batches.length == 1) {
                    if (batches[0]) {
                        return batches[0];
                    } else {
                        return '-';
                    }
                } else {
                    return '-';
                }
            } else if (field == 'location__path') {
                /* Determine how many locations */
                var locations = [];

                data.forEach(function(item) {
                    var loc = item.location;

                    if (!locations.includes(loc)) {
                        locations.push(loc);
                    }
                });

                if (locations.length > 1) {
                    return "In " + locations.length + " locations";
                } else {
                    // A single location!
                    return renderLink(row.location__path, '/stock/location/' + row.location + '/')
                }
            } else if (field == 'notes') {
                var notes = [];

                data.forEach(function(item) {
                    var note = item.notes;

                    if (!note || note == '') {
                        note = '-';
                    }

                    if (!notes.includes(note)) {
                        notes.push(note);
                    }
                });

                if (notes.length > 1) {
                    return '...';
                } else if (notes.length == 1) {
                    return notes[0] || '-';
                } else {
                    return '-';
                }
            }
            else {
                return '';
            }
        },
        columns: [
            {
                checkbox: true,
                title: 'Select',
                searchable: false,
            },
            {
                field: 'pk',
                title: 'ID',
                visible: false,
            },
            {
                field: 'part__name',
                title: 'Part',
                sortable: true,
                formatter: function(value, row, index, field) {

                    var name = row.part__IPN;

                    if (name) {
                        name += ' | ';
                    }

                    name += row.part__name;

                    if (row.part__revision) {
                        name += " | ";
                        name += row.part__revision;
                    }

                    var url = '';

                    if (row.supplier_part) {
                        url = `/supplier-part/${row.supplier_part}/`;
                    } else {
                        url = `/part/${row.part}/`;
                    }

                    return imageHoverIcon(row.part__thumbnail) + renderLink(name, url);
                }
            },
            {
                field: 'part__description',
                title: 'Description',
                sortable: true,
            },
            {
                field: 'quantity',
                title: 'Stock',
                sortable: true,
                formatter: function(value, row, index, field) {

                    var val = value;

                    // If there is a single unit with a serial number, use the serial number
                    if (row.serial && row.quantity == 1) {
                        val = '# ' + row.serial;
                    }

                    var text = renderLink(val, '/stock/item/' + row.pk + '/');

                    return text;
                }
            },
            {
                field: 'status',
                title: 'Status',
                sortable: 'true',
                formatter: function(value, row, index, field) {
                    return stockStatusDisplay(value);
                },
            },
            {
                field: 'batch',
                title: 'Batch',
                sortable: true,
            },
            {
                field: 'location__path',
                title: 'Location',
                sortable: true,
                formatter: function(value, row, index, field) {
                    if (value) {
                        return renderLink(value, '/stock/location/' + row.location + '/');
                    }
                    else {
                        return 'No stock location set';
                    }
                }
            },
            {
                field: 'notes',
                title: 'Notes',
            }
        ],
    });

    if (options.buttons) {
        linkButtonsToSelection(table, options.buttons);
    }

    function stockAdjustment(action) {
        var items = $("#stock-table").bootstrapTable("getSelections");

        var stock = [];

        items.forEach(function(item) {
            stock.push(item.pk);
        });

        // Buttons for launching secondary modals
        var secondary = [];

        if (action == 'move') {
            secondary.push({
                field: 'destination',
                label: 'New Location',
                title: 'Create new location',
                url: "/stock/location/new/",
            });
        }

        launchModalForm("/stock/adjust/",
            {
                data: {
                    action: action,
                    stock: stock,
                },
                success: function() {
                    $("#stock-table").bootstrapTable('refresh');
                },
                secondary: secondary,
            }
        );
    }

    // Automatically link button callbacks
    $('#multi-item-stocktake').click(function() {
        stockAdjustment('count');
    });

    $('#multi-item-remove').click(function() {
        stockAdjustment('take');
    });

    $('#multi-item-add').click(function() {
        stockAdjustment('add');
    });

    $("#multi-item-move").click(function() {
        stockAdjustment('move');
    });

    $("#multi-item-order").click(function() {
        var selections = $("#stock-table").bootstrapTable("getSelections");

        var stock = [];

        selections.forEach(function(item) {
            stock.push(item.pk);
        });

        launchModalForm("/order/purchase-order/order-parts/", {
            data: {
                stock: stock,
            },
        });
    });

    $("#multi-item-delete").click(function() {
        var selections = $("#stock-table").bootstrapTable("getSelections");

        var stock = [];

        selections.forEach(function(item) {
            stock.push(item.pk);
        });

        stockAdjustment('delete');
    });
}

function loadStockTrackingTable(table, options) {

    var cols = [
        {
            field: 'pk',
            visible: false,
        },
        {
            field: 'date',
            title: 'Date',
            sortable: true,
            formatter: function(value, row, index, field) {
                var m = moment(value);
                if (m.isValid()) {
                    var html = m.format('dddd MMMM Do YYYY'); // + '
' + m.format('h:mm a');
                    return html;
                }

                return 'N/A';
            }
        },
    ];

    // If enabled, provide a link to the referenced StockItem
    if (options.partColumn) {
        cols.push({
            field: 'item',
            title: 'Stock Item',
            sortable: true,
            formatter: function(value, row, index, field) {
                return renderLink(value.part_name, value.url);
            }
        });
    }

    // Stock transaction description
    cols.push({
        field: 'title',
        title: 'Description',
        sortable: true,
        formatter: function(value, row, index, field) {
            var html = "" + value + "";

            if (row.notes) {
                html += "
" + row.notes + "";
            }

            if (row.link) {
                html += "
" + row.link + "";
            }

            return html;
        }
    });

    cols.push({
        field: 'quantity',
        title: 'Quantity',
        formatter: function(value, row, index, field) {
            return parseFloat(value);
        },
    });

    cols.push({
        sortable: true,
        field: 'user',
        title: 'User',
        formatter: function(value, row, index, field) {
            if (value)
            {
                // TODO - Format the user's first and last names
                return value.username;
            }
            else
            {
                return "No user information";
            }
        }
    });

    cols.push({
        sortable: false,
        formatter: function(value, row, index, field) {
            // Manually created entries can be edited or deleted
            if (!row.system) {
                var bEdit = "<button title='Edit tracking entry' class='btn btn-entry-edit btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/edit/'></button>";
                var bDel = "<button title='Delete tracking entry' class='btn btn-entry-delete btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/delete/'></button>";

                return "
" + bEdit + bDel + "
";
            } else {
                return "";
            }
        }
    });

    table.inventreeTable({
        method: 'get',
        queryParams: options.params,
        columns: cols,
        url: options.url,
    });

    if (options.buttons) {
        linkButtonsToSelection(table, options.buttons);
    }

    table.on('click', '.btn-entry-edit', function() {
        var button = $(this);

        launchModalForm(button.attr('url'), {
            reload: true,
        });
    });

    table.on('click', '.btn-entry-delete', function() {
        var button = $(this);

        launchModalForm(button.attr('url'), {
            reload: true,
        });
    });
}<|endoftext|>


<commit_before>var heroes = { bans1: [], bans2: [], picks1: [], picks2: [] };
var command = io(document.location.origin+'/livedraft');
var livedraft;
var draftid;

command.on('connect', function(data) {
    command.emit('join', 'livedraft');
});

command.on('joined', function(data) {
    console.log('(command) joined ' + data);
});

command.on('message', function(data) {
    switch (data.action) {
        case "connect":
            draftid = data.value;
            livedraftConnect();
            console.log("initiating connection to livedraft url");
            break;
        case "disconnect":
            livedraft.disconnect();
            console.log("administratively disconnected");
            break;
        default:
            console.log(data);
    }
});

command.on('reload', function(data){
    console.log("reloading...");
    location.reload();
});

function livedraftConnect() {
    livedraft = io(livedraft_url,{query:"draft_id="+draftid});
    livedraft.on('connect', function(data) {
        console.log("connected to livedraft "+draftid);
    });
    livedraft.on('draft_update', function(data){
        if (typeof data.heroes !== "undefined") {
            $('#time-pool').text(data.timer);
            $('#blue-pool').text(data.timer_bonus1);
            $('#red-pool').text(data.timer_bonus2);
            if (JSON.stringify(data.heroes) !== JSON.stringify(heroes)) {
                if (JSON.stringify(data.heroes.bans1) !== JSON.stringify(heroes.bans1)) {
                    $.each($(data.heroes.bans1).not(heroes.bans1), function(i, val) {
                        var num = data.heroes.bans1.indexOf(val)+1;
                        console.log("Team 1 Banned: " + num + " - " + translated[val] );
                        updateValue({ id: 'blue-b'+num, value: translated[val] });
                    });
                }
                if (JSON.stringify(data.heroes.bans2) !== JSON.stringify(heroes.bans2)) {
                    $.each($(data.heroes.bans2).not(heroes.bans2), function(i, val) {
                        var num = data.heroes.bans2.indexOf(val)+1;
                        console.log("Team 2 Banned: " + num + " - " + translated[val] );
                        updateValue({ id: 'red-b'+num, value: translated[val] });
                    });
                }
                if (JSON.stringify(data.heroes.picks1) !== JSON.stringify(heroes.picks1)) {
                    $.each($(data.heroes.picks1).not(heroes.picks1), function(i, val) {
                        var num = data.heroes.picks1.indexOf(val)+1;
                        console.log("Team 1 Picked: " + num + " - " + translated[val] );
                        updateValue({ id: 'blue-p'+num, value: translated[val] });
                    });
                }
                if (JSON.stringify(data.heroes.picks2) !== JSON.stringify(heroes.picks2)) {
                    $.each($(data.heroes.picks2).not(heroes.picks2), function(i, val) {
                        var num = data.heroes.picks2.indexOf(val)+1;
                        console.log("Team 2 Picked: " + num + " - " + translated[val] );
                        updateValue({ id: 'red-p'+num, value: translated[val] });
                    });
                }
                console.log(data);
                heroes = data.heroes;
                var team = [null, "blue", "red"];
                var stage = [null, null, 'b', 'p'];
                $('#'+team[data.turn]+'-'+stage[data.status]+data.turn_index+' .overlay-bg').removeClass('waiting').addClass('animated myturn');
                $('#time-pool').text(data.timer);
                $('#blue-pool').text(data.timer_bonus1);
                $('#red-pool').text(data.timer_bonus2);
            }
        } else {
            console.log(data);
        }
        if ((data.status === 3) && (data.done === 1)) {
            livedraft.disconnect();
            console.log("draft over");
        }
    });
}

var translated = {
    383: 'abathur',
    345: 'anubarak',
    367: 'arthas',
    343: 'azmodan',
    347: 'brightwing',
    355: 'chen',
    375: 'diablo',
    385: 'etc',
    387: 'falstad',
    379: 'gazlowe',
    377: 'illidan',
    341: 'jaina',
    415: 'kaelthas',
    339: 'kerrigan',
    357: 'lili',
    407: 'the-lost-vikings',
    381: 'malfurion',
    349: 'muradin',
    359: 'murky',
    373: 'nazeebo',
    389: 'nova',
    369: 'raynor',
    363: 'rehgar',
    391: 'sgt-hammer',
    393: 'sonya',
    395: 'stitches',
    413: 'sylvanas',
    365: 'tassadar',
    403: 'thrall',
    351: 'tychus',
    353: 'tyrael',
    397: 'tyrande',
    399: 'uther',
    371: 'valla',
    361: 'zagara',
    401: 'zeratul'
    };

// $(document).click(function() { demo();});

function demo() {
    updateValue({ id: 'blue-name', value: 'Cloud9 Maelstrom' });
    updateValue({ id: 'red-name', value: 'Tempo Storm' });
    var base = 3000;

    setTimeout( function() { updateValue({ id: 'blue-b1',  value: 'valla' }); $('#red-b1 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*1);
    setTimeout( function() { updateValue({ id: 'red-b1',   value: 'kaelthas' }); $('#blue-p1 .overlay-bg').removeClass('waiting').addClass('animated myturn'); },  base*2);
    setTimeout( function() { updateValue({ id: 'blue-p1',  value: 'valla' }); $('#red-p1 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#red-p2 .overlay-bg').removeClass('waiting').addClass('animated myturn');}, base*3);
    setTimeout( function() { updateValue({ id: 'red-p1',   value: 'kaelthas' });  }, base*4);
    setTimeout( function() { updateValue({ id: 'red-p2',   value: 'uther' }); $('#blue-p2 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#blue-p3 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*5);
    setTimeout( function() { updateValue({ id: 'blue-p2',  value: 'illidan' });  }, base*6);
    setTimeout( function() { updateValue({ id: 'blue-p3',  value: 'anubarak' }); $('#red-p3 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#red-p4 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*7);
    setTimeout( function() { updateValue({ id: 'red-p3',   value: 'gazlowe' });  }, base*8);
    setTimeout( function() { updateValue({ id: 'red-p4',   value: 'murky' }); $('#blue-p4 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#blue-p5 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*9);
    setTimeout( function() { updateValue({ id: 'blue-p4',  value: 'kerrigan' }); }, base*10);
    setTimeout( function() { updateValue({ id: 'blue-p5',  value: 'chen' }); $('#red-p5 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*11);
    setTimeout( function() { updateValue({ id: 'red-p5',   value: 'sgt-hammer' }); }, base*12);

    return true;
}<commit_msg>fix - prevent websocket connection happening automatically<commit_after>var heroes = { bans1: [], bans2: [], picks1: [], picks2: [] };
var command = io(document.location.origin+'/livedraft');
var livedraft = io(false);
var draftid;

command.on('connect', function(data) {
    command.emit('join', 'livedraft');
});

command.on('joined', function(data) {
    console.log('(command) joined ' + data);
});

command.on('message', function(data) {
    switch (data.action) {
        case "connect":
            draftid = data.value;
            livedraftConnect();
            console.log("initiating connection to livedraft url");
            break;
        case "disconnect":
            livedraft.disconnect();
            console.log("administratively disconnected");
            break;
        default:
            console.log(data);
    }
});

command.on('reload', function(data){
    console.log("reloading...");
    location.reload();
});

function livedraftConnect() {
    livedraft = io(livedraft_url,{query:"draft_id="+draftid});
    livedraft.on('connect', function(data) {
        console.log("connected to livedraft "+draftid);
    });
    livedraft.on('draft_update', function(data){
        if (typeof data.heroes !== "undefined") {
            $('#time-pool').text(data.timer);
            $('#blue-pool').text(data.timer_bonus1);
            $('#red-pool').text(data.timer_bonus2);
            if (JSON.stringify(data.heroes) !== JSON.stringify(heroes)) {
                if (JSON.stringify(data.heroes.bans1) !== JSON.stringify(heroes.bans1)) {
                    $.each($(data.heroes.bans1).not(heroes.bans1), function(i, val) {
                        var num = data.heroes.bans1.indexOf(val)+1;
                        console.log("Team 1 Banned: " + num + " - " + translated[val] );
                        updateValue({ id: 'blue-b'+num, value: translated[val] });
                    });
                }
                if (JSON.stringify(data.heroes.bans2) !== JSON.stringify(heroes.bans2)) {
                    $.each($(data.heroes.bans2).not(heroes.bans2), function(i, val) {
                        var num = data.heroes.bans2.indexOf(val)+1;
                        console.log("Team 2 Banned: " + num + " - " + translated[val] );
                        updateValue({ id: 'red-b'+num, value: translated[val] });
                    });
                }
                if (JSON.stringify(data.heroes.picks1) !== JSON.stringify(heroes.picks1)) {
                    $.each($(data.heroes.picks1).not(heroes.picks1), function(i, val) {
                        var num = data.heroes.picks1.indexOf(val)+1;
                        console.log("Team 1 Picked: " + num + " - " + translated[val] );
                        updateValue({ id: 'blue-p'+num, value: translated[val] });
                    });
                }
                if (JSON.stringify(data.heroes.picks2) !== JSON.stringify(heroes.picks2)) {
                    $.each($(data.heroes.picks2).not(heroes.picks2), function(i, val) {
                        var num = data.heroes.picks2.indexOf(val)+1;
                        console.log("Team 2 Picked: " + num + " - " + translated[val] );
                        updateValue({ id: 'red-p'+num, value: translated[val] });
                    });
                }
                console.log(data);
                heroes = data.heroes;
                var team = [null, "blue", "red"];
                var stage = [null, null, 'b', 'p'];
                $('#'+team[data.turn]+'-'+stage[data.status]+data.turn_index+' .overlay-bg').removeClass('waiting').addClass('animated myturn');
                $('#time-pool').text(data.timer);
                $('#blue-pool').text(data.timer_bonus1);
                $('#red-pool').text(data.timer_bonus2);
            }
        } else {
            console.log(data);
        }
        if ((data.status === 3) && (data.done === 1)) {
            livedraft.disconnect();
            console.log("draft over");
        }
    });
}

var translated = {
    383: 'abathur',
    345: 'anubarak',
    367: 'arthas',
    343: 'azmodan',
    347: 'brightwing',
    355: 'chen',
    375: 'diablo',
    385: 'etc',
    387: 'falstad',
    379: 'gazlowe',
    377: 'illidan',
    341: 'jaina',
    415: 'kaelthas',
    339: 'kerrigan',
    357: 'lili',
    407: 'the-lost-vikings',
    381: 'malfurion',
    349: 'muradin',
    359: 'murky',
    373: 'nazeebo',
    389: 'nova',
    369: 'raynor',
    363: 'rehgar',
    391: 'sgt-hammer',
    393: 'sonya',
    395: 'stitches',
    413: 'sylvanas',
    365: 'tassadar',
    403: 'thrall',
    351: 'tychus',
    353: 'tyrael',
    397: 'tyrande',
    399: 'uther',
    371: 'valla',
    361: 'zagara',
    401: 'zeratul'
    };

// $(document).click(function() { demo();});

function demo() {
    updateValue({ id: 'blue-name', value: 'Cloud9 Maelstrom' });
    updateValue({ id: 'red-name', value: 'Tempo Storm' });
    var base = 3000;

    setTimeout( function() { updateValue({ id: 'blue-b1',  value: 'valla' }); $('#red-b1 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*1);
    setTimeout( function() { updateValue({ id: 'red-b1',   value: 'kaelthas' }); $('#blue-p1 .overlay-bg').removeClass('waiting').addClass('animated myturn'); },  base*2);
    setTimeout( function() { updateValue({ id: 'blue-p1',  value: 'valla' }); $('#red-p1 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#red-p2 .overlay-bg').removeClass('waiting').addClass('animated myturn');}, base*3);
    setTimeout( function() { updateValue({ id: 'red-p1',   value: 'kaelthas' });  }, base*4);
    setTimeout( function() { updateValue({ id: 'red-p2',   value: 'uther' }); $('#blue-p2 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#blue-p3 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*5);
    setTimeout( function() { updateValue({ id: 'blue-p2',  value: 'illidan' });  }, base*6);
    setTimeout( function() { updateValue({ id: 'blue-p3',  value: 'anubarak' }); $('#red-p3 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#red-p4 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*7);
    setTimeout( function() { updateValue({ id: 'red-p3',   value: 'gazlowe' });  }, base*8);
    setTimeout( function() { updateValue({ id: 'red-p4',   value: 'murky' }); $('#blue-p4 .overlay-bg').removeClass('waiting').addClass('animated myturn'); $('#blue-p5 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*9);
    setTimeout( function() { updateValue({ id: 'blue-p4',  value: 'kerrigan' }); }, base*10);
    setTimeout( function() { updateValue({ id: 'blue-p5',  value: 'chen' }); $('#red-p5 .overlay-bg').removeClass('waiting').addClass('animated myturn'); }, base*11);
    setTimeout( function() { updateValue({ id: 'red-p5',   value: 'sgt-hammer' }); }, base*12);

    return true;
}<|endoftext|>


<commit_before>var _ = require('lodash')

var _zzNode = require('./zzNode.js').zzNode
var _types = require('./types.js').types
var _uuid = require('./uuid.js').uuid
var _strings = require('./strings.js').strings

// designed to work with a nodejs server
// Uses only those zzb features not dependent on jquery/BootstrapDialog

// name
//   the name of the global cache object to use

exports.zzbLoader = function(options) {
  options = _.merge({name: 'zzb'})

  // has it already been loaded yet?
  if (global[options.zzb]) {
    return global[options.zzb]
  }

  var _zzb = function () {}
  _zzb.prototype.zzNode = _zzNode
  _zzb.prototype.types = new _types
  _zzb.prototype.uuid = new _uuid
  _zzb.prototype.strings = new _strings

  global[options.name] = new _zzb()

  // always gets a copy b/c referenced libs depends on it
  global['zzb'] = global[options.name]

  return global[options.name]
}
<commit_msg>server-side global cache assignment<commit_after>var _ = require('lodash')

var _zzNode = require('./zzNode.js').zzNode
var _types = require('./types.js').types
var _uuid = require('./uuid.js').uuid
var _strings = require('./strings.js').strings

// designed to work with a nodejs server
// Uses only those zzb features not dependent on jquery/BootstrapDialog

// name
//   the name of the global cache object to use

exports.zzbLoader = function(options) {
  options = _.merge({name: 'zzb', overwriteCached: false})

  // has it already been loaded yet?
  if (global[options.zzb] && !options.overwriteCached) {
    return global[options.zzb]
  }

  var _zzb = function () {}
  _zzb.prototype.zzNode = _zzNode
  _zzb.prototype.types = new _types
  _zzb.prototype.uuid = new _uuid
  _zzb.prototype.strings = new _strings

  // always gets a copy b/c referenced libs depends on it
  global['zzb'] = new _zzb()

  if (global[options.zzb] && options.overwriteCached) {
    global[options.name]
    global[options.name].prototype.zzNode = _zzNode
    global[options.name].prototype.types = new _types
    global[options.name].prototype.uuid = new _uuid
    global[options.name].prototype.strings = new _strings
  } else {
    global[options.name] = global['zzb']
  }

  return global[options.name]
}
<|endoftext|>


<commit_before>function(doc) {
if (doc.type == "Vrac"){
    for(certification in doc.declaration) {
    	if (certification.match(/^certification/g)) {
    		for(genre in doc.declaration[certification]) {
    	    	if (genre.match(/^genre/g)) {
    	    		for(appellation in doc.declaration[certification][genre]) {
    	    			if (appellation.match(/^appellation/g)) {
 				            var code_appellation = appellation.replace("appellation_","");
    	    	    		for(mention in doc.declaration[certification][genre][appellation]) {
    	    	    			if (mention.match(/^mention/g)) {
    	    	    	    		for(lieu in doc.declaration[certification][genre][appellation][mention]) {
    	    	    	    			if (lieu.match(/^lieu/g)) {
    	    	    	    	    		for(couleur in doc.declaration[certification][genre][appellation][mention][lieu]) {
    	    	    	    	    			if (couleur.match(/^couleur/g)) {
    	    	    	    	    	    		for(cepage in doc.declaration[certification][genre][appellation][mention][lieu][couleur]) {
    	    	    	    	    	    			if (cepage.match(/^cepage/g)) {
    	    	    	    	    	    				var code_cepage = cepage.replace("cepage_","");
    	    	    	    	    	    				var numero_cepage = null;
    	    	    	    	    	    				for(detail in doc.declaration[certification][genre][appellation][mention][lieu][couleur][cepage].detail) {
    	    	    	    	    	    					var produit = doc.declaration[certification][genre][appellation][mention][lieu][couleur][cepage].detail[detail];
    	    	    	    	    	    					if (produit.actif) {
                                            				  if(doc.valide.statut == "VALIDE" || doc.valide.statut == "ENLEVEMENT"){
                                        						var produitHash = "/declaration/"+certification+"/"+genre+"/"+appellation+"/"+mention+"/"+lieu+"/"+couleur+"/"+cepage;
											var vendeurNom = "";
											if(doc.vendeur.intitule){ vendeurNom = doc.vendeur.intitule+" "; }
											vendeurNom = vendeurNom + doc.vendeur.raison_sociale;

											var acheteurNom = "";
											if(doc.acheteur.intitule){ acheteurNom = doc.acheteur.intitule+" "; }
											acheteurNom = acheteurNom + doc.acheteur.raison_sociale;

											emit(["NONSOLDE", doc.vendeur_identifiant, produitHash, doc.type_contrat],[doc.numero_visa, acheteurNom, produit.volume_propose, produit.volume_enleve, vendeurNom]);

                                              				   }
    	    	    	    	    	    					}
									 }
    	    	    	    	    	    			}
    	    	    	    	    	    		}
    	    	    	    	    			}
    	    	    	    	    		}
    	    	    	    			}
    	    	    	    		}
    	    	    			}
    	    	    		}
    	    			}
    	    		}
    	    	}
    		}
    	}
    }
}
}
<commit_msg>Vue des contrats par produit, prend aussi les contrats bouteilles et les marque comme soldé au bout de 2 ans<commit_after>function(doc) {
    if (doc.type == "Vrac"){
        for(certification in doc.declaration) {
            if (certification.match(/^certification/g)) {
                for(genre in doc.declaration[certification]) {
                    if (genre.match(/^genre/g)) {
                        for(appellation in doc.declaration[certification][genre]) {
                            if (appellation.match(/^appellation/g)) {
                                var code_appellation = appellation.replace("appellation_","");
                                for(mention in doc.declaration[certification][genre][appellation]) {
                                    if (mention.match(/^mention/g)) {
                                        for(lieu in doc.declaration[certification][genre][appellation][mention]) {
                                            if (lieu.match(/^lieu/g)) {
                                                for(couleur in doc.declaration[certification][genre][appellation][mention][lieu]) {
                                                    if (couleur.match(/^couleur/g)) {
                                                        for(cepage in doc.declaration[certification][genre][appellation][mention][lieu][couleur]) {
                                                            if (cepage.match(/^cepage/g)) {
                                                                var code_cepage = cepage.replace("cepage_","");
                                                                var numero_cepage = null;
                                                                for(detail in doc.declaration[certification][genre][appellation][mention][lieu][couleur][cepage].detail) {
                                                                    var produit = doc.declaration[certification][genre][appellation][mention][lieu][couleur][cepage].detail[detail];
                                                                    if (produit.actif) {
                                                                        if(doc.valide.date_validation){
                                                                            var produitHash = "/declaration/"+certification+"/"+genre+"/"+appellation+"/"+mention+"/"+lieu+"/"+couleur+"/"+cepage;
                                                                            var vendeurNom = "";
                                                                            if(doc.vendeur.intitule){ vendeurNom = doc.vendeur.intitule+" "; }
                                                                            vendeurNom = vendeurNom + doc.vendeur.raison_sociale;

                                                                            var acheteurNom = "";
                                                                            if(doc.acheteur.intitule){ acheteurNom = doc.acheteur.intitule+" "; }
                                                                            acheteurNom = acheteurNom + doc.acheteur.raison_sociale;

                                                                            var statut = "NONSOLDE";

                                                                            if(doc.valide.statut == "CLOTURE" && doc.type_contrat != "BOUTEILLE") {
                                                                                statut = "SOLDE";
                                                                            }

                                                                            var now = new Date();
                                                                            var annee_limite = (now.getFullYear() - 2);
                                                                            var annee_contrat = doc.valide.date_validation.split("-")[0];

                                                                            if(annee_contrat < annee_limite) {
                                                                                statut = "SOLDE";
                                                                            }

                                                                            emit([statut, doc.vendeur_identifiant, produitHash, "VIN_" + doc.type_contrat],[doc.numero_visa, acheteurNom, produit.volume_propose, produit.volume_enleve, vendeurNom]);
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// @flow

import * as React from 'react';

import genesis from 'lib/facts/genesis';
import {
  threadInfoSelector,
  ancestorThreadInfos,
} from 'lib/selectors/thread-selectors';
import { threadIsPending } from 'lib/shared/thread-utils';
import { type ThreadInfo } from 'lib/types/thread-types';

import { useSelector } from '../redux/redux-utils';
import { useStyles } from '../themes/colors';
import { SingleLine } from './single-line.react';

type Props = {|
  +threadInfo: ThreadInfo,
  +unread: ?boolean,
|};
function ThreadAncestorsLabel(props: Props): React.Node {
  const { unread, threadInfo } = props;
  const styles = useStyles(unboundStyles);
  const ancestorThreads: $ReadOnlyArray<ThreadInfo> = useSelector((state) => {
    if (!threadIsPending(threadInfo.id)) {
      return ancestorThreadInfos(threadInfo.id)(state).slice(0, -1);
    }
    const genesisThreadInfo = threadInfoSelector(state)[genesis.id];
    return genesisThreadInfo ? [genesisThreadInfo] : [];
  });

  const ancestorPath: string = React.useMemo(() => {
    const path = ancestorThreads.map((each) => each.uiName);
    return path.join(' > ');
  }, [ancestorThreads]);

  const ancestorPathStyle = React.useMemo(() => {
    return unread ? [styles.pathText, styles.unread] : styles.pathText;
  }, [styles.pathText, styles.unread, unread]);

  if (!ancestorPath) {
    return null;
  }

  return <SingleLine style={ancestorPathStyle}>{ancestorPath}</SingleLine>;
}

const unboundStyles = {
  pathText: {
    opacity: 0.8,
    fontSize: 12,
    color: 'listForegroundTertiaryLabel',
  },
  unread: {
    color: 'listForegroundLabel',
  },
};

export default ThreadAncestorsLabel;
<commit_msg>[native] Replace ">" with chevron icon in `ThreadAncestorsLabel`<commit_after>// @flow

import * as React from 'react';
import { Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome5';

import genesis from 'lib/facts/genesis';
import {
  threadInfoSelector,
  ancestorThreadInfos,
} from 'lib/selectors/thread-selectors';
import { threadIsPending } from 'lib/shared/thread-utils';
import { type ThreadInfo } from 'lib/types/thread-types';

import { useSelector } from '../redux/redux-utils';
import { useColors, useStyles } from '../themes/colors';

type Props = {|
  +threadInfo: ThreadInfo,
  +unread: ?boolean,
|};
function ThreadAncestorsLabel(props: Props): React.Node {
  const { unread, threadInfo } = props;
  const styles = useStyles(unboundStyles);
  const colors = useColors();
  const ancestorThreads: $ReadOnlyArray<ThreadInfo> = useSelector((state) => {
    if (!threadIsPending(threadInfo.id)) {
      return ancestorThreadInfos(threadInfo.id)(state).slice(0, -1);
    }
    const genesisThreadInfo = threadInfoSelector(state)[genesis.id];
    return genesisThreadInfo ? [genesisThreadInfo] : [];
  });

  const chevronIcon = React.useMemo(
    () => (
      <Icon
        name="chevron-right"
        size={8}
        color={colors.listForegroundTertiaryLabel}
      />
    ),
    [colors.listForegroundTertiaryLabel],
  );

  const ancestorPath = React.useMemo(() => {
    const path = [];
    for (const thread of ancestorThreads) {
      path.push(<Text key={thread.id}>{thread.uiName}</Text>);
      path.push(
        <View key={`>${thread.id}`} style={styles.chevron}>
          {chevronIcon}
        </View>,
      );
    }
    path.pop();
    return path;
  }, [ancestorThreads, chevronIcon, styles.chevron]);

  const ancestorPathStyle = React.useMemo(() => {
    return unread ? [styles.pathText, styles.unread] : styles.pathText;
  }, [styles.pathText, styles.unread, unread]);

  if (!ancestorPath) {
    return null;
  }

  return (
    <Text numberOfLines={1} style={ancestorPathStyle}>
      {ancestorPath}
    </Text>
  );
}

const unboundStyles = {
  pathText: {
    opacity: 0.8,
    fontSize: 12,
    color: 'listForegroundTertiaryLabel',
  },
  unread: {
    color: 'listForegroundLabel',
  },
  chevron: {
    paddingHorizontal: 3,
  },
};

export default ThreadAncestorsLabel;
<|endoftext|>


<commit_before>/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */

var PORT = process.env.PORT || 9000

var Seneca = require('seneca')

Seneca({tag: 'info'})
  .listen(PORT)

  .use('../info.js')

  .add('role:info,need:part', function (msg, reply) {
    reply()

    this
      .act(msg,{part:'npm'})
      .act(msg,{part:'github'})
  })

  .client({pin:'role:info,need:part,part:npm', host:'npm', port:PORT})
  .client({pin:'role:info,need:part,part:github', host:'github', port:PORT})
<commit_msg>stage<commit_after>/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */

var PORT = process.env.PORT || 9000

var Seneca = require('seneca')

Seneca({tag: 'info'})
  .listen(PORT)

  .use('redis-transport')
  .use('../info.js')

  .client({pin:'role:info,need:part', type:'redis', host:'redis'})
  .listen({pin:'role:info,collect:part', type:'redis', host:'redis'})
<|endoftext|>