<commit_before>
document.write('
SLF4J-related buzz
');

document.write('
Hello SLF4J');
document.write('
');

document.write('
Innovation in the Log space');
document.write('
');

document.write('
Frameworks I use');
document.write('
');

document.write('
VERSION 99.0');
document.write('
');

document.write('
JCL and SLF4J');
document.write('
');

document.write('
Code Template for Netbeans');
document.write('
');

document.write('
Maven2, Cargo etc.');
document.write('
');

document.write('
JCL woes');
document.write('
');

document.write('
Embedded Web Integration');
document.write('
');

document.write('
How to Use SLF4J with log4j');
document.write('
');

document.write('
Cool down the hot deployment');
document.write('
');

document.write('
Join us: Be Commons-Logging Free!');
document.write('
');
<commit_msg>more blogs<commit_after>
document.write('
SLF4J-related buzz
');

document.write('
SLF4J soapbox');
document.write('
');

document.write('
JDK logging');
document.write('
');

document.write('
oh wait!');
document.write('
');

document.write('
Open comment');
document.write('
');

document.write('
Hello SLF4J');
document.write('
');

document.write('
Innovation in the Log space');
document.write('
');

document.write('
Frameworks I use');
document.write('
');

document.write('
VERSION 99.0');
document.write('
');

document.write('
JCL and SLF4J');
document.write('
');

document.write('
Code Template for Netbeans');
document.write('
');

document.write('
Maven2, Cargo etc.');
document.write('
');

document.write('
JCL woes');
document.write('
');

document.write('
Embedded Web Integration');
document.write('
');

document.write('
How to Use SLF4J with log4j');
document.write('
');

document.write('
Cool down the hot deployment');
document.write('
');

document.write('
Join us: Be Commons-Logging Free!');
document.write('
');
<|endoftext|>


<commit_before>'use strict';

var BaseOverviewsDataview = require('./base');
var BaseDataview = require('../aggregation');
var debug = require('debug')('windshaft:widget:aggregation:overview');

var dot = require('dot');
dot.templateSettings.strip = false;

var filteredQueryTpl = dot.template([
    'filtered_source AS (',
    '  SELECT *',
    '  FROM ({{=it._query}}) _cdb_filtered_source',
    '  {{?it._aggregationColumn  && it._isFloatColumn}}WHERE',
    '    {{=it._aggregationColumn}} != \'infinity\'::float',
    '  AND',
    '    {{=it._aggregationColumn}} != \'-infinity\'::float',
    '  AND',
    '    {{=it._aggregationColumn}} != \'NaN\'::float{{?}}',
    ')'
].join(' \n'));

var summaryQueryTpl = dot.template([
    'summary AS (',
    '  SELECT',
    '  sum(_feature_count) AS count,',
    '  sum(CASE WHEN {{=it._column}} IS NULL THEN 1 ELSE 0 END) AS nulls_count',
    '  {{?it._isFloatColumn}},sum(',
    '    CASE',
    '      WHEN {{=it._aggregationColumn}} = \'infinity\'::float OR {{=it._aggregationColumn}} = \'-infinity\'::float',
    '      THEN 1',
    '      ELSE 0',
    '    END',
    '  ) AS infinities_count,',
    '  sum(CASE WHEN {{=it._aggregationColumn}} = \'NaN\'::float THEN 1 ELSE 0 END) AS nans_count{{?}}',
    '  FROM ({{=it._query}}) _cdb_aggregation_nulls',
    ')'
].join('\n'));

var rankedCategoriesQueryTpl = dot.template([
    'categories AS(',
    '  SELECT {{=it._column}} AS category, {{=it._aggregation}} AS value,',
    '    row_number() OVER (ORDER BY {{=it._aggregation}} desc) as rank',
    '  FROM filtered_source',
    '  {{?it._aggregationColumn!==null}}WHERE {{=it._aggregationColumn}} IS NOT NULL{{?}}',
    '  GROUP BY {{=it._column}}',
    '  ORDER BY 2 DESC',
    ')'
].join('\n'));

var categoriesSummaryMinMaxQueryTpl = dot.template([
    'categories_summary_min_max AS(',
    '  SELECT max(value) max_val, min(value) min_val',
    '  FROM categories',
    ')'
].join('\n'));

var categoriesSummaryCountQueryTpl = dot.template([
    'categories_summary_count AS(',
    '  SELECT count(1) AS categories_count',
    '  FROM (',
    '    SELECT {{=it._column}} AS category',
    '    FROM filtered_source',
    '    GROUP BY {{=it._column}}',
    '  ) _cdb_categories_count',
    ')'
].join('\n'));

var rankedAggregationQueryTpl = dot.template([
    'SELECT CAST(category AS text), value, false as agg, nulls_count, min_val, max_val,',
    '    count, categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    '  FROM categories, summary, categories_summary_min_max, categories_summary_count',
    '  WHERE rank < {{=it._limit}}',
    'UNION ALL',
    'SELECT \'Other\' category, sum(value), true as agg, nulls_count, min_val, max_val,',
    '    count, categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    '  FROM categories, summary, categories_summary_min_max, categories_summary_count',
    '  WHERE rank >= {{=it._limit}}',
    'GROUP BY nulls_count, min_val, max_val, count,',
    '  categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}'
].join('\n'));

var aggregationQueryTpl = dot.template([
    'SELECT CAST({{=it._column}} AS text) AS category, {{=it._aggregation}} AS value, false as agg,',
    '  nulls_count, min_val, max_val, count, categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    'FROM filtered_source, summary, categories_summary_min_max, categories_summary_count',
    'GROUP BY category, nulls_count, min_val, max_val, count,',
    '  categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    'ORDER BY value DESC'
].join('\n'));

var CATEGORIES_LIMIT = 6;

function Aggregation (query, options, queryRewriter, queryRewriteData, params, queries) {
    BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params, queries);

    this._checkOptions(options);

    this.query = query;
    this.queries = queries;
    this.column = options.column;
    this.aggregation = options.aggregation;
    this.aggregationColumn = options.aggregationColumn;
    this._isFloatColumn = null;
}

Aggregation.prototype = Object.create(BaseOverviewsDataview.prototype);
Aggregation.prototype.constructor = Aggregation;

module.exports = Aggregation;

Aggregation.prototype.sql = function (psql, override, callback) {
    var self = this;

    if (!callback) {
        callback = override;
        override = {};
    }

    var _query = this.rewrittenQuery(this.query);
    var _aggregationColumn = this.aggregation !== 'count' ? this.aggregationColumn : null;

    if (this.aggregationColumn && this._isFloatColumn === null) {
        this._isFloatColumn = false;
        this.getColumnType(psql, this.aggregationColumn, this.queries.no_filters, function (err, type) {
            if (!err && !!type) {
                self._isFloatColumn = type.float;
            }
            self.sql(psql, override, callback);
        });
        return null;
    }

    var aggregationSql;
    if (override.ownFilter) {
        aggregationSql = [
            'WITH',
            [
                filteredQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                summaryQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                rankedCategoriesQueryTpl({
                    _query: _query,
                    _column: this.column,
                    _aggregation: this.getAggregationSql(),
                    _aggregationColumn: _aggregationColumn
                }),
                categoriesSummaryMinMaxQueryTpl({
                    _query: _query,
                    _column: this.column
                }),
                categoriesSummaryCountQueryTpl({
                    _query: _query,
                    _column: this.column
                })
            ].join(',\n'),
            aggregationQueryTpl({
                _isFloatColumn: this._isFloatColumn,
                _query: _query,
                _column: this.column,
                _aggregation: this.getAggregationSql(),
                _limit: CATEGORIES_LIMIT
            })
        ].join('\n');
    } else {
        aggregationSql = [
            'WITH',
            [
                filteredQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                summaryQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                rankedCategoriesQueryTpl({
                    _query: _query,
                    _column: this.column,
                    _aggregation: this.getAggregationSql(),
                    _aggregationColumn: _aggregationColumn
                }),
                categoriesSummaryMinMaxQueryTpl({
                    _query: _query,
                    _column: this.column
                }),
                categoriesSummaryCountQueryTpl({
                    _query: _query,
                    _column: this.column
                })
            ].join(',\n'),
            rankedAggregationQueryTpl({
                _isFloatColumn: this._isFloatColumn,
                _query: _query,
                _column: this.column,
                _limit: CATEGORIES_LIMIT
            })
        ].join('\n');
    }

    debug(aggregationSql);

    return callback(null, aggregationSql, { usesOverviews: true });
};

var aggregationFnQueryTpl = {
    count: dot.template('sum(_feature_count)'),
    sum: dot.template('sum({{=it._aggregationColumn}}*_feature_count)')
};

const VALID_OPERATIONS = {
    count: [],
    sum: ['aggregationColumn']
};

Aggregation.prototype._checkOptions = function (options) {
    if (!VALID_OPERATIONS[options.aggregation]) {
        throw new Error(`Aggregation does not support '${options.aggregation}' operation in dataview overview options`);
    }

    const requiredOptions = VALID_OPERATIONS[options.aggregation];
    const missingOptions = requiredOptions.filter(requiredOption => !options.hasOwnProperty(requiredOption));

    if (missingOptions.length > 0) {
        throw new Error(
            `Aggregation '${options.aggregation}' is missing some options for overview: ${missingOptions.join(',')}`
        );
    }
};

Aggregation.prototype.getAggregationSql = function () {
    return aggregationFnQueryTpl[this.aggregation]({
        _aggregationFn: this.aggregation,
        _aggregationColumn: this.aggregationColumn || 1
    });
};
<commit_msg>Do not use object built-ins<commit_after>'use strict';

var BaseOverviewsDataview = require('./base');
var BaseDataview = require('../aggregation');
var debug = require('debug')('windshaft:widget:aggregation:overview');

var dot = require('dot');
dot.templateSettings.strip = false;

var filteredQueryTpl = dot.template([
    'filtered_source AS (',
    '  SELECT *',
    '  FROM ({{=it._query}}) _cdb_filtered_source',
    '  {{?it._aggregationColumn  && it._isFloatColumn}}WHERE',
    '    {{=it._aggregationColumn}} != \'infinity\'::float',
    '  AND',
    '    {{=it._aggregationColumn}} != \'-infinity\'::float',
    '  AND',
    '    {{=it._aggregationColumn}} != \'NaN\'::float{{?}}',
    ')'
].join(' \n'));

var summaryQueryTpl = dot.template([
    'summary AS (',
    '  SELECT',
    '  sum(_feature_count) AS count,',
    '  sum(CASE WHEN {{=it._column}} IS NULL THEN 1 ELSE 0 END) AS nulls_count',
    '  {{?it._isFloatColumn}},sum(',
    '    CASE',
    '      WHEN {{=it._aggregationColumn}} = \'infinity\'::float OR {{=it._aggregationColumn}} = \'-infinity\'::float',
    '      THEN 1',
    '      ELSE 0',
    '    END',
    '  ) AS infinities_count,',
    '  sum(CASE WHEN {{=it._aggregationColumn}} = \'NaN\'::float THEN 1 ELSE 0 END) AS nans_count{{?}}',
    '  FROM ({{=it._query}}) _cdb_aggregation_nulls',
    ')'
].join('\n'));

var rankedCategoriesQueryTpl = dot.template([
    'categories AS(',
    '  SELECT {{=it._column}} AS category, {{=it._aggregation}} AS value,',
    '    row_number() OVER (ORDER BY {{=it._aggregation}} desc) as rank',
    '  FROM filtered_source',
    '  {{?it._aggregationColumn!==null}}WHERE {{=it._aggregationColumn}} IS NOT NULL{{?}}',
    '  GROUP BY {{=it._column}}',
    '  ORDER BY 2 DESC',
    ')'
].join('\n'));

var categoriesSummaryMinMaxQueryTpl = dot.template([
    'categories_summary_min_max AS(',
    '  SELECT max(value) max_val, min(value) min_val',
    '  FROM categories',
    ')'
].join('\n'));

var categoriesSummaryCountQueryTpl = dot.template([
    'categories_summary_count AS(',
    '  SELECT count(1) AS categories_count',
    '  FROM (',
    '    SELECT {{=it._column}} AS category',
    '    FROM filtered_source',
    '    GROUP BY {{=it._column}}',
    '  ) _cdb_categories_count',
    ')'
].join('\n'));

var rankedAggregationQueryTpl = dot.template([
    'SELECT CAST(category AS text), value, false as agg, nulls_count, min_val, max_val,',
    '    count, categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    '  FROM categories, summary, categories_summary_min_max, categories_summary_count',
    '  WHERE rank < {{=it._limit}}',
    'UNION ALL',
    'SELECT \'Other\' category, sum(value), true as agg, nulls_count, min_val, max_val,',
    '    count, categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    '  FROM categories, summary, categories_summary_min_max, categories_summary_count',
    '  WHERE rank >= {{=it._limit}}',
    'GROUP BY nulls_count, min_val, max_val, count,',
    '  categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}'
].join('\n'));

var aggregationQueryTpl = dot.template([
    'SELECT CAST({{=it._column}} AS text) AS category, {{=it._aggregation}} AS value, false as agg,',
    '  nulls_count, min_val, max_val, count, categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    'FROM filtered_source, summary, categories_summary_min_max, categories_summary_count',
    'GROUP BY category, nulls_count, min_val, max_val, count,',
    '  categories_count{{?it._isFloatColumn}}, nans_count, infinities_count{{?}}',
    'ORDER BY value DESC'
].join('\n'));

var CATEGORIES_LIMIT = 6;

function Aggregation (query, options, queryRewriter, queryRewriteData, params, queries) {
    BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params, queries);

    this._checkOptions(options);

    this.query = query;
    this.queries = queries;
    this.column = options.column;
    this.aggregation = options.aggregation;
    this.aggregationColumn = options.aggregationColumn;
    this._isFloatColumn = null;
}

Aggregation.prototype = Object.create(BaseOverviewsDataview.prototype);
Aggregation.prototype.constructor = Aggregation;

module.exports = Aggregation;

Aggregation.prototype.sql = function (psql, override, callback) {
    var self = this;

    if (!callback) {
        callback = override;
        override = {};
    }

    var _query = this.rewrittenQuery(this.query);
    var _aggregationColumn = this.aggregation !== 'count' ? this.aggregationColumn : null;

    if (this.aggregationColumn && this._isFloatColumn === null) {
        this._isFloatColumn = false;
        this.getColumnType(psql, this.aggregationColumn, this.queries.no_filters, function (err, type) {
            if (!err && !!type) {
                self._isFloatColumn = type.float;
            }
            self.sql(psql, override, callback);
        });
        return null;
    }

    var aggregationSql;
    if (override.ownFilter) {
        aggregationSql = [
            'WITH',
            [
                filteredQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                summaryQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                rankedCategoriesQueryTpl({
                    _query: _query,
                    _column: this.column,
                    _aggregation: this.getAggregationSql(),
                    _aggregationColumn: _aggregationColumn
                }),
                categoriesSummaryMinMaxQueryTpl({
                    _query: _query,
                    _column: this.column
                }),
                categoriesSummaryCountQueryTpl({
                    _query: _query,
                    _column: this.column
                })
            ].join(',\n'),
            aggregationQueryTpl({
                _isFloatColumn: this._isFloatColumn,
                _query: _query,
                _column: this.column,
                _aggregation: this.getAggregationSql(),
                _limit: CATEGORIES_LIMIT
            })
        ].join('\n');
    } else {
        aggregationSql = [
            'WITH',
            [
                filteredQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                summaryQueryTpl({
                    _isFloatColumn: this._isFloatColumn,
                    _query: _query,
                    _column: this.column,
                    _aggregationColumn: _aggregationColumn
                }),
                rankedCategoriesQueryTpl({
                    _query: _query,
                    _column: this.column,
                    _aggregation: this.getAggregationSql(),
                    _aggregationColumn: _aggregationColumn
                }),
                categoriesSummaryMinMaxQueryTpl({
                    _query: _query,
                    _column: this.column
                }),
                categoriesSummaryCountQueryTpl({
                    _query: _query,
                    _column: this.column
                })
            ].join(',\n'),
            rankedAggregationQueryTpl({
                _isFloatColumn: this._isFloatColumn,
                _query: _query,
                _column: this.column,
                _limit: CATEGORIES_LIMIT
            })
        ].join('\n');
    }

    debug(aggregationSql);

    return callback(null, aggregationSql, { usesOverviews: true });
};

var aggregationFnQueryTpl = {
    count: dot.template('sum(_feature_count)'),
    sum: dot.template('sum({{=it._aggregationColumn}}*_feature_count)')
};

const VALID_OPERATIONS = {
    count: [],
    sum: ['aggregationColumn']
};

Aggregation.prototype._checkOptions = function (options) {
    if (!VALID_OPERATIONS[options.aggregation]) {
        throw new Error(`Aggregation does not support '${options.aggregation}' operation in dataview overview options`);
    }

    const requiredOptions = VALID_OPERATIONS[options.aggregation];
    const missingOptions = requiredOptions.filter(requiredOption => !Object.prototype.hasOwnProperty.call(options, requiredOption));

    if (missingOptions.length > 0) {
        throw new Error(
            `Aggregation '${options.aggregation}' is missing some options for overview: ${missingOptions.join(',')}`
        );
    }
};

Aggregation.prototype.getAggregationSql = function () {
    return aggregationFnQueryTpl[this.aggregation]({
        _aggregationFn: this.aggregation,
        _aggregationColumn: this.aggregationColumn || 1
    });
};
<|endoftext|>


<commit_before>//@flow
import template from '../templates/PopupStack.hbs';

const classes = {
    POPUP_REGION: 'js-popup-region-',
    POPUP_FADE: 'popup-fade'
};

const POPUP_ID_PREFIX = 'popup-region-';

export default Marionette.View.extend({
    initialize() {
        this.__stack = [];
        this.__forceFadeBackground = false;
    },

    template: Handlebars.compile(template),

    ui: {
        fadingPanel: '.js-fading-panel'
    },

    showPopup(view, options) {
        const { fadeBackground, transient, hostEl } = options;

        if (!transient) {
            this.__removeTransientPopups();
        }

        const popupId = _.uniqueId(POPUP_ID_PREFIX);
        const regionEl = document.createElement('div');
        regionEl.setAttribute('data-popup-id', popupId);
        regionEl.classList.add('js-core-ui__global-popup-region');

        let parentPopup;
        let parentPopupId = null;

        if (hostEl) {
            parentPopup = hostEl.closest && hostEl.closest('.js-core-ui__global-popup-region');
            parentPopupId = parentPopup ? parentPopup.getAttribute('popup-id') : null;
        }
        const config = {
            view,
            options,
            regionEl,
            popupId,
            parentPopupId
        };

        if (parentPopupId) {
            // If there is a child popup, it must be closed:
            // 1. There might be nested dropdowns
            // 2. There can't be dropdowns opened on the same level
            const childPopupDef = this.__stack.find(x => x.parentPopupId === parentPopupId);
            if (childPopupDef) {
                this.closePopup(childPopupDef.popupId);
            }
        }

        this.$el.append(regionEl);
        this.addRegion(popupId, {
            el: regionEl
        });
        this.getRegion(popupId).show(view);

        if (fadeBackground) {
            let lastIndex = -1;
            this.__stack.forEach((x, i) => (lastIndex = x.options.fadeBackground ? i : lastIndex));

            if (lastIndex !== -1) {
                this.__stack[lastIndex].regionEl.classList.remove(classes.POPUP_FADE);
            } else {
                this.__toggleFadedBackground(true);
            }
            regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = popupId;
        }

        this.__stack.push(config);
        view.popupId = popupId;

        return popupId;
    },

    showElInPopup(view, options) {
        const { fadeBackground, transient } = options;

        if (!transient) {
            this.__removeTransientPopups();
        }

        const popupId = _.uniqueId(POPUP_ID_PREFIX);
        const regionEl = document.createElement('div');
        regionEl.setAttribute('data-popup-id', popupId);
        regionEl.classList.add('js-core-ui__global-popup-region');

        const config = {
            view,
            options,
            regionEl,
            popupId,
            parentPopupId: null
        };

        this.$el.append(regionEl);
        this.addRegion(popupId, {
            el: regionEl
        });
        this.prevSublingOfContentEl = view.prev();
        this.getRegion(popupId).$el.append('

');
        view.appendTo(this.getRegion(popupId).$el.children('.modal-window-wrapper'));

        if (fadeBackground) {
            let lastIndex = -1;
            this.__stack.forEach((x, i) => (lastIndex = x.options.fadeBackground ? i : lastIndex));

            if (lastIndex !== -1) {
                this.__stack[lastIndex].regionEl.classList.remove(classes.POPUP_FADE);
            } else {
                this.__toggleFadedBackground(true);
            }
            regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = popupId;
        }

        this.__stack.push(config);
        view.popupId = popupId;

        return popupId;
    },

    closePopup(popupId = null) {
        if (this.__stack.length === 0) {
            return;
        }

        let targets = [];
        const popupDef = this.__stack.find(x => x.popupId === popupId);
        if (popupDef) {
            if (!popupDef.options.transient) {
                this.__removeTransientPopups();
            }
            // All the children of the popup will also be closed
            // Important: we collect only logical children because another popup might have been opened at the same level already.
            // e.g.: focus-blur events (usually focus comes first) - one popup is opened on focus and the previous one is closed on blur.
            if (this.__stack.includes(popupDef)) {
                targets = [popupDef];
                const handleChildren = pId => {
                    const children = this.__stack.filter(x => x.parentPopupId === pId);
                    targets.push(...children);
                    children.forEach(c => handleChildren(c.popupId));
                };
                handleChildren(popupId);
            } else {
                targets = [];
            }
        } else if (popupId) {
            // If we don't find the popup, it must have been closed so the job is done
            targets = [];
        } else {
            // Close all transient popups and the top-most non-transient
            this.__removeTransientPopups();
            const topMostNonTransient = this.__stack[this.__stack.length - 1];
            if (topMostNonTransient) {
                targets = [topMostNonTransient];
            }
        }
        targets.reverse().forEach(pd => {
            this.__removePopup(pd);
        });

        const filteredStackList = this.__stack.filter(x => x.options.fadeBackground);
        const lastElement = filteredStackList && filteredStackList[filteredStackList.length - 1];

        if (lastElement) {
            lastElement.regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = lastElement.popupId;
        } else {
            this.topPopupId = undefined;
            this.__toggleFadedBackground(this.__forceFadeBackground);
        }
    },

    closeElPopup(popupId = null) {
        if (this.__stack.length === 0) {
            return;
        }

        let targets = [];
        const popupDef = this.__stack.find(x => x.popupId === popupId);
        if (popupDef) {
            if (!popupDef.options.transient) {
                this.__removeTransientPopups();
            }
            // All the children of the popup will also be closed
            // Important: we collect only logical children because another popup might have been opened at the same level already.
            // e.g.: focus-blur events (usually focus comes first) - one popup is opened on focus and the previous one is closed on blur.
            if (this.__stack.includes(popupDef)) {
                targets = [popupDef];
                const handleChildren = pId => {
                    const children = this.__stack.filter(x => x.parentPopupId === pId);
                    targets.push(...children);
                    children.forEach(c => handleChildren(c.popupId));
                };
                handleChildren(popupId);
            } else {
                targets = [];
            }
        } else if (popupId) {
            // If we don't find the popup, it must have been closed so the job is done
            targets = [];
        } else {
            // Close all transient popups and the top-most non-transient
            this.__removeTransientPopups();
            const topMostNonTransient = this.__stack[this.__stack.length - 1];
            if (topMostNonTransient) {
                targets = [topMostNonTransient];
            }
        }
        popupDef.view.insertAfter(this.prevSublingOfContentEl);

        delete this.prevSublingOfContentEl;

        targets.reverse().forEach(pd => {
            this.__removePopup(pd);
        });

        const filteredStackList = this.__stack.filter(x => x.options.fadeBackground);
        const lastElement = filteredStackList && filteredStackList[filteredStackList.length - 1];

        if (lastElement) {
            lastElement.regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = lastElement.popupId;
        } else {
            this.topPopupId = undefined;
            this.__toggleFadedBackground(this.__forceFadeBackground);
        }
    },

    isPopupOnTop(popupId) {
        return this.topPopupId === popupId;
    },

    async closeTopPopup() {
        if (this.__stack.length === 0) {
            return;
        }
        const config = this.__stack[this.__stack.length - 1];
        if (!config.view.__isNeedToPrevent || !config.view.__isNeedToPrevent()) {
            if (config.view.close) {
                const results = await config.view.close();
                if (results) {
                    this.closePopup(config.popupId);
                }
            } else {
                this.closePopup(config.popupId);
            }
        }
    },

    __removeTransientPopups() {
        this.__stack
            .filter(x => x.options.transient)
            .reverse()
            .forEach(popupDef => {
                this.__removePopup(popupDef);
            });
    },

    __removePopup(popupDef) {
        this.removeRegion(popupDef.popupId);
        this.el.removeChild(popupDef.regionEl);
        this.__stack.splice(this.__stack.indexOf(popupDef), 1);
        this.trigger('popup:close', popupDef.popupId);
    },

    get(popupId) {
        const index = this.__stack.findIndex(x => x.popupId === popupId);
        if (index === -1) {
            return [];
        }
        return this.__stack.slice(index).map(x => x.view);
    },

    getStack() {
        return this.__stack;
    },

    fadeBackground(fade) {
        this.__forceFadeBackground = fade;
        this.__toggleFadedBackground(this.__forceFadeBackground || this.__stack.find(x => x.options.fadeBackground));
    },

    __toggleFadedBackground(fade) {
        this.ui.fadingPanel.toggleClass('fadingPanel_open', fade);
    }
});
<commit_msg>Better popup el handling.<commit_after>//@flow
import template from '../templates/PopupStack.hbs';

const classes = {
    POPUP_REGION: 'js-popup-region-',
    POPUP_FADE: 'popup-fade'
};

const POPUP_ID_PREFIX = 'popup-region-';

export default Marionette.View.extend({
    initialize() {
        this.__stack = [];
        this.__forceFadeBackground = false;
    },

    template: Handlebars.compile(template),

    ui: {
        fadingPanel: '.js-fading-panel'
    },

    showPopup(view, options) {
        const { fadeBackground, transient, hostEl } = options;

        if (!transient) {
            this.__removeTransientPopups();
        }

        const popupId = _.uniqueId(POPUP_ID_PREFIX);
        const regionEl = document.createElement('div');
        regionEl.setAttribute('data-popup-id', popupId);
        regionEl.classList.add('js-core-ui__global-popup-region');

        let parentPopup;
        let parentPopupId = null;

        if (hostEl) {
            parentPopup = hostEl.closest && hostEl.closest('.js-core-ui__global-popup-region');
            parentPopupId = parentPopup ? parentPopup.getAttribute('popup-id') : null;
        }
        const config = {
            view,
            options,
            regionEl,
            popupId,
            parentPopupId
        };

        if (parentPopupId) {
            // If there is a child popup, it must be closed:
            // 1. There might be nested dropdowns
            // 2. There can't be dropdowns opened on the same level
            const childPopupDef = this.__stack.find(x => x.parentPopupId === parentPopupId);
            if (childPopupDef) {
                this.closePopup(childPopupDef.popupId);
            }
        }

        this.$el.append(regionEl);
        this.addRegion(popupId, {
            el: regionEl
        });
        this.getRegion(popupId).show(view);

        if (fadeBackground) {
            let lastIndex = -1;
            this.__stack.forEach((x, i) => (lastIndex = x.options.fadeBackground ? i : lastIndex));

            if (lastIndex !== -1) {
                this.__stack[lastIndex].regionEl.classList.remove(classes.POPUP_FADE);
            } else {
                this.__toggleFadedBackground(true);
            }
            regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = popupId;
        }

        this.__stack.push(config);
        view.popupId = popupId;

        return popupId;
    },

    showElInPopup(view, options) {
        const { fadeBackground, transient } = options;

        if (!transient) {
            this.__removeTransientPopups();
        }

        const popupId = _.uniqueId(POPUP_ID_PREFIX);
        const regionEl = document.createElement('div');
        regionEl.setAttribute('data-popup-id', popupId);
        regionEl.classList.add('js-core-ui__global-popup-region');

        const config = {
            view,
            options,
            regionEl,
            popupId,
            parentPopupId: null
        };

        this.$el.append(regionEl);
        this.addRegion(popupId, {
            el: regionEl
        });
        this.prevSublingOfContentEl = view.prev();
        if (this.prevSublingOfContentEl.legnth === 0) {
            delete this.prevSublingOfContentEl;
            this.parentOfContentEl = view.parent();
        }
        this.getRegion(popupId).$el.append('

');

        view.appendTo(this.getRegion(popupId).$el.children('.modal-window-wrapper'));

        if (fadeBackground) {
            let lastIndex = -1;
            this.__stack.forEach((x, i) => (lastIndex = x.options.fadeBackground ? i : lastIndex));

            if (lastIndex !== -1) {
                this.__stack[lastIndex].regionEl.classList.remove(classes.POPUP_FADE);
            } else {
                this.__toggleFadedBackground(true);
            }
            regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = popupId;
        }

        this.__stack.push(config);
        view.popupId = popupId;

        return popupId;
    },

    closePopup(popupId = null) {
        if (this.__stack.length === 0) {
            return;
        }

        let targets = [];
        const popupDef = this.__stack.find(x => x.popupId === popupId);
        if (popupDef) {
            if (!popupDef.options.transient) {
                this.__removeTransientPopups();
            }
            // All the children of the popup will also be closed
            // Important: we collect only logical children because another popup might have been opened at the same level already.
            // e.g.: focus-blur events (usually focus comes first) - one popup is opened on focus and the previous one is closed on blur.
            if (this.__stack.includes(popupDef)) {
                targets = [popupDef];
                const handleChildren = pId => {
                    const children = this.__stack.filter(x => x.parentPopupId === pId);
                    targets.push(...children);
                    children.forEach(c => handleChildren(c.popupId));
                };
                handleChildren(popupId);
            } else {
                targets = [];
            }
        } else if (popupId) {
            // If we don't find the popup, it must have been closed so the job is done
            targets = [];
        } else {
            // Close all transient popups and the top-most non-transient
            this.__removeTransientPopups();
            const topMostNonTransient = this.__stack[this.__stack.length - 1];
            if (topMostNonTransient) {
                targets = [topMostNonTransient];
            }
        }
        targets.reverse().forEach(pd => {
            this.__removePopup(pd);
        });

        const filteredStackList = this.__stack.filter(x => x.options.fadeBackground);
        const lastElement = filteredStackList && filteredStackList[filteredStackList.length - 1];

        if (lastElement) {
            lastElement.regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = lastElement.popupId;
        } else {
            this.topPopupId = undefined;
            this.__toggleFadedBackground(this.__forceFadeBackground);
        }
    },

    closeElPopup(popupId = null) {
        if (this.__stack.length === 0) {
            return;
        }

        let targets = [];
        const popupDef = this.__stack.find(x => x.popupId === popupId);
        if (popupDef) {
            if (!popupDef.options.transient) {
                this.__removeTransientPopups();
            }
            // All the children of the popup will also be closed
            // Important: we collect only logical children because another popup might have been opened at the same level already.
            // e.g.: focus-blur events (usually focus comes first) - one popup is opened on focus and the previous one is closed on blur.
            if (this.__stack.includes(popupDef)) {
                targets = [popupDef];
                const handleChildren = pId => {
                    const children = this.__stack.filter(x => x.parentPopupId === pId);
                    targets.push(...children);
                    children.forEach(c => handleChildren(c.popupId));
                };
                handleChildren(popupId);
            } else {
                targets = [];
            }
        } else if (popupId) {
            // If we don't find the popup, it must have been closed so the job is done
            targets = [];
        } else {
            // Close all transient popups and the top-most non-transient
            this.__removeTransientPopups();
            const topMostNonTransient = this.__stack[this.__stack.length - 1];
            if (topMostNonTransient) {
                targets = [topMostNonTransient];
            }
        }
        if (this.prevSublingOfContentEl) {
            popupDef.view.insertAfter(this.prevSublingOfContentEl);
            delete this.prevSublingOfContentEl;
        } else {
            popupDef.view.prepend(this.parentOfContentEl);
            delete this.parentOfContentEl;
        }

        targets.reverse().forEach(pd => {
            this.__removePopup(pd);
        });

        const filteredStackList = this.__stack.filter(x => x.options.fadeBackground);
        const lastElement = filteredStackList && filteredStackList[filteredStackList.length - 1];

        if (lastElement) {
            lastElement.regionEl.classList.add(classes.POPUP_FADE);
            this.topPopupId = lastElement.popupId;
        } else {
            this.topPopupId = undefined;
            this.__toggleFadedBackground(this.__forceFadeBackground);
        }
    },

    isPopupOnTop(popupId) {
        return this.topPopupId === popupId;
    },

    async closeTopPopup() {
        if (this.__stack.length === 0) {
            return;
        }
        const config = this.__stack[this.__stack.length - 1];
        if (!config.view.__isNeedToPrevent || !config.view.__isNeedToPrevent()) {
            if (config.view.close) {
                const results = await config.view.close();
                if (results) {
                    this.closePopup(config.popupId);
                }
            } else {
                this.closePopup(config.popupId);
            }
        }
    },

    __removeTransientPopups() {
        this.__stack
            .filter(x => x.options.transient)
            .reverse()
            .forEach(popupDef => {
                this.__removePopup(popupDef);
            });
    },

    __removePopup(popupDef) {
        this.removeRegion(popupDef.popupId);
        this.el.removeChild(popupDef.regionEl);
        this.__stack.splice(this.__stack.indexOf(popupDef), 1);
        this.trigger('popup:close', popupDef.popupId);
    },

    get(popupId) {
        const index = this.__stack.findIndex(x => x.popupId === popupId);
        if (index === -1) {
            return [];
        }
        return this.__stack.slice(index).map(x => x.view);
    },

    getStack() {
        return this.__stack;
    },

    fadeBackground(fade) {
        this.__forceFadeBackground = fade;
        this.__toggleFadedBackground(this.__forceFadeBackground || this.__stack.find(x => x.options.fadeBackground));
    },

    __toggleFadedBackground(fade) {
        this.ui.fadingPanel.toggleClass('fadingPanel_open', fade);
    }
});
<|endoftext|>


<commit_before>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

import {
  ViroSceneNavigator,
  ViroScene,
  ViroBox,
  ViroMaterials,
  ViroNode,
  ViroOrbitCamera,
  ViroCamera,
  ViroAmbientLight,
  ViroOmniLight,
  ViroSpotLight,
  ViroDirectionalLight,
  ViroImage,
  ViroVideo,
  Viro360Image,
  Viro360Video,
  ViroFlexView,
  ViroUtils,
  ViroText,
  ViroAnimations,
  ViroAnimatedComponent,
  ViroQuad,
  ViroSkyBox,
  ViroSphere,
  Viro3DObject,
} from 'react-viro';

let polarToCartesian = ViroUtils.polarToCartesian;
var createReactClass = require('create-react-class');

var count = 0;

// **This test has not been done.  This is placeholder for scene and navigation arrows**

var ReleaseMenu = require("./ReleaseMenu.js");

var ViroCameraHUDTest = createReactClass({

  getInitialState() {
    return {
        activeCamera:1,
        fov: 60,
    };
  },

  render: function() {
    return (
     <ViroScene onClick={this._toggleCamera} ref="cameraScene">
     <ReleaseMenu sceneNavigator={this.props.sceneNavigator}/>
     <ViroAmbientLight color="#ffffff"/>
     <ViroOmniLight position={[0, 0, -5]} color="#ffffff" attenuationStartDistance={40} attenuationEndDistance={50}/>

     <ViroCamera
         fieldOfView={this.state.fov}
         position={[0,0,0]}
         active={this.state.activeCamera == 1}
         animation={{name:"testLoopMove",
                     loop:true,
                     run:true,
                     onStart:this._onStart,
                     onFinish:this._onFinish}}>
              <ViroBox position={[0, 0, -5]} materials={"blueColor"} />
              <Viro3DObject source={require('./res/gltf/Buggy.glb')}
                            position={[0, .5, -3]}
                            scale={[0.005,0.005,0.005]}
                            type="GLB"
                            />
      </ViroCamera>

      <ViroCamera
          position={[0, 0, -10]}
          rotation={[0, 180, 0]}
          fieldOfView={this.state.fov}
          active={this.state.activeCamera == 2} >
          <ViroBox
             position={[0, 0, -4]}
             scale={[0.8 , 0.8 , 0.8]}
             materials={["redColor"]}
             height={1}
             width={1}
             length={1} />

            <ViroText style={styles.centeredText} position={[-0.5, -1, -6]} text={"HUD Text"}
                    width={2} height={2} />
      </ViroCamera>

      <ViroText style={styles.centeredText} position={[-2, -1, -4]} text={"Active Camera:" + this.state.activeCamera}
             width={2} height={2}  onClick={this._toggleCamera} />

     </ViroScene>

    );
  },

  _onStart(){
    console.log("Animation Camera onStart();");
  },
  _onFinish(){
    console.log("Animation Camera onFinish();");
  },

  _showNext() {
    this.props.sceneNavigator.replace({scene:require('./SceneTest1')});
  },

  _toggleCamera(){
      var newCamera = this.state.activeCamera + 1;
      if (newCamera > 2) {
          newCamera = 1;
      }
      this.setState({
         activeCamera:newCamera
      });
  },
});

var styles = StyleSheet.create({
  centeredText: {
      fontFamily: 'Arial',
      fontSize: 25,
      color: '#ffffff',
      textAlignVertical: 'center',
      textAlign: 'center',
  },
});

ViroMaterials.createMaterials({
  redColor: {
      fresnelExponent: .5,
      shininess: 2.0,
      diffuseColor: "#ff0000"
  },
  blueColor: {
      fresnelExponent: .5,
      shininess: 2.0,
      diffuseColor: "#0000ff"
  },
  blue: {
      shininess: 2.0,
      lightingModel: "Lambert",
      diffuseColor: "#0000ff"
    },
  heart: {
      lightingModel: "Phong",
      diffuseTexture: require('../res/heart_d.jpg'),
    },
});

ViroAnimations.registerAnimations({
    moveRight:{properties:{positionX:"+=2"}, duration: 2000, easing:"Linear"},
    moveLeft:{properties:{positionX:"-=2"}, duration: 2000, easing:"Linear"},
    testLoopMove:[
        ["moveRight", "moveLeft"]
    ],
});

module.exports = ViroCameraHUDTest;
<commit_msg>VIRO-3908: Removed Complex 3D model in ViroCameraHudTest for a simple one instead<commit_after>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

import {
  ViroSceneNavigator,
  ViroScene,
  ViroBox,
  ViroMaterials,
  ViroNode,
  ViroOrbitCamera,
  ViroCamera,
  ViroAmbientLight,
  ViroOmniLight,
  ViroSpotLight,
  ViroDirectionalLight,
  ViroImage,
  ViroVideo,
  Viro360Image,
  Viro360Video,
  ViroFlexView,
  ViroUtils,
  ViroText,
  ViroAnimations,
  ViroAnimatedComponent,
  ViroQuad,
  ViroSkyBox,
  ViroSphere,
  Viro3DObject,
} from 'react-viro';

let polarToCartesian = ViroUtils.polarToCartesian;
var createReactClass = require('create-react-class');

var count = 0;

// **This test has not been done.  This is placeholder for scene and navigation arrows**

var ReleaseMenu = require("./ReleaseMenu.js");

var ViroCameraHUDTest = createReactClass({

  getInitialState() {
    return {
        activeCamera:1,
        fov: 60,
    };
  },

  render: function() {
    return (
     <ViroScene onClick={this._toggleCamera} ref="cameraScene">
     <ReleaseMenu sceneNavigator={this.props.sceneNavigator}/>
     <ViroAmbientLight color="#ffffff"/>
     <ViroOmniLight position={[0, 0, -5]} color="#ffffff" attenuationStartDistance={40} attenuationEndDistance={50}/>

     <ViroCamera
         fieldOfView={this.state.fov}
         position={[0,0,0]}
         active={this.state.activeCamera == 1}
         animation={{name:"testLoopMove",
                     loop:true,
                     run:true,
                     onStart:this._onStart,
                     onFinish:this._onFinish}}>
              <ViroBox position={[0, 0, -5]} materials={"blueColor"} />
              <Viro3DObject source={require('./res/gltf/DuckGlb.glb')}
                            position={[0, .5, -3]}
                            scale={[0.5,0.5,0.5]}
                            type="GLB"
                            />
      </ViroCamera>

      <ViroCamera
          position={[0, 0, -10]}
          rotation={[0, 180, 0]}
          fieldOfView={this.state.fov}
          active={this.state.activeCamera == 2} >
          <ViroBox
             position={[0, 0, -4]}
             scale={[0.8 , 0.8 , 0.8]}
             materials={["redColor"]}
             height={1}
             width={1}
             length={1} />

            <ViroText style={styles.centeredText} position={[-0.5, -1, -6]} text={"HUD Text"}
                    width={2} height={2} />
      </ViroCamera>

      <ViroText style={styles.centeredText} position={[-2, -1, -4]} text={"Active Camera:" + this.state.activeCamera}
             width={2} height={2}  onClick={this._toggleCamera} />

     </ViroScene>

    );
  },

  _onStart(){
    console.log("Animation Camera onStart();");
  },
  _onFinish(){
    console.log("Animation Camera onFinish();");
  },

  _showNext() {
    this.props.sceneNavigator.replace({scene:require('./SceneTest1')});
  },

  _toggleCamera(){
      var newCamera = this.state.activeCamera + 1;
      if (newCamera > 2) {
          newCamera = 1;
      }
      this.setState({
         activeCamera:newCamera
      });
  },
});

var styles = StyleSheet.create({
  centeredText: {
      fontFamily: 'Arial',
      fontSize: 25,
      color: '#ffffff',
      textAlignVertical: 'center',
      textAlign: 'center',
  },
});

ViroMaterials.createMaterials({
  redColor: {
      fresnelExponent: .5,
      shininess: 2.0,
      diffuseColor: "#ff0000"
  },
  blueColor: {
      fresnelExponent: .5,
      shininess: 2.0,
      diffuseColor: "#0000ff"
  },
  blue: {
      shininess: 2.0,
      lightingModel: "Lambert",
      diffuseColor: "#0000ff"
    },
  heart: {
      lightingModel: "Phong",
      diffuseTexture: require('../res/heart_d.jpg'),
    },
});

ViroAnimations.registerAnimations({
    moveRight:{properties:{positionX:"+=2"}, duration: 2000, easing:"Linear"},
    moveLeft:{properties:{positionX:"-=2"}, duration: 2000, easing:"Linear"},
    testLoopMove:[
        ["moveRight", "moveLeft"]
    ],
});

module.exports = ViroCameraHUDTest;
<|endoftext|>


<commit_before>"use strict";

const Handler = require('../../router/handler');
const isEmptyObject = require('../../../util/isEmptyObject');

/**
 * Load the session for the current request.  If the session is either invalid
 * or has expired, then generate a new session.
 * @class
 * @extends Defiant.Plugin.Router.Handler
 * @memberOf Defiant.Plugin.Session
 */
class SessionHandler extends Handler {
  /**
   * A request has been made.  Process the request and provide the necessary
   * [Renderable]{@link Defiant.Plugin.Theme.Renderable}.
   * @function
   * @async
   * @param {Defiant.Context} context
   *   The request context.
   */
  async init(context) {
    let Session = context.engine.pluginRegistry.get('Session');

    // Use a Promise just to clean up the code execution flow.
    // TODO: Rework.
    await new Promise(async(accept, reject) => {
      let currentTime = Math.round(new Date().getTime() / 1000),
          newExpiration = currentTime + Session.sessionLifetime;

      // Try to load a session if it exists.
      await Session.sessionReader(context.request, context.response);

      if ((!context.request.sessionId) || (!context.request.sessionId.id)) {
        // No session exists, so create one.
        await Session.generateSession(context);
        return accept();
      }

      // The connection claims a session.  Is it already loaded?
      if (Session.sessions[context.request.sessionId.id]) {
        let session = Session.sessions[context.request.sessionId.id];
        // Has the session expired?
        if (currentTime > session.expire) {
          delete Session.sessions[session.id];
          await Session.deleteSessionFile(session.id);
          await Session.generateSession(context);
          return accept();
        }
        // Update the session.
        session.expire = newExpiration;
        await Session.writeSessionFile(session);

        /**
         * @member {Defiant.Plugin.Settings.Data} Defiant.Context#session
         *   The session for the current connection.
         */
        context.session = session;
        return accept();
      }

      // The session does not exist in memory.  Try to load it from a file.
      let session = await Session.readSessionFile(context.request.sessionId.id);
      if (!session || isEmptyObject(session)) {
        await Session.generateSession(context);
        return accept();
      }

      // Has the session expired?
      if (currentTime > session.expire) {
        await Session.deleteSessionFile(session.id);
        await Session.generateSession(context);
        return accept();
      }

      // The session exists.  Update it.
      Session.sessions[session.id] = session;
      session.expire = newExpiration;
      await Session.writeSessionFile(session);
      context.session = session;
      return accept();
    });

    // Set the volatile session object.
    if (!Session.volatile[context.session.id]) {
      Session.volatile[context.session.id] = {};
    }
    context.volatile = Session.volatile[context.session.id];
  }
}

SessionHandler.id = 'Session.SessionHandler';
SessionHandler.path = '';
SessionHandler.weight = -550;

module.exports = SessionHandler;
<commit_msg>Doc: added missing doc for Defiant.Context#volatile<commit_after>"use strict";

const Handler = require('../../router/handler');
const isEmptyObject = require('../../../util/isEmptyObject');

/**
 * Load the session for the current request.  If the session is either invalid
 * or has expired, then generate a new session.
 * @class
 * @extends Defiant.Plugin.Router.Handler
 * @memberOf Defiant.Plugin.Session
 */
class SessionHandler extends Handler {
  /**
   * A request has been made.  Process the request and provide the necessary
   * [Renderable]{@link Defiant.Plugin.Theme.Renderable}.
   * @function
   * @async
   * @param {Defiant.Context} context
   *   The request context.
   */
  async init(context) {
    let Session = context.engine.pluginRegistry.get('Session');

    // Use a Promise just to clean up the code execution flow.
    // TODO: Rework.
    await new Promise(async(accept, reject) => {
      let currentTime = Math.round(new Date().getTime() / 1000),
          newExpiration = currentTime + Session.sessionLifetime;

      // Try to load a session if it exists.
      await Session.sessionReader(context.request, context.response);

      if ((!context.request.sessionId) || (!context.request.sessionId.id)) {
        // No session exists, so create one.
        await Session.generateSession(context);
        return accept();
      }

      // The connection claims a session.  Is it already loaded?
      if (Session.sessions[context.request.sessionId.id]) {
        let session = Session.sessions[context.request.sessionId.id];
        // Has the session expired?
        if (currentTime > session.expire) {
          delete Session.sessions[session.id];
          await Session.deleteSessionFile(session.id);
          await Session.generateSession(context);
          return accept();
        }
        // Update the session.
        session.expire = newExpiration;
        await Session.writeSessionFile(session);

        /**
         * @member {Defiant.Plugin.Settings.Data} Defiant.Context#session
         *   The session for the current connection.
         */
        context.session = session;
        return accept();
      }

      // The session does not exist in memory.  Try to load it from a file.
      let session = await Session.readSessionFile(context.request.sessionId.id);
      if (!session || isEmptyObject(session)) {
        await Session.generateSession(context);
        return accept();
      }

      // Has the session expired?
      if (currentTime > session.expire) {
        await Session.deleteSessionFile(session.id);
        await Session.generateSession(context);
        return accept();
      }

      // The session exists.  Update it.
      Session.sessions[session.id] = session;
      session.expire = newExpiration;
      await Session.writeSessionFile(session);
      context.session = session;
      return accept();
    });

    // Set the volatile session object.
    if (!Session.volatile[context.session.id]) {
      Session.volatile[context.session.id] = {};
    }

    /**
     * @member {Object} Defiant.Context#volatile
     *   Hold volatile session content.
     */
    context.volatile = Session.volatile[context.session.id];
  }
}

SessionHandler.id = 'Session.SessionHandler';
SessionHandler.path = '';
SessionHandler.weight = -550;

module.exports = SessionHandler;
<|endoftext|>


<commit_before>exports.init = function(PIN, PIXELCNT) {
  var PULSECNT=0;

  responder=function(cb,d){
    if(cb){cb({"success":d[0], "data":d[1], "details":d[2]});}
  };

  return {

    /********************************************************
       off
    ********************************************************/
    off:function(){
      var pixels=new Uint8ClampedArray(PIXELCNT*3);

      for(var p=0; p<pixels.length; p+=3){
          pixels[p]=0;
          pixels[p+1]=0;
          pixels[p+2]=0;
      }

      require("neopixel").write(PIN, pixels);
    },

    /********************************************************
       FADE
    ********************************************************/
    fade:function(params,cb){
      if(!params.from){ responder(cb,[false,null,"missing from color"]);}
      if(typeof params.from[0]!=='object'){ params.from=[params.from]; }

      if(!params.to){ responder(cb,[false,null,"missing to color"]);}
      if(typeof params.to[0]!=='object'){ params.to=[params.to]; }

      if(!params.time){params.time=1000;}

      var interval=null,
          speed=(1000/20)*(params.time/1000),

          rStep=[],
          gStep=[],
          bStep=[],
          R=[],
          G=[],
          B=[],
          stepsRemaining=speed;

          pixels=new Uint8ClampedArray(PIXELCNT*3);

      for(var p=0; p<params.to.length; p++){
            rStep[p]=(params.to[p][0]-params.from[p][0])/speed;
            gStep[p]=(params.to[p][1]-params.from[p][1])/speed;
            bStep[p]=(params.to[p][2]-params.from[p][2])/speed;
            R[p]=params.from[p][0];
            G[p]=params.from[p][1];
            B[p]=params.from[p][2];
      }

      var fromColorIndex=0;
      for(var p=0; p<pixels.length; p+=3){
          pixels[p]=params.from[fromColorIndex][0];
          pixels[p+1]=params.from[fromColorIndex][1];
          pixels[p+2]=params.from[fromColorIndex][2];

          fromColorIndex++;
          if(fromColorIndex>=params.from.length){
            fromColorIndex=0;
          }
      }

      interval=setInterval(function(){
        for(var p=0; p<params.to.length; p++){

          R[p]+=rStep[p];
          G[p]+=gStep[p];
          B[p]+=bStep[p];
        }

        var colorIndex=0;
        for(var p=0; p<pixels.length; p+=3){
          pixels[p]=R[colorIndex];
          pixels[p+1]=G[colorIndex];
          pixels[p+2]=B[colorIndex];

          colorIndex++;
          if(colorIndex>=params.to.length){
            colorIndex=0;
          }
        }

        if(stepsRemaining<=0){
          clearInterval(interval);
          responder(cb,[true,null,"fade complete"]);
        }else{
          //console.log(pixels);
          require("neopixel").write(PIN, pixels);
          stepsRemaining--;
        }
      },20);
    },

    /********************************************************
       PULSE
    ********************************************************/
    pulse:function(params,cb){

      if(!params.from){ responder(cb,[false,null,"missing from color"]);}
      if(typeof params.from[0]!=='object'){ params.from=[params.from]; }

      if(!params.to){ responder(cb,[false,null,"missing to color"]);}
      if(typeof params.to[0]!=='object'){ params.to=[params.to]; }

      if(!params.cnt){params.cnt=1;}

      if(!params.time_in){params.time_in=1000;}
      if(!params.time_out){params.time_out=1000;}

      var that=this;

      this.fade({
          "from":params.from,
          "to":params.to,
          "time":params.time_in
        },function(r){

          that.fade({
            "to":params.to,
            "from":params.from,
            "time":params.time_out
          },function(r){

            if(PULSECNT>params.cnt){
              responder(cb,[true,null,"pulse complete"]);
              PULSECNT=0;
            }else{
              PULSECNT++;
              that.pulse();
            }
          });
        });
    },
  };
};

<commit_msg>Added heartbeat and blink<commit_after>exports.init = function(PIN, PIXELCNT) {
  let PULSECNT=0;

  let blinker={
    "cnt":1,
    "rate_on":1,
    "rate_off":1,
    "pixel_colors":null,
    "blink_fx":'sync',
    "color_index":0,
    "pixel_index":0,
    "on":false,
    "cb":null,

    reset:function(){
      this.cnt=1;
      this.rate_on=1;
      this.rate_off=1;
      this.pixel_colors=null;
      this.blink_fx='sync';
      this.color_index=0;
      this.pixel_index=0;
      this.on=false;
      this.cb=null;

    },

    blink:function(){
      let pArray=new Uint8ClampedArray(PIXELCNT*3);

      if(this.cnt>=0){

        switch(this.blink_fx){
          case 'random':
          break;
          case 'sequence':
            for(var p=0; p<pArray.length; p+=3){
              pArray[p]= ((this.pixel_index === (p/3)) ? this.pixel_colors[p] : 0);
              pArray[p+1]=((this.pixel_index === (p/3)) ? this.pixel_colors[p+1] : 0);
              pArray[p+2]=((this.pixel_index === (p/3)) ? this.pixel_colors[p+2] : 0);
            }

            this.pixel_index++;
            if(this.pixel_index>=PIXELCNT){
               this.pixel_index=0;
            }

          break;
          default: //sync
            for(var p=0; p<pArray.length; p+=3){
              pArray[p]=((this.on) ? this.pixel_colors[p] : 0);
              pArray[p+1]=((this.on) ? this.pixel_colors[p+1] : 0);
              pArray[p+2]=((this.on) ? this.pixel_colors[p+2] : 0);
            }

            this.on=!this.on;

          break;
        }

        require("neopixel").write(PIN, pArray);
        setTimeout(function(){ blinker.blink();}, 1000*((!blinker.on) ? blinker.rate_on : blinker.rate_off));
        this.cnt--;
        return true;

      }else{
        if(blinker.cb){
          responder(blinker.cb,[true,null,"blink complete"]);
        }

      }

    }
  };

  responder=function(cb,d){
    if(cb){cb({"success":d[0], "data":d[1], "details":d[2]});}
  };

  return {

    /********************************************************
       off
    ********************************************************/
    off:function(){
      var pixels=new Uint8ClampedArray(PIXELCNT*3);

      blinker.reset();

      for(var p=0; p<pixels.length; p+=3){
          pixels[p]=0;
          pixels[p+1]=0;
          pixels[p+2]=0;
      }
      require("neopixel").write(PIN, pixels);
    },

    /********************************************************
       FADE
    ********************************************************/
    fade:function(params,cb){
      if(!params.from){ responder(cb,[false,null,"missing from color"]);}
      if(typeof params.from[0]!=='object'){ params.from=[params.from]; }

      if(!params.to){ responder(cb,[false,null,"missing to color"]);}
      if(typeof params.to[0]!=='object'){ params.to=[params.to]; }

      if(!params.time){params.time=1000;}

      var interval=null,
          speed=(1000/20)*(params.time/1000),

          rStep=[],
          gStep=[],
          bStep=[],
          R=[],
          G=[],
          B=[],
          stepsRemaining=speed;

          pixels=new Uint8ClampedArray(PIXELCNT*3);

      for(var p=0; p<params.to.length; p++){
            rStep[p]=(params.to[p][0]-params.from[p][0])/speed;
            gStep[p]=(params.to[p][1]-params.from[p][1])/speed;
            bStep[p]=(params.to[p][2]-params.from[p][2])/speed;
            R[p]=params.from[p][0];
            G[p]=params.from[p][1];
            B[p]=params.from[p][2];
      }

      var fromColorIndex=0;
      for(var p=0; p<pixels.length; p+=3){
          pixels[p]=params.from[fromColorIndex][0];
          pixels[p+1]=params.from[fromColorIndex][1];
          pixels[p+2]=params.from[fromColorIndex][2];

          fromColorIndex++;
          if(fromColorIndex>=params.from.length){
            fromColorIndex=0;
          }
      }

      interval=setInterval(function(){
        for(var p=0; p<params.to.length; p++){

          R[p]+=rStep[p];
          G[p]+=gStep[p];
          B[p]+=bStep[p];
        }

        var colorIndex=0;
        for(var p=0; p<pixels.length; p+=3){
          pixels[p]=R[colorIndex];
          pixels[p+1]=G[colorIndex];
          pixels[p+2]=B[colorIndex];

          colorIndex++;
          if(colorIndex>=params.to.length){
            colorIndex=0;
          }
        }

        if(stepsRemaining<=0){
          clearInterval(interval);
          responder(cb,[true,null,"fade complete"]);
        }else{
          require("neopixel").write(PIN, pixels);
          stepsRemaining--;
        }
      },20);
    },

    /********************************************************
       PULSE
    ********************************************************/
    pulse:function(params,cb){

      if(!params.from){ responder(cb,[false,null,"missing from color"]);}
      if(typeof params.from[0]!=='object'){ params.from=[params.from]; }

      if(!params.to){ responder(cb,[false,null,"missing to color"]);}
      if(typeof params.to[0]!=='object'){ params.to=[params.to]; }

      if(!params.cnt){params.cnt=1;}

      if(!params.time_in){params.time_in=1000;}
      if(!params.time_out){params.time_out=1000;}

      var that=this;

      this.fade({
          "from":params.from,
          "to":params.to,
          "time":params.time_in
        },function(r){
          var theOtherThing=that;
          that.fade({
            "to":params.from,
            "from":params.to,
            "time":params.time_out
          },function(r){
              PULSECNT++;
            if(PULSECNT>=params.cnt){
              responder(cb,[true,null,"pulse complete"]);
              PULSECNT=0;
            }else{
              theOtherThing.pulse(params,cb);
            }
          });
        });
    },

    /********************************************************
       HEARTBEAT
    ********************************************************/
    heartbeat:function(params,cb){
      if(!params.color){ responder(cb,[false,null,"missing heartbeat color"]);}
      if(typeof params.color[0]!=='object'){ params.color=[params.color]; }

      if(!params.cnt){params.cnt=1;}

      if(!params.rate){params.rate=1;}

      var that=this,
          firstBeatToColor=[],
          secondBeatToColor=[];

      params.color.forEach(function(color){
        firstBeatToColor.push([color[0]*0.25, color[1]*0.25, color[2]*0.25]);
        secondBeatToColor.push([color[0]*0.1, color[1]*0.1, color[2]*0.1]);
      });

      this.fade({
          "from":params.color,
          "to":firstBeatToColor,
          "time":350/params.rate
        },function(r){
          var theOtherThing=that;
          that.fade({
            "from":params.color,
            "to":secondBeatToColor,
            "time":550/params.rate
          },function(r){
              PULSECNT++;
            if(PULSECNT>=params.cnt){
              responder(cb,[true,null,"heartbeat complete"]);
              PULSECNT=0;
            }else{
              setTimeout(function(){theOtherThing.heartbeat(params,cb);},200);
            }
          });
        });

    },

    /********************************************************
       BLINK
    ********************************************************/
    blink:function(params,cb){
      blinker.reset();
      if(!params.color){ responder(cb,[false,null,"missing heartbeat color"]); return;}
      if(typeof params.color[0]!=='object'){ params.color=[params.color]; }

      if(!params.cnt){params.cnt=1;}
      blinker.cnt=params.cnt*2;

      if(params.rate){ blinker.rate_on=params.rate; blinker.rate_off=params.rate;}else{
        if(!params.rate_on){params.rate_on=1;}
        blinker.rate_on=params.rate_on;

        if(!params.rate_off){params.rate_off=1;}
        blinker.rate_off=params.rate_off;
      }

      if(!params.color_fx){params.color_fx="set";}
      blinker.color_fx=params.color_fx;

      if(!params.blink_fx){params.blink_fx="sync";}
      blinker.blink_fx=params.blink_fx;

      if(cb){ blinker.cb=cb;}

      var interval=null,
          pixels=new Uint8ClampedArray(PIXELCNT*3);

      //We want to fill all the colors if the amount of color set in is less than the cnt of pixels
      var colorIndex=0;
      for(var p=0; p<pixels.length; p+=3){
        pixels[p]=params.color[colorIndex][0];
        pixels[p+1]=params.color[colorIndex][1];
        pixels[p+2]=params.color[colorIndex][2];

        colorIndex++;
        if(colorIndex>=params.color.length){ colorIndex=0; }
      }

      blinker.pixel_colors=pixels;

      blinker.blink();

    }

  };
};
<|endoftext|>


<commit_before>//@ sourceUrl=src/test/resources/scripts/test-renderer.js

function render(fruit, request, $, _) {
  console.log(arguments.length);
  $('ul > li').repeat(fruit, function(type, li) {
    li.text(type);
  });
  return $.markup();
}<commit_msg>Adds sourceURL to test-renderer.js for debugging :)<commit_after>//@ sourceURL=src/test/resources/scripts/test-renderer.js

function render(fruit, request, $, _) {
    $('ul > li').repeat(fruit, function (type, li) {
        li.text(type);
    });
    return $.markup();
}<|endoftext|>


<commit_before>import component from "./index.vue";
import assert from "assert";
import {WebGLRenderer} from "three";

const {computed, methods} = component;

describe("canvasコンポーネントのテスト", function() {
    describe("computedのテスト", function() {
        describe("_rendererのテスト", function() {
            it("メソッドの存在確認", function() {
                assert.equal(typeof computed._renderer, "function");
            });
            it("_rendererメソッドはWebGLRendererのインスタンスを返す", function() {
                const canvas = document.createElement("canvas");
                try {
                    if (!(window.WebGLRenderingContext && (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")))) {
                        // Skip test when WebGL disabled.
                        return;
                    };
                } catch (e) {
                    // Skip test when WebGL disabled.
        			return;
        		}
                const _this = {
                    $refs: {
                        canvas
                    }
                };
                const result = computed._renderer.apply(_this);
                assert(result instanceof WebGLRenderer);
            });
        });
    });
    describe("methodsのテスト", function() {
        describe("マウス・タッチハンドリング", function() {
            describe("panのテスト", function() {
                it("メソッドの存在確認", function() {
                    assert.equal(typeof methods.pan, "function");
                });
                it("this.translate2Dを呼び出す", function() {
                    const vm = {
                        count: 0,
                        translate2D(...args) {
                            ++this.count;
                            this.args = args;
                        }
                    };
                    methods.pan.call(vm, 10, 8.5);
                    assert.equal(vm.count, 1);
                    assert.equal(vm.args.length, 1);
                    assert.equal(vm.args[0][0], 10);
                    assert.equal(vm.args[0][1], -8.5);
                });
            });
            describe("orbitのテスト", function() {
                it("メソッドの存在確認", function() {
                    assert.equal(typeof methods.orbit, "function");
                });
                it("this.rotateを呼び出す", function() {
                    const vm = {
                        count: 0,
                        rotate(...args) {
                            ++this.count;
                            this.args = args;
                        }
                    };
                    methods.orbit.call(vm, 1, 2.2);
                    assert.equal(vm.count, 1);
                    assert.equal(vm.args.length, 1);
                    assert.equal(vm.args[0][0], 2.2);
                    assert.equal(vm.args[0][1], 1);
                });
            });
            describe("scaleのテスト", function() {
                it("メソッドの存在確認", function() {
                    assert.equal(typeof methods.scale, "function");
                });
                it("this.rotateを呼び出す", function() {
                    const vm = {
                        count: 0,
                        zoom(...args) {
                            ++this.count;
                            this.args = args;
                        }
                    };
                    methods.scale.call(vm, 1.1);
                    assert.equal(vm.count, 1);
                    assert.equal(vm.args.length, 1);
                    assert.equal(vm.args[0], 1.1);
                });
            });
            describe("mouseイベントの処理", function() {
                before(function() {
                    // IE11以下のため、マウスイベントコンストラクタのポリフィル
                    try {
                        new MouseEvent("test");
                        this.MouseEvent = MouseEvent;
                    } catch (e) {
                        this.MouseEvent = class extends Event {
                            constructor(eventType, params = {bubbles: false, cancelable: false}) {
                                super();
                                const mouseEvent = document.createEvent("MouseEvent");
                                mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                                return mouseEvent;
                            }
                        };
                    }
                });
                it("handleMousedownでマウスイベントをキャプチャ", function() {
                    const vm = {};
                    const e = new this.MouseEvent("mousedown");
                    methods.handleMousedown.call(vm, e);
                    assert.equal(vm.mouseEvent, e);
                });
                it("handleMousemoveでthis.panを呼び出す", function() {
                    const vm = {
                        mouseEvent: new this.MouseEvent("mousedown", {
                            clientX: 324,
                            clientY: 225
                        }),
                        count: 0,
                        pan(x, y) {
                            this.argX = x;
                            this.argY = y;
                            ++this.count;
                        }
                    };
                    methods.handleMousemove.call(vm, new this.MouseEvent("mousemove", {
                        clientX: 424,
                        clientY: 375
                    }));
                    assert.equal(vm.count, 1);
                    assert.equal(vm.argX, -100);
                    assert.equal(vm.argY, -150);
                });
                it("Ctrl押下時、handleMousemoveでthis.orbitを呼び出す", function() {
                    const vm = {
                        mouseEvent: new this.MouseEvent("mousedown", {
                            clientX: 324,
                            clientY: 225
                        }),
                        count: 0,
                        orbit(x, y) {
                            this.argX = x;
                            this.argY = y;
                            ++this.count;
                        }
                    };
                    methods.handleMousemove.call(vm, new this.MouseEvent("mousemove", {
                        clientX: 424,
                        clientY: 375,
                        ctrlKey: true
                    }));
                    assert.equal(vm.count, 1);
                    assert.equal(vm.argX, -100);
                    assert.equal(vm.argY, -150);
                });
                it("handleMouseupでマウスイベントをクリア", function() {
                    const vm = {
                        mouseEvent: new this.MouseEvent("mousemove")
                    };
                    methods.handleMouseup.call(vm, new this.MouseEvent("mouseup"));
                    assert.strictEqual(vm.mouseEvent, null);
                });
            });
        });
    });
});
<commit_msg>ポリフィルの修正<commit_after>import component from "./index.vue";
import assert from "assert";
import {WebGLRenderer} from "three";

const {computed, methods} = component;

describe("canvasコンポーネントのテスト", function() {
    describe("computedのテスト", function() {
        describe("_rendererのテスト", function() {
            it("メソッドの存在確認", function() {
                assert.equal(typeof computed._renderer, "function");
            });
            it("_rendererメソッドはWebGLRendererのインスタンスを返す", function() {
                const canvas = document.createElement("canvas");
                try {
                    if (!(window.WebGLRenderingContext && (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")))) {
                        // Skip test when WebGL disabled.
                        return;
                    };
                } catch (e) {
                    // Skip test when WebGL disabled.
        			return;
        		}
                const _this = {
                    $refs: {
                        canvas
                    }
                };
                const result = computed._renderer.apply(_this);
                assert(result instanceof WebGLRenderer);
            });
        });
    });
    describe("methodsのテスト", function() {
        describe("マウス・タッチハンドリング", function() {
            describe("panのテスト", function() {
                it("メソッドの存在確認", function() {
                    assert.equal(typeof methods.pan, "function");
                });
                it("this.translate2Dを呼び出す", function() {
                    const vm = {
                        count: 0,
                        translate2D(...args) {
                            ++this.count;
                            this.args = args;
                        }
                    };
                    methods.pan.call(vm, 10, 8.5);
                    assert.equal(vm.count, 1);
                    assert.equal(vm.args.length, 1);
                    assert.equal(vm.args[0][0], 10);
                    assert.equal(vm.args[0][1], -8.5);
                });
            });
            describe("orbitのテスト", function() {
                it("メソッドの存在確認", function() {
                    assert.equal(typeof methods.orbit, "function");
                });
                it("this.rotateを呼び出す", function() {
                    const vm = {
                        count: 0,
                        rotate(...args) {
                            ++this.count;
                            this.args = args;
                        }
                    };
                    methods.orbit.call(vm, 1, 2.2);
                    assert.equal(vm.count, 1);
                    assert.equal(vm.args.length, 1);
                    assert.equal(vm.args[0][0], 2.2);
                    assert.equal(vm.args[0][1], 1);
                });
            });
            describe("scaleのテスト", function() {
                it("メソッドの存在確認", function() {
                    assert.equal(typeof methods.scale, "function");
                });
                it("this.rotateを呼び出す", function() {
                    const vm = {
                        count: 0,
                        zoom(...args) {
                            ++this.count;
                            this.args = args;
                        }
                    };
                    methods.scale.call(vm, 1.1);
                    assert.equal(vm.count, 1);
                    assert.equal(vm.args.length, 1);
                    assert.equal(vm.args[0], 1.1);
                });
            });
            describe("mouseイベントの処理", function() {
                before(function() {
                    // IE11以下のため、マウスイベントコンストラクタのポリフィル
                    try {
                        new MouseEvent("test");
                        this.MouseEvent = MouseEvent;
                    } catch (e) {
                        this.MouseEvent = class extends Event {
                            constructor(eventType, params = {bubbles: false, cancelable: false}) {
                                super(eventType);
                                const mouseEvent = document.createEvent("MouseEvent");
                                mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                                return mouseEvent;
                            }
                        };
                    }
                });
                it("handleMousedownでマウスイベントをキャプチャ", function() {
                    const vm = {};
                    const e = new this.MouseEvent("mousedown");
                    methods.handleMousedown.call(vm, e);
                    assert.equal(vm.mouseEvent, e);
                });
                it("handleMousemoveでthis.panを呼び出す", function() {
                    const vm = {
                        mouseEvent: new this.MouseEvent("mousedown", {
                            clientX: 324,
                            clientY: 225
                        }),
                        count: 0,
                        pan(x, y) {
                            this.argX = x;
                            this.argY = y;
                            ++this.count;
                        }
                    };
                    methods.handleMousemove.call(vm, new this.MouseEvent("mousemove", {
                        clientX: 424,
                        clientY: 375
                    }));
                    assert.equal(vm.count, 1);
                    assert.equal(vm.argX, -100);
                    assert.equal(vm.argY, -150);
                });
                it("Ctrl押下時、handleMousemoveでthis.orbitを呼び出す", function() {
                    const vm = {
                        mouseEvent: new this.MouseEvent("mousedown", {
                            clientX: 324,
                            clientY: 225
                        }),
                        count: 0,
                        orbit(x, y) {
                            this.argX = x;
                            this.argY = y;
                            ++this.count;
                        }
                    };
                    methods.handleMousemove.call(vm, new this.MouseEvent("mousemove", {
                        clientX: 424,
                        clientY: 375,
                        ctrlKey: true
                    }));
                    assert.equal(vm.count, 1);
                    assert.equal(vm.argX, -100);
                    assert.equal(vm.argY, -150);
                });
                it("handleMouseupでマウスイベントをクリア", function() {
                    const vm = {
                        mouseEvent: new this.MouseEvent("mousemove")
                    };
                    methods.handleMouseup.call(vm, new this.MouseEvent("mouseup"));
                    assert.strictEqual(vm.mouseEvent, null);
                });
            });
        });
    });
});
<|endoftext|>