<commit_before>CustomUploadButton = {
    /*
     * Dummy version of Valum's file uploader widget.
     * Overrides everything so I can use a simple file widget.
     * Only necessary so as not to throw errors.
     */
    init: function(o) {
        return this;
    },

    reset: function() {
    }
}

PANDA.views.DataUpload = Backbone.View.extend({
    el: $("#content"),

    events: {
        "click #upload-begin":         "begin_event",
        "click #upload-continue":      "continue_event",
        "click #upload-start-over":    "start_over_event"
    },

    file_uploader: null,
    dataset: null,
    upload: null,
    dataset_is_new: false,

    initialize: function() {
        _.bindAll(this);
    },

    reset: function(dataset_slug) {
        this.file_uploader = null;
        this.upload = null;

        if (dataset_slug) {
            this.dataset_is_new = false;
            this.dataset = new PANDA.models.Dataset({ resource_uri: PANDA.API + "/dataset/" + dataset_slug + "/" });

            this.dataset.fetch({
                async: false,
                success: _.bind(function(model, response) {
                    this.render();
                }, this),
                error: _.bind(function(model, response) {
                    if (response.status == 404) {
                        Redd.goto_not_found();
                    } else {
                        Redd.goto_server_error();
                    }
                }, this)
            });
        } else {
            this.dataset_is_new = true;
            this.dataset = null;
            this.render();
        }
    },

    render: function() {
        if (this.dataset) {
            dataset_json = this.dataset.toJSON();
        } else {
            dataset_json = null;
        }

        var context = PANDA.utils.make_context({ dataset: dataset_json });

        this.el.html(PANDA.templates.data_upload(context));

        this.file_uploader = new qq.FileUploaderBasic({
            action: "/data_upload/",
            multiple: false,
            allowedExtensions: ["csv", "xls", "xlsx"],
            onSubmit: this.on_submit,
            onProgress: this.on_progress,
            onComplete: this.on_complete,
            showMessage: this.step_one_error_message,
            sizeLimit: PANDA.settings.MAX_UPLOAD_SIZE,
            messages: {
                typeError: "{file} is not a supported type. Only CSV, XLS, and XLSX files are currently supported.",
                sizeError: "{file} is too large, the maximum file size is " + PANDA.settings.MAX_UPLOAD_SIZE + " bytes.",
                emptyError: "{file} is empty.",
                onLeave: "Your file is being uploaded, if you leave now the upload will be cancelled."
            }
        });

        // Create upload button
        var upload_button = CustomUploadButton.init();
        this.file_uploader._button = upload_button;

        $("#upload-file").bind("change", this.on_file_selected);
    },

    on_file_selected: function() {
        var filename = $("#upload-file").val();
        var ext = filename.substr(filename.lastIndexOf('.') + 1);

        if (ext == 'xls' || ext == 'xlsx') {
            $("#step-1 .notes.xls").show();
        } else {
            $("#step-1 .notes.xls").hide();
        }

        $("#upload-begin").removeAttr("disabled");
    },

    on_submit: function(id, fileName) {
        /*
         * Handler for when a file upload starts.
         */
        if (this.dataset) {
            this.file_uploader.setParams({ dataset_slug: this.dataset.get("slug") });
        }

        this.step_two();
    },

    on_progress: function(id, fileName, loaded, total) {
        /*
         * Handler for when a file upload reports its progress.
         */
        var pct = Math.floor(loaded / total * 100);

        $(".upload-progress .progress-value").css("width", pct + "%");
        $(".upload-progress .progress-text").html('' + pct + '% uploaded');
    },

    on_complete: function(id, fileName, responseJSON) {
        /*
         * Handler for when a file upload is completed.
         */
        if (responseJSON.success) {
            this.upload = new PANDA.models.DataUpload(responseJSON);

            // Verify headers match
            if (this.dataset && this.dataset.get("columns")) {
                if (!this.upload.get("columns").equals(this.dataset.get("columns"))) {
                    this.step_two_error_message("The columns headers in this file do not match those of the existing data.");
                    return;
                }
            }

            this.step_three();
        } else if (responseJSON.forbidden) {
            Redd.goto_login(window.location.hash);
        } else {
            this.step_two_error_message(responseJSON.error_message);
        }
    },

    step_one_error_message: function(message) {
        $("#upload-file").attr("disabled", true);
        $("#step-1-alert").alert("alert-error", message + ' <input id="step-1-start-over" type="button" class="btn" value="Try again" />' , false);
        $("#step-1-start-over").click(this.start_over_event);
    },

    step_two_error_message: function(message) {
        $("#step-2-alert").alert("alert-error", message + ' <input id="step-2-start-over" type="button" class="btn" value="Try again" />' , false);
        $("#step-2-start-over").click(this.start_over_event);
    },

    step_three_error_message: function(message) {
        $("#step-3-alert").alert("alert-error", message + ' <input id="step-3-start-over" type="button" class="btn" value="Try again" />' , false);
        $("#step-3-start-over").click(this.start_over_event);
    },

    step_one: function() {
        $(".alert").hide();
        $("#step-2").addClass("disabled");
        $("#step-2 .notes").hide();
        this.on_progress(null, null, 0, 1);
        $("#step-3 .sample-data").hide();
        $("#step-3 .sample-data").empty();
        $("#step-3").addClass("disabled");
        $("#upload-continue").attr("disabled", true);
        $("#upload-start-over").attr("disabled", true);

        $("#upload-file").attr("disabled", false);
        $("#upload-begin").attr("disabled", false);
        $("#step-1").removeClass("disabled");

        $("#step-3").removeClass("well");
        $("#step-1").addClass("well");
    },

    step_two: function() {
        $("#upload-begin").attr("disabled", true);
        $("#step-1").addClass("disabled");
        $("#upload-file").attr("disabled", true);

        $("#step-2").removeClass("disabled");

        $("#step-1").removeClass("well");
        $("#step-2").addClass("well");
    },

    step_three: function() {
        $("#step-2").addClass("disabled");

        sample_data_html = PANDA.templates.inline_sample_data(this.upload.toJSON());
        $("#step-3 .sample-data").html(sample_data_html);
        $("#step-3 .sample-data").show();

        $("#step-3").removeClass("disabled");
        $("#upload-continue").attr("disabled", false);
        $("#upload-start-over").attr("disabled", false);

        $("#step-2").removeClass("well");
        $("#step-3").addClass("well");
    },

    begin_event: function() {
        // Initiate upload
        this.file_uploader._onInputChange($("#upload-file")[0]);
    },

    continue_event: function() {
        fileName = this.upload.get("original_filename");

        if (!this.dataset) {
            this.dataset = new PANDA.models.Dataset({
                name: fileName.substr(0, fileName.lastIndexOf('.')) || fileName,
            });

            this.dataset.save({}, { async: false });
        }

        this.dataset.data_uploads.add(this.upload);
        this.dataset.patch({}, { async: false })

        // Begin import, runs synchronously so errors may be caught immediately
        this.dataset.import_data(
            this.upload.get("id"),
            _.bind(function() {
                    Redd.goto_dataset_view(this.dataset.get("slug"));
            }, this),
            _.bind(function(error) {
                // Preemptive import errors (mismatched columns, etc.)
                this.upload.destroy()
                this.step_three_error_message(error.error_message);
            }, this)
        );
    },

    start_over_event: function() {
        if (this.upload) {
            this.upload.destroy({ async: false });
            this.upload = null;
        }

        if (this.dataset_is_new && this.dataset) {
            this.dataset.destroy({ async: false });
            this.dataset = null;
        }

        if (this.dataset) {
            this.reset(this.dataset.get("slug"));
        } else {
            this.reset();
        }
    }
});

<commit_msg>Disable continue and start-over on click. Closes #407.<commit_after>CustomUploadButton = {
    /*
     * Dummy version of Valum's file uploader widget.
     * Overrides everything so I can use a simple file widget.
     * Only necessary so as not to throw errors.
     */
    init: function(o) {
        return this;
    },

    reset: function() {
    }
}

PANDA.views.DataUpload = Backbone.View.extend({
    el: $("#content"),

    events: {
        "click #upload-begin":         "begin_event",
        "click #upload-continue":      "continue_event",
        "click #upload-start-over":    "start_over_event"
    },

    file_uploader: null,
    dataset: null,
    upload: null,
    dataset_is_new: false,

    initialize: function() {
        _.bindAll(this);
    },

    reset: function(dataset_slug) {
        this.file_uploader = null;
        this.upload = null;

        if (dataset_slug) {
            this.dataset_is_new = false;
            this.dataset = new PANDA.models.Dataset({ resource_uri: PANDA.API + "/dataset/" + dataset_slug + "/" });

            this.dataset.fetch({
                async: false,
                success: _.bind(function(model, response) {
                    this.render();
                }, this),
                error: _.bind(function(model, response) {
                    if (response.status == 404) {
                        Redd.goto_not_found();
                    } else {
                        Redd.goto_server_error();
                    }
                }, this)
            });
        } else {
            this.dataset_is_new = true;
            this.dataset = null;
            this.render();
        }
    },

    render: function() {
        if (this.dataset) {
            dataset_json = this.dataset.toJSON();
        } else {
            dataset_json = null;
        }

        var context = PANDA.utils.make_context({ dataset: dataset_json });

        this.el.html(PANDA.templates.data_upload(context));

        this.file_uploader = new qq.FileUploaderBasic({
            action: "/data_upload/",
            multiple: false,
            allowedExtensions: ["csv", "xls", "xlsx"],
            onSubmit: this.on_submit,
            onProgress: this.on_progress,
            onComplete: this.on_complete,
            showMessage: this.step_one_error_message,
            sizeLimit: PANDA.settings.MAX_UPLOAD_SIZE,
            messages: {
                typeError: "{file} is not a supported type. Only CSV, XLS, and XLSX files are currently supported.",
                sizeError: "{file} is too large, the maximum file size is " + PANDA.settings.MAX_UPLOAD_SIZE + " bytes.",
                emptyError: "{file} is empty.",
                onLeave: "Your file is being uploaded, if you leave now the upload will be cancelled."
            }
        });

        // Create upload button
        var upload_button = CustomUploadButton.init();
        this.file_uploader._button = upload_button;

        $("#upload-file").bind("change", this.on_file_selected);
    },

    on_file_selected: function() {
        var filename = $("#upload-file").val();
        var ext = filename.substr(filename.lastIndexOf('.') + 1);

        if (ext == 'xls' || ext == 'xlsx') {
            $("#step-1 .notes.xls").show();
        } else {
            $("#step-1 .notes.xls").hide();
        }

        $("#upload-begin").removeAttr("disabled");
    },

    on_submit: function(id, fileName) {
        /*
         * Handler for when a file upload starts.
         */
        if (this.dataset) {
            this.file_uploader.setParams({ dataset_slug: this.dataset.get("slug") });
        }

        this.step_two();
    },

    on_progress: function(id, fileName, loaded, total) {
        /*
         * Handler for when a file upload reports its progress.
         */
        var pct = Math.floor(loaded / total * 100);

        $(".upload-progress .progress-value").css("width", pct + "%");
        $(".upload-progress .progress-text").html('' + pct + '% uploaded');
    },

    on_complete: function(id, fileName, responseJSON) {
        /*
         * Handler for when a file upload is completed.
         */
        if (responseJSON.success) {
            this.upload = new PANDA.models.DataUpload(responseJSON);

            // Verify headers match
            if (this.dataset && this.dataset.get("columns")) {
                if (!this.upload.get("columns").equals(this.dataset.get("columns"))) {
                    this.step_two_error_message("The columns headers in this file do not match those of the existing data.");
                    return;
                }
            }

            this.step_three();
        } else if (responseJSON.forbidden) {
            Redd.goto_login(window.location.hash);
        } else {
            this.step_two_error_message(responseJSON.error_message);
        }
    },

    step_one_error_message: function(message) {
        $("#upload-file").attr("disabled", true);
        $("#step-1-alert").alert("alert-error", message + ' <input id="step-1-start-over" type="button" class="btn" value="Try again" />' , false);
        $("#step-1-start-over").click(this.start_over_event);
    },

    step_two_error_message: function(message) {
        $("#step-2-alert").alert("alert-error", message + ' <input id="step-2-start-over" type="button" class="btn" value="Try again" />' , false);
        $("#step-2-start-over").click(this.start_over_event);
    },

    step_three_error_message: function(message) {
        $("#step-3-alert").alert("alert-error", message + ' <input id="step-3-start-over" type="button" class="btn" value="Try again" />' , false);
        $("#step-3-start-over").click(this.start_over_event);
    },

    step_one: function() {
        $(".alert").hide();
        $("#step-2").addClass("disabled");
        $("#step-2 .notes").hide();
        this.on_progress(null, null, 0, 1);
        $("#step-3 .sample-data").hide();
        $("#step-3 .sample-data").empty();
        $("#step-3").addClass("disabled");
        $("#upload-continue").attr("disabled", true);
        $("#upload-start-over").attr("disabled", true);

        $("#upload-file").attr("disabled", false);
        $("#upload-begin").attr("disabled", false);
        $("#step-1").removeClass("disabled");

        $("#step-3").removeClass("well");
        $("#step-1").addClass("well");
    },

    step_two: function() {
        $("#upload-begin").attr("disabled", true);
        $("#step-1").addClass("disabled");
        $("#upload-file").attr("disabled", true);

        $("#step-2").removeClass("disabled");

        $("#step-1").removeClass("well");
        $("#step-2").addClass("well");
    },

    step_three: function() {
        $("#step-2").addClass("disabled");

        sample_data_html = PANDA.templates.inline_sample_data(this.upload.toJSON());
        $("#step-3 .sample-data").html(sample_data_html);
        $("#step-3 .sample-data").show();

        $("#step-3").removeClass("disabled");
        $("#upload-continue").attr("disabled", false);
        $("#upload-start-over").attr("disabled", false);

        $("#step-2").removeClass("well");
        $("#step-3").addClass("well");
    },

    begin_event: function() {
        // Initiate upload
        this.file_uploader._onInputChange($("#upload-file")[0]);
    },

    continue_event: function() {
        // Prevent double-clicks
        $("#upload-continue").attr("disabled", true);
        $("#upload-start-over").attr("disabled", true);

        fileName = this.upload.get("original_filename");

        if (!this.dataset) {
            this.dataset = new PANDA.models.Dataset({
                name: fileName.substr(0, fileName.lastIndexOf('.')) || fileName,
            });

            this.dataset.save({}, { async: false });
        }

        this.dataset.data_uploads.add(this.upload);
        this.dataset.patch({}, { async: false })

        // Begin import, runs synchronously so errors may be caught immediately
        this.dataset.import_data(
            this.upload.get("id"),
            _.bind(function() {
                    Redd.goto_dataset_view(this.dataset.get("slug"));
            }, this),
            _.bind(function(error) {
                // Preemptive import errors (mismatched columns, etc.)
                this.upload.destroy()
                this.step_three_error_message(error.error_message);
            }, this)
        );
    },

    start_over_event: function() {
        // Prevent double-clicks
        $("#upload-continue").attr("disabled", true);
        $("#upload-start-over").attr("disabled", true);

        if (this.upload) {
            this.upload.destroy({ async: false });
            this.upload = null;
        }

        if (this.dataset_is_new && this.dataset) {
            this.dataset.destroy({ async: false });
            this.dataset = null;
        }

        if (this.dataset) {
            this.reset(this.dataset.get("slug"));
        } else {
            this.reset();
        }
    }
});

<|endoftext|>


<commit_before>/**
 * jsonalyzer Python code completion
 *
 * @copyright 2015, Ajax.org B.V.
 * @author Lennart Kats <lennart add c9.io>
 */
define(function(require, exports, module) {

var baseHandler = require("plugins/c9.ide.language/base_handler");
var workerUtil = require("plugins/c9.ide.language/worker_util");

var KEYWORD_REGEX = new RegExp(
    "^(and|as|assert|break|class|continue|def|del|elif|else|except|exec|"
    + "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|"
    + "raise|return|try|while|with|yield)$"
);
var DAEMON_PORT = 10880;
var ERROR_PORT_IN_USE = 98;
var ERROR_NO_SERVER = 7;

var handler = module.exports = Object.create(baseHandler);
var pythonVersion = "python2";
var pythonPath = "";
var jediServer;
var launchCommand;
var showedJediError;
var daemon;

handler.handlesLanguage = function(language) {
    return language === "python";
};

handler.init = function(callback) {
    var emitter = handler.getEmitter();
    emitter.on("set_python_config", function(e) {
        pythonVersion = e.pythonVersion;
        pythonPath = e.pythonPath;
        if (daemon) {
            daemon.kill();
            daemon = null;
        }
    });
    emitter.on("set_python_scripts", function(e) {
        jediServer = e.jediServer;
        launchCommand = e.launchCommand;
    });
    callback();
};

handler.getIdentifierRegex = function() {
    return /\w/;
};

handler.getCompletionRegex = function() {
    return (/(\.|\b(import|from|if|while|from|raise|return) )$/);
};

handler.getExpressionPrefixRegex = function() {
     // Match strings that can be an expression or its prefix, i.e.
     // keywords/identifiers followed by whitespace and/or operators
    return /(\b\w+\s+|\b(if|while|for|print)\s*\(|([{[\-+*%<>!|&/]|==|!=)\s*)+/;
};

/**
 * Complete code at the current cursor position.
 */
handler.complete = function(doc, fullAst, pos, options, callback) {
    callDaemon("completions", handler.path, doc, pos, options, function(err, results, meta) {
        if (err) return callback(err);

        results && results.forEach(function beautifyCompletion(r) {
            r.isContextual = true;
            r.guessTooltip = true;
            r.replaceText = r.replaceText || r.name;
            r.priority = r.name[0] === "_" || r.replaceText === r.replaceText.toUpperCase() ? 3 : 4;
            r.icon = r.icon || "property";
            r.icon = r.name[0] === "_" ? r.icon.replace(/2?$/, "2") : r.icon;
            r.noDoc = options.noDoc;
            if (!r.doc)
                return;
            var docLines = r.doc.split(/\r\n|\n|\r/);
            var docBody = docLines.slice(2).join("\n");
            r.docHeadHtml = workerUtil.filterDocumentation(docLines[0]).replace(/^([A-Za-z0-9$_]+\()self, /, "$1");
            r.doc = workerUtil.filterDocumentation(docBody.replace(/``/g, "'"));
        });
        callback(null, results);
    });
};

/**
 * Jump to the definition of what's under the cursor.
 */
handler.jumpToDefinition = function(doc, fullAst, pos, options, callback) {
    callDaemon("goto_definitions", handler.path, doc, pos, options, callback);
};

/**
 * Predict how to complete code next. Did the user just type 'mat'?
 * Then we probably only have a completion 'math'. So we can predict
 * that the user may type 'math.' next and precompute completions.
 */
handler.predictNextCompletion = function(doc, fullAst, pos, options, callback) {
    var predicted = options.matches.filter(function(m) {
        return m.isContextual
            && m.icon !== "method"
            && !m.replaceText.match(KEYWORD_REGEX);
    });
    var line = doc.getLine(pos.row);
    if (predicted.length > 0 && "import".substr(0, line.length) === line)
        return callback(null, "import ");
    if (predicted.length !== 1)
        return callback();
    if (/^\s+import /.test(line))
        return callback();
    console.log("[python_worker] Predicted our next completion will be for " + predicted[0].replaceText + ".");
    callback(null, {
        predicted: predicted[0].replaceText + ".",
        showEarly: predicted[0].replaceText === "self" || predicted[0].icon === "package"
    });
};

/**
 * Invoke a function on our jedi python daemon. It runs as an HTTP daemon
 * so we use curl to send a request.
 */
function callDaemon(command, path, doc, pos, options, callback) {
    var line = doc.getLine(pos.row);
    ensureDaemon(function(err, dontRetry) {
        if (err) return callback(err);

        var start = Date.now();
        workerUtil.execAnalysis(
            "curl",
            {
                mode: "stdin",
                json: true,
                args: [
                    "-s", "--data-binary", "@-", // get input from stdin
                    "localhost:" + DAEMON_PORT + "?mode=" + command
                    + "&row=" + (pos.row + 1) + "&column=" + pos.column
                    + "&path=" + path.replace(/^\//, "")
                    + (options.noDoc ? "&nodoc=1" : ""),
                ],
            },
            function onResult(err, stdout, stderr, meta) {
                if (err) {
                    if (err.code === ERROR_NO_SERVER && !dontRetry) {
                        daemon = null;
                        return callDaemon(command, path, doc, pos, options, callback);
                    }
                    return callback(err);
                }

                if (typeof stdout !== "object")
                    return callback(new Error("Couldn't parse python-jedi output: " + stdout));

                console.log("[python_worker] " + command + " in " + (Date.now() - start)
                    + "ms (jedi: " + meta.serverTime + "ms): "
                    + line.substr(0, pos.column));

                callback(null, stdout, meta);
            }
        );
    });
}

/**
 * Make sure we're running a jedi daemon (../server/jedi_server.py).
 * It listens on a port in the workspace container or host.
 */
function ensureDaemon(callback) {
    if (daemon)
        return done(daemon.err);

    daemon = {
        err: new Error("Still starting daemon, enhance your calm"),
        kill: function() {
            this.killed = true;
        }
    };

    workerUtil.spawn(
        "bash",
        {
            args: [
                "-c", launchCommand, "--", pythonVersion,
                "$PYTHON -c '" + jediServer + "' daemon --port " + DAEMON_PORT
            ],
            env: { PYTHONPATH: pythonPath },
        },
        function(err, child) {
            var output = "";
            if (err) {
                daemon.err = err;
                return workerUtil.showError("Could not start python completion daemon. Please reload to try again.");
            }
            daemon = child;
            daemon.err = null;

            if (daemon.killed)
                daemon.kill();

            // We (re)start the daemon after 10 minutes to conserve memory
            var killTimer = setTimeout(daemon.kill.bind(daemon), 10 * 60 * 1000);

            child.stderr.on("data", function(data) {
                output += data;
                if (/Daemon listening/.test(data))
                    done();
            });
            child.on("exit", function(code) {
                if (code === ERROR_PORT_IN_USE) // someone else running daemon?
                    return done(null, true);
                if (!code || /Daemon listening/.test(output)) // everything ok, try again later
                    daemon = null;
                clearTimeout(killTimer);
                done(code && new Error("[python_worker] Daemon failed: " + output));
            });
        }
    );

    function done(err) {
        if (err && /No module named jedi/.test(err.message) && !showedJediError) {
            workerUtil.showError("Jedi not found. Please run 'pip install jedi' or 'sudo pip install jedi' to enable Python code completion.");
            showedJediError = true;
        }
        callback && callback(err);
        callback = null;
    }
}

});<commit_msg>Support some more characters in prefix regex<commit_after>/**
 * jsonalyzer Python code completion
 *
 * @copyright 2015, Ajax.org B.V.
 * @author Lennart Kats <lennart add c9.io>
 */
define(function(require, exports, module) {

var baseHandler = require("plugins/c9.ide.language/base_handler");
var workerUtil = require("plugins/c9.ide.language/worker_util");

var KEYWORD_REGEX = new RegExp(
    "^(and|as|assert|break|class|continue|def|del|elif|else|except|exec|"
    + "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|"
    + "raise|return|try|while|with|yield)$"
);
var DAEMON_PORT = 10880;
var ERROR_PORT_IN_USE = 98;
var ERROR_NO_SERVER = 7;

var handler = module.exports = Object.create(baseHandler);
var pythonVersion = "python2";
var pythonPath = "";
var jediServer;
var launchCommand;
var showedJediError;
var daemon;

handler.handlesLanguage = function(language) {
    return language === "python";
};

handler.init = function(callback) {
    var emitter = handler.getEmitter();
    emitter.on("set_python_config", function(e) {
        pythonVersion = e.pythonVersion;
        pythonPath = e.pythonPath;
        if (daemon) {
            daemon.kill();
            daemon = null;
        }
    });
    emitter.on("set_python_scripts", function(e) {
        jediServer = e.jediServer;
        launchCommand = e.launchCommand;
    });
    callback();
};

handler.getIdentifierRegex = function() {
    return /\w/;
};

handler.getCompletionRegex = function() {
    return (/(\.|\b(import|from|if|while|from|raise|return) )$/);
};

handler.getExpressionPrefixRegex = function() {
     // Match strings that can be an expression or its prefix, i.e.
     // keywords/identifiers followed by whitespace and/or operators
    return /(\b\w+\s+|\b(if|while|for|print)\s*\(|([{[\-+*%<>!|&/,%]|==|!=)\s*)+/;
};

/**
 * Complete code at the current cursor position.
 */
handler.complete = function(doc, fullAst, pos, options, callback) {
    callDaemon("completions", handler.path, doc, pos, options, function(err, results, meta) {
        if (err) return callback(err);

        results && results.forEach(function beautifyCompletion(r) {
            r.isContextual = true;
            r.guessTooltip = true;
            r.replaceText = r.replaceText || r.name;
            r.priority = r.name[0] === "_" || r.replaceText === r.replaceText.toUpperCase() ? 3 : 4;
            r.icon = r.icon || "property";
            r.icon = r.name[0] === "_" ? r.icon.replace(/2?$/, "2") : r.icon;
            r.noDoc = options.noDoc;
            if (!r.doc)
                return;
            var docLines = r.doc.split(/\r\n|\n|\r/);
            var docBody = docLines.slice(2).join("\n");
            r.docHeadHtml = workerUtil.filterDocumentation(docLines[0]).replace(/^([A-Za-z0-9$_]+\()self, /, "$1");
            r.doc = workerUtil.filterDocumentation(docBody.replace(/``/g, "'"));
        });
        callback(null, results);
    });
};

/**
 * Jump to the definition of what's under the cursor.
 */
handler.jumpToDefinition = function(doc, fullAst, pos, options, callback) {
    callDaemon("goto_definitions", handler.path, doc, pos, options, callback);
};

/**
 * Predict how to complete code next. Did the user just type 'mat'?
 * Then we probably only have a completion 'math'. So we can predict
 * that the user may type 'math.' next and precompute completions.
 */
handler.predictNextCompletion = function(doc, fullAst, pos, options, callback) {
    var predicted = options.matches.filter(function(m) {
        return m.isContextual
            && m.icon !== "method"
            && !m.replaceText.match(KEYWORD_REGEX);
    });
    var line = doc.getLine(pos.row);
    if (predicted.length > 0 && "import".substr(0, line.length) === line)
        return callback(null, "import ");
    if (predicted.length !== 1)
        return callback();
    if (/^\s+import /.test(line))
        return callback();
    console.log("[python_worker] Predicted our next completion will be for " + predicted[0].replaceText + ".");
    callback(null, {
        predicted: predicted[0].replaceText + ".",
        showEarly: predicted[0].replaceText === "self" || predicted[0].icon === "package"
    });
};

/**
 * Invoke a function on our jedi python daemon. It runs as an HTTP daemon
 * so we use curl to send a request.
 */
function callDaemon(command, path, doc, pos, options, callback) {
    var line = doc.getLine(pos.row);
    ensureDaemon(function(err, dontRetry) {
        if (err) return callback(err);

        var start = Date.now();
        workerUtil.execAnalysis(
            "curl",
            {
                mode: "stdin",
                json: true,
                args: [
                    "-s", "--data-binary", "@-", // get input from stdin
                    "localhost:" + DAEMON_PORT + "?mode=" + command
                    + "&row=" + (pos.row + 1) + "&column=" + pos.column
                    + "&path=" + path.replace(/^\//, "")
                    + (options.noDoc ? "&nodoc=1" : ""),
                ],
            },
            function onResult(err, stdout, stderr, meta) {
                if (err) {
                    if (err.code === ERROR_NO_SERVER && !dontRetry) {
                        daemon = null;
                        return callDaemon(command, path, doc, pos, options, callback);
                    }
                    return callback(err);
                }

                if (typeof stdout !== "object")
                    return callback(new Error("Couldn't parse python-jedi output: " + stdout));

                console.log("[python_worker] " + command + " in " + (Date.now() - start)
                    + "ms (jedi: " + meta.serverTime + "ms): "
                    + line.substr(0, pos.column));

                callback(null, stdout, meta);
            }
        );
    });
}

/**
 * Make sure we're running a jedi daemon (../server/jedi_server.py).
 * It listens on a port in the workspace container or host.
 */
function ensureDaemon(callback) {
    if (daemon)
        return done(daemon.err);

    daemon = {
        err: new Error("Still starting daemon, enhance your calm"),
        kill: function() {
            this.killed = true;
        }
    };

    workerUtil.spawn(
        "bash",
        {
            args: [
                "-c", launchCommand, "--", pythonVersion,
                "$PYTHON -c '" + jediServer + "' daemon --port " + DAEMON_PORT
            ],
            env: { PYTHONPATH: pythonPath },
        },
        function(err, child) {
            var output = "";
            if (err) {
                daemon.err = err;
                return workerUtil.showError("Could not start python completion daemon. Please reload to try again.");
            }
            daemon = child;
            daemon.err = null;

            if (daemon.killed)
                daemon.kill();

            // We (re)start the daemon after 10 minutes to conserve memory
            var killTimer = setTimeout(daemon.kill.bind(daemon), 10 * 60 * 1000);

            child.stderr.on("data", function(data) {
                output += data;
                if (/Daemon listening/.test(data))
                    done();
            });
            child.on("exit", function(code) {
                if (code === ERROR_PORT_IN_USE) // someone else running daemon?
                    return done(null, true);
                if (!code || /Daemon listening/.test(output)) // everything ok, try again later
                    daemon = null;
                clearTimeout(killTimer);
                done(code && new Error("[python_worker] Daemon failed: " + output));
            });
        }
    );

    function done(err) {
        if (err && /No module named jedi/.test(err.message) && !showedJediError) {
            workerUtil.showError("Jedi not found. Please run 'pip install jedi' or 'sudo pip install jedi' to enable Python code completion.");
            showedJediError = true;
        }
        callback && callback(err);
        callback = null;
    }
}

});<|endoftext|>


<commit_before>var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.

// Report crashes to our server.
require('crash-reporter').start();

// 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.
var mainWindow = null;

// Quit when all windows are closed.
app.on('window-all-closed', function() {
  // 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();
  }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
  // Create the browser window.
  mainWindow = new BrowserWindow({width: 800, height: 600});

  // and load the index.html of the app.
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

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

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // 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;
  });
});
<commit_msg>open up bigger<commit_after>var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.

// Report crashes to our server.
require('crash-reporter').start();

// 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.
var mainWindow = null;

// Quit when all windows are closed.
app.on('window-all-closed', function() {
  // 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();
  }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
  // Create the browser window.
  mainWindow = new BrowserWindow({width: 1000, height: 800});

  // and load the index.html of the app.
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

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

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // 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;
  });
});
<|endoftext|>


<commit_before>/**
  * Generate CSS Selector for an element
  *
  * Copyright (c) 2010 Ankit Ahuja
  * Dual licensed under GPL and MIT licenses.
 **/

var SelectorGenerator =  {

    generate: function(el, granularityLevel) {
            if (!el)
                return null;
            el = $(el);
            if (granularityLevel == 'low')
                return this.inspectLow(el);
            else if (granularityLevel == 'high')
                return this.inspectHigh(el, 0);
            else
                return this.inspect(el, 0);
    },

    // inspect an element and return a CSS selector for it. this is the default mode
    inspect: function(el, level) {
        var elId = el.attr('id');
        var elClass = $.trim(el.attr("class").replace('stylebot-selected', ''));

        if (elClass.length != 0)
        {
            var classes = elClass.split(" ");
            var len = classes.length;
            var response = el[0].tagName.toLowerCase();

            for (var i = 0; i < len; i++)
                response += "." + classes[i];

            return response;
        }

        if (elId.length != 0)
        {
            return "#" + elId;
        }

        // don't go beyond 2 levels up
        if (level < 2)
            return this.inspect(el.parent(), level + 1) + " " + el[0].tagName.toLowerCase();
        else
            return el[0].tagName.toLowerCase();
    },

    inspectHigh: function(el, level) {
        var elId = el.attr('id');
        if (elId.length != 0)
            return "#" + elId;

        var elClass = $.trim(el.attr("class").replace('stylebot-selected', ''));
        var elTag = el[0].tagName.toLowerCase();
        var val;

        if (level < 1)
        {
            val = this.inspectHigh(el.parent(), level + 1) + " " + elTag;
            if (elClass.length != 0)
                val += "." + elClass;
        }
        else
        {
            val = elTag;
            if (elClass.length != 0)
                val += "." + elClass;
        }
        return val;
    },

    inspectLow: function(el) {
        return el[0].tagName.toLowerCase();
    }
};<commit_msg>updated selector generator to use .prop and fixed issues in .attr<commit_after>/**
  * Generate CSS Selector for an element
  *
  * Copyright (c) 2010 Ankit Ahuja
  * Dual licensed under GPL and MIT licenses.
 **/

var SelectorGenerator =  {

    generate: function(el, granularityLevel) {
        if (!el)
            return null;

        $el = $(el);

        if (granularityLevel === 'low')
            return this.inspectLow($el);

        else if (granularityLevel === 'high')
            return this.inspectHigh($el, 0);

        else
            return this.inspect($el, 0);
    },

    // inspect an element and return a CSS selector for it. this is the default mode
    inspect: function(el, level) {
        var elClass = el.attr("class");

        if (elClass != undefined) {
            elClass = $.trim(elClass.replace('stylebot-selected', ''));

            if (elClass.length != 0)
            {
                var classes = elClass.split(" ");
                var len = classes.length;

                var selector = el.prop('tagName');
                selector = selector ? selector.toLowerCase() : "";

                for (var i = 0; i < len; i++)
                    selector += "." + classes[i];

                return selector;
            }
        }

        var elId = el.attr('id');
        if (elId != undefined)
        {
            return "#" + elId;
        }

        var elTag = el.prop('tagName');
        elTag = elTag ? elTag.toLowerCase() : "";

        // don't go beyond 2 levels up
        //
        if (level < 2)
            return this.inspect(el.parent(), level + 1) + " " + elTag;
        else
            return elTag;
    },

    inspectHigh: function(el, level) {
        var elId = el.attr('id');

        if (elId != undefined)
            return "#" + elId;

        var elClass = el.attr("class");

        if (elClass != undefined) {
            elClass = $.trim(elClass.replace('stylebot-selected', ''));
        }

        else {
            elClass = "";
        }

        var elTag = el.prop('tagName');
        elTag = elTag ? elTag.toLowerCase : "";

        var selector;

        if (level < 1)
        {
            selector = this.inspectHigh(el.parent(), level + 1) + " " + elTag;

            if (elClass.length != 0) {
                selector += "." + elClass;
            }
        }

        else
        {
            selector = elTag;

            if (elClass.length != 0) {
                selector += "." + elClass;
            }
        }

        return selector;
    },

    inspectLow: function(el) {
        var elTag = el.prop('tagName');
        return elTag ? elTag.toLowerCase() : "";
    }
};<|endoftext|>


<commit_before>/**
 * jsonalyzer Python code completion
 *
 * @copyright 2015, Ajax.org B.V.
 * @author Lennart Kats <lennart add c9.io>
 */
define(function(require, exports, module) {

var baseHandler = require("plugins/c9.ide.language/base_handler");
var workerUtil = require("plugins/c9.ide.language/worker_util");

var KEYWORD_REGEX = new RegExp(
    "^(and|as|assert|break|class|continue|def|del|elif|else|except|exec|"
    + "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|"
    + "raise|return|try|while|with|yield)$"
);
var DAEMON_PORT = 10880;
var ERROR_PORT_IN_USE = 98;
var ERROR_NO_SERVER = 7;

var handler = module.exports = Object.create(baseHandler);
var pythonVersion = "python2";
var pythonPath = "";
var jediServer;
var launchCommand;
var showedJediError;
var daemon;

handler.handlesLanguage = function(language) {
    return language === "python";
};

handler.init = function(callback) {
    var emitter = handler.getEmitter();
    emitter.on("set_python_config", function(e) {
        pythonVersion = e.pythonVersion;
        pythonPath = e.pythonPath;
        if (daemon) {
            daemon.kill();
            daemon = null;
        }
    });
    emitter.on("set_python_scripts", function(e) {
        jediServer = e.jediServer;
        launchCommand = e.launchCommand;
    });
    callback();
};

handler.getIdentifierRegex = function() {
    return /\w/;
};

handler.getCompletionRegex = function() {
    return (/(\.|\b(import|from|if|while|from|raise|return) |% )$/);
};

handler.getExpressionPrefixRegex = function() {
     // Match strings that can be an expression or its prefix, i.e.
     // keywords/identifiers followed by whitespace and/or operators
    return /(\b\w+\s+|\b(if|while|for|print)\s*\(|([{[\-+*%<>!|&/,%]|==|!=)\s*)+/;
};

/**
 * Complete code at the current cursor position.
 */
handler.complete = function(doc, fullAst, pos, options, callback) {
    callDaemon("completions", handler.path, doc, pos, options, function(err, results, meta) {
        if (err) return callback(err);

        results && results.forEach(function beautifyCompletion(r) {
            r.isContextual = true;
            r.guessTooltip = true;
            r.replaceText = r.replaceText || r.name;
            r.priority = r.name[0] === "_" || r.replaceText === r.replaceText.toUpperCase() ? 3 : 4;
            r.icon = r.icon || "property";
            r.icon = r.name[0] === "_" ? r.icon.replace(/2?$/, "2") : r.icon;
            r.noDoc = options.noDoc;
            if (!r.doc)
                return;
            var docLines = r.doc.split(/\r\n|\n|\r/);
            var docBody = docLines.slice(2).join("\n");
            r.docHeadHtml = workerUtil.filterDocumentation(docLines[0]).replace(/^([A-Za-z0-9$_]+\()self, /, "$1");
            r.doc = workerUtil.filterDocumentation(docBody.replace(/``/g, "'"));
        });
        callback(null, results);
    });
};

/**
 * Jump to the definition of what's under the cursor.
 */
handler.jumpToDefinition = function(doc, fullAst, pos, options, callback) {
    callDaemon("goto_definitions", handler.path, doc, pos, options, callback);
};

/**
 * Predict how to complete code next. Did the user just type 'mat'?
 * Then we probably only have a completion 'math'. So we can predict
 * that the user may type 'math.' next and precompute completions.
 */
handler.predictNextCompletion = function(doc, fullAst, pos, options, callback) {
    var predicted = options.matches.filter(function(m) {
        return m.isContextual
            && m.icon !== "method"
            && !m.replaceText.match(KEYWORD_REGEX);
    });
    var line = doc.getLine(pos.row);
    if (predicted.length > 0 && "import".substr(0, line.length) === line)
        return callback(null, "import ");
    if (predicted.length !== 1)
        return callback();
    if (/^\s+import /.test(line))
        return callback();
    console.log("[python_completer] Predicted our next completion will be for " + predicted[0].replaceText + ".");
    callback(null, {
        predicted: predicted[0].replaceText + ".",
        showEarly: predicted[0].replaceText === "self" || predicted[0].icon === "package"
    });
};

/**
 * Invoke a function on our jedi python daemon. It runs as an HTTP daemon
 * so we use curl to send a request.
 */
function callDaemon(command, path, doc, pos, options, callback) {
    var line = doc.getLine(pos.row);
    ensureDaemon(function(err, dontRetry) {
        if (err) return callback(err);

        var start = Date.now();
        workerUtil.execAnalysis(
            "curl",
            {
                mode: "stdin",
                json: true,
                args: [
                    "-s", "--data-binary", "@-", // get input from stdin
                    "localhost:" + DAEMON_PORT + "?mode=" + command
                    + "&row=" + (pos.row + 1) + "&column=" + pos.column
                    + "&path=" + path.replace(/^\//, "")
                    + (options.noDoc ? "&nodoc=1" : ""),
                ],
            },
            function onResult(err, stdout, stderr, meta) {
                if (err) {
                    if (err.code === ERROR_NO_SERVER && !dontRetry) {
                        daemon = null;
                        return callDaemon(command, path, doc, pos, options, callback);
                    }
                    return callback(err);
                }

                if (typeof stdout !== "object")
                    return callback(new Error("Couldn't parse python-jedi output: " + stdout));

                console.log("[python_completer] " + command + " in " + (Date.now() - start)
                    + "ms (jedi: " + meta.serverTime + "ms): "
                    + line.substr(0, pos.column));

                callback(null, stdout, meta);
            }
        );
    });
}

/**
 * Make sure we're running a jedi daemon (../server/jedi_server.py).
 * It listens on a port in the workspace container or host.
 */
function ensureDaemon(callback) {
    if (daemon)
        return done(daemon.err);

    daemon = {
        err: new Error("Still starting daemon, enhance your calm"),
        kill: function() {
            this.killed = true;
        }
    };

    workerUtil.spawn(
        "bash",
        {
            args: [
                "-c", launchCommand, "--", pythonVersion,
                "$PYTHON -c '" + jediServer + "' daemon --port " + DAEMON_PORT
            ],
            env: { PYTHONPATH: pythonPath },
        },
        function(err, child) {
            var output = "";
            if (err) {
                daemon.err = err;
                return workerUtil.showError("Could not start python completion daemon. Please reload to try again.");
            }
            daemon = child;
            daemon.err = null;

            if (daemon.killed)
                daemon.kill();

            // We (re)start the daemon after 10 minutes to conserve memory
            var killTimer = setTimeout(daemon.kill.bind(daemon), 10 * 60 * 1000);

            child.stderr.on("data", function(data) {
                output += data;
                if (/Daemon listening/.test(data))
                    done();
            });
            child.on("exit", function(code) {
                if (code === ERROR_PORT_IN_USE) // someone else running daemon?
                    return done(null, true);
                if (!code || /Daemon listening/.test(output)) // everything ok, try again later
                    daemon = null;
                clearTimeout(killTimer);
                done(code && new Error("[python_completer] Daemon failed: " + output));
            });
        }
    );

    function done(err) {
        if (err && /No module named jedi/.test(err.message) && !showedJediError) {
            workerUtil.showError("Jedi not found. Please run 'pip install jedi' or 'sudo pip install jedi' to enable Python code completion.");
            showedJediError = true;
        }
        callback && callback(err);
        callback = null;
    }
}

});<commit_msg>Rename and better explain getCacheCompletionRegex<commit_after>/**
 * jsonalyzer Python code completion
 *
 * @copyright 2015, Ajax.org B.V.
 * @author Lennart Kats <lennart add c9.io>
 */
define(function(require, exports, module) {

var baseHandler = require("plugins/c9.ide.language/base_handler");
var workerUtil = require("plugins/c9.ide.language/worker_util");

var KEYWORD_REGEX = new RegExp(
    "^(and|as|assert|break|class|continue|def|del|elif|else|except|exec|"
    + "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|"
    + "raise|return|try|while|with|yield)$"
);
var DAEMON_PORT = 10880;
var ERROR_PORT_IN_USE = 98;
var ERROR_NO_SERVER = 7;

var handler = module.exports = Object.create(baseHandler);
var pythonVersion = "python2";
var pythonPath = "";
var jediServer;
var launchCommand;
var showedJediError;
var daemon;

handler.handlesLanguage = function(language) {
    return language === "python";
};

handler.init = function(callback) {
    var emitter = handler.getEmitter();
    emitter.on("set_python_config", function(e) {
        pythonVersion = e.pythonVersion;
        pythonPath = e.pythonPath;
        if (daemon) {
            daemon.kill();
            daemon = null;
        }
    });
    emitter.on("set_python_scripts", function(e) {
        jediServer = e.jediServer;
        launchCommand = e.launchCommand;
    });
    callback();
};

handler.getIdentifierRegex = function() {
    return /\w/;
};

handler.getCompletionRegex = function() {
    return (/(\.|\b(import|from|if|while|from|raise|return) |% )$/);
};

handler.getCacheCompletionRegex = function() {
     // Match strings that can be an expression or its prefix, i.e.
     // keywords/identifiers followed by whitespace and/or operators
    return /(\b\w+\s+|\b(if|while|for|print)\s*\(|([{[\-+*%<>!|&/,%]|==|!=)\s*)+/;
};

/**
 * Complete code at the current cursor position.
 */
handler.complete = function(doc, fullAst, pos, options, callback) {
    callDaemon("completions", handler.path, doc, pos, options, function(err, results, meta) {
        if (err) return callback(err);

        results && results.forEach(function beautifyCompletion(r) {
            r.isContextual = true;
            r.guessTooltip = true;
            r.replaceText = r.replaceText || r.name;
            r.priority = r.name[0] === "_" || r.replaceText === r.replaceText.toUpperCase() ? 3 : 4;
            r.icon = r.icon || "property";
            r.icon = r.name[0] === "_" ? r.icon.replace(/2?$/, "2") : r.icon;
            r.noDoc = options.noDoc;
            if (!r.doc)
                return;
            var docLines = r.doc.split(/\r\n|\n|\r/);
            var docBody = docLines.slice(2).join("\n");
            r.docHeadHtml = workerUtil.filterDocumentation(docLines[0]).replace(/^([A-Za-z0-9$_]+\()self, /, "$1");
            r.doc = workerUtil.filterDocumentation(docBody.replace(/``/g, "'"));
        });
        callback(null, results);
    });
};

/**
 * Jump to the definition of what's under the cursor.
 */
handler.jumpToDefinition = function(doc, fullAst, pos, options, callback) {
    callDaemon("goto_definitions", handler.path, doc, pos, options, callback);
};

/**
 * Predict how to complete code next. Did the user just type 'mat'?
 * Then we probably only have a completion 'math'. So we can predict
 * that the user may type 'math.' next and precompute completions.
 */
handler.predictNextCompletion = function(doc, fullAst, pos, options, callback) {
    var predicted = options.matches.filter(function(m) {
        return m.isContextual
            && m.icon !== "method"
            && !m.replaceText.match(KEYWORD_REGEX);
    });
    var line = doc.getLine(pos.row);
    if (predicted.length > 0 && "import".substr(0, line.length) === line)
        return callback(null, "import ");
    if (predicted.length !== 1)
        return callback();
    if (/^\s+import /.test(line))
        return callback();
    console.log("[python_completer] Predicted our next completion will be for " + predicted[0].replaceText + ".");
    callback(null, {
        predicted: predicted[0].replaceText + ".",
        showEarly: predicted[0].replaceText === "self" || predicted[0].icon === "package"
    });
};

/**
 * Invoke a function on our jedi python daemon. It runs as an HTTP daemon
 * so we use curl to send a request.
 */
function callDaemon(command, path, doc, pos, options, callback) {
    var line = doc.getLine(pos.row);
    ensureDaemon(function(err, dontRetry) {
        if (err) return callback(err);

        var start = Date.now();
        workerUtil.execAnalysis(
            "curl",
            {
                mode: "stdin",
                json: true,
                args: [
                    "-s", "--data-binary", "@-", // get input from stdin
                    "localhost:" + DAEMON_PORT + "?mode=" + command
                    + "&row=" + (pos.row + 1) + "&column=" + pos.column
                    + "&path=" + path.replace(/^\//, "")
                    + (options.noDoc ? "&nodoc=1" : ""),
                ],
            },
            function onResult(err, stdout, stderr, meta) {
                if (err) {
                    if (err.code === ERROR_NO_SERVER && !dontRetry) {
                        daemon = null;
                        return callDaemon(command, path, doc, pos, options, callback);
                    }
                    return callback(err);
                }

                if (typeof stdout !== "object")
                    return callback(new Error("Couldn't parse python-jedi output: " + stdout));

                console.log("[python_completer] " + command + " in " + (Date.now() - start)
                    + "ms (jedi: " + meta.serverTime + "ms): "
                    + line.substr(0, pos.column));

                callback(null, stdout, meta);
            }
        );
    });
}

/**
 * Make sure we're running a jedi daemon (../server/jedi_server.py).
 * It listens on a port in the workspace container or host.
 */
function ensureDaemon(callback) {
    if (daemon)
        return done(daemon.err);

    daemon = {
        err: new Error("Still starting daemon, enhance your calm"),
        kill: function() {
            this.killed = true;
        }
    };

    workerUtil.spawn(
        "bash",
        {
            args: [
                "-c", launchCommand, "--", pythonVersion,
                "$PYTHON -c '" + jediServer + "' daemon --port " + DAEMON_PORT
            ],
            env: { PYTHONPATH: pythonPath },
        },
        function(err, child) {
            var output = "";
            if (err) {
                daemon.err = err;
                return workerUtil.showError("Could not start python completion daemon. Please reload to try again.");
            }
            daemon = child;
            daemon.err = null;

            if (daemon.killed)
                daemon.kill();

            // We (re)start the daemon after 10 minutes to conserve memory
            var killTimer = setTimeout(daemon.kill.bind(daemon), 10 * 60 * 1000);

            child.stderr.on("data", function(data) {
                output += data;
                if (/Daemon listening/.test(data))
                    done();
            });
            child.on("exit", function(code) {
                if (code === ERROR_PORT_IN_USE) // someone else running daemon?
                    return done(null, true);
                if (!code || /Daemon listening/.test(output)) // everything ok, try again later
                    daemon = null;
                clearTimeout(killTimer);
                done(code && new Error("[python_completer] Daemon failed: " + output));
            });
        }
    );

    function done(err) {
        if (err && /No module named jedi/.test(err.message) && !showedJediError) {
            workerUtil.showError("Jedi not found. Please run 'pip install jedi' or 'sudo pip install jedi' to enable Python code completion.");
            showedJediError = true;
        }
        callback && callback(err);
        callback = null;
    }
}

});<|endoftext|>


<commit_before>var express = require('express');
var app = express();

var state = {
  currentUsers: [],
  allowed: true,
  currentlyChecking: false
}

function handleSending() {
  if(state.currentUsers.length > 1) {
    console.log("WE'RE READY!!!");
    //DO STUFF
    state.allowed = false;
    setTimeout(function(){
      state.allowed = true;
    }, 15000);
  } else {
    console.log('failure');
  }

  state.currentUsers = [];
}

function checkLocation (loc) {
  // 43.083849, -77.679825
  var center = {
    x : 43.083849,
    y : -77.679825
  };
  var radius = 0.001;
  return Math.pow(loc[0] - center.x, 2) + Math.pow(loc[1] - center.y, 2) < Math.pow(radius, 2);
}

app.get('/', function(req, res, next) {
  var user = req.query.username;
  if(req.query.location && state.currentUsers.indexOf(user) === -1 && state.allowed){
    var location = req.query.location.split(';');
    if (checkLocation(location)) {
      console.log('added user', user);
      state.currentUsers.push(user);
    }

    if(!state.currentlyChecking) {
      state.currentlyChecking = true;
      setTimeout(handleSending, 6*1000);
    }
  }
  res.send();
});
app.set('port', process.env.PORT || 8000);
app.listen(app.get('port'));
<commit_msg>That might help<commit_after>var express = require('express');
var app = express();

var state = {
  currentUsers: [],
  allowed: true,
  currentlyChecking: false
}

function handleSending() {
  if(state.currentUsers.length > 1) {
    console.log("WE'RE READY!!!");
    //DO STUFF
    state.allowed = false;
    setTimeout(function(){
      state.allowed = true;
    }, 15000);
  } else {
    console.log('failure');
  }
  state.currentlyChecking = false;
  state.currentUsers = [];
}

function checkLocation (loc) {
  // 43.083849, -77.679825
  var center = {
    x : 43.083849,
    y : -77.679825
  };
  var radius = 0.001;
  return Math.pow(loc[0] - center.x, 2) + Math.pow(loc[1] - center.y, 2) < Math.pow(radius, 2);
}

app.get('/', function(req, res, next) {
  var user = req.query.username;
  if(req.query.location && state.currentUsers.indexOf(user) === -1 && state.allowed){
    var location = req.query.location.split(';');
    if (checkLocation(location)) {
      console.log('added user', user);
      state.currentUsers.push(user);
    }

    if(!state.currentlyChecking) {
      state.currentlyChecking = true;
      setTimeout(handleSending, 6*1000);
    }
  }
  res.send();
});
app.set('port', process.env.PORT || 8000);
app.listen(app.get('port'));
<|endoftext|>


<commit_before>//mongoDB
// //folder architecture for a project
// var projectSchema = new mongoose.Schema({
//   projectName: String,
//   projectFileTree: String // obj_json_str
// });

//mongoDB
//insert the straight up mongo

//MySQL

var knex = require('knex');

//creates database
var db = knex({
  client: 'mysql',
  connection: {
    host: process.env.DB_HOST || 'localhost',
    user: 'root',
    password: '',
    database: 'code_friends',
  }
});

//users schema
db.schema.hasTable('users').then(function(exists){
  if(!exists){
    db.schema.createTable('users', function(user){
      user.increments('id').primary();
      user.string('username', 255);
      user.timestamps();
    })
    .then(function(){
      console.log('created table: users');
    })
    .catch(function(error){
      console.log('error creating users: ', error);
    })
  }
});

//projects schema
db.schema.hasTable('projects').then(function(exists){
  if(!exists){
    db.schema.createTable('projects', function(project){
      project.increments('id').primary();
      project.string('project_name', 255);
      project.timestamps();
    })
    .then(function(){
      console.log('created table: projects');
    })
    .catch(function(error){
      console.log('error creating projects: ', error);
    })
  }
});

//creates join table for users and projects
db.schema.hasTable('users_projects').then(function(exists){
  if(!exists){
    db.schema.createTable('users_projects', function(users_projects){
      users_projects.increments('id').primary();
      users_projects.integer('user_id').unsigned().references('id').inTable('users');
      users_projects.integer('project_id').unsigned().references('id').inTable('projects');
      users_projects.timestamps();
    })
    .then(function(){
      console.log('created table: user_projects');
    })
    .catch(function(error){
      console.log('error creating user_projects: ', error);
    })
  }
});

var bookshelf = require('bookshelf')(db);
module.exports = bookshelf;

//to create database at beginning of project
  //go to terminal
  //mysql -u root
  //create database 'name of database'
<commit_msg>Add Auth<commit_after>//mongoDB
// //folder architecture for a project
// var projectSchema = new mongoose.Schema({
//   projectName: String,
//   projectFileTree: String // obj_json_str
// });

//mongoDB
//insert the straight up mongo

//MySQL

var knex = require('knex');

//creates database
var db = knex({
  client: 'mysql',
  connection: {
    host: process.env.DB_HOST || 'localhost',
    user: 'root',
    password: '',
    database: 'code_friends',
  }
});

//users schema
db.schema.hasTable('users').then(function (exists) {
  if (!exists) {
    db.schema.createTable('users', function (user) {
        user.increments('id').primary();
        user.string('username', 255);
        user.timestamps();
      })
      .then(function () {
        console.log('created table: users');
      })
      .catch(function (error) {
        console.log('error creating users: ', error);
      });
  }
});

//projects schema
db.schema.hasTable('projects').then(function (exists) {
  if (!exists) {
    db.schema.createTable('projects', function (project) {
        project.increments('id').primary();
        project.string('project_name', 255);
        project.timestamps();
      })
      .then(function () {
        console.log('created table: projects');
      })
      .catch(function (error) {
        console.log('error creating projects: ', error);
      });
  }
});

//creates join table for users and projects
db.schema.hasTable('users_projects').then(function (exists) {
  if (!exists) {
    db.schema.createTable('users_projects', function (userProjects) {
        userProjects.increments('id').primary();
        userProjects.integer('user_id').unsigned().references('id').inTable('users');
        userProjects.integer('project_id').unsigned().references('id').inTable('projects');
        userProjects.timestamps();
      })
      .then(function () {
        console.log('created table: user_projects');
      })
      .catch(function (error) {
        console.log('error creating user_projects: ', error);
      });
  }
});

var bookshelf = require('bookshelf')(db);
module.exports = bookshelf;

//to create database at beginning of project
//go to terminal
//mysql -u root
//create database 'name of database'<|endoftext|>


<commit_before>import _get from 'lodash/get'
import styled from 'styled-components'

import {shadeColor, scale, theme} from '../utilStyles'

const declareDivider = ({theme, isOpen, isFramed}) => {
  const cssShared = `
    &:first-child {
      border-bottom-color: ${shadeColor(_get(theme, 'colors.paper'), 1)};
      border-bottom-style: ${isFramed ? 'solid' : 'none'};
    }

    &:last-child,
    &:nth-child(3) {
      border-top-color: ${shadeColor(_get(theme, 'colors.paper'), 1)};
      border-top-style: ${isFramed ? 'solid' : 'none'};
    }
  `

  if (isOpen) {
    return `
      ${cssShared}
      &:first-child {
        border-bottom-width: 1px;
      }

      &:last-child,
      &:nth-child(3) {
        border-top-width: 1px;
      }
    `
  } else {
    return `
      ${cssShared}
      &:first-child {
        border-bottom-width: 0;
      }

      &:last-child {
        border-top-width: 0;
      }

      &:nth-child(3) {
        border-top-width: 1px;
      }
    `
  }
}

export const StyledIconWrapper = styled.span`
  display: none;
  font-size: ${scale.font(1)};

  &:hover {
    color: ${theme.color('secondaryLight')};
  }
`

const StyledPanelHeaderFooter = styled.div`
  && {
    background-color: #f2f2f2;
    display: flex;
    padding: ${({isFramed}) => (isFramed ? '4px 8px 4px 8px' : 0)};
    align-items: center;

    &:hover {
      cursor: pointer;

      ${StyledIconWrapper} {
        display: block;
      }
    }

    > div {
      flex: 1 1 auto;
    }
    ${props => declareDivider(props)}
  }
`

export default StyledPanelHeaderFooter
<commit_msg>fix(tocco-ui): fix flicker in Firefox on panel hovers<commit_after>import _get from 'lodash/get'
import styled from 'styled-components'

import {shadeColor, scale, theme} from '../utilStyles'

const declareDivider = ({theme, isOpen, isFramed}) => {
  const cssShared = `
    &:first-child {
      border-bottom-color: ${shadeColor(_get(theme, 'colors.paper'), 1)};
      border-bottom-style: ${isFramed ? 'solid' : 'none'};
    }

    &:last-child,
    &:nth-child(3) {
      border-top-color: ${shadeColor(_get(theme, 'colors.paper'), 1)};
      border-top-style: ${isFramed ? 'solid' : 'none'};
    }
  `

  if (isOpen) {
    return `
      ${cssShared}
      &:first-child {
        border-bottom-width: 1px;
      }

      &:last-child,
      &:nth-child(3) {
        border-top-width: 1px;
      }
    `
  } else {
    return `
      ${cssShared}
      &:first-child {
        border-bottom-width: 0;
      }

      &:last-child {
        border-top-width: 0;
      }

      &:nth-child(3) {
        border-top-width: 1px;
      }
    `
  }
}

export const StyledIconWrapper = styled.span`
  opacity: 0;
  font-size: ${scale.font(1)};

  &:hover {
    color: ${theme.color('secondaryLight')};
  }
`

const StyledPanelHeaderFooter = styled.div`
  && {
    background-color: #f2f2f2;
    display: flex;
    padding: ${({isFramed}) => (isFramed ? '4px 8px 4px 8px' : 0)};
    align-items: center;

    &:hover {
      cursor: pointer;

      ${StyledIconWrapper} {
        opacity: 1;
      }
    }

    > div {
      flex: 1 1 auto;
    }
    ${props => declareDivider(props)}
  }
`

export default StyledPanelHeaderFooter
<|endoftext|>


<commit_before>'use strict';
var chalk = require('chalk');
var compareVersion = require('compare-version');
var yeoman = require('yeoman-generator');
var pkgName = require('pkg-name');

module.exports = yeoman.generators.Base.extend({
  initializing: function () {
    this.pkg = require('../package.json');
    this.compareVersion = compareVersion;
  },

  prompting: function () {
    var cb = this.async();
    var log = this.log;

    var welcome = this.yeoman +
    '"Project Name" should not contain "jquery" or "js" and ' +
    'should be a unique ID not already in use at plugins.jquery.com. "Project ' +
    'title" should be a human-readable title, and doesn\'t need to contain ' +
    'the word "jQuery", although it may. For example, a plugin titled "Awesome ' +
    'Plugin" might have the name "awesome-plugin".' +
    '\n\n' +
    'For more information, please see the following documentation:' +
    '\n\n' +
    'Naming Your Plugin      http://plugins.jquery.com/docs/names/\n' +
    'Publishing Your Plugin  http://plugins.jquery.com/docs/publish/\n' +
    'Package Manifest        http://plugins.jquery.com/docs/package-manifest/\n';

    log(welcome);

    var prompts = [{
      name: 'name',
      message: 'Project Name',
      default: this.appname,
      filter: function (input) {
        var done = this.async();

        pkgName(input, function (err, available) {
          if (!available.bower && !available.npm) {
            log.info(chalk.yellow(input) + ' already exists on npm and Bower. You might want to use another name.');
          } else {
            if (!available.bower) {
              log.info(chalk.yellow(input) + ' already exists on Bower. You might want to use another name.');
            }

            if (!available.npm) {
              log.info(chalk.yellow(input) + ' already exists on npm. You might want to use another name.');
            }
          }

          done(input);
        });
      }
    }, {
      name: 'title',
      default: 'Awesome jQuery plugin'
    }, {
      name: 'description',
      default: 'The best jQuery plugin ever.'
    }, {
      name: 'version'
    }, {
      name: 'repository'
    }, {
      name: 'license',
      default: 'MIT'
    }, {
      name: 'github_username',
    }, {
      name: 'author_name'
    }, {
      name: 'author_email'
    }, {
      name: 'jquery_version',
      message: 'jQuery Version'
    }];

    var nameToMessage = function (name) {
      return name.split('_').map(
        function (x) {
          return this._.capitalize(x);
        }.bind(this)
      ).join(' ') + ':';
    }.bind(this);

    // Generate prompt messages if only the name is defined.
    prompts.map(function (entry) {
      if (entry.message === undefined) {
        entry.message = nameToMessage(entry.name);
      }
      return entry;
    }.bind(this));

    this.currentYear = (new Date()).getFullYear();

    this.prompt(prompts, function (props) {
      this.props = props;
      // For easier access in the templates.
      this.slugname = this._.slugify(props.name);
      this.camelname = this._.camelize(props.name);
      cb();
    }.bind(this));
  },

  configuration: function () {
    this.copy('editorconfig', '.editorconfig');
    this.copy('jshintrc', '.jshintrc');
    this.copy('gitignore', '.gitignore');
    this.copy('travis.yml', '.travis.yml');
    this.template('_package.json', 'package.json');
    this.template('bower.json', 'bower.json');
  },

  source: function () {
    this.mkdir('src');
    this.copy('src/jshintrc', 'src/.jshintrc');
    this.template('src/name.js', 'src/' + this.slugname + '.js');
  },

  test: function () {
    this.mkdir('test');
    this.copy('test/jshintrc', 'test/.jshintrc');
    this.template('test/name_test.js', 'test/' + this.slugname + '_test.js');
    this.template('test/name.html', 'test/' + this.slugname + '.html');
  },

  writing: function () {
    this.template('readme.md');
    this.template('Gruntfile.js');
    this.template('name.jquery.json', this.slugname + '.jquery.json');
    this.copy('contributing.md', 'contributing.md');
  },

  install: function () {
    this.installDependencies({
      skipInstall: this.options['skip-install']
    });
  }
});
<commit_msg>Use inquirer's 'when' instead of 'filter' to check if a package name is available on npm or Bower<commit_after>'use strict';
var chalk = require('chalk');
var compareVersion = require('compare-version');
var yeoman = require('yeoman-generator');
var pkgName = require('pkg-name');

module.exports = yeoman.generators.Base.extend({
  initializing: function () {
    this.pkg = require('../package.json');
    this.compareVersion = compareVersion;
  },

  welcome: function () {
    var welcome = this.yeoman +
    '"Project Name" should not contain "jquery" or "js" and ' +
    'should be a unique ID not already in use at plugins.jquery.com. "Project ' +
    'title" should be a human-readable title, and doesn\'t need to contain ' +
    'the word "jQuery", although it may. For example, a plugin titled "Awesome ' +
    'Plugin" might have the name "awesome-plugin".' +
    '\n\n' +
    'For more information, please see the following documentation:' +
    '\n\n' +
    'Naming Your Plugin      http://plugins.jquery.com/docs/names/\n' +
    'Publishing Your Plugin  http://plugins.jquery.com/docs/publish/\n' +
    'Package Manifest        http://plugins.jquery.com/docs/package-manifest/\n';

    this.log(welcome);
  },

  promptingName: function () {
    var cb = this.async();

    var prompts = [{
      name: 'name',
      message: 'Project Name',
      default: this.appname,
    }, {
      type: 'confirm',
      name: 'pkgName',
      message: 'The name above already exists on npm or Bower, choose another?',
      default: true,
      when: function (answers) {
        var done = this.async();

        pkgName(answers.name, function (err, available) {
          if (!available.npm || !available.bower) {
            done(true);
          }

          done(false);
        });
      }
    }];

    this.prompt(prompts, function (props) {
      if (props.pkgName) {
        return this.promptingName();
      }

      // For easier access in the templates.
      this.slugname = this._.slugify(props.name);

      cb();
    }.bind(this));
  },

  prompting: function () {
    var cb = this.async();

    var prompts = [{
      name: 'title',
      default: 'Awesome jQuery plugin'
    }, {
      name: 'description',
      default: 'The best jQuery plugin ever.'
    }, {
      name: 'version'
    }, {
      name: 'repository'
    }, {
      name: 'license',
      default: 'MIT'
    }, {
      name: 'github_username',
    }, {
      name: 'author_name'
    }, {
      name: 'author_email'
    }, {
      name: 'jquery_version',
      message: 'jQuery Version'
    }];

    var nameToMessage = function (name) {
      return name.split('_').map(
        function (x) {
          return this._.capitalize(x);
        }.bind(this)
      ).join(' ') + ':';
    }.bind(this);

    // Generate prompt messages if only the name is defined.
    prompts.map(function (entry) {
      if (entry.message === undefined) {
        entry.message = nameToMessage(entry.name);
      }
      return entry;
    }.bind(this));

    this.currentYear = (new Date()).getFullYear();

    this.prompt(prompts, function (props) {
      this.props = props;
      // For easier access in the templates.
      this.camelname = this._.camelize(props.name);
      cb();
    }.bind(this));
  },

  configuration: function () {
    this.copy('editorconfig', '.editorconfig');
    this.copy('jshintrc', '.jshintrc');
    this.copy('gitignore', '.gitignore');
    this.copy('travis.yml', '.travis.yml');
    this.template('_package.json', 'package.json');
    this.template('bower.json', 'bower.json');
  },

  source: function () {
    this.mkdir('src');
    this.copy('src/jshintrc', 'src/.jshintrc');
    this.template('src/name.js', 'src/' + this.slugname + '.js');
  },

  test: function () {
    this.mkdir('test');
    this.copy('test/jshintrc', 'test/.jshintrc');
    this.template('test/name_test.js', 'test/' + this.slugname + '_test.js');
    this.template('test/name.html', 'test/' + this.slugname + '.html');
  },

  writing: function () {
    this.template('readme.md');
    this.template('Gruntfile.js');
    this.template('name.jquery.json', this.slugname + '.jquery.json');
    this.copy('contributing.md', 'contributing.md');
  },

  install: function () {
    this.installDependencies({
      skipInstall: this.options['skip-install']
    });
  }
});
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');

var db = {};

//******DATABASE SET UP

db.dbURI = 'mongodb://localhost/ballotize';
mongoose.connect(db.dbURI);
db.Schema = mongoose.Schema;
db.roomSchema = new db.Schema ({
  roomcode: { type: String, required: true, unique: true },
  categories: {},
  candidates: {},
  voters: {},
  results: {}
});
db.roomSchema.plugin(uniqueValidator);
db.Room = mongoose.model('Room', db.roomSchema);

module.exports = db;<commit_msg>[feat] edits room schema in db.js<commit_after>var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');

var db = {};

//******DATABASE SET UP

db.dbURI = 'mongodb://localhost/ballotize';
mongoose.connect(db.dbURI);
db.Schema = mongoose.Schema;
db.roomSchema = new db.Schema ({
  roomcode: { type: String, required: true, unique: true },
  options: {},
  numberOfWinners: { type: Number },
  voters: {},
  results: {}
});
db.roomSchema.plugin(uniqueValidator);
db.Room = mongoose.model('Room', db.roomSchema);

module.exports = db;<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright 2015 France Labs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
/**
 *
 * @class AjaxFranceLabs.AutocompleteModule
 * @extends AjaxFranceLabs.AbstractModule
 *
 * @documentation http://www.francelabs.com/en/AjaxFranceLabs/widget-module-documentation#autocomplete_module
 *
 */
AjaxFranceLabs.AutocompleteModule = AjaxFranceLabs.AbstractModule
.extend({

	// Variables

	optionsExtend : true,

	options : {},

	render : null,

	field : null,

	openOnFieldFocus : false,

	valueSelectFormat : function(value) {
		return value
	},

	singleValue : false,

	type : 'autocomplete',

	cache : [],

	lastXhr : null,

	// Methods

	init : function() {
		if (!this.initialized) {
			this.initialized = true;
			var self = this;
			var opt = {
					delay : 50,
					minLength : 0,
					source : function(request, response) {
						var term = AjaxFranceLabs.extractLast(request.term).toLowerCase();
						if (term in self.cache) {
							response(self.cache[term]);
							return;
						}
						var f = (self.field === null) ? '' : '&f='
							+ self.field;
						if (AjaxFranceLabs.extractLast(request.term) != '') {
							self.lastXhr = self.manager
							.executeRequest(
									self.connectionInfo.serverUrl,
									self.connectionInfo.servlet,
									self.connectionInfo.queryString
									+ encodeURIComponent('"' + AjaxFranceLabs
											.extractLast(request.term)
											+ '"')
											+ f + "&autocomplete=true",
											function(data, status, xhr) {
										var src = [];
										// self.manager.executeRequest('',
										// '', 'q=' +
										// AjaxFranceLabs.extractLast(request.term)
										// + f,
										// function(data) {
										if (data.spellcheck.suggestions.length > 1) {

											$.each(data.spellcheck.collations, function(index, value) {
												if (value != 'collation'){
													src.push(data.spellcheck.collations[index].collationQuery.replace(/"/g, ''));
												}

											});

											self.cache[term] = src;
											if (xhr === self.lastXhr) {
												response(src);
											}
										}

									});
							// });
						}
					},
					search : function() {
						var term = AjaxFranceLabs.extractLast(this.value);
						if (term.length < self.autocompleMinLength) {
							return false;
						}
					},
					select : function(event, ui) {
						if (self.singleValue === true) {
							this.value = self
							.valueSelectFormat(ui.item.value);
							this.value +=  ("\u200c");
						} else {
							var terms = AjaxFranceLabs.split(this.value);
							terms.pop();
							terms.push(self
									.valueSelectFormat(ui.item.value));
							terms.push("");
							this.value = terms.join("\u200c ");
							this.value = this.value.slice(0,-2);
						}
						return false;
					},
					focus : function() {
						return false;
					}
			};
			if (this.optionsExtend === true) {
				var newOpt = {};
				$.extend(true, newOpt, opt, this.options);
				this.options = newOpt;
			}
			$(this.elm).autocomplete(this.options);
			if (this.openOnFieldFocus === true) {
				$(this.elm).click(function() {
					$(this).autocomplete('search');
				});
			}
			if (typeof this.render === 'function') {
				$(this.elm).data("autocomplete")._renderItem = this.render;
			}
			if (this.manager.connectionInfo.autocomplete === undefined
					&& this.options.source == null)
				throw 'AutocompleteModule: connectionInfo not defined in Manager';
			else
				this.connectionInfo = this.manager.connectionInfo.autocomplete;
		}
	}
});<commit_msg>[DATAFARI-131] Fix Autocomplete not working<commit_after>/*******************************************************************************
 * Copyright 2015 France Labs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
/**
 *
 * @class AjaxFranceLabs.AutocompleteModule
 * @extends AjaxFranceLabs.AbstractModule
 *
 * @documentation http://www.francelabs.com/en/AjaxFranceLabs/widget-module-documentation#autocomplete_module
 *
 */
AjaxFranceLabs.AutocompleteModule = AjaxFranceLabs.AbstractModule
.extend({

	// Variables

	optionsExtend : true,

	options : {},

	render : null,

	field : null,

	openOnFieldFocus : false,

	valueSelectFormat : function(value) {
		return value
	},

	singleValue : false,

	type : 'autocomplete',

	cache : [],

	lastXhr : null,

	// Methods

	init : function() {
		if (!this.initialized) {
			this.initialized = true;
			var self = this;
			var opt = {
					delay : 50,
					minLength : 0,
					source : function(request, response) {
						var term = AjaxFranceLabs.extractLast(request.term).toLowerCase();
						if (term in self.cache) {
							response(self.cache[term]);
							return;
						}
						var f = (self.field === null) ? '' : '&f='
							+ self.field;
						if ((AjaxFranceLabs.extractLast(request.term) != '') && ((/\s/.test(AjaxFranceLabs.extractLast(request.term)))))  {
							self.lastXhr = self.manager
							.executeRequest(
									self.connectionInfo.serverUrl,
									self.connectionInfo.servlet,
									self.connectionInfo.queryString
									+ encodeURIComponent('"' + AjaxFranceLabs
											.extractLast(request.term)
											+ '"')
											+ f + "&autocomplete=true",
											function(data, status, xhr) {
										var src = [];
										// self.manager.executeRequest('',
										// '', 'q=' +
										// AjaxFranceLabs.extractLast(request.term)
										// + f,
										// function(data) {
										if (data.spellcheck.suggestions.length > 1) {

											$.each(data.spellcheck.collations, function(index, value) {
												if (value != 'collation'){
													src.push(data.spellcheck.collations[index].collationQuery.replace(/"/g, ''));
												}

											});

											self.cache[term] = src;
											if (xhr === self.lastXhr) {
												response(src);
											}
										}

									});
							// });
						}
						else if (AjaxFranceLabs.extractLast(request.term) != '') {
							self.lastXhr = self.manager
							.executeRequest(
									self.connectionInfo.serverUrl,
									self.connectionInfo.servlet,
									self.connectionInfo.queryString
									+ encodeURIComponent('' + AjaxFranceLabs
											.extractLast(request.term)
											+ '')
											+ f + "&autocomplete=true",
											function(data, status, xhr) {
										var src = [];
										// self.manager.executeRequest('',
										// '', 'q=' +
										// AjaxFranceLabs.extractLast(request.term)
										// + f,
										// function(data) {
										if (data.spellcheck.suggestions.length > 1) {

											$.each(data.spellcheck.collations, function(index, value) {
												if (value != 'collation'){
													src.push(data.spellcheck.collations[index].collationQuery.replace(/"/g, ''));
												}

											});

											self.cache[term] = src;
											if (xhr === self.lastXhr) {
												response(src);
											}
										}

									});
							// });
						}
					},
					search : function() {
						var term = AjaxFranceLabs.extractLast(this.value);
						if (term.length < self.autocompleMinLength) {
							return false;
						}
					},
					select : function(event, ui) {
						if (self.singleValue === true) {
							this.value = self
							.valueSelectFormat(ui.item.value);
							this.value +=  ("\u200c");
						} else {
							var terms = AjaxFranceLabs.split(this.value);
							terms.pop();
							terms.push(self
									.valueSelectFormat(ui.item.value));
							terms.push("");
							this.value = terms.join("\u200c ");
							this.value = this.value.slice(0,-2);
						}
						return false;
					},
					focus : function() {
						return false;
					}
			};
			if (this.optionsExtend === true) {
				var newOpt = {};
				$.extend(true, newOpt, opt, this.options);
				this.options = newOpt;
			}
			$(this.elm).autocomplete(this.options);
			if (this.openOnFieldFocus === true) {
				$(this.elm).click(function() {
					$(this).autocomplete('search');
				});
			}
			if (typeof this.render === 'function') {
				$(this.elm).data("autocomplete")._renderItem = this.render;
			}
			if (this.manager.connectionInfo.autocomplete === undefined
					&& this.options.source == null)
				throw 'AutocompleteModule: connectionInfo not defined in Manager';
			else
				this.connectionInfo = this.manager.connectionInfo.autocomplete;
		}
	}
});<|endoftext|>