<commit_before>import { Meteor } from 'meteor/meteor';

import { Minutes } from '/imports/minutes'
import { MeetingSeries } from '/imports/meetingseries'
import { UserRoles } from '/imports/userroles'

import { TopicListConfig } from '../topic/topicsList'

import { GlobalSettings } from '/imports/GlobalSettings'

import { FlashMessage } from '../../helpers/flashMessage'

var _minutesID; // the ID of these minutes

var orphanFlashMessage = false;

/**
 * togglePrintView
 * Prepares the DOM view for printing - on and off
 * @param switchOn - optional (if missing, function toggles on <=> off)
 */
var togglePrintView = function (switchOn) {
    if (switchOn === undefined) {   // toggle on <=> off
        Session.set("minutesedit.PrintViewActive", ! Session.get("minutesedit.PrintViewActive"));
    } else {
        Session.set("minutesedit.PrintViewActive", switchOn);
    }

    if (Session.get("minutesedit.PrintViewActive")) {
        // expand all topics, but save current state before!
        Session.set("minutesedit.collapsetopics-save4print."+_minutesID, Session.get("minutesedit.collapsetopics."+_minutesID));
        Session.set("minutesedit.collapsetopics."+_minutesID, undefined);

        Session.set("participants.expand", false);
        $(".help").hide();
        Meteor.setTimeout(function(){$(".collapse").addClass("in");}, 100);

        // give collapsibles some time for animation
        Meteor.setTimeout(function(){$(".expand-collapse-triangle").hide();}, 350);
        // as material checkboxes do not print correctly...
        // change material checkbox to normal checkbox for printing
        Meteor.setTimeout(function(){$("div.checkbox").toggleClass('checkbox print-checkbox');}, 360);
        Meteor.setTimeout(function(){openPrintDialog();}, 500);
    } else {
        // change back normal checkboxes to material checkboxes after printing
        $("div.print-checkbox").toggleClass('checkbox print-checkbox');
        $(".expand-collapse-triangle").show();
        $(".collapse").removeClass("in");
        // restore old topic collapsible state
        Session.set("minutesedit.collapsetopics."+_minutesID, Session.get("minutesedit.collapsetopics-save4print."+_minutesID));
    }
};

// Automatically restore view after printing
(function() {
    var afterPrint = function() {
        togglePrintView(false);
    };

    if (window.matchMedia) {
        var mediaQueryList = window.matchMedia('print');
        mediaQueryList.addListener(function(mql) {
            if (! mql.matches) {
                afterPrint();
            }
        });
    }

    window.onafterprint = afterPrint;
}());

Template.minutesedit.onCreated(function () {
    Session.set('minutesedit.checkParent', false);
    _minutesID = this.data;
});

Template.minutesedit.onDestroyed(function() {
    if (orphanFlashMessage) {
        FlashMessage.hide();
    }
});

var isMinuteFinalized = function () {
    let aMin = new Minutes(_minutesID);
    return (aMin && aMin.isFinalized);
};

var isModerator = function () {
    let aMin = new Minutes(_minutesID);
    return (aMin && aMin.isCurrentUserModerator());
};

var toggleTopicSorting = function () {
    let topicList = $('#topicPanel'),
        isFinalized = isMinuteFinalized();

    if (!isFinalized && isModerator()) {
        topicList.sortable('enable');
    }

    if (isFinalized) {
        topicList.sortable('disable');
    }
};

var updateTopicSorting = function () {
    let sorting = $('#topicPanel').find('> div.well'),
        minute = new Minutes(_minutesID),
        newTopicSorting = [];

    for (let i = 0; i < sorting.length; ++i) {
        let topicId = $(sorting[i]).attr('data-id');
        let topic = minute.findTopic(topicId);

        newTopicSorting.push(topic);
    }

    minute.update({topics: newTopicSorting});
};

var openPrintDialog = function () {
    var ua = navigator.userAgent.toLowerCase();
    var isAndroid = ua.indexOf("android") > -1;

    if (isAndroid) {
        // https://developers.google.com/cloud-print/docs/gadget
        var gadget = new cloudprint.Gadget();
        gadget.setPrintDocument("url", $('title').html(), window.location.href, "utf-8");
        gadget.openPrintDialog();
    } else {
        window.print();
    }
};

var sendActionItems = true;
var sendInformationItems = true;

Template.minutesedit.onRendered(function () {
    let datePickerNode = this.$('#id_minutesdatePicker');
    datePickerNode.datetimepicker({
        format: "YYYY-MM-DD"
    });

    let aMin = new Minutes(_minutesID);
    if (!aMin.isFinalized) {
        let ms = aMin.parentMeetingSeries();
        if (ms) {
            let minDate = ms.getMinimumAllowedDateForMinutes(_minutesID);
            if (minDate) {
                minDate.setDate(minDate.getDate() + 1);
                datePickerNode.data("DateTimePicker").minDate(minDate);
            }
        }
    }

    $('#topicPanel').sortable({
        appendTo: document.body,
        axis: 'y',
        items: '> .well',
        opacity: 0.5,
        disabled: true,
        handle: '.topicDragDropHandle',
        update: updateTopicSorting
    });

    toggleTopicSorting();

    // enable the parent series check after 2 seconds delay to make sure
    // there was enough time to update the meeting series
    Meteor.setTimeout(function() {
        Session.set('minutesedit.checkParent', true);
    }, 2000);
});

Template.minutesedit.helpers({
    checkParentSeries: function() {
        if (!Session.get('minutesedit.checkParent')) return;

        let aMin = new Minutes(_minutesID);
        try {
            aMin.checkParent();
            if (orphanFlashMessage) {
                FlashMessage.hide();
                orphanFlashMessage = false;
            }
        } catch(error) {
            let msg = 'Unfortunately the minute is not linked to its parent series correctly - please contact your ' +
                'system administrator.';
            (new FlashMessage('Error', msg, 'alert-danger', -1)).show();
            orphanFlashMessage = true;
        }
    },

    meetingSeries: function() {
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            return aMin.parentMeetingSeries();
        }
        return null;
    },

    minutes: function () {
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            return aMin;
        }
        return null;
    },

    isFinalized: function () {
        return isMinuteFinalized();
    },

    getFinalizedText: function () {
        let aMin = new Minutes(_minutesID);
        return aMin.getFinalizedString();
    },

    finalizeHistoryTooltip: function (buttontype) {
        let aMin = new Minutes(_minutesID);
        let tooltip = buttontype ? buttontype+"\n" : "";
        if (aMin.finalizedHistory) {
            tooltip += "\nHistory:\n"+aMin.finalizedHistory.join("\n");
        }
        return tooltip;
    },

    disableUIControl: function () {
        let aMin = new Minutes(_minutesID);
        let usrRole = new UserRoles();
        return (aMin.isFinalized || !usrRole.isModeratorOf(aMin.parentMeetingSeriesID())) ? "readonly" : "";
    },

    isUnfinalizeAllowed: function () {
        let aMin = new Minutes(_minutesID);
        return aMin.parentMeetingSeries().isUnfinalizeMinutesAllowed(_minutesID);
    },

    isModeratorOfParentSeries: function () {
        let aMin = new Minutes(_minutesID);
        let usrRole = new UserRoles();

        return usrRole.isModeratorOf(aMin.parentMeetingSeriesID());
    },

    getTopicsListConfig: function() {
        let aMin = new Minutes(_minutesID);
        return new TopicListConfig(aMin.topics, _minutesID, /*readonly*/ (isMinuteFinalized() || !isModerator()), aMin.parentMeetingSeriesID());
    },

    mobileButton() {
        if (Session.get("global.isMobileWidth")) {
            return "btn-xs";
        }
        return "";
    },

    isReadOnly() {
        return (isMinuteFinalized() || !isModerator());
    },

    isPrintView() {
        if (Session.get("minutesedit.PrintViewActive")) {
            return "btn-info";
        }
    }
});

Template.minutesedit.events({
    "click #btnHideHelp": function () {
        $(".help").hide();  // use jQuery to find and hide class
    },
    "dp.change #id_minutesdatePicker": function (evt, tmpl) {
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            if (aMin.isFinalized) {
                // event will be called on page load
                // if the meeting is already finalized nothing has to be updated
                return;
            }

            let dateNode = tmpl.$("#id_minutesdateInput");
            let aDate = tmpl.find("#id_minutesdateInput").value;

            dateNode.parent().removeClass("has-error");
            if (!aMin.parentMeetingSeries().isMinutesDateAllowed(aMin._id, aDate)) {
                dateNode.parent().addClass("has-error");
                tmpl.find("#id_minutesdateInput").value = aMin.date;
                return;
            }

            aMin.update({date: aDate});
        }
    },

    'click #btn_sendAgenda': async function(evt, tmpl) {
        evt.preventDefault();
        let sendBtn = tmpl.$("#btn_sendAgenda");
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            console.log("Send agenda: " + aMin._id + " from series: " + aMin.meetingSeries_id);

            let sendAgenda = async () => {
                sendBtn.prop('disabled', true);
                try {
                    let result = await aMin.sendAgenda();
                    Session.set('errorTitle', 'OK');
                    Session.set('errorReason', "Agenda was sent to " + result + " recipients successfully");
                    Session.set('errorType', "alert-success");
                } catch (error) {
                    Session.set('errorTitle', 'Error');
                    Session.set('errorReason', error.reason);
                }
                sendBtn.prop('disabled', false);
            };

            if (aMin.getAgendaSentAt()) {
                let date = aMin.getAgendaSentAt();

                let dialogContent = "
Do you really want to sent the agenda for this meeting minute dated on "
                    + aMin.date + "?
"
                    + "It was already sent on " + formatDateISO8601(date) + " at " + date.getHours() + ":" + date.getMinutes() + "
";

                confirmationDialog(
                    /* callback called if user wants to continue */
                    sendAgenda,
                    /* Dialog content */
                    dialogContent,
                    "Confirm sending agenda",
                    "Send Agenda",
                    "btn-success"
                );
            } else {
                await sendAgenda();
            }
        }
    },

    'click #btn_finalizeMinutes': function(evt) {
        evt.preventDefault();
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            console.log("Finalize minutes: " + aMin._id + " from series: " + aMin.meetingSeries_id);

            let doFinalize = function () {
                aMin.finalize(sendActionItems, sendInformationItems);

                toggleTopicSorting();
                Session.set("participants.expand", false);
            };

            if (GlobalSettings.isEMailDeliveryEnabled()) { // only show confirmation Dialog, if mails can be sent.

                let dialogContent = "
Do you really want to finalize this meeting minute dated on " + aMin.date + "?";
                if (aMin.hasOpenActionItems()) {
                    dialogContent += "
<input id='cbSendAI' type='checkbox' class='checkbox' " + ((sendActionItems) ? "checked" : "") + "> send action items
";
                }
                dialogContent +=
                      "
<input id='cbSendII' type='checkbox' class='checkbox' " + ((sendInformationItems) ? "checked" : "") + "> send information items
"
                    + "
";

                confirmationDialog(
                    /* callback called if user wants to continue */
                    doFinalize,
                    /* Dialog content */
                    dialogContent,
                    "Confirm finalize minute",
                    "Finalize",
                    "btn-success"
                );
            } else {
                doFinalize();
            }

        }
    },

    'click #btn_unfinalizeMinutes': function(evt) {
        evt.preventDefault();
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            console.log("Un-Finalize minutes: " + aMin._id + " from series: " + aMin.meetingSeries_id);
            aMin.unfinalize();

            toggleTopicSorting();
            Session.set("participants.expand", true);
        }
    },

    'click #btn_deleteMinutes': function(evt) {
        evt.preventDefault();
        let aMin = new Minutes(_minutesID);
        if (aMin) {

            console.log("Remove Meeting Minute " + this._id + " from Series: " + this.meetingSeries_id);

            let dialogContent = "
Do you really want to delete this meeting minute dated on " + aMin.date + "?
";
            let newTopicsCount = aMin.getNewTopics().length;
            if (newTopicsCount > 0) {
                dialogContent += "
This will remove " + newTopicsCount
                    + " Topics, which were created within this minute.
";
            }
            let closedOldTopicsCount = aMin.getOldClosedTopics().length;
            if (closedOldTopicsCount > 0) {
                let additionally = (newTopicsCount > 0) ? "Additionally " : "";
                dialogContent += "
" + additionally + "" + closedOldTopicsCount
                    + " topics will be opened again, which were closed whithin this minute.
"
            }

            confirmationDialog(
                /* callback called if user wants to continue */
                () => {
                    let ms = new MeetingSeries(aMin.meetingSeries_id);
                    // first route to the parent meetingseries then remove the minute.
                    // otherwise the current route would automatically re-routed to the main page because the
                    // minute is not available anymore -> see router.js
                    Router.go("/meetingseries/"+aMin.meetingSeries_id);
                    ms.removeMinutesWithId(aMin._id);
                },
                /* Dialog content */
                dialogContent
            );

        }
    },

    "click #btnCollapseAll": function (evt, tmpl) {
        let aMin = new Minutes(_minutesID);
        let sessionCollapse = {};
        for (let topicIndex in aMin.topics) {
            let topicId = aMin.topics[topicIndex]._id;
            sessionCollapse[topicId] = true;
        }
        Session.set("minutesedit.collapsetopics."+_minutesID, sessionCollapse);
    },

    "click #btnExpandAll": function (evt, tmpl) {
        Session.set("minutesedit.collapsetopics."+_minutesID, undefined);
    },

    'click #btn_printMinutes': function(evt) {
        evt.preventDefault();
        togglePrintView();
    }
});

// pass event handler for the send-email checkbox to the confirmation dialog
// so we can track changes
Template.confirmationDialog.events({
    'change #cbSendAI': function(evt) {
        sendActionItems = evt.target.checked;
    },
    'change #cbSendII': function(evt) {
        sendInformationItems = evt.target.checked;
    }
});
<commit_msg>Usability: Collapse participants, if they are once scrolled. Fixes #124<commit_after>import { Meteor } from 'meteor/meteor';

import { Minutes } from '/imports/minutes'
import { MeetingSeries } from '/imports/meetingseries'
import { UserRoles } from '/imports/userroles'

import { TopicListConfig } from '../topic/topicsList'

import { GlobalSettings } from '/imports/GlobalSettings'

import { FlashMessage } from '../../helpers/flashMessage'

var _minutesID; // the ID of these minutes

var orphanFlashMessage = false;

/**
 * togglePrintView
 * Prepares the DOM view for printing - on and off
 * @param switchOn - optional (if missing, function toggles on <=> off)
 */
var togglePrintView = function (switchOn) {
    if (switchOn === undefined) {   // toggle on <=> off
        Session.set("minutesedit.PrintViewActive", ! Session.get("minutesedit.PrintViewActive"));
    } else {
        Session.set("minutesedit.PrintViewActive", switchOn);
    }

    if (Session.get("minutesedit.PrintViewActive")) {
        // expand all topics, but save current state before!
        Session.set("minutesedit.collapsetopics-save4print."+_minutesID, Session.get("minutesedit.collapsetopics."+_minutesID));
        Session.set("minutesedit.collapsetopics."+_minutesID, undefined);

        Session.set("participants.expand", false);
        $(".help").hide();
        Meteor.setTimeout(function(){$(".collapse").addClass("in");}, 100);

        // give collapsibles some time for animation
        Meteor.setTimeout(function(){$(".expand-collapse-triangle").hide();}, 350);
        // as material checkboxes do not print correctly...
        // change material checkbox to normal checkbox for printing
        Meteor.setTimeout(function(){$("div.checkbox").toggleClass('checkbox print-checkbox');}, 360);
        Meteor.setTimeout(function(){openPrintDialog();}, 500);
    } else {
        // change back normal checkboxes to material checkboxes after printing
        $("div.print-checkbox").toggleClass('checkbox print-checkbox');
        $(".expand-collapse-triangle").show();
        $(".collapse").removeClass("in");
        // restore old topic collapsible state
        Session.set("minutesedit.collapsetopics."+_minutesID, Session.get("minutesedit.collapsetopics-save4print."+_minutesID));
    }
};

// Automatically restore view after printing
(function() {
    var afterPrint = function() {
        togglePrintView(false);
    };

    if (window.matchMedia) {
        var mediaQueryList = window.matchMedia('print');
        mediaQueryList.addListener(function(mql) {
            if (! mql.matches) {
                afterPrint();
            }
        });
    }

    window.onafterprint = afterPrint;
}());

Template.minutesedit.onCreated(function () {
    Session.set('minutesedit.checkParent', false);
    _minutesID = this.data;

    // Collapse the participants list on scroll
    $(window).scroll(function(){
        Session.set("participants.expand", false);
    });
});

Template.minutesedit.onDestroyed(function() {
    if (orphanFlashMessage) {
        FlashMessage.hide();
    }
    $(window).off("scroll");    // Prohibit accumulating multiple scroll handlers on window
});

var isMinuteFinalized = function () {
    let aMin = new Minutes(_minutesID);
    return (aMin && aMin.isFinalized);
};

var isModerator = function () {
    let aMin = new Minutes(_minutesID);
    return (aMin && aMin.isCurrentUserModerator());
};

var toggleTopicSorting = function () {
    let topicList = $('#topicPanel'),
        isFinalized = isMinuteFinalized();

    if (!isFinalized && isModerator()) {
        topicList.sortable('enable');
    }

    if (isFinalized) {
        topicList.sortable('disable');
    }
};

var updateTopicSorting = function () {
    let sorting = $('#topicPanel').find('> div.well'),
        minute = new Minutes(_minutesID),
        newTopicSorting = [];

    for (let i = 0; i < sorting.length; ++i) {
        let topicId = $(sorting[i]).attr('data-id');
        let topic = minute.findTopic(topicId);

        newTopicSorting.push(topic);
    }

    minute.update({topics: newTopicSorting});
};

var openPrintDialog = function () {
    var ua = navigator.userAgent.toLowerCase();
    var isAndroid = ua.indexOf("android") > -1;

    if (isAndroid) {
        // https://developers.google.com/cloud-print/docs/gadget
        var gadget = new cloudprint.Gadget();
        gadget.setPrintDocument("url", $('title').html(), window.location.href, "utf-8");
        gadget.openPrintDialog();
    } else {
        window.print();
    }
};

var sendActionItems = true;
var sendInformationItems = true;

Template.minutesedit.onRendered(function () {
    let datePickerNode = this.$('#id_minutesdatePicker');
    datePickerNode.datetimepicker({
        format: "YYYY-MM-DD"
    });

    let aMin = new Minutes(_minutesID);
    if (!aMin.isFinalized) {
        let ms = aMin.parentMeetingSeries();
        if (ms) {
            let minDate = ms.getMinimumAllowedDateForMinutes(_minutesID);
            if (minDate) {
                minDate.setDate(minDate.getDate() + 1);
                datePickerNode.data("DateTimePicker").minDate(minDate);
            }
        }
    }

    $('#topicPanel').sortable({
        appendTo: document.body,
        axis: 'y',
        items: '> .well',
        opacity: 0.5,
        disabled: true,
        handle: '.topicDragDropHandle',
        update: updateTopicSorting
    });

    toggleTopicSorting();

    // enable the parent series check after 2 seconds delay to make sure
    // there was enough time to update the meeting series
    Meteor.setTimeout(function() {
        Session.set('minutesedit.checkParent', true);
    }, 2000);
});

Template.minutesedit.helpers({
    checkParentSeries: function() {
        if (!Session.get('minutesedit.checkParent')) return;

        let aMin = new Minutes(_minutesID);
        try {
            aMin.checkParent();
            if (orphanFlashMessage) {
                FlashMessage.hide();
                orphanFlashMessage = false;
            }
        } catch(error) {
            let msg = 'Unfortunately the minute is not linked to its parent series correctly - please contact your ' +
                'system administrator.';
            (new FlashMessage('Error', msg, 'alert-danger', -1)).show();
            orphanFlashMessage = true;
        }
    },

    meetingSeries: function() {
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            return aMin.parentMeetingSeries();
        }
        return null;
    },

    minutes: function () {
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            return aMin;
        }
        return null;
    },

    isFinalized: function () {
        return isMinuteFinalized();
    },

    getFinalizedText: function () {
        let aMin = new Minutes(_minutesID);
        return aMin.getFinalizedString();
    },

    finalizeHistoryTooltip: function (buttontype) {
        let aMin = new Minutes(_minutesID);
        let tooltip = buttontype ? buttontype+"\n" : "";
        if (aMin.finalizedHistory) {
            tooltip += "\nHistory:\n"+aMin.finalizedHistory.join("\n");
        }
        return tooltip;
    },

    disableUIControl: function () {
        let aMin = new Minutes(_minutesID);
        let usrRole = new UserRoles();
        return (aMin.isFinalized || !usrRole.isModeratorOf(aMin.parentMeetingSeriesID())) ? "readonly" : "";
    },

    isUnfinalizeAllowed: function () {
        let aMin = new Minutes(_minutesID);
        return aMin.parentMeetingSeries().isUnfinalizeMinutesAllowed(_minutesID);
    },

    isModeratorOfParentSeries: function () {
        let aMin = new Minutes(_minutesID);
        let usrRole = new UserRoles();

        return usrRole.isModeratorOf(aMin.parentMeetingSeriesID());
    },

    getTopicsListConfig: function() {
        let aMin = new Minutes(_minutesID);
        return new TopicListConfig(aMin.topics, _minutesID, /*readonly*/ (isMinuteFinalized() || !isModerator()), aMin.parentMeetingSeriesID());
    },

    mobileButton() {
        if (Session.get("global.isMobileWidth")) {
            return "btn-xs";
        }
        return "";
    },

    isReadOnly() {
        return (isMinuteFinalized() || !isModerator());
    },

    isPrintView() {
        if (Session.get("minutesedit.PrintViewActive")) {
            return "btn-info";
        }
    }
});

Template.minutesedit.events({
    "click #btnHideHelp": function () {
        $(".help").hide();  // use jQuery to find and hide class
    },
    "dp.change #id_minutesdatePicker": function (evt, tmpl) {
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            if (aMin.isFinalized) {
                // event will be called on page load
                // if the meeting is already finalized nothing has to be updated
                return;
            }

            let dateNode = tmpl.$("#id_minutesdateInput");
            let aDate = tmpl.find("#id_minutesdateInput").value;

            dateNode.parent().removeClass("has-error");
            if (!aMin.parentMeetingSeries().isMinutesDateAllowed(aMin._id, aDate)) {
                dateNode.parent().addClass("has-error");
                tmpl.find("#id_minutesdateInput").value = aMin.date;
                return;
            }

            aMin.update({date: aDate});
        }
    },

    'click #btn_sendAgenda': async function(evt, tmpl) {
        evt.preventDefault();
        let sendBtn = tmpl.$("#btn_sendAgenda");
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            console.log("Send agenda: " + aMin._id + " from series: " + aMin.meetingSeries_id);

            let sendAgenda = async () => {
                sendBtn.prop('disabled', true);
                try {
                    let result = await aMin.sendAgenda();
                    Session.set('errorTitle', 'OK');
                    Session.set('errorReason', "Agenda was sent to " + result + " recipients successfully");
                    Session.set('errorType', "alert-success");
                } catch (error) {
                    Session.set('errorTitle', 'Error');
                    Session.set('errorReason', error.reason);
                }
                sendBtn.prop('disabled', false);
            };

            if (aMin.getAgendaSentAt()) {
                let date = aMin.getAgendaSentAt();

                let dialogContent = "
Do you really want to sent the agenda for this meeting minute dated on "
                    + aMin.date + "?
"
                    + "It was already sent on " + formatDateISO8601(date) + " at " + date.getHours() + ":" + date.getMinutes() + "
";

                confirmationDialog(
                    /* callback called if user wants to continue */
                    sendAgenda,
                    /* Dialog content */
                    dialogContent,
                    "Confirm sending agenda",
                    "Send Agenda",
                    "btn-success"
                );
            } else {
                await sendAgenda();
            }
        }
    },

    'click #btn_finalizeMinutes': function(evt) {
        evt.preventDefault();
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            console.log("Finalize minutes: " + aMin._id + " from series: " + aMin.meetingSeries_id);

            let doFinalize = function () {
                aMin.finalize(sendActionItems, sendInformationItems);

                toggleTopicSorting();
                Session.set("participants.expand", false);
            };

            if (GlobalSettings.isEMailDeliveryEnabled()) { // only show confirmation Dialog, if mails can be sent.

                let dialogContent = "
Do you really want to finalize this meeting minute dated on " + aMin.date + "?";
                if (aMin.hasOpenActionItems()) {
                    dialogContent += "
<input id='cbSendAI' type='checkbox' class='checkbox' " + ((sendActionItems) ? "checked" : "") + "> send action items
";
                }
                dialogContent +=
                      "
<input id='cbSendII' type='checkbox' class='checkbox' " + ((sendInformationItems) ? "checked" : "") + "> send information items
"
                    + "
";

                confirmationDialog(
                    /* callback called if user wants to continue */
                    doFinalize,
                    /* Dialog content */
                    dialogContent,
                    "Confirm finalize minute",
                    "Finalize",
                    "btn-success"
                );
            } else {
                doFinalize();
            }

        }
    },

    'click #btn_unfinalizeMinutes': function(evt) {
        evt.preventDefault();
        let aMin = new Minutes(_minutesID);
        if (aMin) {
            console.log("Un-Finalize minutes: " + aMin._id + " from series: " + aMin.meetingSeries_id);
            aMin.unfinalize();

            toggleTopicSorting();
            Session.set("participants.expand", true);
        }
    },

    'click #btn_deleteMinutes': function(evt) {
        evt.preventDefault();
        let aMin = new Minutes(_minutesID);
        if (aMin) {

            console.log("Remove Meeting Minute " + this._id + " from Series: " + this.meetingSeries_id);

            let dialogContent = "
Do you really want to delete this meeting minute dated on " + aMin.date + "?
";
            let newTopicsCount = aMin.getNewTopics().length;
            if (newTopicsCount > 0) {
                dialogContent += "
This will remove " + newTopicsCount
                    + " Topics, which were created within this minute.
";
            }
            let closedOldTopicsCount = aMin.getOldClosedTopics().length;
            if (closedOldTopicsCount > 0) {
                let additionally = (newTopicsCount > 0) ? "Additionally " : "";
                dialogContent += "
" + additionally + "" + closedOldTopicsCount
                    + " topics will be opened again, which were closed whithin this minute.
"
            }

            confirmationDialog(
                /* callback called if user wants to continue */
                () => {
                    let ms = new MeetingSeries(aMin.meetingSeries_id);
                    // first route to the parent meetingseries then remove the minute.
                    // otherwise the current route would automatically re-routed to the main page because the
                    // minute is not available anymore -> see router.js
                    Router.go("/meetingseries/"+aMin.meetingSeries_id);
                    ms.removeMinutesWithId(aMin._id);
                },
                /* Dialog content */
                dialogContent
            );

        }
    },

    "click #btnCollapseAll": function (evt, tmpl) {
        let aMin = new Minutes(_minutesID);
        let sessionCollapse = {};
        for (let topicIndex in aMin.topics) {
            let topicId = aMin.topics[topicIndex]._id;
            sessionCollapse[topicId] = true;
        }
        Session.set("minutesedit.collapsetopics."+_minutesID, sessionCollapse);
    },

    "click #btnExpandAll": function (evt, tmpl) {
        Session.set("minutesedit.collapsetopics."+_minutesID, undefined);
    },

    'click #btn_printMinutes': function(evt) {
        evt.preventDefault();
        togglePrintView();
    }
});

// pass event handler for the send-email checkbox to the confirmation dialog
// so we can track changes
Template.confirmationDialog.events({
    'change #cbSendAI': function(evt) {
        sendActionItems = evt.target.checked;
    },
    'change #cbSendII': function(evt) {
        sendInformationItems = evt.target.checked;
    }
});
<|endoftext|>


<commit_before>Template.registrantDetails.helpers({
    ageGroupOptions: function () {
        return [
            {label: "Child (0-5)", value: "child"},
            {label: "Youth (6-12)", value: "youth"},
            {label: "Teen (13-17)", value: "teen"},
            {label: "Young Friend (18-25)", value: "youngAdult"},
            {label: "Adult (26+)", value: "adult"}
        ];
    },
    registrationTypeOptions: function () {
        return [
            {label: "Commuter", value: "commuter"},
            {label: "Daily", value: "daily"},
            {label: "Full Week", value: "weekly"}
        ];
    }
});

Template.registrantDetails.events({
    'change #registration_type': function () {
        // trying to reset days selection when template changes
        // for some reason this is not working, or is it?
        resetReactiveVars();
        $("#accommodations").val("");

        // cycle through each day
        $('input[name="days"]').each(function() {
            // make sure day is not checked
            this.checked = false;
        });
    },
    'change #age_group': function () {
        console.log("Age group changed.");
        $("#accommodations").val("");
//        registrationFeeVar.set();
//        resetReactiveVars();
//        setReactiveVars();
//        setRegistrationFeeVar();
    }
});
<commit_msg>Removed ageGroupOptions. Cleanup.<commit_after>Template.registrantDetails.helpers({
    'registrationTypeOptions': function () {
        // registration types used on the registration form
        return [
            {label: "Commuter", value: "commuter"},
            {label: "Daily", value: "daily"},
            {label: "Full Week", value: "weekly"}
        ];
    }
});

Template.registrantDetails.events({
    'change #registration_type': function () {
        // clean up form values for accommodations and days
        // to make sure no erroneous values remain

        resetReactiveVars();

        // Clear the accommodations selection
        $("#accommodations").val("");

        // Clear all day checkboxes
        $('input[name="days"]').each(function() {
            // make sure day is not checked
            this.checked = false;
        });
    },
    'change #age': function () {
        // Get the value of the age field
        var ageValue = $('#age').val();

        // Calculate the age group based on the age value
        var ageGroup = calculateAgeGroup(ageValue);

        // Reset the accommodations selection
        // as accommodations depend on age group
        $("#accommodations").val("");

        // Set the age group reactive variable
        // for price calculations
        ageGroupVar.set(ageGroup);
        console.log("Age group calculation: " + ageGroupVar.get());
    }
});
<|endoftext|>


<commit_before>cc.Class({
    extends: cc.Component,

    properties: {
        pillarPrefab: {
            default: null,
            type: cc.Prefab,
            tooltip: "柱子障碍物的 Prefab",
        },

        scroreSpacePrefab: {
            default: null,
            type: cc.Prefab,
            tooltip: "柱子障碍物中间的空隙 prefab",
        },

        scoreLabel: {
            default: null,
            type: cc.Label,
            tooltip: "显示分数的 label 组件",
        },

        score: {
            default: 0,
            visible: false,
            tooltip: "玩家分数",
        },

        pillarSapce: {
            default: 0,
            tooltip: "上下障碍物的中间空隙间距",
        },

        pillarMinHeight: {
            default: 0,
            tooltip: "上下预留给障碍物的最小高度",
        },

        pillarMoveSpeed: {
            default: 0,
            tooltip: "障碍物的移动速度",
        },

        pillarGenerateMargin: {
            default: 0,
            tooltip: "间隔多远生成一次障碍物",
        },

        pillars: {
            default: [],
            visible: false,
            tooltip: "记录所有障碍物的数组",
        },

        lastPillarGenerateMargin: {
            default: 0,
            visible: false,
            tooltip: "距离上一次生成障碍物间隔了多远了",
        },

        birdPrefab: {
            default: null,
            type: cc.Prefab,
            tooltip: "小鸟的 Prefab",
        },

        bird: {
            default: null,
            visible: false,
            tooltip: "运行时生成的，当前在画面中的鸟",
        },

        birdUpSpeed: {
            default: 0.0,
            tooltip: "点击屏幕时，鸟获得的上升速度",
        },

        birdSpeed: {
            default: 0.0,
            visible: false,
            tooltip: "鸟当前在 y 方向上的速度",
        },

        birdGravitationalAcceleration: {
            default: 0.0,
            tooltip: "鸟下降的重力加速度",
        },

        isCollided: {
            default: false,
            visible: false,
            tooltip: "是否发生了碰撞",
        }
    },

    // use this for initialization
    onLoad: function () {
        this.setupEventListener();
        this.setupCollisionListener();
        this.setupBird();
        this.setupPillars();
    },

    // called every frame, uncomment this function to activate update callback
    update: function (dt) {
        if (this.isCollided) {
            return ;
        }

        // 本次更新移动的距离
        let dtSpace = dt * this.pillarMoveSpeed;

        // 移动各个障碍物
        for (let i = 0; i < this.pillars.length; i++) {
            let pillarArr = this.pillars[i];
            let upPillar = pillarArr[0];
            let downPillar = pillarArr[1];
            let scoreSpace = pillarArr[2];

            upPillar.x -= dtSpace;
            downPillar.x -= dtSpace;
            scoreSpace.x -= dtSpace;
        }

        // 记录距离上一次生成障碍物间隔了多远了
        this.lastPillarGenerateMargin += dtSpace;

        // 检查是否需要生成新的障碍物
        if (this.lastPillarGenerateMargin >= this.pillarGenerateMargin) {
            // TODO：这里会有误差的应该
            let x = this.node.width / 2 + this.pillars[0][0].width / 2;
            this.generateTwoPillar(x);
            this.lastPillarGenerateMargin = 0;
        }

        // 离开屏幕的障碍物的清理
        for (let i = 0; i < this.pillars.length; i++) {
            let pillarArr = this.pillars[i];
            let upPillar = pillarArr[0];
            let downPillar = pillarArr[1];
            let scoreSpace = pillarArr[2];

            let minX = -this.node.width / 2 - upPillar.width / 2;
            if (upPillar.x < minX) {
                this.pillars.shift();
                upPillar.removeFromParent();
                downPillar.removeFromParent();
                scoreSpace.removeFromParent();
            }
        }

        //鸟的当前速度
        let currentBirdSpeed = this.birdSpeed - this.birdGravitationalAcceleration * dt;
        this.birdSpeed = currentBirdSpeed;
        let birdUpHeight = dt * this.birdSpeed;
        this.bird.rotation = -20.0 * (currentBirdSpeed / this.birdUpSpeed);
        let birdY = this.bird.getPositionY() + birdUpHeight;
        this.bird.setPositionY(birdY);
    },

    /**
     * 生成初始的障碍物
     */
    setupPillars: function () {
        let tmpPillar = cc.instantiate(this.pillarPrefab);
        // 最大可生成的位置
        let maxX = this.node.width / 2 + tmpPillar.width / 2;
        // 记录下最后一次生成位置的下一个位置
        this.generateTwoPillar(maxX);
        // 距离上一个生成位置已经间隔了多远
        this.lastPillarGenerateMargin = 0;
    },

    /**
     * 生成一对新的障碍物并自动加入到场景中
     * @param x 障碍物生成的水平位置
     */
    generateTwoPillar: function (x) {
        // 障碍物的宽度
        let width = cc.instantiate(this.pillarPrefab).width;

        // 障碍物间隙中心位置上下
        // 这里已经照顾到了上下障碍物都有个最小高度
        let effectHeight = this.node.height - this.pillarMinHeight * 2 - this.pillarSapce;
        let spaceCenterY = Math.random() * effectHeight - effectHeight / 2;

         // 上边障碍物的下边缘位置
        let upPillarDownY = spaceCenterY + this.pillarSapce / 2;
        // 上边障碍物的高度
        let upPillarHeight = this.node.height / 2 - upPillarDownY;
        // 上边障碍物的 Y
        let upY = upPillarDownY + upPillarHeight / 2;
        // 生成上边的障碍物
        let upPillar = this.generateAPillar(x, upY, width, upPillarHeight, 0);

        // 下边障碍物的上边缘位置
        let downPillarUpY = spaceCenterY - this.pillarSapce / 2;
        // 下边障碍物的高度
        let downPillarHeight = this.node.height / 2 + upPillarDownY;
        // 下边障碍物的 Y
        let downY = downPillarUpY - downPillarHeight / 2;
        // 设置下边障碍物的位置大小
        let downPillar = this.generateAPillar(x, downY, width, downPillarHeight, 180);

        // 中间空隙中添加一个 scoreSpace 用于计分
        let scoreSpace = cc.instantiate(this.scroreSpacePrefab);
        this.node.addChild(scoreSpace);
        scoreSpace.width = width;
        scoreSpace.height = upPillarDownY - downPillarUpY;
        scoreSpace.setPositionX(x);
        scoreSpace.setPositionY(downPillarUpY + scoreSpace.height / 2);
        let scoreSpaceCollider = scoreSpace.getComponent(cc.BoxCollider);
        scoreSpaceCollider.size.width = scoreSpace.width;
        scoreSpaceCollider.size.height = scoreSpace.height;
        scoreSpaceCollider.offset.x = 0;
        scoreSpaceCollider.offset.y = 0;

        // 放到障碍物数组中
        this.pillars.push([upPillar, downPillar, scoreSpace]);
    },

    /**
     * 生成一个新的障碍物并自动加入到场景中
     */
    generateAPillar: function (x, y, width, height, rotation) {
        // 生成障碍物实例
        let pillar = cc.instantiate(this.pillarPrefab);
        this.node.addChild(pillar);

        // 设置障碍物的旋转
        pillar.rotation = rotation;
        // 设置障碍物的位置大小
        pillar.width = width;
        pillar.height = height;
        pillar.setPositionX(x);
        pillar.setPositionY(y);
        // 设置碰撞体的位置大小
        let collider = pillar.getComponent(cc.BoxCollider);
        collider.size.width = pillar.width;
        collider.size.height = pillar.height;
        collider.offset.x = 0;
        collider.offset.y = 0;

        return pillar;
    },

    /**
     * 生成初始的小鸟
     */
    setupBird: function () {
        this.bird = cc.instantiate(this.birdPrefab);
        // 初始化位置(x始终不变)
        //x不变
        let x = -200;
        let y = 0;
        this.bird.setPositionX(x);
        this.bird.setPositionY(y);
        this.node.addChild(this.bird);
    },

    /**
     * 初始化系统事件监听
     */
    setupEventListener: function () {
        this.node.on(cc.Node.EventType.TOUCH_START, function (event) {
            if (this.isCollided) {
                return;
            }

            this.birdSpeed = this.birdUpSpeed;
            this.bird.rotation = -20;
        }, this);
    },

    /**
     * 初始化碰撞检测
     */
    setupCollisionListener: function () {
        this.node.on('collided', function (event) {
            this.getComponent('PillarGenerator').isCollided = true;
        });

        this.node.on('score', function (event) {
            let script = this.getComponent('PillarGenerator');
            script.score++;
            script.scoreLabel.string = script.score.toString();
        })
    },

});
<commit_msg>restart<commit_after>cc.Class({
    extends: cc.Component,

    properties: {
        pillarPrefab: {
            default: null,
            type: cc.Prefab,
            tooltip: "柱子障碍物的 Prefab",
        },

        scroreSpacePrefab: {
            default: null,
            type: cc.Prefab,
            tooltip: "柱子障碍物中间的空隙 prefab",
        },

        scoreLabel: {
            default: null,
            type: cc.Label,
            tooltip: "显示分数的 label 组件",
        },

        score: {
            default: 0,
            visible: false,
            tooltip: "玩家分数",
        },

        pillarSapce: {
            default: 0,
            tooltip: "上下障碍物的中间空隙间距",
        },

        pillarMinHeight: {
            default: 0,
            tooltip: "上下预留给障碍物的最小高度",
        },

        pillarMoveSpeed: {
            default: 0,
            tooltip: "障碍物的移动速度",
        },

        pillarGenerateMargin: {
            default: 0,
            tooltip: "间隔多远生成一次障碍物",
        },

        pillars: {
            default: [],
            visible: false,
            tooltip: "记录所有障碍物的数组",
        },

        lastPillarGenerateMargin: {
            default: 0,
            visible: false,
            tooltip: "距离上一次生成障碍物间隔了多远了",
        },

        birdPrefab: {
            default: null,
            type: cc.Prefab,
            tooltip: "小鸟的 Prefab",
        },

        bird: {
            default: null,
            visible: false,
            tooltip: "运行时生成的，当前在画面中的鸟",
        },

        birdUpSpeed: {
            default: 0.0,
            tooltip: "点击屏幕时，鸟获得的上升速度",
        },

        birdSpeed: {
            default: 0.0,
            visible: false,
            tooltip: "鸟当前在 y 方向上的速度",
        },

        birdGravitationalAcceleration: {
            default: 0.0,
            tooltip: "鸟下降的重力加速度",
        },

        isCollided: {
            default: false,
            visible: false,
            tooltip: "是否发生了碰撞",
        }
    },

    // use this for initialization
    onLoad: function () {
        this.setupEventListener();
        this.setupCollisionListener();
        this.setupBird();
        this.setupPillars();
    },

    // called every frame, uncomment this function to activate update callback
    update: function (dt) {
        if (this.isCollided) {
            return ;
        }

        // 本次更新移动的距离
        let dtSpace = dt * this.pillarMoveSpeed;

        // 移动各个障碍物
        for (let i = 0; i < this.pillars.length; i++) {
            let pillarArr = this.pillars[i];
            let upPillar = pillarArr[0];
            let downPillar = pillarArr[1];
            let scoreSpace = pillarArr[2];

            upPillar.x -= dtSpace;
            downPillar.x -= dtSpace;
            scoreSpace.x -= dtSpace;
        }

        // 记录距离上一次生成障碍物间隔了多远了
        this.lastPillarGenerateMargin += dtSpace;

        // 检查是否需要生成新的障碍物
        if (this.lastPillarGenerateMargin >= this.pillarGenerateMargin) {
            // TODO：这里会有误差的应该
            let x = this.node.width / 2 + this.pillars[0][0].width / 2;
            this.generateTwoPillar(x);
            this.lastPillarGenerateMargin = 0;
        }

        // 离开屏幕的障碍物的清理
        for (let i = 0; i < this.pillars.length; i++) {
            let pillarArr = this.pillars[i];
            let upPillar = pillarArr[0];
            let downPillar = pillarArr[1];
            let scoreSpace = pillarArr[2];

            let minX = -this.node.width / 2 - upPillar.width / 2;
            if (upPillar.x < minX) {
                this.pillars.shift();
                upPillar.removeFromParent();
                downPillar.removeFromParent();
                scoreSpace.removeFromParent();
            }
        }

        //鸟的当前速度
        let currentBirdSpeed = this.birdSpeed - this.birdGravitationalAcceleration * dt;
        this.birdSpeed = currentBirdSpeed;
        let birdUpHeight = dt * this.birdSpeed;
        this.bird.rotation = -20.0 * (currentBirdSpeed / this.birdUpSpeed);
        let birdY = this.bird.getPositionY() + birdUpHeight;
        this.bird.setPositionY(birdY);
    },

    /**
     * 生成初始的障碍物
     */
    setupPillars: function () {
        let tmpPillar = cc.instantiate(this.pillarPrefab);
        // 最大可生成的位置
        let maxX = this.node.width / 2 + tmpPillar.width / 2;
        // 记录下最后一次生成位置的下一个位置
        this.generateTwoPillar(maxX);
        // 距离上一个生成位置已经间隔了多远
        this.lastPillarGenerateMargin = 0;
    },

    /**
     * 重新开始一局新游戏
     */
    restartGame: function () {
        // 移除各个障碍物
        for (let i = 0; i < this.pillars.length; i++) {
            let pillarArr = this.pillars[i];
            let upPillar = pillarArr[0];
            let downPillar = pillarArr[1];
            let scoreSpace = pillarArr[2];

            upPillar.removeFromParent();
            downPillar.removeFromParent();
            scoreSpace.removeFromParent();
        }
        this.pillars = [];

        // 移除鸟
        this.bird.removeFromParent();

        // 分数
        this.score = 0;
        this.scoreLabel.string = this.score.toString();

        // 重新初始化设置
        this.setupPillars();
        this.setupBird();

        // 重新开始游戏
        this.isCollided = false;
    },

    /**
     * 生成一对新的障碍物并自动加入到场景中
     * @param x 障碍物生成的水平位置
     */
    generateTwoPillar: function (x) {
        // 障碍物的宽度
        let width = cc.instantiate(this.pillarPrefab).width;

        // 障碍物间隙中心位置上下
        // 这里已经照顾到了上下障碍物都有个最小高度
        let effectHeight = this.node.height - this.pillarMinHeight * 2 - this.pillarSapce;
        let spaceCenterY = Math.random() * effectHeight - effectHeight / 2;

         // 上边障碍物的下边缘位置
        let upPillarDownY = spaceCenterY + this.pillarSapce / 2;
        // 上边障碍物的高度
        let upPillarHeight = this.node.height / 2 - upPillarDownY;
        // 上边障碍物的 Y
        let upY = upPillarDownY + upPillarHeight / 2;
        // 生成上边的障碍物
        let upPillar = this.generateAPillar(x, upY, width, upPillarHeight, 0);

        // 下边障碍物的上边缘位置
        let downPillarUpY = spaceCenterY - this.pillarSapce / 2;
        // 下边障碍物的高度
        let downPillarHeight = this.node.height / 2 + upPillarDownY;
        // 下边障碍物的 Y
        let downY = downPillarUpY - downPillarHeight / 2;
        // 设置下边障碍物的位置大小
        let downPillar = this.generateAPillar(x, downY, width, downPillarHeight, 180);

        // 中间空隙中添加一个 scoreSpace 用于计分
        let scoreSpace = cc.instantiate(this.scroreSpacePrefab);
        this.node.addChild(scoreSpace);
        scoreSpace.width = width;
        scoreSpace.height = upPillarDownY - downPillarUpY;
        scoreSpace.setPositionX(x);
        scoreSpace.setPositionY(downPillarUpY + scoreSpace.height / 2);
        let scoreSpaceCollider = scoreSpace.getComponent(cc.BoxCollider);
        scoreSpaceCollider.size.width = scoreSpace.width;
        scoreSpaceCollider.size.height = scoreSpace.height;
        scoreSpaceCollider.offset.x = 0;
        scoreSpaceCollider.offset.y = 0;

        // 放到障碍物数组中
        this.pillars.push([upPillar, downPillar, scoreSpace]);
    },

    /**
     * 生成一个新的障碍物并自动加入到场景中
     */
    generateAPillar: function (x, y, width, height, rotation) {
        // 生成障碍物实例
        let pillar = cc.instantiate(this.pillarPrefab);
        this.node.addChild(pillar);

        // 设置障碍物的旋转
        pillar.rotation = rotation;
        // 设置障碍物的位置大小
        pillar.width = width;
        pillar.height = height;
        pillar.setPositionX(x);
        pillar.setPositionY(y);
        // 设置碰撞体的位置大小
        let collider = pillar.getComponent(cc.BoxCollider);
        collider.size.width = pillar.width;
        collider.size.height = pillar.height;
        collider.offset.x = 0;
        collider.offset.y = 0;

        return pillar;
    },

    /**
     * 生成初始的小鸟
     */
    setupBird: function () {
        this.bird = cc.instantiate(this.birdPrefab);
        // 初始化位置(x始终不变)
        //x不变
        let x = -200;
        let y = 0;
        this.bird.setPositionX(x);
        this.bird.setPositionY(y);
        this.node.addChild(this.bird);
    },

    /**
     * 初始化系统事件监听
     */
    setupEventListener: function () {
        this.node.on(cc.Node.EventType.TOUCH_START, function (event) {
            if (this.isCollided) {
                this.restartGame();

                return;
            }

            this.birdSpeed = this.birdUpSpeed;
            this.bird.rotation = -20;
        }, this);
    },

    /**
     * 初始化碰撞检测
     */
    setupCollisionListener: function () {
        this.node.on('collided', function (event) {
            this.getComponent('PillarGenerator').isCollided = true;
        });

        this.node.on('score', function (event) {
            let script = this.getComponent('PillarGenerator');
            script.score++;
            script.scoreLabel.string = script.score.toString();
        })
    },

});
<|endoftext|>


<commit_before>describe("Utilities:", function() {

    describe("merge", function() {

    });

    describe("resolveAll", function() {

    });

});
<commit_msg>Added specs for Utilities.resolveAll.<commit_after>var Chai = require("chai");
var Sinon = require("sinon");
var Types = require("./helpers/types");
var Utilities = require("../lib/utilities");

var expect = Chai.expect;
var types = Types();

describe("Utilities:", function() {

    beforeEach(function() {
        this.sandbox = Sinon.sandbox.create();
    });

    afterEach(function() {
        this.sandbox.restore();
    });

    describe("merge", function() {

    });

    describe("resolveAll", function() {

        it("is a function", function() {
            expect(Utilities.resolveAll).to.be.a("function");
        });

        it("accepts an array of values that contain a 'resolve' property", function() {
            var loader = {
                resolve: function() {
                    return "loader";
                }
            };
            var plugin = {
                resolve: function() {
                    return "plugin";
                }
            };

            var actual = Utilities.resolveAll([loader, plugin]);
            var expected = ["loader", "plugin"];

            expect(actual).to.eql(expected);
        });

        it("throws if an array isn't passed", function() {
            var error = "";

            Object.keys(types).forEach(function(type) {
                if (type == "array")
                    return;

                expect(function() {
                    Utilities.resolveAll(types[type]);
                }).to.throw(error);
            });
        });

        it("throws if values in the passed array don't contain a resolve function", function() {
            var error = "";

            Object.keys(types).forEach(function(type) {
                if (type == "array")
                    return;

                expect(function() {
                    Utilities.resolveAll([types[type]]);
                }).to.throw(error);
            });
        });

        it("calls the 'resolve' property of object passed", function() {
            var loader = {
                resolve: this.sandbox.spy()
            };
            var plugin = {
                resolve: this.sandbox.spy()
            };

            Utilities.resolveAll([loader, plugin]);

            expect(loader.resolve.callCount).to.eq(1);
            expect(plugin.resolve.callCount).to.eq(1);
        });

    });

});
<|endoftext|>


<commit_before>var assert = require("assert");
var utils = require('../lib/utils/utilities');
var Property = require('../index').Property;
var validations = require('../index').validations;

describe('Utilities->String Utilities', function () {
    it('#capitalizeFirstLetter(string) should return null if the given string is a null', function () {
        assert.equal(null, utils.capitalizeFirstLetter(null), "It is null");
    });
    it('#capitalizeFirstLetter(string) should return null if the given string is undefined', function () {
        assert.equal(null, utils.capitalizeFirstLetter(undefined), "It is null");
    });
    it('#capitalizeFirstLetter(string) should return "Thing" if the given string is "thing" ', function () {
        assert.equal("Thing", utils.capitalizeFirstLetter("thing"), "It is Thing");
    });
    it('#capitalizeFirstLetter(string) should return "Thing" if the given string is "Thing" ', function () {
        assert.equal("Thing", utils.capitalizeFirstLetter("Thing"), "It is Thing");
    });
});

describe('Utilities->Object decoration', function () {

    var objectToBeDecorated = {};
    var simplePropertyTuple = new Property("age", null, null);
    var arrayPropertyTuple = new Property("invoices", null, validations.isArray);
    var arrayPropertyNoLetterSTuple = new Property("people", null, validations.isArray);

    objectToBeDecorated = utils.decorateWithGettersAndSetters(objectToBeDecorated, [simplePropertyTuple, arrayPropertyTuple, arrayPropertyNoLetterSTuple]);

    it('#decorateWithGettersAndSetters(objectToBeDecorated, propertyTuples) should return an object with a getter and a setter for a given non array property', function () {
        assert.equal("function", typeof objectToBeDecorated.getAge, "Creates a getter for the property");
        assert.equal("function", typeof objectToBeDecorated.setAge, "Creates a setter for the array property");
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, propertyTuples) should return an object with a getter and a setter for a given array property', function () {
        assert.equal("function", typeof objectToBeDecorated.getInvoices, "Creates a getter for the array property");
        assert.equal("function", typeof objectToBeDecorated.setInvoices, "Creates a setter for the array property");
        assert.equal("function", typeof objectToBeDecorated.addInvoice, "Adds a helper function to add an item to an array property");
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, propertyTuples) should not remove last "s" character from array item when generating add operation if the property name does not finish with "s"', function () {
        assert.equal("undefined", typeof objectToBeDecorated.addPeopl, "Should not follow logic of removing last character if property name does not finish with S");
        assert.equal("function", typeof objectToBeDecorated.addPeople, "Should generate an add function with the very same capitalized name of the property");
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, propertyTuples) should provide valid getters and setters for the required properties', function () {
        objectToBeDecorated.setAge("45");
        assert.equal("45", objectToBeDecorated.getAge());
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, propertyTuples) should return null if object to be decorated or given properties are null or undefined', function () {
        assert.equal(null, utils.decorateWithGettersAndSetters(null, null));
        assert.equal(null, utils.decorateWithGettersAndSetters(null, []));
        assert.equal(null, utils.decorateWithGettersAndSetters(null, undefined));
        assert.equal(null, utils.decorateWithGettersAndSetters(undefined, undefined));
        assert.equal(null, utils.decorateWithGettersAndSetters({}, undefined));
    });
});<commit_msg>removed tuple name from comments and variables since its no longer used<commit_after>var assert = require("assert");
var utils = require('../lib/utils/utilities');
var Property = require('../index').Property;
var validations = require('../index').validations;

describe('Utilities->String Utilities', function () {
    it('#capitalizeFirstLetter(string) should return null if the given string is a null', function () {
        assert.equal(null, utils.capitalizeFirstLetter(null), "It is null");
    });
    it('#capitalizeFirstLetter(string) should return null if the given string is undefined', function () {
        assert.equal(null, utils.capitalizeFirstLetter(undefined), "It is null");
    });
    it('#capitalizeFirstLetter(string) should return "Thing" if the given string is "thing" ', function () {
        assert.equal("Thing", utils.capitalizeFirstLetter("thing"), "It is Thing");
    });
    it('#capitalizeFirstLetter(string) should return "Thing" if the given string is "Thing" ', function () {
        assert.equal("Thing", utils.capitalizeFirstLetter("Thing"), "It is Thing");
    });
});

describe('Utilities->Object decoration', function () {

    var objectToBeDecorated = {};
    var simpleProperty = new Property("age", null, null);
    var arrayProperty = new Property("invoices", null, validations.isArray);
    var arrayPropertyNoLetterS = new Property("people", null, validations.isArray);

    objectToBeDecorated = utils.decorateWithGettersAndSetters(objectToBeDecorated, [simpleProperty, arrayProperty, arrayPropertyNoLetterS]);

    it('#decorateWithGettersAndSetters(objectToBeDecorated, properties) should return an object with a getter and a setter for a given non array property', function () {
        assert.equal("function", typeof objectToBeDecorated.getAge, "Creates a getter for the property");
        assert.equal("function", typeof objectToBeDecorated.setAge, "Creates a setter for the array property");
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, properties) should return an object with a getter and a setter for a given array property', function () {
        assert.equal("function", typeof objectToBeDecorated.getInvoices, "Creates a getter for the array property");
        assert.equal("function", typeof objectToBeDecorated.setInvoices, "Creates a setter for the array property");
        assert.equal("function", typeof objectToBeDecorated.addInvoice, "Adds a helper function to add an item to an array property");
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, properties) should not remove last "s" character from array item when generating add operation if the property name does not finish with "s"', function () {
        assert.equal("undefined", typeof objectToBeDecorated.addPeopl, "Should not follow logic of removing last character if property name does not finish with S");
        assert.equal("function", typeof objectToBeDecorated.addPeople, "Should generate an add function with the very same capitalized name of the property");
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, properties) should provide valid getters and setters for the required properties', function () {
        objectToBeDecorated.setAge("45");
        assert.equal("45", objectToBeDecorated.getAge());
    });

    it('#decorateWithGettersAndSetters(objectToBeDecorated, properties) should return null if object to be decorated or given properties are null or undefined', function () {
        assert.equal(null, utils.decorateWithGettersAndSetters(null, null));
        assert.equal(null, utils.decorateWithGettersAndSetters(null, []));
        assert.equal(null, utils.decorateWithGettersAndSetters(null, undefined));
        assert.equal(null, utils.decorateWithGettersAndSetters(undefined, undefined));
        assert.equal(null, utils.decorateWithGettersAndSetters({}, undefined));
    });
});<|endoftext|>


<commit_before>/**
 * Mock objects for browser Document class.
 */

class Element {

    constructor() {
        this.lastChild = this;
        this.checked = false;
        this.childNodes = [];
    }

    appendChild() {
        return this;
    }

    cloneNode() {
        return this;
    }

    setAttribute() {
    }

    insertBefore() {
    }
}

class Document {

    constructor() {
        this.location = {href: ""}
        this.documentElement = {}
        this.styleSheets = []
        this.head = new Element();
        this.body = new Element();
    }

    createDocumentFragment() {
        return new Element();
    }

    createElement() {
        return new Element();
    }
}

class DOMImplementation {

    createHTMLDocument() {
        return new Document();
    }
}

export {Document, DOMImplementation};<commit_msg>fix unit tests<commit_after>/**
 * Mock objects for browser Document class.
 */

class Element {

    constructor() {
        this.lastChild = this;
        this.checked = false;
        this.childNodes = [];
    }

    appendChild() {
        return this;
    }

    cloneNode() {
        return this;
    }

    setAttribute() {
    }

    insertBefore() {
    }
}

class Document {

    constructor() {
        this.location = {href: ""}
        this.documentElement = new Element();
        this.documentElement.firstElementChild = new Element();
        this.styleSheets = []
        this.head = new Element();
        this.body = new Element();
    }

    createDocumentFragment() {
        return new Element();
    }

    createElement() {
        return new Element();
    }
}

class DOMImplementation {

    createHTMLDocument() {
        return new Document();
    }
}

export {Document, DOMImplementation};<|endoftext|>


<commit_before>import test from 'ava';

import hasValue from './../../src/utils/hasValue';

test('hasValue should return false when null is present', (t) => {
  const result = hasValue(null);
  t.is(result, false);
});

test('hasValue should return false when undefined is present', (t) => {
  const result = hasValue(undefined);
  t.is(result, false);
});

test('hasValue should return false when empty string is present', (t) => {
  const result = hasValue('');
  t.is(result, false);
});

test('hasValue should work as expected', (t) => {
  t.is(hasValue('true'), true);
  t.is(hasValue(0), true);
  t.is(hasValue(1.2), true);
  t.is(hasValue({}), true);
  t.is(hasValue([]), true);
  t.is(hasValue(() => {}), true);
});
<commit_msg>fix test: hasValue should work as expected -> empty array should false result<commit_after>import test from 'ava';

import hasValue from './../../src/utils/hasValue';

test('hasValue should return false when null is present', (t) => {
  const result = hasValue(null);
  t.is(result, false);
});

test('hasValue should return false when undefined is present', (t) => {
  const result = hasValue(undefined);
  t.is(result, false);
});

test('hasValue should return false when empty string is present', (t) => {
  const result = hasValue('');
  t.is(result, false);
});

test('hasValue should work as expected', (t) => {
  t.is(hasValue('true'), true);
  t.is(hasValue(0), true);
  t.is(hasValue(1.2), true);
  t.is(hasValue({}), true);
  t.is(hasValue([]), false);
  t.is(hasValue(() => {}), true);
});
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc service
 * @name flowsimUiApp.datapath
 * @description
 * # datapath
 * Service in the flowsimUiApp.
 */
angular.module('flowsimUiApp')
  .factory('datapath', function() {

function Capabilities(datapath) {
  if(datapath) {
    if(datapath instanceof Datapath) {
      // Copy constructor
    } else {
      // JSON constructor
      _.extend(this, datapath);
    }
  } else {
    // default constructor
  }
}

function Configuration(datapath) {
  if(datapath) {
    if(datapath instanceof Capabilities) {
      // capability constructor
    } else if(datapath instanceof Configuration) {
      // copy constructor
    } else {
      // JSON constructor
      _.extend(this, datapath);
    }
  } else {
    // default constructor
  }
}

return {
  Capabilities: Capabilities,
  Configuration: Configuration
};

});
<commit_msg>latest<commit_after>'use strict';

/**
 * @ngdoc service
 * @name flowsimUiApp.datapath
 * @description
 * # datapath
 * Service in the flowsimUiApp.
 */
angular.module('flowsimUiApp')
  .factory('datapath', function() {

function Capabilities(datapath) {
  if(datapath) {
    if(datapath instanceof Datapath) {
      // Copy constructor
      this.datapath_id     = datapath.datapath_id;
      this.ip_reassembly   = datapath.ip_reassembly;
      this.n_buffers       = datapath.n_buffers;
      this.mfr_description = datapath.mfr_description;
      this.hw_description  = datapath.hw_description;
      this.sw_description  = datapath.sw_description;
      this.serial_num      = datapath.serial_num;
      this.dp_description  = datapath.dp_description;
    } else {
      // JSON constructor
      _.extend(this, datapath);
    }
  } else {
    // default constructor
    this.datapath_id   = '01:23:45:67:89:ab'; // FIXME: bad default
    this.n_buffers     = 1024;
    this.ip_reassembly = true;
    // Descriptions
    this.mfr_description = '';
    this.hw_description  = '';
    this.sw_description  = '';
    this.serial_num      = '';
    this.dp_description  = '';
  }
}

function Configuration(datapath) {
  if(datapath) {
    if(datapath instanceof Capabilities) {
      // capability constructor
      this.capabilities = datapath;
    } else if(datapath instanceof Configuration) {
      // copy constructor
    } else {
      // JSON constructor
      _.extend(this, datapath);
    }
  } else {
    // default constructor
  }
}

var TIPS = {
  datapath_id: 'Unique id of the datapath',
  ip_reassembly: 'Datapath can reassemble IP fragments',
  n_buffers: 'Number of packets that can be buffered for controller',
  mfr_description: '',
  hw_description: '',
  sw_description: '',
  serial_num: '',
  dp_description: ''
};

var TESTS = {
  datapath_id:     function() { return true; },
  n_buffers:       fgConstraints.isUInt(0, 0xffff),
  mfr_description: function(v) { return !v || v.length <= 256 ; },
  hw_description:  function(v) { return !v || v.length <= 256; },
  sw_description:  function(v) { return !v || v.length <= 256; },
  serial_num:      function(v) { return !v || v.length <= 32; },
  dp_description:  function(v) { return !v || v.length <= 256; }
};

return {
  Capabilities: Capabilities,
  Configuration: Configuration,
  TIPS: TIPS,
  TESTS: TESTS
};

});
<|endoftext|>


<commit_before>var tests = [];
var disabled = 0;
var curr = 0;
var timer = null;
var TC_TIMEOUT = 15000;

window.addEventListener("load", function() {
    try{
	chrome.management.getAll( function(exts) {
	    var str = "";

	    for (var i = 0; i < exts.length; i++){
        	if(exts[i].type == "extension" && exts[i].name.substring(0,3) == "tc-"){
        	    tests.push(exts[i]);
        	    str +=  i + " " + JSON.stringify(exts[i]) + "
";
        	}
	    }
	    debug(str);
	    //runTest();
	    disableAll(function(){runTest();});
	});
    }
    catch(err){}
});

function checkDisabledAll(callback){
    disabled++;
    if (disabled == tests.length) {
	if(callback){callback();}
    }
}

function disableAll(callback){
    for (var i = 0; i < tests.length; i++) {
	if (tests[i].enabled == true) {
	    chrome.management.setEnabled(tests[curr].id, false, function(){
		checkDisabledAll(callback);
	    });
	}
	else {
	    checkDisabledAll(callback);
	}
    }
}

chrome.extension.onMessageExternal.addListener(
    function(request, sender, sendResponse) {
	if(sender.id == tests[curr].id) {
	    if(timer){clearTimeout(timer);}
	    var log = document.getElementById('log');
	    var results = decodeURIComponent(request);
	    log.innerHTML += encodeURIComponent("
" + tests[curr].name + "

" + results + "
");//decodeURIComponent();
	    chrome.management.setEnabled(tests[curr].id, false, function(){
        	curr++;
        	runTest();
	    });
	}
});

function runTest(){
    if(curr == tests.length) {
	result();
    }
    if(curr >= tests.length) {
	return;
    }
    chrome.management.setEnabled(tests[curr].id, true, function(){
	timer = setTimeout(function(){
	    chrome.management.setEnabled(tests[curr].id, false, function(){
		var log = document.getElementById('log');
		log.innerHTML += encodeURIComponent("
" + tests[curr].name + "

");

		curr++;

		runTest();
	    });
	},TC_TIMEOUT);
    });
}

function summarizeResults(html){
    var div = document.createElement('div');
    	div.innerHTML = '
'+ html + '
';

    	html = div.firstElementChild;

    var tests = html.querySelectorAll('.results'),
    	testcases = html.querySelectorAll('.results tbody tr'),
    	fails = html.querySelectorAll('tr.fail'),
    	notrun = html.querySelectorAll('tr.notrun'),
    	passes = html.querySelectorAll('tr.pass');
    var str = [ "

Tests: ", tests.length, " [testcases: ",
	testcases.length, "]", "

Pass: ", passes.length,
	" / Fail: ", fails.length, " / Not run: ", notrun.length,
	"

" ].join('');

    var passesPr = +(passes.length * 100 / testcases.length).toFixed(0);
    var failsPr = +(fails.length * 100 / testcases.length).toFixed(0);
    var notrunPr = +(notrun.length * 100 / testcases.length).toFixed(0);

    var str_progress =  [
        '
',
	''
		+ passesPr + '%',
	'' + failsPr
		+ '%',
	'' + notrunPr + '%',
	' ', '
' ].join('');
    return str + str_progress;
}
function result(){

    var css = "html{font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans}#log .warning,#log .warning a{color:#000;background:#FF0}#log .error,#log .error a{color:#FFF;background:red}#log pre{border:1px solid #000;padding:1em}section.summary{margin-bottom:1em}table.results{border-collapse:collapse;table-layout:fixed;width:100%}table.results th:first-child,table.results td:first-child{width:4em}table.results th:last-child,table.results td:last-child{width:50%}table.results.assertions th:last-child,table.results.assertions td:last-child{width:35%}table.results th{border-bottom:medium solid #000;padding:0 0 .5em}table.results td{border-bottom:thin solid #000;padding:1em 1em .5em}tr.pass>td:first-child{color:green}tr.notrun>td:first-child{color:blue}.pass>td:first-child,.fail>td:first-child,.timeout>td:first-child,.notrun>td:first-child{font-variant:small-caps}table.results span{display:block}h2{font-size:1.3em}a{border:2px solid #00C;color:#fff;background-color:#00C;display:block;line-height:1.5em;padding:0 .5em}a:hover{background-color:#fff;color:#00C}#info_progress{width:100%;position:relative;background:rgba(0,0,0,0.5);height:25px}#info_progress .percent{position:absolute;left:0;top:0;color:#FFF;font-weight:700;height:25px;line-height:25px;display:block;background:green;text-align:center}#info_progress .percent.fail{background:red}#info_progress .percent.notrun{background:gray}tr.fail>td:first-child,tr.timeout>td:first-child{color:red}table.results span.expected,table.results span.actual{font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;white-space:pre}";
    var str = "data:text/html,<!DOCTYPE html><title>RAPORT</title>";
    var results = document.getElementById('log');
    var stats = summarizeResults(decodeURIComponent(results.innerHTML));
    //console.log();
    str += stats + results.innerHTML;
    chrome.windows.create({"url": str, focused: true});

}
function debug(msg) {
	var url = "data:text/html," + msg;
	//chrome.tabs.create({"url": url});
}<commit_msg>added method for cleainig all tabs before starting single test<commit_after>var tests = [];
var disabled = 0;
var curr = 0;
var timer = null;
var TC_TIMEOUT = 15000;

window.addEventListener("load", function() {
    try{
	chrome.management.getAll( function(exts) {
	    var str = "";

	    for (var i = 0; i < exts.length; i++){
        	if(exts[i].type == "extension" && exts[i].name.substring(0,3) == "tc-"){
        	    tests.push(exts[i]);
        	    str +=  i + " " + JSON.stringify(exts[i]) + "
";
        	}
	    }
	    //debug(str);
	    //runTest();
	    disableAll(function(){prepareEnvironment(runTest);});
	});
    }
    catch(err){}
});

function checkDisabledAll(callback){
    disabled++;
    if (disabled == tests.length) {
	if(callback){callback();}
    }
}

function disableAll(callback){
    for (var i = 0; i < tests.length; i++) {
	if (tests[i].enabled == true) {
	    chrome.management.setEnabled(tests[curr].id, false, function(){
		checkDisabledAll(callback);
	    });
	}
	else {
	    checkDisabledAll(callback);
	}
    }
}

function prepareEnvironment(callback){
    chrome.windows.getAll({populate: true}, function(wins){
	if(wins.length){
	    for(var i=0; i<wins.length; i++){
		var tabs = [];
		tabs = tabs.concat(wins[i].tabs);
	    }
	    var waitForClosingNo = tabs.length-1;
	    if(waitForClosingNo <= 0){ if(callback){callback();} }

	    for (var i=0; i < tabs.length; i++) {
		if(tabs[i].url != "chrome://extensions/") {
		    chrome.tabs.remove(tabs[i].id, function(){
        		waitForClosingNo--;
        		    if(waitForClosingNo == 0 && callback){
        			callback();
        		}
		    });
		}

	    }
	} else {
	    if(callback){callback();}
	}
    });
}

chrome.extension.onMessageExternal.addListener(
    function(request, sender, sendResponse) {
	if(sender.id == tests[curr].id) {
	    if(timer){clearTimeout(timer);}
	    var log = document.getElementById('log');
	    var results = decodeURIComponent(request);
	    log.innerHTML += encodeURIComponent("
" + tests[curr].name + "

" + results + "
");//decodeURIComponent();
	    chrome.management.setEnabled(tests[curr].id, false, function(){
        	curr++;
        	prepareEnvironment(runTest);
	    });
	}
});

function runTest(){
    if(curr == tests.length) {
	result();
    }
    if(curr >= tests.length) {
	return;
    }
    chrome.management.setEnabled(tests[curr].id, true, function(){
	timer = setTimeout(function(){
	    chrome.management.setEnabled(tests[curr].id, false, function(){
		var log = document.getElementById('log');
		log.innerHTML += encodeURIComponent("
" + tests[curr].name + "

");

		curr++;

		prepareEnvironment(runTest);
	    });
	},TC_TIMEOUT);
    });
}

function summarizeResults(html){
    var div = document.createElement('div');
    	div.innerHTML = '
'+ html + '
';

    	html = div.firstElementChild;

    var tests = html.querySelectorAll('.results'),
    	testcases = html.querySelectorAll('.results tbody tr'),
    	fails = html.querySelectorAll('tr.fail'),
    	notrun = html.querySelectorAll('tr.notrun'),
    	passes = html.querySelectorAll('tr.pass');
    var str = [ "

Tests: ", tests.length, " [testcases: ",
	testcases.length, "]", "

Pass: ", passes.length,
	" / Fail: ", fails.length, " / Not run: ", notrun.length,
	"

" ].join('');

    var passesPr = +(passes.length * 100 / testcases.length).toFixed(0);
    var failsPr = +(fails.length * 100 / testcases.length).toFixed(0);
    var notrunPr = +(notrun.length * 100 / testcases.length).toFixed(0);

    var str_progress =  [
        '
',
	''
		+ passesPr + '%',
	'' + failsPr
		+ '%',
	'' + notrunPr + '%',
	' ', '
' ].join('');
    return str + str_progress;
}
function result(){

    var css = "html{font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans}#log .warning,#log .warning a{color:#000;background:#FF0}#log .error,#log .error a{color:#FFF;background:red}#log pre{border:1px solid #000;padding:1em}section.summary{margin-bottom:1em}table.results{border-collapse:collapse;table-layout:fixed;width:100%}table.results th:first-child,table.results td:first-child{width:4em}table.results th:last-child,table.results td:last-child{width:50%}table.results.assertions th:last-child,table.results.assertions td:last-child{width:35%}table.results th{border-bottom:medium solid #000;padding:0 0 .5em}table.results td{border-bottom:thin solid #000;padding:1em 1em .5em}tr.pass>td:first-child{color:green}tr.notrun>td:first-child{color:blue}.pass>td:first-child,.fail>td:first-child,.timeout>td:first-child,.notrun>td:first-child{font-variant:small-caps}table.results span{display:block}h2{font-size:1.3em}a{border:2px solid #00C;color:#fff;background-color:#00C;display:block;line-height:1.5em;padding:0 .5em}a:hover{background-color:#fff;color:#00C}#info_progress{width:100%;position:relative;background:rgba(0,0,0,0.5);height:25px}#info_progress .percent{position:absolute;left:0;top:0;color:#FFF;font-weight:700;height:25px;line-height:25px;display:block;background:green;text-align:center}#info_progress .percent.fail{background:red}#info_progress .percent.notrun{background:gray}tr.fail>td:first-child,tr.timeout>td:first-child{color:red}table.results span.expected,table.results span.actual{font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;white-space:pre}";
    var str = "data:text/html,<!DOCTYPE html><title>RAPORT</title>";
    var results = document.getElementById('log');
    var stats = summarizeResults(decodeURIComponent(results.innerHTML));
    //console.log();
    str += stats + results.innerHTML;
    chrome.windows.create({"url": str, focused: true});

}
function debug(msg) {
	var url = "data:text/html," + msg;
	//chrome.tabs.create({"url": url});
}<|endoftext|>


<commit_before>var tape = require('tape'),
    comboBreaker = require('..'),
    redundant,
    broken
;

redundant = 'I really really really really love pizza.';

tape('combo breaking', function (t) {
    broken = comboBreaker(redundant, 'really ');
    t.equal(broken, 'I really love pizza.');
    t.end();
});

tape('`options.keep`', function (t) {
    broken = comboBreaker(redundant, 'really ', { keep: 2 });
    t.equal(broken, 'I really really love pizza.');
    t.end();
});
<commit_msg>Add failing tests for regex meta characters<commit_after>var tape = require('tape'),
    comboBreaker = require('..'),
    redundant,
    broken
;

redundant = 'I really really really really love pizza.';

tape('combo breaking', function (t) {
    broken = comboBreaker(redundant, 'really ');
    t.equal(broken, 'I really love pizza.');
    t.end();
});

tape('`options.keep`', function (t) {
    broken = comboBreaker(redundant, 'really ', { keep: 2 });
    t.equal(broken, 'I really really love pizza.');
    t.end();
});

tape('escaping of regex characters', function (t) {
    t.test('├─ `$` character', function (t) {
        broken = comboBreaker('a million dollar$$$$$$$$$$$$$$$', '$');
        t.equal(broken, 'a million dollar$', '$ character');
        t.end();
    });

    t.test('├─ `*` character', function (t) {
        broken = comboBreaker('i can tell no lies***********', '*');
        t.equal(broken, 'i can tell no lies*');
        t.end();
    });

    t.test('├─ `)` character', function (t) {
        broken = comboBreaker('())))))))))))))', ')');
        t.equal(broken, '()');
        t.end();
    });

    t.test('├─ `|` character', function (t) {
        broken = comboBreaker('pipe pipe pipe ||||| pipe', '|');
        t.equal(broken, 'pipe pipe pipe | pipe');
        t.end();
    });

    t.test('├─ `.` character', function (t) {
        broken = comboBreaker('dot dot dot ........ dot dot', '.');
        t.equal(broken, 'dot dot dot . dot dot');
        t.end();
    });

    t.test('├─ `?` character', function (t) {
        broken = comboBreaker('why???????', '?');
        t.equal(broken, 'why?');
        t.end();
    });

    t.test('└─ `\\` character', function (t) {
        broken = comboBreaker('back slash slash \\\\\\\\ slash', '\\');
        t.equal(broken, 'back slash slash \\ slash');
        t.end();
    });
});
<|endoftext|>


<commit_before>export default {
  querySelector(el) {
    global.document.querySelector = () => el || null;
  },
  binding() {
    return {
      modifiers: {},
      expression: 'exp',
      value: 'someval'
    };
  },
  vnode(shouldThrow, result, callback) {
    return {
      context: {
        $validator: this.validator(shouldThrow, result, callback),
        $nextTick: (cb) => {
          cb();
        }
      },
      data: {
        directives: []
      }
    };
  },
  validator(shouldThrow = true, result = false, callback) {
    return {
      validate(name, value) {
        if (shouldThrow) {
          throw (String(value));
        }
        return new Promise((resolve, reject) => {
          if (shouldThrow) {
            reject(String(value));
            return;
          }
          resolve(result);
        }).then(something => {
          if (typeof callback === 'function') callback();
          return something;
        });
      },
      attach() {

      }
    };
  },
  file: (name, type, size = 1) => ({
    name,
    type,
    size: size * 1024
  }),
  dimensionsTest: (dimensions, fails = false) => {
    global.window.URL = {
      createObjectURL() {
        return 'data:image/png;base64,AAAAAAA';
      }
    };

    global.Image = class Image {
          // eslint-disable-next-line
          set src(value) {
            this.width = dimensions.width;
            this.height = dimensions.height;

            this[fails ? 'onerror' : 'onload']();
          }
      };
  }
};
<commit_msg>remove uneeded method<commit_after>export default {
  querySelector(el) {
    global.document.querySelector = () => el || null;
  },
  binding() {
    return {
      modifiers: {},
      expression: 'exp',
      value: 'someval'
    };
  },
  vnode(shouldThrow, result, callback) {
    return {
      context: {
        $validator: this.validator(shouldThrow, result, callback),
        $nextTick: (cb) => {
          cb();
        }
      },
      data: {
        directives: []
      }
    };
  },
  validator(shouldThrow = true, result = false, callback) {
    return {
      validate(name, value) {
        if (shouldThrow) {
          throw (String(value));
        }
        return new Promise((resolve, reject) => {
          if (shouldThrow) {
            reject(String(value));
            return;
          }
          resolve(result);
        }).then(something => {
          if (typeof callback === 'function') callback();
          return something;
        });
      },
      attach() {

      }
    };
  },
  file: (name, type, size = 1) => ({
    name,
    type,
    size: size * 1024
  })
};
<|endoftext|>