<commit_before>/**
 * ___________                     __      _____
 * \__    ___/___________    ____ |  | __ /     \   ____
 *   |    |  \_  __ \__  \ _/ ___\|  |/ //  \ /  \_/ __ \
 *   |    |   |  | \// __ \\  \___|    </    Y    \  ___/
 *   |____|   |__|  (____  /\___  >__|_ \____|__  /\___  >
 *                       \/     \/     \/       \/     \/
 *
 *
 * jQuery TrackMe v2.1.4 - 12/07/2016
 * --------------------------------
 * Original author: Marco Trevisani (marco.trevisani@ynap.com)
 * Further changes, comments:
 * --- v2.14:
 * - added no follow links feature.
 * --- v2.1.3:
 * - added placeholder feature for labels.
 * --- v2.1.2:
 * - added simple description :)
 * - added new public function trackEvent{trackingInfoObject}
 *
 *
 **** Description:
 * What does this plugin?
 * - It attaches the event tracking on elements with specific classes reading data attributes for the tracking info.
 * - It tracks the user behavior during filling of the form.
 *
 **** Available custom classes:
 * js-track-me          {any element} - track event on click.
 * js-track-me-hover:   {any element} - track event on mouseover.
 * js-track-me-focus:   {any element} - track event on focus.
 * js-track-me-form:    {form} - track user behavior during filling of the form (skipped inputs and inputs not valid).
 *
 **** Data Attributes:
 * data-tracking-category               - Set the event category.
 * data-tracking-action                 - Set the event action.
 * data-tracking-label                  - Set the event label.
 * data-tracking-form-id                - Track only if this form is valid.
 * data-tracking-event                  - Track only when this event will dispatched.
 * data-tracking-label-checked          - {checkbox only} this is the event label when the checkbox is checked.
 * data-tracking-label-not-checked      - {checkbox only} this is the event label when the checkbox isn't checked.
 * data-tracking-label-on               - {element with a switch functionality} Set the event label when the switch is on. (es: accordion open, option turned on...).
 * data-tracking-label-off              - {element with a switch functionality} Set the event label when the switch is off. (es: accordion closed, option turned off...).
 *
 **** Initialisation Options:
 *      $(selector).trackMe({
 *       debug: false,
 *       formTracking {
 *           completedEvents: false,
 *           oneTimeOnly: true,
 *           labelCompleted: "completed",
 *           labelNotValid: "not valid",
 *           labelSkipped: "skipped"
 *       },
 *       category: "custom global category",
 *       action: "custom global action",
 *       callback: function() {
 *          console.log("Event tracked.");
 *
 **** Usage Example:
 *
 *  JS: $(selector).trackMe();
 *  HTML: Click Me!
 *
 **** More Examples:
 *
 * You can set custom global action and label using public functions:
 *
 *      $(selector).trackMe();
 *      $(selector).data("plugin_trackMe").setTrackingCategory("custom global category");
 *      $(selector).data("plugin_trackMe").setTrackingAction("custom global action");
 *
 */
;
(function ($, window, document) {
    "use strict";

    var pluginName = "trackMe";

    function TrackMe (element, options) {
        this.element = element;
        this._name = pluginName;
        this._defaults = $.fn.trackMe.defaults;
        this.options = $.extend({}, this._defaults, options);
        this.trackingData = {};
        this.init();
    }

    // - Private Functions - - -
    var formIsValid = function (formId) {
        if (formId !== undefined) {
            var $formToValidate = $("#" + formId);
            if ($formToValidate.length && !$formToValidate.valid()) {
                return false;
            }
        }
        return true;
    };

    // ( Debug Layer )
    var onlineOrStageEnvironment = function () {
            if (document.location.hostname.match("yoox.com$") || document.location.hostname.match("yoox.cn$")) {
                return true;
            }
            return false;
        },
        checkQueryString = function () {
            //if (location.search.match("td=1$")) {
            //    return true;
            //}
            //return false;
            return true;
        },
        debugTrackedEvent = function (category, action, label) {
            if (!onlineOrStageEnvironment() && checkQueryString()) {
                var messageText = "[EVENT] --------------------\nCategory: " +
                        category +
                        "\nAction: " +
                        action +
                        "\nLabel: " +
                        label +
                        "\n----------------------------",
                    messageHtml = "Category: " +
                        category +
                        "
 Action: " +
                        action +
                        "
 Label: " +
                        label +
                        "
",
                    $message = $("
").html("New Event:").after($("
").html(messageHtml)),
                    $messageContainer = $("
", { "class": "track-event-notification-layer fade-in" });

                if (!$(".track-event-notification-layer").length) {
                    $messageContainer.append($message);
                    $("body").append($messageContainer);
                } else {
                    clearTimeout(window.closeDebugLayerTimeout);
                    $(".track-event-notification-layer").append($message).removeClass("fade-out").addClass("fade-in");
                }

                window.closeDebugLayerTimeout = setTimeout(function () {
                        $(".track-event-notification-layer").removeClass("fade-in").addClass("fade-out").html("");
                    },
                    3000);

                console.log(messageText);
            }
        };

    // - Public Functions - - -
    $.extend(TrackMe.prototype,
    {
        init: function () {
            this.buildCache();
            this.bindEvents();
        },

        destroy: function () {
            this.unbindEvents();
            this.$element.removeData();
        },

        // Cache DOM nodes for performance
        buildCache: function () {
            this.$element = $(this.element);
        },

        // Bind events that trigger methods
        bindEvents: function () {
            var plugin = this;

            plugin.$element.on("click" + "." + plugin._name,
                ".js-track-me",
                function (e) {
                    if (plugin.options.debugNoFollowLinks) {
                        e.preventDefault();
                        e.stopPropagation();
                    }
                    plugin.startTracking.call(plugin, $(this));
                });

            plugin.$element.on("hover" + "." + plugin._name,
                ".js-track-me-hover",
                function () {
                    plugin.startTracking.call(plugin, $(this));
                });

            plugin.$element.on("focus" + "." + plugin._name,
                ".js-track-me-focus",
                function () {
                    plugin.startTracking.call(plugin, $(this));
                });

            plugin.$element.on("blur" + "." + plugin._name,
                ".js-track-form input:not([type=submit]), .js-track-form select",
                function () {
                    // track only REQUIRED input not already tracked.
                    if (!$(this).data("alreadyTracked") && $(this).data("valRequired") !== undefined) {
                        plugin.startTrackingForm.call(plugin, $(this));
                    }
                });
        },

        // Unbind events that trigger methods
        unbindEvents: function () {
            this.$element.off("." + this._name);
        },

        getTrackingData: function ($elm) {
            return {
                category: ($elm.data("trackingCategory")) === undefined
                    ? this.options.category
                    : $elm.data("trackingCategory"),
                action: ($elm.data("trackingAction")) === undefined ? this.options.action : $elm.data("trackingAction"),
                label: $elm.data("trackingLabel"),
                labelChecked: $elm.data("trackingLabelChecked"),
                labelNotChecked: $elm.data("trackingLabelNotChecked"),
                labelOn: $elm.data("trackingLabelOn"),
                labelOff: $elm.data("trackingLabelOff"),
                event: $elm.data("trackingEvent"),
                formToValidate: $elm.data("trackingFormId")
            };
        },

        getFormTrackingData: function ($elm) {
            var $form = $elm.closest("form");
            return {
                category: ($form.data("trackingCategory")) === undefined
                    ? this.options.category
                    : $form.data("trackingCategory"),
                action: ($form.data("trackingAction")) === undefined
                    ? this.options.action
                    : $form.data("trackingAction"),
                label: $form.data("trackingFormName"),
                fieldName: ($elm.data("trackingName")) === undefined ? $elm.attr("name") : $elm.data("trackingName")
            };
        },

        startTracking: function ($element) {
            var plugin = this;
            this.trackingData = this.getTrackingData($element);

            // Track checkbox events
            if ($element.is("input[type=checkbox]") && plugin.trackingData.labelChecked !== undefined) {
                var label = $element.is(":checked")
                    ? plugin.trackingData.labelChecked
                    : plugin.trackingData.labelNotChecked;

                if (plugin.trackingData.event === undefined && label !== undefined) {
                    plugin.trackUserEvent(plugin.trackingData.category, plugin.trackingData.action, label);
                } else {
                    $("body")
                        .off(plugin.trackingData.event)
                        .one(plugin.trackingData.event,
                            function () {
                                plugin.trackUserEvent(plugin.trackingData.category, plugin.trackingData.action, label);
                            });
                }
                // Track switch events
            } else if (plugin.trackingData.labelOn !== undefined || plugin.trackingData.labelOff !== undefined) {
                if ($element.hasClass("js-track-me-on")) {
                    $element.removeClass("js-track-me-on");
                    plugin.trackUserEvent(plugin.trackingData.category,
                        plugin.trackingData.action,
                        plugin.trackingData.labelOff);
                } else {
                    $element.addClass("js-track-me-on");
                    plugin.trackUserEvent(plugin.trackingData.category,
                        plugin.trackingData.action,
                        plugin.trackingData.labelOn);
                }
                // Track only if form is valid
            } else if (plugin.trackingData.formToValidate !== undefined) {
                if (formIsValid(plugin.trackingData.formToValidate)) {
                    plugin.trackUserEvent(plugin.trackingData.category,
                        plugin.trackingData.action,
                        plugin.trackingData.label);
                }

                // Track on custom event
            } else {
                if (plugin.trackingData.event === undefined) {
                    plugin.trackUserEvent(plugin.trackingData.category,
                        plugin.trackingData.action,
                        plugin.trackingData.label);
                } else {
                    $("body")
                        .off(plugin.trackingData.event)
                        .one(plugin.trackingData.event,
                            function () {
                                plugin.trackUserEvent(plugin.trackingData.category,
                                    plugin.trackingData.action,
                                    plugin.trackingData.label);
                            });
                }
            }

            this.callback();
        },

        startTrackingForm: function ($element) {
            var plugin = this;
            this.trackingData = this.getFormTrackingData($element);

            if ($element.val().length === 0) {
                plugin.trackUserEvent(plugin.trackingData.category,
                    plugin.trackingData.action,
                    plugin.trackingData.label +
                    " " +
                    plugin.options.formTracking.labelSkipped +
                    " " +
                    plugin.trackingData.fieldName);
            } else if (!$element.valid()) {
                plugin.trackUserEvent(plugin.trackingData.category,
                    plugin.trackingData.action,
                    plugin.trackingData.label +
                    " " +
                    plugin.options.formTracking.labelNotValid +
                    " " +
                    plugin.trackingData.fieldName);
            } else {
                if (this.options.formTracking.completedEvents) {
                    plugin.trackUserEvent(plugin.trackingData.category,
                        plugin.trackingData.action,
                        plugin.trackingData.label +
                        " " +
                        plugin.options.formTracking.labelCompleted +
                        " " +
                        plugin.trackingData.fieldName);
                }
            }
            if (this.options.formTracking.oneTimeOnly) {
                $element.data("alreadyTracked", true);
            }

            this.callback();
        },

        setTrackingCategory: function (category) {
            this.options.category = category;
        },

        setTrackingAction: function (action) {
            this.options.action = action;
        },

        addPlaceholder: function (placeholder) {
            $.extend(this.options.placeholders, placeholder);
        },

        updateTrackingData: function (updatedTrackingData) {
            $.extend(true, this.trackingData, updatedTrackingData);
        },

        getCurrentTrackingCategory: function () {
            return this.options.category;
        },

        getCurrentTrackingAction: function () {
            return this.options.action;
        },
        managePlaceholder: function (text) {
            var myRegexp = /{{([a-zA-Z0-9]*)}}/g,
                result = text.match(myRegexp),
                placeholderText,
                i;
            if (result) {
                for (i = 0; i <= result.length; i = i + 1) {
                    placeholderText = this.options.placeholders[result[i]] !== undefined
                        ? this.options.placeholders[result[i]]
                        : "";
                    text = text.replace(result[i], placeholderText);
                }
            }
            return text;
        },
        trackUserEvent: function (category, action, label) {
            if (label !== undefined && action !== undefined && label !== "" && action !== "") {
                if (this.options.debug) {
                    debugTrackedEvent(category, action, label);
                }

                label = this.managePlaceholder(label);

                $Y.track.userEvent("ga", { category: category, action: action, label: label });
            }
        },

        trackEvent: function (trackInfo) {
            trackInfo.category = trackInfo.category || this.options.category;
            trackInfo.action = trackInfo.action || this.options.action;

            if (trackInfo.label !== undefined &&
                trackInfo.action !== undefined &&
                trackInfo.label !== "" &&
                trackInfo.action !== "") {
                if (this.options.debug) {
                    debugTrackedEvent(trackInfo.category, trackInfo.action, trackInfo.label);
                }

                $Y.track.userEvent("ga",
                { category: trackInfo.category, action: trackInfo.action, label: trackInfo.label });
            }
        },

        callback: function () {
            // Cache onComplete option
            var onComplete = this.options.onComplete;

            if (typeof onComplete === "function") {
                onComplete.call(this.element);
            }
        },

        trackingData: {
            category: "",
            action: "",
            label: "",
            labelChecked: "",
            labelNotChecked: "",
            labelOn: "",
            labelOff: "",
            event: "",
            formToValidate: ""
        }
    });

    $.fn.trackMe = function (options) {
        this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName, new TrackMe(this, options));
            }
        });

        return this;
    };

    $.fn.trackMe.defaults = {
        debug: false, // true: activate the event notification layer
        debugNoFollowLinks: false // true: stop propagation on click,
        formTracking: {
            completedEvents: false,
            oneTimeOnly: true,
            labelCompleted: "completed",
            labelNotValid: "not valid",
            labelSkipped: "skipped"
        },
        category: "",
        action: "",
        placeholders: {},
        onComplete: function () {
        }
    };

    $.fn.triggerDelayed = function (event, delay) {
        delay = delay || 50;
        var element = $(this);
        setTimeout(function () {
                element.trigger(event);
            },
            delay);
    };

}(jQuery, window, document));<commit_msg>tracking on keyup (first char only :)<commit_after>/**
 * ___________                     __      _____
 * \__    ___/___________    ____ |  | __ /     \   ____
 *   |    |  \_  __ \__  \ _/ ___\|  |/ //  \ /  \_/ __ \
 *   |    |   |  | \// __ \\  \___|    </    Y    \  ___/
 *   |____|   |__|  (____  /\___  >__|_ \____|__  /\___  >
 *                       \/     \/     \/       \/     \/
 *
 *
 * jQuery TrackMe v2.1.5 - 15/07/2016
 * --------------------------------
 * Original author: Marco Trevisani (marco.trevisani@ynap.com)
 * Further changes, comments:
 * --- v2.15:
 * - added tracking on keyup event.
 * --- v2.14:
 * - added no follow links feature.
 * --- v2.1.3:
 * - added placeholder feature for labels.
 * --- v2.1.2:
 * - added simple description :)
 * - added new public function trackEvent{trackingInfoObject}
 *
 *
 **** Description:
 * What does this plugin?
 * - It attaches the event tracking on elements with specific classes reading data attributes for the tracking info.
 * - It tracks the user behavior during filling of the form.
 *
 **** Available custom classes:
 * js-track-me          {any element} - track event on click.
 * js-track-me-hover:   {any element} - track event on mouseover.
 * js-track-me-focus:   {any element} - track event on focus.
 * js-track-me-form:    {form} - track user behavior during filling of the form (skipped inputs and inputs not valid).
 *
 **** Data Attributes:
 * data-tracking-category               - Set the event category.
 * data-tracking-action                 - Set the event action.
 * data-tracking-label                  - Set the event label.
 * data-tracking-form-id                - Track only if this form is valid.
 * data-tracking-event                  - Track only when this event will dispatched.
 * data-tracking-label-checked          - {checkbox only} this is the event label when the checkbox is checked.
 * data-tracking-label-not-checked      - {checkbox only} this is the event label when the checkbox isn't checked.
 * data-tracking-label-on               - {element with a switch functionality} Set the event label when the switch is on. (es: accordion open, option turned on...).
 * data-tracking-label-off              - {element with a switch functionality} Set the event label when the switch is off. (es: accordion closed, option turned off...).
 *
 **** Initialisation Options:
 *      $(selector).trackMe({
 *       debug: false,
 *       formTracking {
 *           completedEvents: false,
 *           oneTimeOnly: true,
 *           labelCompleted: "completed",
 *           labelNotValid: "not valid",
 *           labelSkipped: "skipped"
 *       },
 *       category: "custom global category",
 *       action: "custom global action",
 *       callback: function() {
 *          console.log("Event tracked.");
 *
 **** Usage Example:
 *
 *  JS: $(selector).trackMe();
 *  HTML: Click Me!
 *
 **** More Examples:
 *
 * You can set custom global action and label using public functions:
 *
 *      $(selector).trackMe();
 *      $(selector).data("plugin_trackMe").setTrackingCategory("custom global category");
 *      $(selector).data("plugin_trackMe").setTrackingAction("custom global action");
 *
 */
;
(function ($, window, document) {
    "use strict";

    var pluginName = "trackMe";

    function TrackMe (element, options) {
        this.element = element;
        this._name = pluginName;
        this._defaults = $.fn.trackMe.defaults;
        this.options = $.extend({}, this._defaults, options);
        this.trackingData = {};
        this.init();
    }

    // - Private Functions - - -
    var formIsValid = function (formId) {
        if (formId !== undefined) {
            var $formToValidate = $("#" + formId);
            if ($formToValidate.length && !$formToValidate.valid()) {
                return false;
            }
        }
        return true;
    };

    // ( Debug Layer )
    var onlineOrStageEnvironment = function () {
            if (document.location.hostname.match("yoox.com$") || document.location.hostname.match("yoox.cn$")) {
                return true;
            }
            return false;
        },
        checkQueryString = function () {
            //if (location.search.match("td=1$")) {
            //    return true;
            //}
            //return false;
            return true;
        },
        debugTrackedEvent = function (category, action, label) {
            if (!onlineOrStageEnvironment() && checkQueryString()) {
                var messageText = "[EVENT] --------------------\nCategory: " +
                        category +
                        "\nAction: " +
                        action +
                        "\nLabel: " +
                        label +
                        "\n----------------------------",
                    messageHtml = "Category: " +
                        category +
                        "
 Action: " +
                        action +
                        "
 Label: " +
                        label +
                        "
",
                    $message = $("
").html("New Event:").after($("
").html(messageHtml)),
                    $messageContainer = $("
", { "class": "track-event-notification-layer fade-in" });

                if (!$(".track-event-notification-layer").length) {
                    $messageContainer.append($message);
                    $("body").append($messageContainer);
                } else {
                    clearTimeout(window.closeDebugLayerTimeout);
                    $(".track-event-notification-layer").append($message).removeClass("fade-out").addClass("fade-in");
                }

                window.closeDebugLayerTimeout = setTimeout(function () {
                        $(".track-event-notification-layer").removeClass("fade-in").addClass("fade-out").html("");
                    },
                    3000);

                console.log(messageText);
            }
        };

    // - Public Functions - - -
    $.extend(TrackMe.prototype,
        {
            init: function () {
                this.buildCache();
                this.bindEvents();
            },

            destroy: function () {
                this.unbindEvents();
                this.$element.removeData();
            },

            // Cache DOM nodes for performance
            buildCache: function () {
                this.$element = $(this.element);
            },

            // Bind events that trigger methods
            bindEvents: function () {
                var plugin = this;

                plugin.$element.on("click" + "." + plugin._name,
                    ".js-track-me",
                    function (e) {
                        if (plugin.options.debugNoFollowLinks) {
                            e.preventDefault();
                            e.stopPropagation();
                        }
                        plugin.startTracking.call(plugin, $(this));
                    });

                plugin.$element.on("hover" + "." + plugin._name,
                    ".js-track-me-hover",
                    function () {
                        plugin.startTracking.call(plugin, $(this));
                    });

                plugin.$element.on("keyup" + "." + plugin._name,
                    ".js-track-me-keyup",
                    function () {
                        // track only REQUIRED input not already tracked.
                        if (!$(this).data("alreadyTracked")) {
                            plugin.startTracking.call(plugin, $(this));
                        }
                    });

                plugin.$element.on("focus" + "." + plugin._name,
                    ".js-track-me-focus",
                    function () {
                        plugin.startTracking.call(plugin, $(this));
                    });

                plugin.$element.on("blur" + "." + plugin._name,
                    ".js-track-form input:not([type=submit]), .js-track-form select",
                    function () {
                        // track only REQUIRED input not already tracked.
                        if (!$(this).data("alreadyTracked") && $(this).data("valRequired") !== undefined) {
                            plugin.startTrackingForm.call(plugin, $(this));
                        }
                    });
            },

            // Unbind events that trigger methods
            unbindEvents: function () {
                this.$element.off("." + this._name);
            },

            getTrackingData: function ($elm) {
                return {
                    category: ($elm.data("trackingCategory")) === undefined
                        ? this.options.category
                        : $elm.data("trackingCategory"),
                    action: ($elm.data("trackingAction")) === undefined ? this.options.action : $elm.data("trackingAction"),
                    label: $elm.data("trackingLabel"),
                    labelChecked: $elm.data("trackingLabelChecked"),
                    labelNotChecked: $elm.data("trackingLabelNotChecked"),
                    labelOn: $elm.data("trackingLabelOn"),
                    labelOff: $elm.data("trackingLabelOff"),
                    event: $elm.data("trackingEvent"),
                    formToValidate: $elm.data("trackingFormId")
                };
            },

            getFormTrackingData: function ($elm) {
                var $form = $elm.closest("form");
                return {
                    category: ($form.data("trackingCategory")) === undefined
                        ? this.options.category
                        : $form.data("trackingCategory"),
                    action: ($form.data("trackingAction")) === undefined
                        ? this.options.action
                        : $form.data("trackingAction"),
                    label: $form.data("trackingFormName"),
                    fieldName: ($elm.data("trackingName")) === undefined ? $elm.attr("name") : $elm.data("trackingName")
                };
            },

            startTracking: function ($element) {
                var plugin = this;
                this.trackingData = this.getTrackingData($element);

                // Track checkbox events
                if ($element.is("input[type=checkbox]") && plugin.trackingData.labelChecked !== undefined) {
                    var label = $element.is(":checked")
                        ? plugin.trackingData.labelChecked
                        : plugin.trackingData.labelNotChecked;

                    if (plugin.trackingData.event === undefined && label !== undefined) {
                        plugin.trackUserEvent(plugin.trackingData.category, plugin.trackingData.action, label);
                    } else {
                        $("body")
                            .off(plugin.trackingData.event)
                            .one(plugin.trackingData.event,
                                function () {
                                    plugin.trackUserEvent(plugin.trackingData.category, plugin.trackingData.action, label);
                                });
                    }
                    // Track switch events
                } else if (plugin.trackingData.labelOn !== undefined || plugin.trackingData.labelOff !== undefined) {
                    if ($element.hasClass("js-track-me-on")) {
                        $element.removeClass("js-track-me-on");
                        plugin.trackUserEvent(plugin.trackingData.category,
                            plugin.trackingData.action,
                            plugin.trackingData.labelOff);
                    } else {
                        $element.addClass("js-track-me-on");
                        plugin.trackUserEvent(plugin.trackingData.category,
                            plugin.trackingData.action,
                            plugin.trackingData.labelOn);
                    }
                    // Track only if form is valid
                } else if (plugin.trackingData.formToValidate !== undefined) {
                    if (formIsValid(plugin.trackingData.formToValidate)) {
                        plugin.trackUserEvent(plugin.trackingData.category,
                            plugin.trackingData.action,
                            plugin.trackingData.label);
                    }

                    // Track on custom event
                } else {
                    if (plugin.trackingData.event === undefined) {
                        plugin.trackUserEvent(plugin.trackingData.category,
                            plugin.trackingData.action,
                            plugin.trackingData.label);
                    } else {
                        $("body")
                            .off(plugin.trackingData.event)
                            .one(plugin.trackingData.event,
                                function () {
                                    plugin.trackUserEvent(plugin.trackingData.category,
                                        plugin.trackingData.action,
                                        plugin.trackingData.label);
                                });
                    }
                }

                if ($element.hasClass("js-track-me-keyup")) {
                    $element.data("alreadyTracked", true);
                }

                this.callback();
            },

            startTrackingForm: function ($element) {
                var plugin = this;
                this.trackingData = this.getFormTrackingData($element);

                if ($element.val().length === 0) {
                    plugin.trackUserEvent(plugin.trackingData.category,
                        plugin.trackingData.action,
                        plugin.trackingData.label +
                        " " +
                        plugin.options.formTracking.labelSkipped +
                        " " +
                        plugin.trackingData.fieldName);
                } else if (!$element.valid()) {
                    plugin.trackUserEvent(plugin.trackingData.category,
                        plugin.trackingData.action,
                        plugin.trackingData.label +
                        " " +
                        plugin.options.formTracking.labelNotValid +
                        " " +
                        plugin.trackingData.fieldName);
                } else {
                    if (this.options.formTracking.completedEvents) {
                        plugin.trackUserEvent(plugin.trackingData.category,
                            plugin.trackingData.action,
                            plugin.trackingData.label +
                            " " +
                            plugin.options.formTracking.labelCompleted +
                            " " +
                            plugin.trackingData.fieldName);
                    }
                }
                if (this.options.formTracking.oneTimeOnly) {
                    $element.data("alreadyTracked", true);
                }

                this.callback();
            },

            setTrackingCategory: function (category) {
                this.options.category = category;
            },

            setTrackingAction: function (action) {
                this.options.action = action;
            },

            addPlaceholder: function (placeholder) {
                $.extend(this.options.placeholders, placeholder);
            },

            updateTrackingData: function (updatedTrackingData) {
                $.extend(true, this.trackingData, updatedTrackingData);
            },

            getCurrentTrackingCategory: function () {
                return this.options.category;
            },

            getCurrentTrackingAction: function () {
                return this.options.action;
            },
            managePlaceholder: function (text) {
                var myRegexp = /{{([a-zA-Z0-9]*)}}/g,
                    result = text.match(myRegexp),
                    placeholderText,
                    i;
                if (result) {
                    for (i = 0; i <= result.length; i = i + 1) {
                        placeholderText = this.options.placeholders[result[i]] !== undefined
                            ? this.options.placeholders[result[i]]
                            : "";
                        text = text.replace(result[i], placeholderText);
                    }
                }
                return text;
            },
            trackUserEvent: function (category, action, label) {
                if (label !== undefined && action !== undefined && label !== "" && action !== "") {
                    if (this.options.debug) {
                        debugTrackedEvent(category, action, label);
                    }

                    label = this.managePlaceholder(label);

                    $Y.track.userEvent("ga", { category: category, action: action, label: label });
                }
            },

            trackEvent: function (trackInfo) {
                trackInfo.category = trackInfo.category || this.options.category;
                trackInfo.action = trackInfo.action || this.options.action;

                if (trackInfo.label !== undefined &&
                    trackInfo.action !== undefined &&
                    trackInfo.label !== "" &&
                    trackInfo.action !== "") {
                    if (this.options.debug) {
                        debugTrackedEvent(trackInfo.category, trackInfo.action, trackInfo.label);
                    }

                    $Y.track.userEvent("ga",
                        { category: trackInfo.category, action: trackInfo.action, label: trackInfo.label });
                }
            },

            callback: function () {
                // Cache onComplete option
                var onComplete = this.options.onComplete;

                if (typeof onComplete === "function") {
                    onComplete.call(this.element);
                }
            },

            trackingData: {
                category: "",
                action: "",
                label: "",
                labelChecked: "",
                labelNotChecked: "",
                labelOn: "",
                labelOff: "",
                event: "",
                formToValidate: ""
            }
        });

    $.fn.trackMe = function (options) {
        this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName, new TrackMe(this, options));
            }
        });

        return this;
    };

    $.fn.trackMe.defaults = {
        debug: false, // true: activate the event notification layer
        debugNoFollowLinks: false, // DANGEROUS!
        formTracking: {
            completedEvents: false,
            oneTimeOnly: true,
            labelCompleted: "completed",
            labelNotValid: "not valid",
            labelSkipped: "skipped"
        },
        category: "",
        action: "",
        placeholders: {},
        onComplete: function () {
        }
    };

    $.fn.triggerDelayed = function (event, delay) {
        delay = delay || 50;
        var element = $(this);
        setTimeout(function () {
                element.trigger(event);
            },
            delay);
    };

}(jQuery, window, document));<|endoftext|>


<commit_before>function sansTemple(direction) {
  var happensNext;
    if (direction == 'right hallway') {
      happensNext = 'You find a door, it is locked. You head back from where you came.'
    } else if (direction == 'left hallway') {
      happensNext = 'You find a door, it is locked. You head back from where you came.'
    } else if (direction == 'forward hallway') {
      happensNext = 'You find a door, it is locked. You head back from where you came.'
    } else if (direction == 'lower tunnel') {
      happensNext = 'You find a door, it is locked. You head back from where you came.'
    } else if (direction == 'hidden door') {
      happensNext = 'You go through the door into a room. A small, very dark room, that smells of dust and sulfur...'
    } else {
      happensNext = 'You stand there, gaping, not moving. Aiedra wonders, are you alive?'
    }
  return happensNext;
}
sansTemple();
<commit_msg>adding switches to the cases<commit_after>function sansTemple(direction) {
  var happensNext;
    switch (direction) {
      case "right hallway":
         this.happensNext = 'You find a door, it is locked. You head back from where you came.'
      case 'left hallway':
         this.happensNext = 'You find a door, it is locked. You head back from where you came.'
}
  return happensNext;
}
sansTemple();
var place = new sansTemple("right hallway");
console.log(place);
<|endoftext|>


<commit_before>/*
 * Twitter Search Plugin jquery.twitter.js
 * http://code.bocoup.com/jquery-twitter-plugin/
 *
 * Copyright (c) 2010 Bocoup, LLC
 * Authors: Boaz Sender, Rick Waldron, Nick Cammarata
 * Dual licensed under the MIT and GPL licenses.
 * http://code.bocoup.com/license/
 *
 */
var linkify = linkify || function() {};
;(function($, linkify) {

  var
  mention = function( str ) {
    return str.replace(/[@]+[a-z0-9-_]+/ig, function( username ) {
      return username.link("http://twitter.com/"+ username.replace("@","") );
    });
  },
  hashtags = function( str ) {
    return str.replace(/[#]+[a-z0-9-_]+/ig, function( tag ) {
      return tag.link("http://search.twitter.com/search?q="+tag.replace("#","%23"));
    });
  };

  $.twitter = function (options, callback) {
    // Fail if the options arg is not set
    if ( !options ) {
      return false;
    }

    // Set a temporary default query object
    var query,
        // Set up a string to be used later in the case that exclusions have been set
        exclusionsStr = "",
        // Set up a regex to be used later in the case that exclusions have been set
        exclusionsExp = new RegExp(false);

    // If options is a string use it as standalone query
    if ( typeof options === "string" ) {
      query = $.extend({}, $.twitter.opts, {
        q: options
      });
    // Else prepare the options object to be serialized
    } else {
      // If a limit is set, add it to the query object
      options.rpp = options.limit ? options.limit : options.rpp;

      // If no limit is set, make the limit the rpp
      options.limit = options.limit ? options.limit : options.rpp;

      // If there are exlusions, turn them into a regex string
      exclusionsStr = options.exclusions ? options.exclusions.replace(" ", "|") : false;

      // If there are exlusions, turn the regex string we just made into a RegExp
      exclusionsExp = exclusionsStr ? new RegExp( exclusionsStr ) : false;

      // Make a new object that is a merger of the options passed in with the default $.twitter.opts object
      // and assign it to the query variable
      query = $.extend({}, $.twitter.opts, options);

      // If there are exclusions, or replies or retweets are set to false, multiply the results to ask for from twitter by ten
      // We need to do this so that we have some meat to work with if the exclusions are common
      query.rpp = query.exclusions || !query.replies || !query.retweets  ? (query.rpp * 10) : query.rpp;

    }

    // Call Twitter JSONP
    $.getJSON("http://search.twitter.com/search.json?callback=?", query, function(tweets){
      callback(tweets, query, exclusionsExp);
    });
  };

  $.fn.twitter = function( options, callback ) {
    // Fail gracefully if the options arg is not set
    // return the jQuery obj so that chaining does not break
    if ( !options ) {
      return this;
    }

    // Begin to iterate over the jQuery collection that the method was called on
    return this.each(function () {
      // Cache `this`
      var $this = $(this);

      $.twitter(options, function( tweets, query, exclusionsExp ) {
        //Create and cache a new UL
        var $tweets = $("
"),
            // Create a counter variable to count up how many tweets we have rendered
            // unfortunately we have to do this, because exclusions, retweet booleans and replies booleans
            // are not supported by the Twitter Search API
            limitInt = 0,
            i;

        // If there are results to work with
        if ( tweets.results && tweets.results.length ) {

          //  Iterate over returned tweets
          for ( i in tweets.results ) {

            // Cache tweet content
            var tweet = tweets.results[i],
                // Set a variable to determine weather replies are set to false, and if so, weather the tweet starts with a reply
                allowReply = !query.replies && tweet.to_user_id ? false : true,
                // Set a variable to determine weather retweets are set to false, and if so, weather the tweet starts with a retweet
                allowRetweet = !query.retweets && tweet.text.slice(0,2) === "RT" ? false : true;

            // Only proceed if allow reply is false
            if ( !allowReply ) {
              continue;
            }

            // Only proceed if allow retweet is false
            if ( !allowRetweet ) {
              continue;
            }

            // If exlusions set and none of the exlusions is found in the tweet then add it to the DOM
            if ( exclusionsExp && exclusionsExp.test(tweet.text) ) {
              continue;
            }

            // Create and cache new LI
            var $tweet = $("
", {
              "class": "tweet"
            });

            // Make the avatar, and append it to the $tweet
            if ( query.avatar === true ) {
              $tweet.append($("", {
                href: "http://twitter.com/" + tweet.from_user,
                html: ""
              }));
            }

            // Make the tweet text, and append it to the $tweet, then to the parent
            $tweet.append($("", {
              "class": "content",
              html: "@" + tweet.from_user + ": " + mention(hashtags(linkify(tweet.text)))
            }))
            // Append tweet to the $tweets ul
            .appendTo($tweets);

            // Count up our counter variable
            limitInt++;

            // If the counter is equal to the limit, stop rendering tweets
            if ( limitInt === query.limit ) {
              break;
            }
          }

          // Inject the $tweets into the DOM
          $this.html($tweets);

          if(callback){
            callback(true);
          }

        // Else there are no results to work with
        } else {
          // Update the DOM to reflect that no results were found
          $this.html($("
", {
            "class": "twitter-notFound",
            text: query.notFoundText
          }));

          if(callback){
            callback(false);
          }
        }
      });
    });
  };

  $.twitter.opts = {
    // Number of tweets to get
    // not in twitter search api, maps to and supersedes rpp (results per page)
    limit: 7,
    // Space delimited list of strings to exclude  (eg: "_ s gr @b")
    // not in twitter search api, done in plugin
    exclusions: "",
    // Text to display if no results are found
    // not in twitter search api, done in plugin
    notFoundText: "No results found on twitter",
    // Include replies?
    // not in twitter search api, done in plugin
    replies: true,
    // Include replies?
    // not in twitter search api, done in plugin
    retweets: true,
    // All of these words
    ands: "",
    // This exact phrase
    phrase: "",
    // Any of these words
    ors : "",
    // None of these words
    nots: "",
    // This hashtag
    tag : "",
    // Written in language
    lang: "",
    // From this person
    from: "",
    // To this person
    to: "",
    // Referencing this person
    ref: "",
    // Near this place
    near: "",
    // Within this distance
    within: "",
    // Distance unit (miles or kilometers)
    units: "",
    // Since this date
    since: "",
    // Until this date
    until: "",
    // Attitude: "?" or :)" or ":)"
    tude: "",
    // Containing: "links"
    filter: "",
    // Include retweet?: "retweets"
    include: "",
    // Results per page
    rpp: 5,
    // Default query
    q: "",
    // Add an avatar image of the user
    avatar: true
  };
}(jQuery, linkify));
<commit_msg>escaping unescaped dash in regexes to pass hint<commit_after>/*
 * Twitter Search Plugin jquery.twitter.js
 * http://code.bocoup.com/jquery-twitter-plugin/
 *
 * Copyright (c) 2010 Bocoup, LLC
 * Authors: Boaz Sender, Rick Waldron, Nick Cammarata
 * Dual licensed under the MIT and GPL licenses.
 * http://code.bocoup.com/license/
 *
 */
var linkify = linkify || function() {};
;(function($, linkify) {

  var
  mention = function( str ) {
    return str.replace(/[@]+[a-z0\-9-_]+/ig, function( username ) {
      return username.link("http://twitter.com/"+ username.replace("@","") );
    });
  },
  hashtags = function( str ) {
    return str.replace(/[#]+[a-z0\-9-_]+/ig, function( tag ) {
      return tag.link("http://search.twitter.com/search?q="+tag.replace("#","%23"));
    });
  };

  $.twitter = function (options, callback) {
    // Fail if the options arg is not set
    if ( !options ) {
      return false;
    }

    // Set a temporary default query object
    var query,
        // Set up a string to be used later in the case that exclusions have been set
        exclusionsStr = "",
        // Set up a regex to be used later in the case that exclusions have been set
        exclusionsExp = new RegExp(false);

    // If options is a string use it as standalone query
    if ( typeof options === "string" ) {
      query = $.extend({}, $.twitter.opts, {
        q: options
      });
    // Else prepare the options object to be serialized
    } else {
      // If a limit is set, add it to the query object
      options.rpp = options.limit ? options.limit : options.rpp;

      // If no limit is set, make the limit the rpp
      options.limit = options.limit ? options.limit : options.rpp;

      // If there are exlusions, turn them into a regex string
      exclusionsStr = options.exclusions ? options.exclusions.replace(" ", "|") : false;

      // If there are exlusions, turn the regex string we just made into a RegExp
      exclusionsExp = exclusionsStr ? new RegExp( exclusionsStr ) : false;

      // Make a new object that is a merger of the options passed in with the default $.twitter.opts object
      // and assign it to the query variable
      query = $.extend({}, $.twitter.opts, options);

      // If there are exclusions, or replies or retweets are set to false, multiply the results to ask for from twitter by ten
      // We need to do this so that we have some meat to work with if the exclusions are common
      query.rpp = query.exclusions || !query.replies || !query.retweets  ? (query.rpp * 10) : query.rpp;

    }

    // Call Twitter JSONP
    $.getJSON("http://search.twitter.com/search.json?callback=?", query, function(tweets){
      callback(tweets, query, exclusionsExp);
    });
  };

  $.fn.twitter = function( options, callback ) {
    // Fail gracefully if the options arg is not set
    // return the jQuery obj so that chaining does not break
    if ( !options ) {
      return this;
    }

    // Begin to iterate over the jQuery collection that the method was called on
    return this.each(function () {
      // Cache `this`
      var $this = $(this);

      $.twitter(options, function( tweets, query, exclusionsExp ) {
        //Create and cache a new UL
        var $tweets = $("
"),
            // Create a counter variable to count up how many tweets we have rendered
            // unfortunately we have to do this, because exclusions, retweet booleans and replies booleans
            // are not supported by the Twitter Search API
            limitInt = 0,
            i;

        // If there are results to work with
        if ( tweets.results && tweets.results.length ) {

          //  Iterate over returned tweets
          for ( i in tweets.results ) {

            // Cache tweet content
            var tweet = tweets.results[i],
                // Set a variable to determine weather replies are set to false, and if so, weather the tweet starts with a reply
                allowReply = !query.replies && tweet.to_user_id ? false : true,
                // Set a variable to determine weather retweets are set to false, and if so, weather the tweet starts with a retweet
                allowRetweet = !query.retweets && tweet.text.slice(0,2) === "RT" ? false : true;

            // Only proceed if allow reply is false
            if ( !allowReply ) {
              continue;
            }

            // Only proceed if allow retweet is false
            if ( !allowRetweet ) {
              continue;
            }

            // If exlusions set and none of the exlusions is found in the tweet then add it to the DOM
            if ( exclusionsExp && exclusionsExp.test(tweet.text) ) {
              continue;
            }

            // Create and cache new LI
            var $tweet = $("
", {
              "class": "tweet"
            });

            // Make the avatar, and append it to the $tweet
            if ( query.avatar === true ) {
              $tweet.append($("", {
                href: "http://twitter.com/" + tweet.from_user,
                html: ""
              }));
            }

            // Make the tweet text, and append it to the $tweet, then to the parent
            $tweet.append($("", {
              "class": "content",
              html: "@" + tweet.from_user + ": " + mention(hashtags(linkify(tweet.text)))
            }))
            // Append tweet to the $tweets ul
            .appendTo($tweets);

            // Count up our counter variable
            limitInt++;

            // If the counter is equal to the limit, stop rendering tweets
            if ( limitInt === query.limit ) {
              break;
            }
          }

          // Inject the $tweets into the DOM
          $this.html($tweets);

          if(callback){
            callback(true);
          }

        // Else there are no results to work with
        } else {
          // Update the DOM to reflect that no results were found
          $this.html($("
", {
            "class": "twitter-notFound",
            text: query.notFoundText
          }));

          if(callback){
            callback(false);
          }
        }
      });
    });
  };

  $.twitter.opts = {
    // Number of tweets to get
    // not in twitter search api, maps to and supersedes rpp (results per page)
    limit: 7,
    // Space delimited list of strings to exclude  (eg: "_ s gr @b")
    // not in twitter search api, done in plugin
    exclusions: "",
    // Text to display if no results are found
    // not in twitter search api, done in plugin
    notFoundText: "No results found on twitter",
    // Include replies?
    // not in twitter search api, done in plugin
    replies: true,
    // Include replies?
    // not in twitter search api, done in plugin
    retweets: true,
    // All of these words
    ands: "",
    // This exact phrase
    phrase: "",
    // Any of these words
    ors : "",
    // None of these words
    nots: "",
    // This hashtag
    tag : "",
    // Written in language
    lang: "",
    // From this person
    from: "",
    // To this person
    to: "",
    // Referencing this person
    ref: "",
    // Near this place
    near: "",
    // Within this distance
    within: "",
    // Distance unit (miles or kilometers)
    units: "",
    // Since this date
    since: "",
    // Until this date
    until: "",
    // Attitude: "?" or :)" or ":)"
    tude: "",
    // Containing: "links"
    filter: "",
    // Include retweet?: "retweets"
    include: "",
    // Results per page
    rpp: 5,
    // Default query
    q: "",
    // Add an avatar image of the user
    avatar: true
  };
}(jQuery, linkify));
<|endoftext|>


<commit_before>import { assert } from 'orbit/lib/assert';
import MemorySource from './memory-source';

var supportsLocalStorage = function() {
  try {
    return 'localStorage' in window && window['localStorage'] !== null;
  } catch(e) {
    return false;
  }
};

/**
 Source for storing data in local storage

 @class LocalStorageSource
 @extends MemorySource
 @namespace OC
 @param {Object}    [options]
 @param {OC.Schema} [options.schema] Schema for source (required)
 @constructor
 */
var LocalStorageSource = MemorySource.extend({
  init: function(options) {
    assert('LocalStorageSource constructor requires `options`', options);
    assert('Your browser does not support local storage!', supportsLocalStorage());

    this._super.apply(this, arguments);

    this.namespace = options['namespace'] || 'orbit'; // local storage key
    this._autosave = options['autosave'] !== undefined ? options['autosave'] : true;
    var autoload = options['autoload'] !== undefined ? options['autoload'] : true;

    this._isDirty = false;

    this.on('didTransform', function() {
      this._saveData();
    }, this);

    if (autoload) this.load();
  },

  load: function() {
    var storage = window.localStorage.getItem(this.namespace);
    if (storage) {
      this.cache.reset(JSON.parse(storage));
    }
  },

  enableAutosave: function() {
    if (!this._autosave) {
      this._autosave = true;
      if (this._isDirty) this._saveData();
    }
  },

  disableAutosave: function() {
    if (this._autosave) {
      this._autosave = false;
    }
  },

  /////////////////////////////////////////////////////////////////////////////
  // Internals
  /////////////////////////////////////////////////////////////////////////////

  _saveData: function(forceSave) {
    if (!this._autosave && !forceSave) {
      this._isDirty = true;
      return;
    }
    window.localStorage.setItem(this.namespace, JSON.stringify(this.cache.get()));
    this._isDirty = false;
  }
});

export default LocalStorageSource;
<commit_msg>Fix LocalStorageSource to observe `transform` event.<commit_after>import { assert } from 'orbit/lib/assert';
import MemorySource from './memory-source';

var supportsLocalStorage = function() {
  try {
    return 'localStorage' in window && window['localStorage'] !== null;
  } catch(e) {
    return false;
  }
};

/**
 Source for storing data in local storage

 @class LocalStorageSource
 @extends MemorySource
 @namespace OC
 @param {Object}    [options]
 @param {OC.Schema} [options.schema] Schema for source (required)
 @constructor
 */
var LocalStorageSource = MemorySource.extend({
  init: function(options) {
    assert('LocalStorageSource constructor requires `options`', options);
    assert('Your browser does not support local storage!', supportsLocalStorage());

    this._super.apply(this, arguments);

    this.namespace = options['namespace'] || 'orbit'; // local storage key
    this._autosave = options['autosave'] !== undefined ? options['autosave'] : true;
    var autoload = options['autoload'] !== undefined ? options['autoload'] : true;

    this._isDirty = false;

    this.on('transform', function() {
      this._saveData();
    }, this);

    if (autoload) this.load();
  },

  load: function() {
    var storage = window.localStorage.getItem(this.namespace);
    if (storage) {
      this.cache.reset(JSON.parse(storage));
    }
  },

  enableAutosave: function() {
    if (!this._autosave) {
      this._autosave = true;
      if (this._isDirty) this._saveData();
    }
  },

  disableAutosave: function() {
    if (this._autosave) {
      this._autosave = false;
    }
  },

  /////////////////////////////////////////////////////////////////////////////
  // Internals
  /////////////////////////////////////////////////////////////////////////////

  _saveData: function(forceSave) {
    if (!this._autosave && !forceSave) {
      this._isDirty = true;
      return;
    }
    window.localStorage.setItem(this.namespace, JSON.stringify(this.cache.get()));
    this._isDirty = false;
  }
});

export default LocalStorageSource;
<|endoftext|>


<commit_before>import _ from 'underscore';
import uuid from 'uuid';

export default class FileHandler {
  constructor(darkwire, socket, chat) {
    this.localFileQueue = [];
    if (window.File && window.FileReader && window.FileList && window.Blob && window.btoa && window.atob && window.Blob && window.URL) {
      this._isSupported = true;
      this.darkwire = darkwire;
      this.socket = socket;
      this.chat = chat;
      this.listen();
    } else {
      this._isSupported = false;
    }
  }

  get isSupported() {
    return this._isSupported;
  }

  set isSupported(state) {
    this._isSupported = state;
    return this;
  }

  confirmTransfer(event) {
    const validFileTypes = ['png','jpg','jpeg','gif','zip','rar','gzip','pdf','txt','json','doc','docx'];
    const file = event.target.files && event.target.files[0];
    const fileName = this.sanitizeFileName(file.name);

    if (file) {
      const fileExt = file.name.split('.').pop().toLowerCase();

      if (validFileTypes.indexOf(fileExt) <= -1) {
        alert('file type not supported');
        return false;
      }

      // Support for only 1MB
      if (file.size > 1000000) {
        alert('Max filesize is 1MB.');
        return false;
      }
      let fileId = uuid.v4();

      let confirmMessage = 'You are about to send ' + fileName + ' to all participants in this chat. Confirm | Cancel';
      let fileData = {
        id: fileId,
        file: file,
        fileName : fileName
      };
      this.localFileQueue.push(fileData);
      this.chat.addChatMessage({
        username: username,
        message: confirmMessage
      });
      this.filesSent++;

    }

    return false;
  }

  encodeFile(fileId) {
    const fileData = _.findWhere(this.localFileQueue, {id: fileId});
    const file = fileData.file || false;

    if (file) {
      // TODO: Remove file from local queue
    } else {
      return false;
    }

    const reader = new FileReader();
    const fileType = file.type || 'file';

    reader.onload = (readerEvent) => {
      const base64 = window.btoa(readerEvent.target.result);
      const additionalData = {
        fileId: fileId,
        fileName: this.sanitizeFileName(file.name)
      };
      this.darkwire.encodeMessage(base64, fileType, additionalData).then((socketData) => {
        this.chat.replaceMessage('#transfer-' + fileId, 'Sent ' + additionalData.fileName + '');
        this.socket.emit('new message', socketData);
      });
      this.resetInput();
    };

    reader.readAsBinaryString(file);
  }

  destroyFile(fileId) {
    const file = _.findWhere(this.localFileQueue, {id: fileId});
    this.localFileQueue = _.without(this.localFileQueue, file);
    this.resetInput();
    return this.chat.replaceMessage('#transfer-' + fileId, 'The file transfer for ' + file.fileName + ' has been canceled.');
  }

  createBlob(base64, fileType) {
    base64 = unescape(base64);
    return new Promise((resolve, reject) => {
      const sliceSize = 1024;
      let byteCharacters = window.atob(base64);
      let byteArrays = [];

      for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        let slice = byteCharacters.slice(offset, offset + sliceSize);

        let byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
          byteNumbers[i] = slice.charCodeAt(i);
        }

        let byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
      }

      resolve(new window.Blob(byteArrays, {type: fileType}));
    });
  }

  createUrlFromBlob(blob) {
    return window.URL.createObjectURL(blob);
  }

  sanitizeFileName(str) {
    return str.replace(/[<>]/ig, '');
  }

  listen() {
    // browser API
    document.getElementById('fileInput').addEventListener('change', this.confirmTransfer.bind(this), false);
    return this;
  }

  resetInput() {
    document.getElementById('fileInput').value = '';
  }
}
<commit_msg>Remove trailing whitespace<commit_after>import _ from 'underscore';
import uuid from 'uuid';

export default class FileHandler {
  constructor(darkwire, socket, chat) {
    this.localFileQueue = [];
    if (window.File && window.FileReader && window.FileList && window.Blob && window.btoa && window.atob && window.Blob && window.URL) {
      this._isSupported = true;
      this.darkwire = darkwire;
      this.socket = socket;
      this.chat = chat;
      this.listen();
    } else {
      this._isSupported = false;
    }
  }

  get isSupported() {
    return this._isSupported;
  }

  set isSupported(state) {
    this._isSupported = state;
    return this;
  }

  confirmTransfer(event) {
    const validFileTypes = ['png','jpg','jpeg','gif','zip','rar','gzip','pdf','txt','json','doc','docx'];
    const file = event.target.files && event.target.files[0];
    const fileName = this.sanitizeFileName(file.name);

    if (file) {
      const fileExt = file.name.split('.').pop().toLowerCase();

      if (validFileTypes.indexOf(fileExt) <= -1) {
        alert('file type not supported');
        return false;
      }

      // Support for only 1MB
      if (file.size > 1000000) {
        alert('Max filesize is 1MB.');
        return false;
      }
      let fileId = uuid.v4();

      let confirmMessage = 'You are about to send ' + fileName + ' to all participants in this chat. Confirm | Cancel';
      let fileData = {
        id: fileId,
        file: file,
        fileName : fileName
      };
      this.localFileQueue.push(fileData);
      this.chat.addChatMessage({
        username: username,
        message: confirmMessage
      });
      this.filesSent++;

    }

    return false;
  }

  encodeFile(fileId) {
    const fileData = _.findWhere(this.localFileQueue, {id: fileId});
    const file = fileData.file || false;

    if (file) {
      // TODO: Remove file from local queue
    } else {
      return false;
    }

    const reader = new FileReader();
    const fileType = file.type || 'file';

    reader.onload = (readerEvent) => {
      const base64 = window.btoa(readerEvent.target.result);
      const additionalData = {
        fileId: fileId,
        fileName: this.sanitizeFileName(file.name)
      };
      this.darkwire.encodeMessage(base64, fileType, additionalData).then((socketData) => {
        this.chat.replaceMessage('#transfer-' + fileId, 'Sent ' + additionalData.fileName + '');
        this.socket.emit('new message', socketData);
      });
      this.resetInput();
    };

    reader.readAsBinaryString(file);
  }

  destroyFile(fileId) {
    const file = _.findWhere(this.localFileQueue, {id: fileId});
    this.localFileQueue = _.without(this.localFileQueue, file);
    this.resetInput();
    return this.chat.replaceMessage('#transfer-' + fileId, 'The file transfer for ' + file.fileName + ' has been canceled.');
  }

  createBlob(base64, fileType) {
    base64 = unescape(base64);
    return new Promise((resolve, reject) => {
      const sliceSize = 1024;
      let byteCharacters = window.atob(base64);
      let byteArrays = [];

      for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        let slice = byteCharacters.slice(offset, offset + sliceSize);

        let byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
          byteNumbers[i] = slice.charCodeAt(i);
        }

        let byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
      }

      resolve(new window.Blob(byteArrays, {type: fileType}));
    });
  }

  createUrlFromBlob(blob) {
    return window.URL.createObjectURL(blob);
  }

  sanitizeFileName(str) {
    return str.replace(/[<>]/ig, '');
  }

  listen() {
    // browser API
    document.getElementById('fileInput').addEventListener('change', this.confirmTransfer.bind(this), false);
    return this;
  }

  resetInput() {
    document.getElementById('fileInput').value = '';
  }
}
<|endoftext|>


<commit_before>/**
 * Created by nikolaykozhukharenko on 4/24/16.
 */

import chai, {expect} from 'chai';
chai.should();
import {isDictLoaded, createDataMap} from './helpers'

describe('dictionary helper', () => {

  let listOfDict = ['dic_01', 'dic_02'];
  let dictState = {
    'dic_01': {
      isLoading: false,
      resources: [1,3,4]
    },
    'dic_02': {
      isLoading: false,
      resources: [5,7,9]
    }
  };

  describe('isDictLoaded fn', () => {

    it('should throw an error if wrong parameters were passed', () => {
      expect(isDictLoaded.bind({}, false, 1)).to.throw(Error)
    });

    it('should return "false" if dictionaries state it empty', () => {
      isDictLoaded([], {}).should.equal(false)
    });

    it('should throw an error if dic does not exists', () => {
      expect(isDictLoaded.bind({}, ['DontExistDictName'], dictState))
        .to.throw(ReferenceError)
    });

    it('should not throw an error if listOfDict eq to string', () => {
      expect(isDictLoaded.bind({}, 'dic_01', dictState))
        .to.not.throw(Error)
    });

    it('should return "true" if data for dictionaries exists', () => {
      isDictLoaded(listOfDict, dictState).should.equal(true)
    });

    it('should return "false" if one of dict "isLoading" right now', () => {
      isDictLoaded(listOfDict, {
        'dic_01': {
          isLoading: true,
          resources: [1,3,5]
        },
        'dic_02': {
          isLoading: false,
          resources: [4,6,7]
        }
      }).should.equal(false)
    });

    it('should return "false" if one of dict do not have "resources" field ', () => {
      isDictLoaded(listOfDict, {
        'dic_01': {
          isLoading: false
        },
        'dic_02': {
          isLoading: false,
          resources: [4,6,7]
        }
      }).should.equal(false)
    });

    it('should return "false" if one of dict has an empty "resources"', () => {
      isDictLoaded(listOfDict, {
        'dic_01': {
          isLoading: false,
          resources: [1,3,5]
        },
        'dic_02': {
          isLoading: false,
          resources: []
        }
      }).should.equal(false)
    });

    it('should return "true" when one dict (as a string) was passed ', () => {
      isDictLoaded('dic_011', {
        'dic_011': {
          isLoading: false,
          resources: [1,3,5]
        },
        'dic_02': {
          isLoading: false,
          resources: []
        }
      }).should.equal(true)
    });

    it('should return "false" if one of dictionaries is absent', () => {
      isDictLoaded([], {}).should.equal(false)
    });

  });

  describe('isDictLoaded fn', () => {
    it('should return an array', () => {
      expect(createDataMap([
        {
          id: 0,
          name: 'name_01'
        }
      ])).to.be.instanceof(Array);
    });

    it('should return a map', () => {
      expect(createDataMap([
        {
          id: 0,
          name: 'name_01'
        },
        {
          id: 1,
          name: 'name_02'
        }
      ])).to.eql(['name_01','name_02'])
    });

    it('should return a map when id order is different', () => {
      expect(createDataMap([
        {
          id: 1,
          name: 'name_01'
        },
        {
          id: 3,
          name: 'name_02'
        }
      ])).to.eql([,'name_01',,'name_02'])
    });
  })
});<commit_msg>remove redundant test case<commit_after>/**
 * Created by nikolaykozhukharenko on 4/24/16.
 */

import chai, {expect} from 'chai';
chai.should();
import {isDictLoaded, createDataMap} from './helpers'

describe('dictionary helper', () => {

  let listOfDict = ['dic_01', 'dic_02'];
  let dictState = {
    'dic_01': {
      isLoading: false,
      resources: [1,3,4]
    },
    'dic_02': {
      isLoading: false,
      resources: [5,7,9]
    }
  };

  describe('isDictLoaded fn', () => {

    it('should throw an error if wrong parameters were passed', () => {
      expect(isDictLoaded.bind({}, false, 1)).to.throw(Error)
    });

    it('should return "false" if dictionaries state it empty', () => {
      isDictLoaded([], {}).should.equal(false)
    });

    it('should throw an error if dic does not exists', () => {
      expect(isDictLoaded.bind({}, ['DontExistDictName'], dictState))
        .to.throw(ReferenceError)
    });

    it('should not throw an error if listOfDict eq to string', () => {
      expect(isDictLoaded.bind({}, 'dic_01', dictState))
        .to.not.throw(Error)
    });

    it('should return "true" if data for dictionaries exists', () => {
      isDictLoaded(listOfDict, dictState).should.equal(true)
    });

    it('should return "false" if one of dict "isLoading" right now', () => {
      isDictLoaded(listOfDict, {
        'dic_01': {
          isLoading: true,
          resources: [1,3,5]
        },
        'dic_02': {
          isLoading: false,
          resources: [4,6,7]
        }
      }).should.equal(false)
    });

    it('should return "false" if one of dict do not have "resources" field ', () => {
      isDictLoaded(listOfDict, {
        'dic_01': {
          isLoading: false
        },
        'dic_02': {
          isLoading: false,
          resources: [4,6,7]
        }
      }).should.equal(false)
    });

    it('should return "false" if one of dict has an empty "resources"', () => {
      isDictLoaded(listOfDict, {
        'dic_01': {
          isLoading: false,
          resources: [1,3,5]
        },
        'dic_02': {
          isLoading: false,
          resources: []
        }
      }).should.equal(false)
    });

    it('should return "true" when one dict (as a string) was passed ', () => {
      isDictLoaded('dic_011', {
        'dic_011': {
          isLoading: false,
          resources: [1,3,5]
        },
        'dic_02': {
          isLoading: false,
          resources: []
        }
      }).should.equal(true)
    });
  });

  describe('isDictLoaded fn', () => {
    it('should return an array', () => {
      expect(createDataMap([
        {
          id: 0,
          name: 'name_01'
        }
      ])).to.be.instanceof(Array);
    });

    it('should return a map', () => {
      expect(createDataMap([
        {
          id: 0,
          name: 'name_01'
        },
        {
          id: 1,
          name: 'name_02'
        }
      ])).to.eql(['name_01','name_02'])
    });

    it('should return a map when id order is different', () => {
      expect(createDataMap([
        {
          id: 1,
          name: 'name_01'
        },
        {
          id: 3,
          name: 'name_02'
        }
      ])).to.eql([,'name_01',,'name_02'])
    });
  })
});<|endoftext|>


<commit_before>(function ($) {
    var accel = 0;
    var overallslide = 0;
    var sensitivity = 20;
    var slides;
    var currentIndex = 0;
    //Waypoints check position relative to waypoint and decide if to scroll to or not...
    $.fn.initslide = function () {

        //var target = $(this).attr('id');
        //alert(target);
        //$(this)

        slides = $(this); //Saves the object in a variable //.children
        //alert("children: " + slides.length);
        /*$( this ).children( 'li.target' ).css("border", "3px double red");*/
        //alert(slides.children.length*slides.children('li').css("width").replace("px",""));
        console.log(slides.css("width")); //TODO: solve width problem
        /*slides.css("width",slides.children.length*slides.children('li').css("width").replace("px","")*2);*/
        $('li:nth-child(' + (currentIndex + 1) + ')').attr('id', 'active');

        var mc = new Hammer(slides.get(0)); //Retrieve DOM Elements to create hammer.js object

        mc.on("panleft panright", function (ev) {
            //            console.log(ev.velocityX +" gesture detected.");
            overallslide = Number(slides.css("left").replace("px",""))-ev.velocityX * sensitivity;

            slides.css("left", overallslide);
        });
        mc.on("swipe", function (ev) {
            //            console.log(ev.velocityX +" gesture detected.");
            /*accel -= ev.velocityX/100;
            while(accel>0)
            {
                console.log("YAYY");
                overallslide+=accel;
                slides.css("left",overallslide);
                accel-=0.001;
            }*/

            console.log(ev.velocityX);
            slides.animate({
                left: "-="+(ev.velocityX*200)
            }, {
                    duration: 250,
                    easing: 'swing'
                });

            //$(this).next();
            //slides.css("left",overallslide);
        });

        /*overallslide += accel;
            accel-=0.01;*/

    }

    $.fn.next = function () { //Next slide
        changeActiveSlideTo(currentIndex + 1);
    }

    function changeActiveSlideTo(i) {
        $('li:nth-child(' + (currentIndex + 1) + ')').attr('id', '');
        currentIndex = i;
        console.log("new index: " + currentIndex);
        $('li:nth-child(' + (currentIndex + 1) + ')').attr('id', 'active');
    }

})(jQuery);<commit_msg>changes<commit_after>(function ($) {
    var vel = 0.1;
    var accel = 0;
    var overallslide = 0;
    var sensitivity = 20;
    var slides;
    var currentIndex = 0;

    //Waypoints check position relative to waypoint and decide if to scroll to or not...
    $.fn.initslide = function () {

        //var target = $(this).attr('id');
        //alert(target);
        //$(this)

        slides = $(this); //Saves the object in a variable //.children
        //alert("children: " + slides.length);
        /*$( this ).children( 'li.target' ).css("border", "3px double red");*/
        //alert(slides.children.length*slides.children('li').css("width").replace("px",""));
        console.log(slides.css("width")); //TODO: solve width problem
        /*slides.css("width",slides.children.length*slides.children('li').css("width").replace("px","")*2);*/
        $('li:nth-child(' + (currentIndex + 1) + ')').attr('id', 'active');

        var mc = new Hammer(slides.get(0)); //Retrieve DOM Elements to create hammer.js object

        mc.on("panleft panright", function (ev) {
            //            console.log(ev.velocityX +" gesture detected.");
            overallslide = Number(slides.css("left").replace("px", "")) - ev.velocityX * sensitivity;

            slides.css("left", overallslide);
        });
        mc.on("swipe", function (ev) {
            //            console.log(ev.velocityX +" gesture detected.");
            /*accel -= ev.velocityX/100;
            while(accel>0)
            {
                console.log("YAYY");
                overallslide+=accel;
                slides.css("left",overallslide);
                accel-=0.001;
            }*/

            console.log(ev.velocityX);
            slides.animate({
                left: "-=" + (ev.velocityX * 200)
            }, {
                duration: 250,
                easing: 'swing'
            });

            //$(this).next();
            //slides.css("left",overallslide);
        }, {
            velocity: vel,

        });

        /*overallslide += accel;
            accel-=0.01;*/

        slides.children('li').click(function () {
            slides.next();
        });
    }

    $.fn.next = function () { //Next slide
        changeActiveSlideTo(currentIndex + 1);
    }

    function changeActiveSlideTo(i) {
        $('li:nth-child(' + (currentIndex + 1) + ')').attr('id', '');
        currentIndex = i;
        console.log("new index: " + currentIndex);
        $('li:nth-child(' + (currentIndex + 1) + ')').attr('id', 'active');
    }

})(jQuery);<|endoftext|>


<commit_before>'use strict';

const
    Util        = require('./util');

const
    config      = require('./config'),
    eventBus    = require('./event-bus'),
    stats       = require('./stats');

class GameEnding {

    constructor(stage) {
        this._stage = stage;

        this._gfx = new PIXI.Container();
        this._gfx.z = 11; // custom property
        this._gfx.x = 200;
        this._gfx.y = 140;
        this._gfx.visible = false;
        this._stage.addChild(this._gfx);

        let background = new PIXI.Graphics();
        background.beginFill(0x444444, 1);
        background.drawRect(0, 0, 400, 310);
        this._gfx.addChild(background);

        let textStyle = {
            font: '36px Arial',
            fill: '#eeeeee'
        };
        let title = new PIXI.Text('End of Game', textStyle);
        title.x = 96;
        title.y = 28;
        this._gfx.addChild(title);

        this._playerRow = new Row(this._gfx, "Player Avg Ratio");
        this._playerRow.y = 108;

        this._ghostsRow = new Row(this._gfx, 'Top Ghost Avg Ratio');
        this._ghostsRow.y = 108 + 42;

        this._developerRow = new Row(this._gfx, "Developer Best");
        this._developerRow.y = 108 + 42 + 42;
    }

    start() {
        let playerRatio = stats.calculatePlayerAverageRatio();
        this._playerRow.awardIcon('pacman');
        this._playerRow.notes = playerRatio.toFixed(2);

        let ghost = stats.calculateTopGhostAverageRatio();
        this._ghostsRow.awardIcon(ghost.name);
        this._ghostsRow.notes = ghost.ratio.toFixed(2);

        this._developerRow.awardIcon('reptile');
        this._developerRow.notes = '2.83     2015-12-6';

        this._gfx.visible = true;
    }

    step(elapsed) {
        //
    }
}

module.exports = GameEnding;

class Row {

    constructor(parentGfx, text) {
        this._parentGfx = parentGfx;

        this._gfx = new PIXI.Container();
        this._gfx.x = 40;
        this._parentGfx.addChild(this._gfx);

        this._iconContainer = new PIXI.Container();
        this._parentGfx.addChild(this._iconContainer);

        let textStyle = {
            font: '16px Arial',
            fill: '#eeeeee'
        };
        let textSprite = new PIXI.Text(text, textStyle);
        textSprite.x = 32 + 16;
        textSprite.y = 6;
        this._gfx.addChild(textSprite);

        let statsStyle = {
            font: '12px Arial',
            fill: '#ffffff'
        };
        this._statsSprite = new PIXI.Text('', statsStyle);
        this._statsSprite.x = 32 + 16 + 192;
        this._statsSprite.y = 8;
        this._gfx.addChild(this._statsSprite);
    }

    awardIcon(name) {
        let icon;

        switch (name) {
            case 'pacman':
                icon = Util.createPacmanIcon(1);
                break;
            case 'blinky':
                icon = Util.createGhostIcon('red', 1);
                break;
            case 'pinky':
                icon = Util.createGhostIcon('pink', 1);
                break;
            case 'inky':
                icon = Util.createGhostIcon('blue', 1);
                break;
            case 'clyde':
                icon = Util.createGhostIcon('orange', 1);
                break;
            case 'reptile':
                icon = Util.createGhostIcon('green', 1);
        }

        this._gfx.addChild(icon);
    }

    set notes(value) {
        this._statsSprite.text = value;
    }

    set y(value) {
        this._gfx.y = value;
    }
}<commit_msg>Update developer score<commit_after>'use strict';

const
    Util        = require('./util');

const
    config      = require('./config'),
    eventBus    = require('./event-bus'),
    stats       = require('./stats');

class GameEnding {

    constructor(stage) {
        this._stage = stage;

        this._gfx = new PIXI.Container();
        this._gfx.z = 11; // custom property
        this._gfx.x = 200;
        this._gfx.y = 140;
        this._gfx.visible = false;
        this._stage.addChild(this._gfx);

        let background = new PIXI.Graphics();
        background.beginFill(0x444444, 1);
        background.drawRect(0, 0, 400, 310);
        this._gfx.addChild(background);

        let textStyle = {
            font: '36px Arial',
            fill: '#eeeeee'
        };
        let title = new PIXI.Text('End of Game', textStyle);
        title.x = 96;
        title.y = 28;
        this._gfx.addChild(title);

        this._playerRow = new Row(this._gfx, "Player Avg Ratio");
        this._playerRow.y = 108;

        this._ghostsRow = new Row(this._gfx, 'Top Ghost Avg Ratio');
        this._ghostsRow.y = 108 + 42;

        this._developerRow = new Row(this._gfx, "Developer Best");
        this._developerRow.y = 108 + 42 + 42;
    }

    start() {
        let playerRatio = stats.calculatePlayerAverageRatio();
        this._playerRow.awardIcon('pacman');
        this._playerRow.notes = playerRatio.toFixed(2);

        let ghost = stats.calculateTopGhostAverageRatio();
        this._ghostsRow.awardIcon(ghost.name);
        this._ghostsRow.notes = ghost.ratio.toFixed(2);

        this._developerRow.awardIcon('reptile');
        this._developerRow.notes = '6.11     2015-12-10';

        this._gfx.visible = true;
    }

    step(elapsed) {
        //
    }
}

module.exports = GameEnding;

class Row {

    constructor(parentGfx, text) {
        this._parentGfx = parentGfx;

        this._gfx = new PIXI.Container();
        this._gfx.x = 40;
        this._parentGfx.addChild(this._gfx);

        this._iconContainer = new PIXI.Container();
        this._parentGfx.addChild(this._iconContainer);

        let textStyle = {
            font: '16px Arial',
            fill: '#eeeeee'
        };
        let textSprite = new PIXI.Text(text, textStyle);
        textSprite.x = 32 + 16;
        textSprite.y = 6;
        this._gfx.addChild(textSprite);

        let statsStyle = {
            font: '12px Arial',
            fill: '#ffffff'
        };
        this._statsSprite = new PIXI.Text('', statsStyle);
        this._statsSprite.x = 32 + 16 + 192;
        this._statsSprite.y = 8;
        this._gfx.addChild(this._statsSprite);
    }

    awardIcon(name) {
        let icon;

        switch (name) {
            case 'pacman':
                icon = Util.createPacmanIcon(1);
                break;
            case 'blinky':
                icon = Util.createGhostIcon('red', 1);
                break;
            case 'pinky':
                icon = Util.createGhostIcon('pink', 1);
                break;
            case 'inky':
                icon = Util.createGhostIcon('blue', 1);
                break;
            case 'clyde':
                icon = Util.createGhostIcon('orange', 1);
                break;
            case 'reptile':
                icon = Util.createGhostIcon('green', 1);
        }

        this._gfx.addChild(icon);
    }

    set notes(value) {
        this._statsSprite.text = value;
    }

    set y(value) {
        this._gfx.y = value;
    }
}<|endoftext|>


<commit_before>const net = require('net');
const {exec} = require('child_process');

const sockPath = process.argv[2];
const prompt = process.argv[3];

const diagnosticsEnabled = process.env.GIT_TRACE && process.env.GIT_TRACE.length !== 0;
const userAskPass = process.env.ATOM_GITHUB_ORIGINAL_SSH_ASKPASS || '';
const workdirPath = process.env.ATOM_GITHUB_WORKDIR_PATH;

function log(message) {
  if (!diagnosticsEnabled) {
    return;
  }

  process.stderr.write(`git-askpass-atom: ${message}\n`);
}

function userHelper() {
  return new Promise((resolve, reject) => {
    if (userAskPass.length === 0) {
      log('no user askpass specified');

      reject(new Error('No user SSH_ASKPASS'));
      return;
    }

    log('attempting user askpass');
    exec(userAskPass, {cwd: workdirPath}, (err, stdout, stderr) => {
      if (err) {
        log(`user askpass failed. this is ok\n${err.stack}`);

        reject(err);
        return;
      }

      log('collected password from user askpass');
      resolve(stdout);
    });
  });
}

function dialog() {
  const payload = {prompt, includeUsername: false};
  log('requesting dialog through Atom socket');
  log(`prompt = "${prompt}"`);

  return new Promise((resolve, reject) => {
    const socket = net.connect(sockPath, () => {
      log('connection established');
      const parts = [];

      socket.on('data', data => parts.push(data));
      socket.on('end', () => {
        log('Atom socket stream terminated');

        try {
          const replyDocument = JSON.parse(parts.join(''));
          log('Atom reply parsed');
          resolve(replyDocument.password);
        } catch (err) {
          log('Unable to parse reply from Atom');
          reject(err);
        }
      });

      log('writing payload');
      socket.write(JSON.stringify(payload) + '\u0000', 'utf8');
      log('payload written');
    });
    socket.setEncoding('utf8');
  });
}

userHelper()
  .catch(() => dialog())
  .then(password => {
    process.stdout.write(password);
    log('success');
    process.exit(0);
  }, err => {
    process.stderr.write(`Unable to prompt through Atom:\n${err.stack}`);
    log('failure');
    process.exit(1);
  });
<commit_msg>Pass prompt to user askpass<commit_after>const net = require('net');
const {execFile} = require('child_process');

const sockPath = process.argv[2];
const prompt = process.argv[3];

const diagnosticsEnabled = process.env.GIT_TRACE && process.env.GIT_TRACE.length !== 0;
const userAskPass = process.env.ATOM_GITHUB_ORIGINAL_SSH_ASKPASS || '';
const workdirPath = process.env.ATOM_GITHUB_WORKDIR_PATH;

function log(message) {
  if (!diagnosticsEnabled) {
    return;
  }

  process.stderr.write(`git-askpass-atom: ${message}\n`);
}

function userHelper() {
  return new Promise((resolve, reject) => {
    if (userAskPass.length === 0) {
      log('no user askpass specified');

      reject(new Error('No user SSH_ASKPASS'));
      return;
    }

    log(`attempting user askpass: ${userAskPass}`);
    execFile(userAskPass, [prompt], {cwd: workdirPath}, (err, stdout, stderr) => {
      if (err) {
        log(`user askpass failed. this is ok\n${err.stack}`);

        reject(err);
        return;
      }

      log('collected password from user askpass');
      resolve(stdout);
    });
  });
}

function dialog() {
  const payload = {prompt, includeUsername: false};
  log('requesting dialog through Atom socket');
  log(`prompt = "${prompt}"`);

  return new Promise((resolve, reject) => {
    const socket = net.connect(sockPath, () => {
      log('connection established');
      const parts = [];

      socket.on('data', data => parts.push(data));
      socket.on('end', () => {
        log('Atom socket stream terminated');

        try {
          const replyDocument = JSON.parse(parts.join(''));
          log('Atom reply parsed');
          resolve(replyDocument.password);
        } catch (err) {
          log('Unable to parse reply from Atom');
          reject(err);
        }
      });

      log('writing payload');
      socket.write(JSON.stringify(payload) + '\u0000', 'utf8');
      log('payload written');
    });
    socket.setEncoding('utf8');
  });
}

userHelper()
  .catch(() => dialog())
  .then(password => {
    process.stdout.write(password);
    log('success');
    process.exit(0);
  }, err => {
    process.stderr.write(`Unable to prompt through Atom:\n${err.stack}`);
    log('failure');
    process.exit(1);
  });
<|endoftext|>


<commit_before>import Component from 'can-component';
import DefineMap from 'can-define/map/';
import view from './contribution-month.stache';
import ContributionMonth from 'bitcentive/models/contribution-month/';

export const ViewModel = DefineMap.extend({
  // Passed props
  contributionMonthId: "string",

  // derived props
  get contributionMonthPromise() {
    if(this.contributionMonthId) {
      return ContributionMonth.get({
        _id: this.contributionMonthId,
        query: {'$populate': ['monthlyOSProjects.osProjectRef']}
      });
    }
  },
  contributionMonth: {
    get: function(initialValue, resolve){
      if(this.contributionMonthPromise) {
        this.contributionMonthPromise.then(resolve, (err) => {
          console.error("Error loading contribution month: ", err);
        });
      }
    }
  }
});

export default Component.extend({
  tag: 'bit-contribution-month',
  ViewModel,
  view
});
<commit_msg>fixed unnecessary ref requests #253<commit_after>import Component from 'can-component';
import DefineMap from 'can-define/map/';
import view from './contribution-month.stache';
import ContributionMonth from 'bitcentive/models/contribution-month/';

export const ViewModel = DefineMap.extend({
  // Passed props
  contributionMonthId: "string",

  // derived props
  get contributionMonthPromise() {
    if(this.contributionMonthId) {
      return ContributionMonth.get({
        _id: this.contributionMonthId,
        query: {'$populate': [
					'monthlyOSProjects.osProjectRef',
					'monthlyClientProjects.clientProjectRef',
					'monthlyContributions.contributorRef',
				]}
      });
    }
  },
  contributionMonth: {
    get: function(initialValue, resolve){
      if(this.contributionMonthPromise) {
        this.contributionMonthPromise.then(resolve, (err) => {
          console.error("Error loading contribution month: ", err);
        });
      }
    }
  }
});

export default Component.extend({
  tag: 'bit-contribution-month',
  ViewModel,
  view
});
<|endoftext|>


<commit_before>/*
 * JavaScript tracker for Snowplow: proxies.js
 *
 * Significant portions copyright 2010 Anthon Pang. Remainder copyright
 * 2012-2014 Snowplow Analytics Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the
 *   names of their contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

;(function(){

	var
		helpers = require('./helpers'),
		object = typeof exports !== 'undefined' ? exports : this;

	/*
	 * Fix-up URL when page rendered from search engine cache or translated page.
	 * TODO: it would be nice to generalise this and/or move into the ETL phase.
	 */
	object.fixupUrl = function (hostName, href, referrer) {
		/*
		 * Extract parameter from URL
		 */
		function getParameter(url, name) {
			// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
			var e = new RegExp('^(?:https?|ftp)(?::/*(?:[^?]+)[?])([^#]+)'),
				matches = e.exec(url),
				f = new RegExp('(?:^|&)' + name + '=([^&]*)'),
				result = matches ? f.exec(matches[1]) : 0;

			return result ? decodeURIComponent(result[1]) : '';
		}

		if (hostName === 'translate.googleusercontent.com') {		// Google
			if (referrer === '') {
				referrer = href;
			}
			href = getParameter(href, 'u');
			hostName = helpers.getHostName(href);
		} else if (hostName === 'cc.bingj.com' ||					// Bing
				hostName === 'webcache.googleusercontent.com' ||	// Google
				hostName.slice(0, 5) === '74.6.') {					// Yahoo (via Inktomi 74.6.0.0/16)
			href = document.links[0].href;
			hostName = helpers.getHostName(href);
		}
		return [hostName, href, referrer];
	}

}());
<commit_msg>proxies.js now has helpers.js as a Browserify dependency<commit_after>/*
 * JavaScript tracker for Snowplow: proxies.js
 *
 * Significant portions copyright 2010 Anthon Pang. Remainder copyright
 * 2012-2014 Snowplow Analytics Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the
 *   names of their contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

;(function(){

	var
		helpers = require('./helpers'),
		object = typeof exports !== 'undefined' ? exports : this;

	/*
	 * Fix-up URL when page rendered from search engine cache or translated page.
	 * TODO: it would be nice to generalise this and/or move into the ETL phase.
	 */
	object.fixupUrl = function (hostName, href, referrer) {
		/*
		 * Extract parameter from URL
		 */
		function getParameter(url, name) {
			// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
			var e = new RegExp('^(?:https?|ftp)(?::/*(?:[^?]+)[?])([^#]+)'),
				matches = e.exec(url),
				f = new RegExp('(?:^|&)' + name + '=([^&]*)'),
				result = matches ? f.exec(matches[1]) : 0;
console.log('matches:', matches)
			return result ? decodeURIComponent(result[1]) : '';
		}

		if (hostName === 'translate.googleusercontent.com') {		// Google
			if (referrer === '') {
				referrer = href;
			}
			href = getParameter(href, 'u');
			hostName = helpers.getHostName(href);
		} else if (hostName === 'cc.bingj.com' ||					// Bing
				hostName === 'webcache.googleusercontent.com' ||	// Google
				hostName.slice(0, 5) === '74.6.') {					// Yahoo (via Inktomi 74.6.0.0/16)
			href = document.links[0].href;
			hostName = helpers.getHostName(href);
		}
		return [hostName, href, referrer];
	}

}());
<|endoftext|>