<commit_before>/**
 * TODO:
 * - [ ] Apply refined lifecycle from Aggregrid
 *      - [ ] repaintSubGrid -> repaintSubCells
 *      - [ ] new rendering flow
 * - [ ] Continuously update aggregate subRow groups after initial aggregation
 * - [ ] Continuously update subrow data cell renderings
 *
 * MAYBEDO:
 * - [ ] Move some of expander lifecycle up to base class
 */
Ext.define('Jarvus.aggregrid.RollupAggregrid', {
    extend: 'Jarvus.aggregrid.Aggregrid',
    xtype: 'jarvus-rollupaggregrid',

    config: {
        subRowsStore: null,
        subDataStore: null,

        parentRowMapper: 'parent_row_id',
        subRowMapper: 'sub_row_id',

        subRowHeaderField: 'title',
        subRowHeaderTpl: false,

        subCellTpl: '{[values.records && values.records.length || 0]}',
        subCellRenderer: false,

        expandable: true,
        expanderHeadersTpl: [
            '
',
                '
',
                    '<tpl for="subRows">',
                        '
',
                            '',
                                '',
                                    '{% values.rowHeaderTpl.applyOut(values, out, parent) %}',
                                '',
                            '	',
                        '
',
                    '</tpl>',
                '
',
            '
'
        ],
        expanderBodyTpl: [
            '
',
                '
',
                    '<tpl for="subRows">',
                        '
',
                            '<tpl for="columns">',
                                '{text}	',
                            '</tpl>',
                        '
',
                    '</tpl>',
                '
',
            '
'
        ]
    },

    // config handlers
    applySubRowsStore: function(store) {
        return Ext.StoreMgr.lookup(store);
    },

    // updateSubRowsStore: function(store, oldStore) {
    //     var me = this;

    //     if (oldStore) {
    //         oldStore.un('datachanged', 'refresh', me);
    //     }

    //     if (store) {
    //         me.refresh();
    //         store.on('datachanged', 'refresh', me);
    //     }
    // },

    applySubDataStore: function(store) {
        return Ext.StoreMgr.lookup(store);
    },

    // updateSubDataStore: function(store, oldStore) {
    //     var me = this,
    //         listeners = {
    //             scope: me,
    //             load: 'onDataStoreLoad',
    //             add: 'onDataStoreAdd',
    //             remove: 'onDataStoreRemove',
    //             update: 'onDataStoreUpdate'
    //         };

    //     if (oldStore) {
    //         oldStore.un(listeners);
    //     }

    //     if (store) {
    //         store.on(listeners);
    //     }
    // },

    applySubRowHeaderTpl: function(tpl) {
        if (!tpl) {
            tpl = new Ext.XTemplate(
                '{[typeof values === "string" ? values : values["' + this.getSubRowHeaderField() + '"]]}'
            );
        } else if (!tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    applyParentRowMapper: function(mapper) {
        if (!Ext.isString(mapper)) {
            return mapper;
        }

        return function(subRowRecord, rowsStore) {
            return rowsStore.getById(subRowRecord.get(mapper));
        };
    },

    applySubRowMapper: function(mapper) {
        if (!Ext.isString(mapper)) {
            return mapper;
        }

        return function(dataRecord, subRowsStore) {
            return subRowsStore.getById(dataRecord.get(mapper));
        };
    },

    applySubCellTpl: function(tpl) {
        if (tpl && !tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    applyExpanderHeadersTpl: function(tpl) {
        if (tpl && !tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    applyExpanderBodyTpl: function(tpl) {
        if (tpl && !tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    // event handlers

    // component methods
    doRefreshGrid: function(me) {
        var rollupRows = me.rollupRows = {},
            rowsStore = me.getRowsStore(),
            rowsCount = rowsStore.getCount(),
            rowIndex = 0, row, rowId;

        me.callParent(arguments);

        // initialize subrows data structure
        for (; rowIndex < rowsCount; rowIndex++) {
            row = rowsStore.getAt(rowIndex);
            rowId = row.getId();

            rollupRows[rowId] = {
                row: row,
                rowId: rowId,
                subRows: [],
                groups: {}
            };
        }
    },

    doExpand: function(me, rowId) {
        console.info('%s.doExpand(%o)', this.getId(), rowId);

        var rollupRow = me.rollupRows[rowId],
            expanderTplData = me.buildExpanderTplData(rowId);

        if (!rollupRow.cellsPainted) {
            rollupRow.headersEl = me.getExpanderHeadersTpl().overwrite(me.rowHeaderExpanderEls[rowId], expanderTplData, true);
            rollupRow.bodyEl = me.getExpanderBodyTpl().overwrite(me.rowExpanderEls[rowId], expanderTplData, true);

            me.afterExpanderRefresh(rowId);

            me.aggregateSubRows(rowId);

            me.fireEventedAction('repaintsubcells', [me, rowId], 'doRepaintSubCells', me);
        }

        me.callParent(arguments);
    },

    buildExpanderTplData: function(rowId) {
        var me = this,
            rowHeaderTpl = me.getSubRowHeaderTpl() || me.getRowHeaderTpl(),

            columnsStore = me.getColumnsStore(),
            columnsCount = columnsStore.getCount(),
            columnIndex = 0,

            subRows = me.getSubRows(rowId),
            subRowsCount = subRows.length,
            subRowIndex = 0,

            data = {},
            columnsData = data.columns = [],
            subRowsData = data.subRows = [];

        // generate columns and rows render data
        for (; columnIndex < columnsCount; columnIndex++) {
            columnsData.push(columnsStore.getAt(columnIndex).getData());
        }

        for (; subRowIndex < subRowsCount; subRowIndex++) {
            subRowsData.push(Ext.apply({
                rowHeaderTpl: rowHeaderTpl,
                columns: columnsData
            }, subRows[subRowIndex].getData()));
        }

        return data;
    },

    groupSubRows: function() {
        if (this.subRowParents) {
            return;
        }

        var me = this,
            rollupRows = me.rollupRows,
            subRowParents = me.subRowParents = {},

            rowsStore = me.getRowsStore(),
            subRowsStore = me.getSubRowsStore(),
            parentRowMapper = me.getParentRowMapper(),
            subRowsCount = subRowsStore.getCount(),
            subRowIndex = 0, subRow, parentRow;

        for (; subRowIndex < subRowsCount; subRowIndex++) {
            subRow = subRowsStore.getAt(subRowIndex);
            parentRow = parentRowMapper(subRow, rowsStore);

            subRowParents[subRow.getId()] = parentRow;
            rollupRows[parentRow.getId()].subRows.push(subRow);
        }
    },

    getSubRows: function(rowId) {
        this.groupSubRows();
        return this.rollupRows[rowId].subRows;
    },

    getParentRow: function(subRowId) {
        this.groupSubRows();
        return this.subRowParents[subRowId];
    },

    afterExpanderRefresh: function(rowId) {
        console.info('%s.afterExpanderRefresh(%o)', this.getId(), rowId);

        var me = this,
            rollupRow = me.rollupRows[rowId],
            headersEl = rollupRow.headersEl,
            bodyEl = rollupRow.bodyEl,
            groups = rollupRow.groups,

            subRowEls = rollupRow.subRowEls = {},
            subRowHeaderEls = rollupRow.subRowHeaderEls = {},

            subRows = rollupRow.subRows,
            subRowsCount = subRows.length,
            subRowIndex = 0, subRow, subRowId, subRowGroups, subRowEl,

            columnsStore = me.getColumnsStore(),
            columnsCount = columnsStore.getCount(),
            columnIndex, column, columnId,
            group;

        // READ phase: query dom to collect references to key elements
        for (; subRowIndex < subRowsCount; subRowIndex++) {
            subRow = subRows[subRowIndex];
            subRowId = subRow.getId();
            subRowGroups = groups[subRowId] || (groups[subRowId] = {});

            subRowHeaderEls[subRowId] = headersEl.down('.jarvus-aggregrid-subrow[data-subrow-id="'+subRowId+'"]');
            subRowEl = subRowEls[subRowId] = bodyEl.down('.jarvus-aggregrid-subrow[data-subrow-id="'+subRowId+'"]');

            for (columnIndex = 0; columnIndex < columnsCount; columnIndex++) {
                column = columnsStore.getAt(columnIndex);
                columnId = column.getId();

                group = subRowGroups[columnId] || (subRowGroups[columnId] = {});
                group.cellEl = subRowEl.down('.jarvus-aggregrid-cell[data-column-id="'+columnId+'"]');
                group.row = subRow;
                group.subRowId = subRowId;
                group.column = column;
                group.columnId = columnId;
            }
        }

        // READ->WRITE phase: sync row heights
        me.syncSubRowHeights(rowId);

        me.fireEvent('afterexpanderrefresh', me, rowId);
    },

    /**
     * @public
     * Synchronizes the heights of rows between the headers and data tables
     */
    syncSubRowHeights: function(rowId) {
        var me = this,
            rollupRow = me.rollupRows[rowId],
            subRowEls = rollupRow.subRowEls,
            subRowHeaderEls = rollupRow.subRowHeaderEls,
            table1RowHeights = {},
            table2RowHeights = {},
            rowKey, maxHeight;

        Ext.batchLayouts(function() {
            // read all the row height in batch first for both tables
            for (rowKey in subRowHeaderEls) { // eslint-disable-line guard-for-in
                table1RowHeights[rowKey] = subRowHeaderEls[rowKey].getHeight();
                table2RowHeights[rowKey] = subRowEls[rowKey].getHeight();
            }

            // write all the max row heights
            for (rowKey in subRowHeaderEls) { // eslint-disable-line guard-for-in
                maxHeight = Math.max(table1RowHeights[rowKey], table2RowHeights[rowKey]);
                subRowHeaderEls[rowKey].select('td, th').setHeight(maxHeight);
                subRowEls[rowKey].select('td, th').setHeight(maxHeight);
            }
        });
    },

    aggregateSubRows: function(rowId) {
        var me = this,
            store = me.getSubDataStore();

        if (!store || !store.isLoaded()) {
            return;
        }

        console.info('%s.aggregateSubRows(%o)', this.getId(), rowId);

        me.fireEventedAction('aggregatesubrows', [me, rowId], 'doAggregateSubRows', me);
    },

    doAggregateSubRows: function(me) {

        // guard against additional runs here rather than in aggregateSubRows(), child classes
        // may provide different implementations that use the rowId parameter to load rows individually
        if (me.groupedSubRecords) {
            return;
        }

        var rollupRows = me.rollupRows,
            groupedSubRecords = me.groupedSubRecords = {},
            subDataStore = me.getSubDataStore(),
            subRowsStore = me.getSubRowsStore(),
            columnsStore = me.getColumnsStore(),
            subRowMapper = me.getSubRowMapper(),
            columnMapper = me.getColumnMapper(),
            subRecordsCount = subDataStore.getCount(),
            subRecordIndex = 0, subRecord, subRecordId, parentRollupRow, subRecordGroupData,
            subRow, subRowId, parentRow, column, columnId, group, groupRecords;

        for (; subRecordIndex < subRecordsCount; subRecordIndex++) {
            subRecord = subDataStore.getAt(subRecordIndex);
            subRecordId = subRecord.getId();

            // get target row and column for this record
            subRow = subRowMapper(subRecord, subRowsStore);
            parentRow = subRow && me.getParentRow(subRow.getId());
            column = columnMapper(subRecord, columnsStore);

            if (!subRow || !parentRow || !column) {
                Ext.Logger.warn('Data record ' + subRecordId + ' not matched to ' + (!subRow ? 'subRow' : !parentRow ? 'parentRow' : 'column')); // eslint-disable-line no-negated-condition, no-nested-ternary
                continue;
            }

            // create metadata container for record indexed by its id
            subRecordGroupData = groupedSubRecords[subRecordId] = {
                record: subRecord,
                subRow: subRow,
                parentRow: parentRow,
                column: column
            };

            // push record to records array for group at [rowId][columnId]
            parentRollupRow = rollupRows[parentRow.getId()];
            group = parentRollupRow.groups;

            subRowId = subRow.getId();
            group = group[subRowId] || (group[subRowId] = {});

            columnId = column.getId();
            group = group[columnId] || (group[columnId] = {});
            groupRecords = group.records || (group.records = []);

            subRecordGroupData.group = group;
            groupRecords.push(subRecordGroupData);
        }
    },

    doRepaintSubCells: function(me, rowId) {
        console.info('%s.doRepaintSubCells(%o)', this.getId(), rowId);

        var rollupRow = me.rollupRows[rowId],
            groups = rollupRow.groups,
            subCellTpl = me.getSubCellTpl(),
            subCellRenderer = me.getSubCellRenderer(),
            subRowId, columns, columnId, group, cellEl;

        if (!subCellTpl && !subCellRenderer) {
            return;
        }

        rollupRow.cellsPainted = true;

        for (subRowId in groups) { // eslint-disable-line guard-for-in
            columns = groups[subRowId];

            for (columnId in columns) { // eslint-disable-line guard-for-in
                group = columns[columnId];
                cellEl = group.cellEl;

                if (subCellTpl) {
                    subCellTpl.overwrite(cellEl, group);
                }

                if (subCellRenderer) {
                    subCellRenderer.call(this, group, cellEl);
                }
            }
        }
    }
});<commit_msg>Upgrade repaintSubCells to new workflow from repaintCells<commit_after>/**
 * TODO:
 * - [ ] Apply refined lifecycle from Aggregrid
 *      - [ ] repaintSubGrid -> repaintSubCells
 *      - [ ] new rendering flow
 * - [ ] Continuously update aggregate subRow groups after initial aggregation
 * - [ ] Continuously update subrow data cell renderings
 *
 * MAYBEDO:
 * - [ ] Move some of expander lifecycle up to base class
 */
Ext.define('Jarvus.aggregrid.RollupAggregrid', {
    extend: 'Jarvus.aggregrid.Aggregrid',
    xtype: 'jarvus-rollupaggregrid',

    config: {
        subRowsStore: null,
        subDataStore: null,

        parentRowMapper: 'parent_row_id',
        subRowMapper: 'sub_row_id',

        subRowHeaderField: 'title',
        subRowHeaderTpl: false,

        subCellTpl: '{[values.records && values.records.length || 0]}',
        subCellRenderer: false,

        expandable: true,
        expanderHeadersTpl: [
            '
',
                '
',
                    '<tpl for="subRows">',
                        '
',
                            '',
                                '',
                                    '{% values.rowHeaderTpl.applyOut(values, out, parent) %}',
                                '',
                            '	',
                        '
',
                    '</tpl>',
                '
',
            '
'
        ],
        expanderBodyTpl: [
            '
',
                '
',
                    '<tpl for="subRows">',
                        '
',
                            '<tpl for="columns">',
                                '{text}	',
                            '</tpl>',
                        '
',
                    '</tpl>',
                '
',
            '
'
        ]
    },

    // config handlers
    applySubRowsStore: function(store) {
        return Ext.StoreMgr.lookup(store);
    },

    // updateSubRowsStore: function(store, oldStore) {
    //     var me = this;

    //     if (oldStore) {
    //         oldStore.un('datachanged', 'refresh', me);
    //     }

    //     if (store) {
    //         me.refresh();
    //         store.on('datachanged', 'refresh', me);
    //     }
    // },

    applySubDataStore: function(store) {
        return Ext.StoreMgr.lookup(store);
    },

    // updateSubDataStore: function(store, oldStore) {
    //     var me = this,
    //         listeners = {
    //             scope: me,
    //             load: 'onDataStoreLoad',
    //             add: 'onDataStoreAdd',
    //             remove: 'onDataStoreRemove',
    //             update: 'onDataStoreUpdate'
    //         };

    //     if (oldStore) {
    //         oldStore.un(listeners);
    //     }

    //     if (store) {
    //         store.on(listeners);
    //     }
    // },

    applySubRowHeaderTpl: function(tpl) {
        if (!tpl) {
            tpl = new Ext.XTemplate(
                '{[typeof values === "string" ? values : values["' + this.getSubRowHeaderField() + '"]]}'
            );
        } else if (!tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    applyParentRowMapper: function(mapper) {
        if (!Ext.isString(mapper)) {
            return mapper;
        }

        return function(subRowRecord, rowsStore) {
            return rowsStore.getById(subRowRecord.get(mapper));
        };
    },

    applySubRowMapper: function(mapper) {
        if (!Ext.isString(mapper)) {
            return mapper;
        }

        return function(dataRecord, subRowsStore) {
            return subRowsStore.getById(dataRecord.get(mapper));
        };
    },

    applySubCellTpl: function(tpl) {
        if (tpl && !tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    applyExpanderHeadersTpl: function(tpl) {
        if (tpl && !tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    applyExpanderBodyTpl: function(tpl) {
        if (tpl && !tpl.isTemplate) {
            tpl = new Ext.XTemplate(tpl);
        }

        return tpl;
    },

    // event handlers

    // component methods
    doRefreshGrid: function(me) {
        var rollupRows = me.rollupRows = {},
            rowsStore = me.getRowsStore(),
            rowsCount = rowsStore.getCount(),
            rowIndex = 0, row, rowId;

        me.callParent(arguments);

        // initialize subrows data structure
        for (; rowIndex < rowsCount; rowIndex++) {
            row = rowsStore.getAt(rowIndex);
            rowId = row.getId();

            rollupRows[rowId] = {
                row: row,
                rowId: rowId,
                subRows: [],
                groups: {}
            };
        }
    },

    doExpand: function(me, rowId) {
        console.info('%s.doExpand(%o)', this.getId(), rowId);

        var rollupRow = me.rollupRows[rowId],
            expanderTplData = me.buildExpanderTplData(rowId);

        if (!rollupRow.cellsPainted) {
            rollupRow.headersEl = me.getExpanderHeadersTpl().overwrite(me.rowHeaderExpanderEls[rowId], expanderTplData, true);
            rollupRow.bodyEl = me.getExpanderBodyTpl().overwrite(me.rowExpanderEls[rowId], expanderTplData, true);

            me.afterExpanderRefresh(rowId);

            me.aggregateSubRows(rowId);

            me.repaintSubCells(rowId);
        }

        me.callParent(arguments);
    },

    buildExpanderTplData: function(rowId) {
        var me = this,
            rowHeaderTpl = me.getSubRowHeaderTpl() || me.getRowHeaderTpl(),

            columnsStore = me.getColumnsStore(),
            columnsCount = columnsStore.getCount(),
            columnIndex = 0,

            subRows = me.getSubRows(rowId),
            subRowsCount = subRows.length,
            subRowIndex = 0,

            data = {},
            columnsData = data.columns = [],
            subRowsData = data.subRows = [];

        // generate columns and rows render data
        for (; columnIndex < columnsCount; columnIndex++) {
            columnsData.push(columnsStore.getAt(columnIndex).getData());
        }

        for (; subRowIndex < subRowsCount; subRowIndex++) {
            subRowsData.push(Ext.apply({
                rowHeaderTpl: rowHeaderTpl,
                columns: columnsData
            }, subRows[subRowIndex].getData()));
        }

        return data;
    },

    groupSubRows: function() {
        if (this.subRowParents) {
            return;
        }

        var me = this,
            rollupRows = me.rollupRows,
            subRowParents = me.subRowParents = {},

            rowsStore = me.getRowsStore(),
            subRowsStore = me.getSubRowsStore(),
            parentRowMapper = me.getParentRowMapper(),
            subRowsCount = subRowsStore.getCount(),
            subRowIndex = 0, subRow, parentRow;

        for (; subRowIndex < subRowsCount; subRowIndex++) {
            subRow = subRowsStore.getAt(subRowIndex);
            parentRow = parentRowMapper(subRow, rowsStore);

            subRowParents[subRow.getId()] = parentRow;
            rollupRows[parentRow.getId()].subRows.push(subRow);
        }
    },

    getSubRows: function(rowId) {
        this.groupSubRows();
        return this.rollupRows[rowId].subRows;
    },

    getParentRow: function(subRowId) {
        this.groupSubRows();
        return this.subRowParents[subRowId];
    },

    afterExpanderRefresh: function(rowId) {
        console.info('%s.afterExpanderRefresh(%o)', this.getId(), rowId);

        var me = this,
            rollupRow = me.rollupRows[rowId],
            headersEl = rollupRow.headersEl,
            bodyEl = rollupRow.bodyEl,
            groups = rollupRow.groups,

            subRowEls = rollupRow.subRowEls = {},
            subRowHeaderEls = rollupRow.subRowHeaderEls = {},

            subRows = rollupRow.subRows,
            subRowsCount = subRows.length,
            subRowIndex = 0, subRow, subRowId, subRowGroups, subRowEl,

            columnsStore = me.getColumnsStore(),
            columnsCount = columnsStore.getCount(),
            columnIndex, column, columnId,
            group;

        // READ phase: query dom to collect references to key elements
        for (; subRowIndex < subRowsCount; subRowIndex++) {
            subRow = subRows[subRowIndex];
            subRowId = subRow.getId();
            subRowGroups = groups[subRowId] || (groups[subRowId] = {});

            subRowHeaderEls[subRowId] = headersEl.down('.jarvus-aggregrid-subrow[data-subrow-id="'+subRowId+'"]');
            subRowEl = subRowEls[subRowId] = bodyEl.down('.jarvus-aggregrid-subrow[data-subrow-id="'+subRowId+'"]');

            for (columnIndex = 0; columnIndex < columnsCount; columnIndex++) {
                column = columnsStore.getAt(columnIndex);
                columnId = column.getId();

                group = subRowGroups[columnId] || (subRowGroups[columnId] = {});
                group.cellEl = subRowEl.down('.jarvus-aggregrid-cell[data-column-id="'+columnId+'"]');
                group.row = subRow;
                group.subRowId = subRowId;
                group.column = column;
                group.columnId = columnId;
            }
        }

        // READ->WRITE phase: sync row heights
        me.syncSubRowHeights(rowId);

        me.fireEvent('afterexpanderrefresh', me, rowId);
    },

    /**
     * @public
     * Synchronizes the heights of rows between the headers and data tables
     */
    syncSubRowHeights: function(rowId) {
        var me = this,
            rollupRow = me.rollupRows[rowId],
            subRowEls = rollupRow.subRowEls,
            subRowHeaderEls = rollupRow.subRowHeaderEls,
            table1RowHeights = {},
            table2RowHeights = {},
            rowKey, maxHeight;

        Ext.batchLayouts(function() {
            // read all the row height in batch first for both tables
            for (rowKey in subRowHeaderEls) { // eslint-disable-line guard-for-in
                table1RowHeights[rowKey] = subRowHeaderEls[rowKey].getHeight();
                table2RowHeights[rowKey] = subRowEls[rowKey].getHeight();
            }

            // write all the max row heights
            for (rowKey in subRowHeaderEls) { // eslint-disable-line guard-for-in
                maxHeight = Math.max(table1RowHeights[rowKey], table2RowHeights[rowKey]);
                subRowHeaderEls[rowKey].select('td, th').setHeight(maxHeight);
                subRowEls[rowKey].select('td, th').setHeight(maxHeight);
            }
        });
    },

    aggregateSubRows: function(rowId) {
        var me = this,
            store = me.getSubDataStore();

        if (!store || !store.isLoaded()) {
            return;
        }

        console.info('%s.aggregateSubRows(%o)', this.getId(), rowId);

        me.fireEventedAction('aggregatesubrows', [me, rowId], 'doAggregateSubRows', me);
    },

    doAggregateSubRows: function(me) {

        // guard against additional runs here rather than in aggregateSubRows(), child classes
        // may provide different implementations that use the rowId parameter to load rows individually
        if (me.groupedSubRecords) {
            return;
        }

        var rollupRows = me.rollupRows,
            groupedSubRecords = me.groupedSubRecords = {},
            subDataStore = me.getSubDataStore(),
            subRowsStore = me.getSubRowsStore(),
            columnsStore = me.getColumnsStore(),
            subRowMapper = me.getSubRowMapper(),
            columnMapper = me.getColumnMapper(),
            subRecordsCount = subDataStore.getCount(),
            subRecordIndex = 0, subRecord, subRecordId, parentRollupRow, subRecordGroupData,
            subRow, subRowId, parentRow, column, columnId, group, groupRecords;

        for (; subRecordIndex < subRecordsCount; subRecordIndex++) {
            subRecord = subDataStore.getAt(subRecordIndex);
            subRecordId = subRecord.getId();

            // get target row and column for this record
            subRow = subRowMapper(subRecord, subRowsStore);
            parentRow = subRow && me.getParentRow(subRow.getId());
            column = columnMapper(subRecord, columnsStore);

            if (!subRow || !parentRow || !column) {
                Ext.Logger.warn('Data record ' + subRecordId + ' not matched to ' + (!subRow ? 'subRow' : !parentRow ? 'parentRow' : 'column')); // eslint-disable-line no-negated-condition, no-nested-ternary
                continue;
            }

            // create metadata container for record indexed by its id
            subRecordGroupData = groupedSubRecords[subRecordId] = {
                record: subRecord,
                subRow: subRow,
                parentRow: parentRow,
                column: column
            };

            // push record to records array for group at [rowId][columnId]
            parentRollupRow = rollupRows[parentRow.getId()];
            group = parentRollupRow.groups;

            subRowId = subRow.getId();
            group = group[subRowId] || (group[subRowId] = {});

            columnId = column.getId();
            group = group[columnId] || (group[columnId] = {});
            groupRecords = group.records || (group.records = []);

            subRecordGroupData.group = group;
            groupRecords.push(subRecordGroupData);
        }
    },

    repaintSubCells: function(rowId) {
        var me = this,
            bufferedRepaintSubCells = me.bufferedRepaintSubCells || (me.bufferedRepaintSubCells = {}),
            repaint = bufferedRepaintSubCells[rowId];

        if (!repaint) {
            repaint = bufferedRepaintSubCells[rowId] = Ext.Function.createBuffered(me.fireEventedAction, 10, me, ['repaintsubcells', [me, rowId], 'doRepaintSubCells', me]);
        }

        repaint();
    },

    doRepaintSubCells: function(me, rowId) {
        console.info('%s.doRepaintSubCells(%o)', this.getId(), rowId);

        var rollupRow = me.rollupRows[rowId],
            groups = rollupRow.groups,
            subCellTpl = me.getSubCellTpl(),
            subCellRenderer = me.getSubCellRenderer(),
            subRowId, columns, columnId, group, cellEl, rendered, dirty;

        if (!subCellTpl && !subCellRenderer) {
            return;
        }

        rollupRow.cellsPainted = true;

        for (subRowId in groups) { // eslint-disable-line guard-for-in
            columns = groups[subRowId];

            for (columnId in columns) { // eslint-disable-line guard-for-in
                group = columns[columnId];
                cellEl = group.cellEl;
                rendered = group.rendered;
                dirty = group.dirty;

                // apply cellTpl if this is the first render OR there's no cellRenderer and the group is dirty
                if (!rendered || (!subCellRenderer && dirty)) {
                    group.tplNode = subCellTpl && subCellTpl.overwrite(cellEl, group);
                }

                if (!rendered || dirty) {
                    group.rendered = subCellRenderer && subCellRenderer.call(me, group, cellEl, rendered || false) || true;
                    group.dirty = false;
                }
            }
        }
    }
});<|endoftext|>


<commit_before>/** A remote change to be send to Prep/Merge.
 *
 * @module core/remote/change
 * @flow
 */

/*::
import type { RemoteDoc, RemoteDeletion } from './document'
import type { Metadata } from '../metadata'
*/

const path = require('path')

const metadata = require('../metadata')

/*::
export type RemoteFileAddition = {
  sideName: 'remote',
  type: 'FileAddition',
  doc: Metadata
}
export type RemoteFileDeletion = {
  sideName: 'remote',
  type: 'FileDeletion',
  doc: Metadata
}
export type RemoteFileMove = {
  sideName: 'remote',
  type: 'FileMove',
  doc: Metadata,
  was: Metadata,
  needRefetch?: true,
  update?: true
}
export type RemoteFileRestoration = {
  sideName: 'remote',
  type: 'FileRestoration',
  doc: Metadata,
  was: Metadata
}
export type RemoteFileTrashing = {
  sideName: 'remote',
  type: 'FileTrashing',
  doc: Metadata,
  was: Metadata
}
export type RemoteFileUpdate = {
  sideName: 'remote',
  type: 'FileUpdate',
  doc: Metadata
}
export type RemoteDirAddition = {
  sideName: 'remote',
  type: 'DirAddition',
  doc: Metadata
}
export type RemoteDirDeletion = {
  sideName: 'remote',
  type: 'DirDeletion',
  doc: Metadata
}
export type RemoteDirMove = {
  sideName: 'remote',
  type: 'DirMove',
  doc: Metadata,
  was: Metadata,
  needRefetch?: true,
  descendantMoves?: RemoteDescendantChange[]
}
export type RemoteDirRestoration = {
  sideName: 'remote',
  type: 'DirRestoration',
  doc: Metadata,
  was: Metadata
}
export type RemoteDirTrashing = {
  sideName: 'remote',
  type: 'DirTrashing',
  doc: Metadata,
  was: Metadata
}
export type RemoteIgnoredChange = {
  sideName: 'remote',
  type: 'IgnoredChange',
  doc: Metadata|RemoteDoc|RemoteDeletion,
  detail: string
}
export type RemoteInvalidChange = {
  sideName: 'remote',
  type: 'InvalidChange',
  doc: *,
  was?: Metadata,
  error: Error
}
export type RemoteUpToDate = {
  sideName: 'remote',
  type: 'UpToDate',
  doc: Metadata,
  was: Metadata
}
export type RemoteDescendantChange = {
  sideName: 'remote',
  type: 'DescendantChange',
  doc: Metadata,
  was: Metadata,
  ancestorPath: string,
  descendantMoves?: RemoteDescendantChange[],
  update?: true
}

export type RemoteChange =
  | RemoteDirAddition
  | RemoteDirDeletion
  | RemoteDirMove
  | RemoteDirRestoration
  | RemoteDirTrashing
  | RemoteFileAddition
  | RemoteFileDeletion
  | RemoteFileMove
  | RemoteFileRestoration
  | RemoteFileTrashing
  | RemoteFileUpdate
  | RemoteIgnoredChange
  | RemoteDescendantChange
  | RemoteInvalidChange
  | RemoteUpToDate
*/

module.exports = {
  added,
  trashed,
  deleted,
  restored,
  upToDate,
  updated,
  isChildMove,
  isOnlyChildMove,
  applyMoveToPath,
  includeDescendant,
  applyMoveInsideMove,
  sort
}

const sideName = 'remote'

// FIXME: return types
function added(
  doc /*: Metadata */
) /*: RemoteFileAddition | RemoteDirAddition */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileAddition',
      doc
    }
  } else {
    return {
      sideName,
      type: 'DirAddition',
      doc
    }
  }
}

function trashed(
  doc /*: Metadata */,
  was /*: Metadata */
) /*: RemoteFileTrashing | RemoteDirTrashing */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileTrashing',
      doc,
      was
    }
  } else {
    return {
      sideName,
      type: 'DirTrashing',
      doc,
      was
    }
  }
}

function deleted(
  doc /*: Metadata */
) /*: RemoteFileDeletion | RemoteDirDeletion */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileDeletion',
      doc
    }
  } else {
    return {
      sideName,
      type: 'DirDeletion',
      doc
    }
  }
}

function restored(
  doc /*: Metadata */,
  was /*: Metadata */
) /*: RemoteFileRestoration | RemoteDirRestoration */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileRestoration',
      doc,
      was
    }
  } else {
    return {
      sideName,
      type: 'DirRestoration',
      doc,
      was
    }
  }
}

function upToDate(
  doc /*: Metadata */,
  was /*: Metadata */
) /*: RemoteUpToDate */ {
  return { sideName, type: 'UpToDate', doc, was }
}

function updated(
  doc /*: Metadata */
) /*: RemoteFileUpdate | RemoteDirAddition */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileUpdate',
      doc
    }
  } else {
    return {
      sideName,
      type: 'DirAddition',
      doc
    }
  }
}

// TODO: Rename args
function isChildMove(
  a /*: RemoteChange */,
  b /*: RemoteChange */
) /*: boolean %checks */ {
  return (
    a.type === 'DirMove' &&
    (b.type === 'DirMove' || b.type === 'FileMove') &&
    b.doc.path.startsWith(a.doc.path + path.sep) &&
    a.was &&
    b.was &&
    b.was.path.startsWith(a.was.path + path.sep)
  )
}

/**
 *          was          doc
 *     a    /a     ->    /a2
 *     b    /a/b   ->    /a2/b
 */
function isOnlyChildMove(
  a /*: RemoteDirMove */,
  b /*: RemoteFileMove|RemoteDirMove */
) /*: boolean %checks */ {
  return (
    isChildMove(a, b) && path.basename(b.doc.path) === path.basename(b.was.path)
  )
}

function applyMoveToPath(
  a /*: RemoteDirMove */,
  p /*: string */
) /*: string */ {
  return p.replace(a.was.path, a.doc.path)
}

function applyMoveInsideMove(
  parentMove /*: RemoteDirMove */,
  childMove /*: RemoteDirMove | RemoteFileMove */
) {
  childMove.was.path = applyMoveToPath(parentMove, childMove.was.path)
  childMove.needRefetch = true
}

const isDelete = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirDeletion' || a.type === 'FileDeletion'
const isAdd = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirAddition' || a.type === 'FileAddition'
const isMove = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirMove' || a.type === 'FileMove' || a.type === 'DescendantChange'
const isTrash = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirTrashing' || a.type === 'FileTrashing'
const isRestore = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirRestoration' || a.type === 'FileRestoration'
const isIgnore = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'IgnoredChange'

function includeDescendant(
  parent /*: RemoteDirMove */,
  e /*: RemoteDescendantChange */
) {
  parent.descendantMoves = parent.descendantMoves || []
  parent.descendantMoves.push(e, ...(e.descendantMoves || []))
  delete e.descendantMoves
}

const createdId = (a /*: RemoteChange */) /*: ?string */ =>
  isAdd(a) || isMove(a) || isRestore(a) ? metadata.id(a.doc.path) : null
const deletedId = (a /*: RemoteChange */) /*: ?string */ =>
  isDelete(a)
    ? metadata.id(a.doc.path)
    : isMove(a) || isTrash(a)
    ? metadata.id(a.was.path)
    : null
const ignoredId = (a /*: RemoteChange */) /*: ?string */ =>
  isIgnore(a) && typeof a.doc.path === 'string' ? metadata.id(a.doc.path) : null
const areParentChild = (p /*: ?string */, c /*: ?string */) /*: boolean */ =>
  !!p && !!c && c.startsWith(p + path.sep)
const lower = (p1 /*: ?string */, p2 /*: ?string */) /*: boolean */ =>
  !!p1 && !!p2 && p1 < p2

const aFirst = -1
const bFirst = 1

const sorter = (a, b) => {
  // if there is one ignored change, it is put back to the end
  if (ignoredId(a) && !ignoredId(b)) return bFirst
  if (ignoredId(b) && !ignoredId(a)) return aFirst
  if (lower(ignoredId(a), ignoredId(b))) return aFirst
  if (lower(ignoredId(b), ignoredId(a))) return bFirst

  // if one action is the parent of another, it takes priority
  if (areParentChild(createdId(a), createdId(b))) return aFirst
  if (areParentChild(createdId(b), createdId(a))) return bFirst
  if (areParentChild(deletedId(b), deletedId(a))) return aFirst
  if (areParentChild(deletedId(a), deletedId(b))) return bFirst
  if (areParentChild(createdId(a), deletedId(b))) return aFirst
  if (areParentChild(createdId(b), deletedId(a))) return bFirst
  if (areParentChild(deletedId(a), createdId(b))) return bFirst
  if (areParentChild(deletedId(b), createdId(a))) return aFirst

  if (deletedId(a) && createdId(b) && deletedId(a) === createdId(b))
    return aFirst
  if (deletedId(b) && createdId(a) && deletedId(b) === createdId(a))
    return bFirst

  // otherwise, order by add path
  if (lower(createdId(a), createdId(b))) return aFirst
  if (lower(createdId(b), createdId(a))) return bFirst

  // if there isnt 2 add paths, sort by del path
  if (lower(deletedId(b), deletedId(a))) return aFirst
  return bFirst
}

function sort(changes /*: Array<RemoteChange> */) /*: void */ {
  changes.sort(sorter)
}
<commit_msg>core/remote/change: Refactor is*ChildMove args<commit_after>/** A remote change to be send to Prep/Merge.
 *
 * @module core/remote/change
 * @flow
 */

/*::
import type { RemoteDoc, RemoteDeletion } from './document'
import type { Metadata } from '../metadata'
*/

const path = require('path')

const metadata = require('../metadata')

/*::
export type RemoteFileAddition = {
  sideName: 'remote',
  type: 'FileAddition',
  doc: Metadata
}
export type RemoteFileDeletion = {
  sideName: 'remote',
  type: 'FileDeletion',
  doc: Metadata
}
export type RemoteFileMove = {
  sideName: 'remote',
  type: 'FileMove',
  doc: Metadata,
  was: Metadata,
  needRefetch?: true,
  update?: true
}
export type RemoteFileRestoration = {
  sideName: 'remote',
  type: 'FileRestoration',
  doc: Metadata,
  was: Metadata
}
export type RemoteFileTrashing = {
  sideName: 'remote',
  type: 'FileTrashing',
  doc: Metadata,
  was: Metadata
}
export type RemoteFileUpdate = {
  sideName: 'remote',
  type: 'FileUpdate',
  doc: Metadata
}
export type RemoteDirAddition = {
  sideName: 'remote',
  type: 'DirAddition',
  doc: Metadata
}
export type RemoteDirDeletion = {
  sideName: 'remote',
  type: 'DirDeletion',
  doc: Metadata
}
export type RemoteDirMove = {
  sideName: 'remote',
  type: 'DirMove',
  doc: Metadata,
  was: Metadata,
  needRefetch?: true,
  descendantMoves?: RemoteDescendantChange[]
}
export type RemoteDirRestoration = {
  sideName: 'remote',
  type: 'DirRestoration',
  doc: Metadata,
  was: Metadata
}
export type RemoteDirTrashing = {
  sideName: 'remote',
  type: 'DirTrashing',
  doc: Metadata,
  was: Metadata
}
export type RemoteIgnoredChange = {
  sideName: 'remote',
  type: 'IgnoredChange',
  doc: Metadata|RemoteDoc|RemoteDeletion,
  detail: string
}
export type RemoteInvalidChange = {
  sideName: 'remote',
  type: 'InvalidChange',
  doc: *,
  was?: Metadata,
  error: Error
}
export type RemoteUpToDate = {
  sideName: 'remote',
  type: 'UpToDate',
  doc: Metadata,
  was: Metadata
}
export type RemoteDescendantChange = {
  sideName: 'remote',
  type: 'DescendantChange',
  doc: Metadata,
  was: Metadata,
  ancestorPath: string,
  descendantMoves?: RemoteDescendantChange[],
  update?: true
}

export type RemoteChange =
  | RemoteDirAddition
  | RemoteDirDeletion
  | RemoteDirMove
  | RemoteDirRestoration
  | RemoteDirTrashing
  | RemoteFileAddition
  | RemoteFileDeletion
  | RemoteFileMove
  | RemoteFileRestoration
  | RemoteFileTrashing
  | RemoteFileUpdate
  | RemoteIgnoredChange
  | RemoteDescendantChange
  | RemoteInvalidChange
  | RemoteUpToDate
*/

module.exports = {
  added,
  trashed,
  deleted,
  restored,
  upToDate,
  updated,
  isChildMove,
  isOnlyChildMove,
  applyMoveToPath,
  includeDescendant,
  applyMoveInsideMove,
  sort
}

const sideName = 'remote'

// FIXME: return types
function added(
  doc /*: Metadata */
) /*: RemoteFileAddition | RemoteDirAddition */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileAddition',
      doc
    }
  } else {
    return {
      sideName,
      type: 'DirAddition',
      doc
    }
  }
}

function trashed(
  doc /*: Metadata */,
  was /*: Metadata */
) /*: RemoteFileTrashing | RemoteDirTrashing */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileTrashing',
      doc,
      was
    }
  } else {
    return {
      sideName,
      type: 'DirTrashing',
      doc,
      was
    }
  }
}

function deleted(
  doc /*: Metadata */
) /*: RemoteFileDeletion | RemoteDirDeletion */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileDeletion',
      doc
    }
  } else {
    return {
      sideName,
      type: 'DirDeletion',
      doc
    }
  }
}

function restored(
  doc /*: Metadata */,
  was /*: Metadata */
) /*: RemoteFileRestoration | RemoteDirRestoration */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileRestoration',
      doc,
      was
    }
  } else {
    return {
      sideName,
      type: 'DirRestoration',
      doc,
      was
    }
  }
}

function upToDate(
  doc /*: Metadata */,
  was /*: Metadata */
) /*: RemoteUpToDate */ {
  return { sideName, type: 'UpToDate', doc, was }
}

function updated(
  doc /*: Metadata */
) /*: RemoteFileUpdate | RemoteDirAddition */ {
  if (metadata.isFile(doc)) {
    return {
      sideName,
      type: 'FileUpdate',
      doc
    }
  } else {
    return {
      sideName,
      type: 'DirAddition',
      doc
    }
  }
}

function isChildMove(
  p /*: RemoteChange */,
  c /*: RemoteChange */
) /*: boolean %checks */ {
  return (
    p.type === 'DirMove' &&
    (c.type === 'DirMove' || c.type === 'FileMove') &&
    c.doc.path.startsWith(p.doc.path + path.sep) &&
    p.was &&
    c.was &&
    c.was.path.startsWith(p.was.path + path.sep)
  )
}

/**
 *          was          doc
 *     p    /p     ->    /p2
 *     c    /p/c   ->    /p2/c
 */
function isOnlyChildMove(
  p /*: RemoteDirMove */,
  c /*: RemoteFileMove|RemoteDirMove */
) /*: boolean %checks */ {
  return (
    isChildMove(p, c) && path.basename(c.doc.path) === path.basename(c.was.path)
  )
}

function applyMoveToPath(
  a /*: RemoteDirMove */,
  p /*: string */
) /*: string */ {
  return p.replace(a.was.path, a.doc.path)
}

function applyMoveInsideMove(
  parentMove /*: RemoteDirMove */,
  childMove /*: RemoteDirMove | RemoteFileMove */
) {
  childMove.was.path = applyMoveToPath(parentMove, childMove.was.path)
  childMove.needRefetch = true
}

const isDelete = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirDeletion' || a.type === 'FileDeletion'
const isAdd = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirAddition' || a.type === 'FileAddition'
const isMove = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirMove' || a.type === 'FileMove' || a.type === 'DescendantChange'
const isTrash = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirTrashing' || a.type === 'FileTrashing'
const isRestore = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'DirRestoration' || a.type === 'FileRestoration'
const isIgnore = (a /*: RemoteChange */) /*: boolean %checks */ =>
  a.type === 'IgnoredChange'

function includeDescendant(
  parent /*: RemoteDirMove */,
  e /*: RemoteDescendantChange */
) {
  parent.descendantMoves = parent.descendantMoves || []
  parent.descendantMoves.push(e, ...(e.descendantMoves || []))
  delete e.descendantMoves
}

const createdId = (a /*: RemoteChange */) /*: ?string */ =>
  isAdd(a) || isMove(a) || isRestore(a) ? metadata.id(a.doc.path) : null
const deletedId = (a /*: RemoteChange */) /*: ?string */ =>
  isDelete(a)
    ? metadata.id(a.doc.path)
    : isMove(a) || isTrash(a)
    ? metadata.id(a.was.path)
    : null
const ignoredId = (a /*: RemoteChange */) /*: ?string */ =>
  isIgnore(a) && typeof a.doc.path === 'string' ? metadata.id(a.doc.path) : null
const areParentChild = (p /*: ?string */, c /*: ?string */) /*: boolean */ =>
  !!p && !!c && c.startsWith(p + path.sep)
const lower = (p1 /*: ?string */, p2 /*: ?string */) /*: boolean */ =>
  !!p1 && !!p2 && p1 < p2

const aFirst = -1
const bFirst = 1

const sorter = (a, b) => {
  // if there is one ignored change, it is put back to the end
  if (ignoredId(a) && !ignoredId(b)) return bFirst
  if (ignoredId(b) && !ignoredId(a)) return aFirst
  if (lower(ignoredId(a), ignoredId(b))) return aFirst
  if (lower(ignoredId(b), ignoredId(a))) return bFirst

  // if one action is the parent of another, it takes priority
  if (areParentChild(createdId(a), createdId(b))) return aFirst
  if (areParentChild(createdId(b), createdId(a))) return bFirst
  if (areParentChild(deletedId(b), deletedId(a))) return aFirst
  if (areParentChild(deletedId(a), deletedId(b))) return bFirst
  if (areParentChild(createdId(a), deletedId(b))) return aFirst
  if (areParentChild(createdId(b), deletedId(a))) return bFirst
  if (areParentChild(deletedId(a), createdId(b))) return bFirst
  if (areParentChild(deletedId(b), createdId(a))) return aFirst

  if (deletedId(a) && createdId(b) && deletedId(a) === createdId(b))
    return aFirst
  if (deletedId(b) && createdId(a) && deletedId(b) === createdId(a))
    return bFirst

  // otherwise, order by add path
  if (lower(createdId(a), createdId(b))) return aFirst
  if (lower(createdId(b), createdId(a))) return bFirst

  // if there isnt 2 add paths, sort by del path
  if (lower(deletedId(b), deletedId(a))) return aFirst
  return bFirst
}

function sort(changes /*: Array<RemoteChange> */) /*: void */ {
  changes.sort(sorter)
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var Url = require('url');

exports.NodeBinaryHttpTransport = function(url) {
  var self = this;
  var http = require('http');
  var https = require('https');

  this.url = url;
  this.buffer = [];
  this.received = null;
  this.offset = 0;

	this.open = function () {
	};

	this.close = function () {
	};

  this.read = function (len) {
    var view = new DataView(this.received, this.offset, len);
    this.offset += len;
    return view;
  };

	this.write = function (bytes) {
    this.buffer.push(bytes);
	};

  this.flush = function (async) {
    if (!async) throw 'Error in NodeBinaryHttpTransport.flush: Binary protocol does not support synchronous calls';

    var size = this.buffer.reduce(function (size, bytes) {
      return size + bytes.byteLength;
    }, 0);

    var ab = new ArrayBuffer(size);
    var allbytes = new Uint8Array(ab);
    var pos = 0;
    this.buffer.forEach(function (bytes) {
      var view = null;
      if (bytes.buffer) view = (bytes instanceof Uint8Array) ? bytes : new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
      else view = new Uint8Array(bytes);

      allbytes.set(view, pos);
      pos += bytes.byteLength;
    });

    this.buffer = [];

    return ab
  };

  this.send = function (client, postData, args, recv_method) {
    args = Array.prototype.slice.call(args, 0);
    var onerror = args.pop();
    var callback = args.length > 0 ? args.pop() : onerror;
    if (typeof callback !== 'function') callback = onerror;

    var purl = Url.parse(this.url);
    var options = {
      hostname: purl['host'],
      port: purl['protocol'] == 'https' ? 443 : 80,
      path: purl['path'],
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-thrift',
        'Accept': 'application/x-thrift'
      }
    };
    var doRequest = (purl['protocol'] == 'https' ? https : http).request

    var req = doRequest(options, function(res) {
      var data = [], dataLength = 0;
      res.on('data', function(chunk) {
        data.push(chunk);
        dataLength += chunk.length;
      });

      res.on('end', function() {
        var buffer = new Buffer(dataLength);
        for (var i = 0, len = data.length, pos = 0; i < len; i++) {
          data[i].copy(buffer, pos);
          pos += data[i].length;
        }
        self.received = bufferToArrayBuffer(buffer);
        callback(recv_method.call(client));
      });
    });

    req.on('error', function(e) {
      onerror(e);
    });

    req.write(arrayBufferToBuffer(postData));
    req.end();
  };

  var arrayBufferToBuffer = function(ab) {
    var buffer = new Buffer(ab.byteLength);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
      buffer[i] = view[i];
    }
    return buffer;
  };

  var bufferToArrayBuffer = function(buffer) {
    var ab = new ArrayBuffer(buffer.length);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
      view[i] = buffer[i];
    }
    return ab;
  };

};

<commit_msg>Handle exceptions on receive methods<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var Url = require('url');

exports.NodeBinaryHttpTransport = function(url) {
  var self = this;
  var http = require('http');
  var https = require('https');

  this.url = url;
  this.buffer = [];
  this.received = null;
  this.offset = 0;

	this.open = function () {
	};

	this.close = function () {
	};

  this.read = function (len) {
    var view = new DataView(this.received, this.offset, len);
    this.offset += len;
    return view;
  };

	this.write = function (bytes) {
    this.buffer.push(bytes);
	};

  this.flush = function (async) {
    if (!async) throw 'Error in NodeBinaryHttpTransport.flush: Binary protocol does not support synchronous calls';

    var size = this.buffer.reduce(function (size, bytes) {
      return size + bytes.byteLength;
    }, 0);

    var ab = new ArrayBuffer(size);
    var allbytes = new Uint8Array(ab);
    var pos = 0;
    this.buffer.forEach(function (bytes) {
      var view = null;
      if (bytes.buffer) view = (bytes instanceof Uint8Array) ? bytes : new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
      else view = new Uint8Array(bytes);

      allbytes.set(view, pos);
      pos += bytes.byteLength;
    });

    this.buffer = [];

    return ab
  };

  this.send = function (client, postData, args, recv_method) {
    args = Array.prototype.slice.call(args, 0);
    var onerror = args.pop();
    var callback = args.length > 0 ? args.pop() : onerror;
    if (typeof callback !== 'function') callback = onerror;

    var purl = Url.parse(this.url);
    var options = {
      hostname: purl['host'],
      port: purl['protocol'] == 'https' ? 443 : 80,
      path: purl['path'],
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-thrift',
        'Accept': 'application/x-thrift'
      }
    };
    var doRequest = (purl['protocol'] == 'https' ? https : http).request

    var req = doRequest(options, function(res) {
      var data = [], dataLength = 0;
      res.on('data', function(chunk) {
        data.push(chunk);
        dataLength += chunk.length;
      });

      res.on('end', function() {
        var buffer = new Buffer(dataLength);
        for (var i = 0, len = data.length, pos = 0; i < len; i++) {
          data[i].copy(buffer, pos);
          pos += data[i].length;
        }
        self.received = bufferToArrayBuffer(buffer);
        try {
          callback(recv_method.call(client));
        } catch(e) {
          onerror(e);
        }
      });
    });

    req.on('error', function(e) {
      onerror(e);
    });

    req.write(arrayBufferToBuffer(postData));
    req.end();
  };

  var arrayBufferToBuffer = function(ab) {
    var buffer = new Buffer(ab.byteLength);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
      buffer[i] = view[i];
    }
    return buffer;
  };

  var bufferToArrayBuffer = function(buffer) {
    var ab = new ArrayBuffer(buffer.length);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
      view[i] = buffer[i];
    }
    return ab;
  };

};

<|endoftext|>


<commit_before>var physicalLayer, transmitAdapter, receiveAdapter;

function onLoad() {
    init();
}

function init() {
    var channel = [ { baseFrequency: 800 } ];

    physicalLayer = new AudioNetwork.PhysicalLayer.PhysicalLayer({
        tx: { channel: channel },
        rx: { channel: channel }
    });
    transmitAdapter = new AudioNetwork.PhysicalLayer.TransmitAdapter(physicalLayer);
    receiveAdapter = new AudioNetwork.PhysicalLayer.ReceiveAdapter(physicalLayer);

    physicalLayer.rx(function (channelIndex, carrierDetail, time) {
        var receiveData = receiveAdapter.receive(channelIndex, carrierDetail, time);
        document.getElementById('rx-status').innerHTML = receiveData.state;
    });

    receiveAdapter.setPacketReceiveHandler(function (channelIndex, data) {
        var rxPacket, str, i;

        rxPacket = document.getElementById('rx-packet');
        str = '';
        for (i = 0; i < data.length; i++) {
            str += (data[i]) + ' ';
        }
        rxPacket.value = str + ' \n' + rxPacket.value;
    });
}

function sendPacket() {
    var dataList, symbol, i, data;

    data = [];
    dataList = (document.getElementById('tx-packet').value + '').split(' ');
    for (i = 0; i < dataList.length; i++) {
        symbol = parseInt(dataList[i]);
        data.push(symbol);
    }

    transmitAdapter.packet(0, data);
}

function reset() {
    receiveAdapter.reset(0);
    document.getElementById('rx-packet').value = '';
}

function sync() {
    transmitAdapter.synchronization(0);
}
<commit_msg>Remove nbsp at simple example<commit_after>var physicalLayer, transmitAdapter, receiveAdapter;

function onLoad() {
    init();
}

function init() {
    var channel = [ { baseFrequency: 800 } ];

    physicalLayer = new AudioNetwork.PhysicalLayer.PhysicalLayer({
        tx: { channel: channel },
        rx: { channel: channel }
    });
    transmitAdapter = new AudioNetwork.PhysicalLayer.TransmitAdapter(physicalLayer);
    receiveAdapter = new AudioNetwork.PhysicalLayer.ReceiveAdapter(physicalLayer);

    physicalLayer.rx(function (channelIndex, carrierDetail, time) {
        var receiveData = receiveAdapter.receive(channelIndex, carrierDetail, time);
        document.getElementById('rx-status').innerHTML = receiveData.state;
    });

    receiveAdapter.setPacketReceiveHandler(function (channelIndex, data) {
        var rxPacket, str, i;

        rxPacket = document.getElementById('rx-packet');
        str = '';
        for (i = 0; i < data.length; i++) {
            str += (data[i]) + ' ';
        }
        rxPacket.value = str + '\n' + rxPacket.value;
    });
}

function sendPacket() {
    var dataList, symbol, i, data;

    data = [];
    dataList = (document.getElementById('tx-packet').value + '').split(' ');
    for (i = 0; i < dataList.length; i++) {
        symbol = parseInt(dataList[i]);
        data.push(symbol);
    }

    transmitAdapter.packet(0, data);
}

function reset() {
    receiveAdapter.reset(0);
    document.getElementById('rx-packet').value = '';
}

function sync() {
    transmitAdapter.synchronization(0);
}
<|endoftext|>


<commit_before>/**
 * CodiceFiscale
 *
 * A javscript object for managing the italian tax code:
 * - create it
 * - check it
 */
function CodiceFiscale(generality) {
    if (!(this instanceof CodiceFiscale)) {
        return new CodiceFiscale(generality);
    }

    var g = this._options(generality);

    this.generality('name', g.name);
    this.generality('lastname', g.lastname);
    this.generality('day', g.day);
    this.generality('month', g.month);
    this.generality('year', g.year);
    this.generality('isMale', g.isMale);
    this.generality('communeName', g.communeName);
}

/** @type {Object} Define the prototype constructor */
CodiceFiscale.prototype.constructor = CodiceFiscale;

/**
 * The generalities infos of person
 *
 * @private
 * @type {Object}
 */
CodiceFiscale.__generalities = {
    /** @type {String} The name */
    name: '',
    /** @type {String} The lastname */
    lastname: '',
    /** @type {String} The day of birth */
    day: '',
    /** @type {String} The month of birth */
    month: '',
    /** @type {String} The year of birth */
    year: '',
    /** @type {Boolean} Set true if is male gender */
    isMale: '',
    /** @type {String} The commun */
    communeName: '',
};

/**
 * All settings variable are here
 *
 * @private
 * @type {Object}
 */
CodiceFiscale.prototype.__settings = {
    /** @type {Number} The number of max chars on italian tax code */
    maxChar: 15,
    /** @type {Array} The array of month in char */
    monthCodes: [
        /** Jan - Feb - Mar */
        'A', 'B', 'C',
        /** Apr - May - Jun */
        'D', 'E', 'H',
        /** Jul - Aug - Sep */
        'L', 'M', 'P',
        /** Oct - Nov - Dec */
        'R', 'S', 'T',
    ],
    /** @type {String} Char to control */
    controlChars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
    /** @type {Object} Table of association of char to control */
    charsControlValue: {
        'even': {
            0: 0,
            1: 1,
            2: 2,
            3: 3,
            4: 4,
            5: 5,
            6: 6,
            7: 7,
            8: 8,
            9: 9,
            A: 0,
            B: 1,
            C: 2,
            D: 3,
            E: 4,
            F: 5,
            G: 6,
            H: 7,
            I: 8,
            J: 9,
            K: 10,
            L: 11,
            M: 12,
            N: 13,
            O: 14,
            P: 15,
            Q: 16,
            R: 17,
            S: 18,
            T: 19,
            U: 20,
            V: 21,
            W: 22,
            X: 23,
            Y: 24,
            Z: 25
        },
        'odd': {
            0: 1,
            1: 0,
            2: 5,
            3: 7,
            4: 9,
            5: 13,
            6: 15,
            7: 17,
            8: 19,
            9: 21,
            A: 1,
            B: 0,
            C: 5,
            D: 7,
            E: 9,
            F: 13,
            G: 15,
            H: 17,
            I: 19,
            J: 21,
            K: 2,
            L: 4,
            M: 18,
            N: 20,
            O: 11,
            P: 3,
            Q: 6,
            R: 8,
            S: 12,
            T: 14,
            U: 16,
            V: 10,
            W: 22,
            X: 25,
            Y: 24,
            Z: 23
        },
    },
    /** @type {JSON} Defined in CodiceFiscale.cadastralCodes.js */
    cadastralCodes: {},
};

/**
 * Return the tax code
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.taxCode = function () {
    var lastnameCode = this.lastnameCode(),
        nameCode = this.nameCode(),
        dateCode = this.dateCode(),
        communeCode = this.communeCode(),
        taxCode = '';

    taxCode = lastnameCode + nameCode + dateCode + communeCode;
    taxCode += this.controlChar();

    return taxCode;
};

/**
 * Return the lastname code [3 chars in uppercase]
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.lastnameCode = function () {
    var lastname = this.generality('lastname'),
        lastnameCode = '';

    lastnameCode = this.__consonants(lastname);
    lastnameCode += this.__vowels(lastname);
    lastnameCode += 'XXX';
    lastnameCode = lastnameCode.substr(0, 3);

    return lastnameCode.toUpperCase();
};

/**
 * Return the name code [3 chars in uppercase]
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.nameCode = function () {
    var name = this.generality('name'),
        nameCode = '';

    nameCode = this.__consonants(name);
    if (nameCode.length >= 4) {
        nameCode = nameCode.charAt(0) + nameCode.charAt(2) + nameCode.charAt(3);
    }
    else {
        nameCode += this.__vowels(name);
        nameCode += 'XXX';
        nameCode = nameCode.substr(0, 3);
    }

    return nameCode.toUpperCase();
};

/**
 * Return the date code
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.dateCode = function () {
    var stringedYear = this.yearCode(),
        stringedMonth = this.monthCode(),
        stringedDay = this.dayCode();

    return '' + stringedYear + stringedMonth + stringedDay;
};

/**
 * Return the year code
 *
 * @public
 * @param  {Number} month The year
 * @return
 */
CodiceFiscale.prototype.yearCode = function () {
    year = this.generality('year').toString();

    return year.substr(year.length - 2, 2);
};

/**
 * Return the month code
 *
 * @public
 * @param  {Number} month The month
 * @return
 */
CodiceFiscale.prototype.monthCode = function () {
    var month = parseInt(this.generality('month') - 1);

    return this.setting('monthCodes')[month];
};

/**
 * Return the day code
 *
 * @public
 * @param  {Number} day The day
 * @return
 */
CodiceFiscale.prototype.dayCode = function () {
    var day = parseInt(this.generality('day'));

    day = (this.generality('isMale')) ? day : day + 40;
    day = ('00' + day.toString()).substring(day.toString().length);

    return day;
};

/**
 * Return the commune code
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.communeCode = function () {
    var communeName = this.generality('communeName'),
        stringToMatch = /^[A-Z]\d\d\d$/i;

    if (communeName.match(stringToMatch)) {
        return communeName;
    }

    return this._commune()[0][1];
};

/**
 * Return the control char of a taxcode
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.controlChar = function () {
    var i = 0,
        val = 0,
        indexChar = 0,
        maxChar = this.setting('maxChar'),
        controlChar = this.setting('controlChars'),
        lastnameCode = this.lastnameCode(),
        nameCode = this.nameCode(),
        dateCode = this.dateCode(),
        communeCode = this.communeCode(),
        partialTaxCode = '';

    // Get the partial tax code
    partialTaxCode = lastnameCode + nameCode + dateCode + communeCode;

    for (i = 0; i < maxChar; i++) {
        indexChar = partialTaxCode[i];
        if (i % 2) {
            val += this._controlValue('even', indexChar);
        }
        else {
            val += this._controlValue('odd', indexChar);
        }
    }

    val = val % controlChar.length;

    return controlChar.charAt(val);
};

/**
 * Get or set settings property
 * This is an interface to only settings
 *
 * @public
 * @param {String} propertyPath The property to set or get
 * @param {mixin}  dataToSet    Data to set, if not defined than return
 */
CodiceFiscale.prototype.setting = function (property, dataToSet) {
    return this.__property('__settings.' + property, dataToSet);
};

/**
 * Get or set generalities property
 * This is an interface to only generalities
 *
 * @public
 * @param {String} propertyPath The property to set or get
 * @param {mixin}  dataToSet    Data to set, if not defined than return
 */
CodiceFiscale.prototype.generality = function (property, dataToSet) {
    return this.__property('__generalities.' + property, dataToSet);
};

/**
 * Return the commune name and code
 *
 * @protected
 * @return {Array}
 */
CodiceFiscale.prototype._commune = function () {
    var communeName = this.generality('communeName'),
        code = [],
        commune = [],
        communeCodeToReturn = [],
        stringToReplace = /([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!<\>\|\:])/g,
        quoted = '',
        re = '',
        regex = '';

    quoted = communeName.replace(stringToReplace, '\\$1');
    regex = new RegExp(quoted, 'i');
    for (code in this.setting('cadastralCodes')) {
        commune = this._communeCadastralCode(code);
        if (commune.match(regex)) {
            communeCodeToReturn.push([commune, code]);
        }
    }

    return communeCodeToReturn;
};

/**
 * Return the cadastralCode selected
 *
 * @protected
 * @return {String}
 */
CodiceFiscale.prototype._communeCadastralCode = function (code) {
    return this.setting('cadastralCodes')[code];
};

/**
 * Return control value of even/odd char
 *
 * @protected
 * @param  {String} type 'even' or 'odd'
 * @param  {String} char The char to check
 * @return {Number}
 */
CodiceFiscale.prototype._controlValue = function (type, char) {
    return this.setting('charsControlValue')[type][char];
};

/**
 * Return the generality setted on Class call
 *
 * @protected
 * @param  {Object|Array} generality The generality passed
 * @return {Object}
 */
CodiceFiscale.prototype._options = function (generality) {
    var options = {
        name: generality.name || generality[0],
        lastname: generality.lastname || generality[1],
        day: generality.day || generality[2],
        month: generality.month || generality[3],
        year: generality.year || generality[4],
        isMale: generality.isMale || generality[5] || false,
        communeName: generality.communeName || generality[6],
    };

    return options;
};

/**
 * Return the cosonants of a string
 *
 * @private
 * @param  {String} string The string to parse
 * @return {String}
 */
CodiceFiscale.prototype.__consonants = function (string) {
    return string.replace(/[^BCDFGHJKLMNPQRSTVWXYZ]/gi, '');
};

/**
 * Return the vowels of a string
 *
 * @private
 * @param  {String} string The string to parse
 * @return {String}
 */
CodiceFiscale.prototype.__vowels = function (string) {
    return string.replace(/[^AEIOU]/gi, '');
};

/**
 * Get or Set the property
 *
 * @private
 * @param {String} propertyPath The property to set or get
 * @param {mixin}  dataToSet    Data to set, if not defined than return
 */
CodiceFiscale.prototype.__property = function (propertyPath, dataToSet) {
    return (function deepProp(self, path, data) {
        if (typeof path === 'string') {
            path = path.split('.');
        }

        if (path.length > 1) {
            var singlePath = path.shift();

            if (self[singlePath] === null || typeof self[singlePath] !== 'object') {
                self[singlePath] = {};
            }

            return deepProp(self[singlePath], path, data);
        }
        else {
            if (typeof data === 'undefined') {
                // Set global property variable
                return self[path[0]];
            }
            else {
                self[path[0]] = data;
            }
        }
    })(this, propertyPath, dataToSet);
};
<commit_msg>fix commune code<commit_after>/**
 * CodiceFiscale
 *
 * A javscript object for managing the italian tax code:
 * - create it
 * - check it
 */
function CodiceFiscale(generality) {
    if (!(this instanceof CodiceFiscale)) {
        return new CodiceFiscale(generality);
    }

    var g = this._options(generality);

    this.generality('name', g.name);
    this.generality('lastname', g.lastname);
    this.generality('day', g.day);
    this.generality('month', g.month);
    this.generality('year', g.year);
    this.generality('isMale', g.isMale);
    this.generality('communeName', g.communeName);
}

/** @type {Object} Define the prototype constructor */
CodiceFiscale.prototype.constructor = CodiceFiscale;

/**
 * The generalities infos of person
 *
 * @private
 * @type {Object}
 */
CodiceFiscale.__generalities = {
    /** @type {String} The name */
    name: '',
    /** @type {String} The lastname */
    lastname: '',
    /** @type {String} The day of birth */
    day: '',
    /** @type {String} The month of birth */
    month: '',
    /** @type {String} The year of birth */
    year: '',
    /** @type {Boolean} Set true if is male gender */
    isMale: '',
    /** @type {String} The commun */
    communeName: '',
};

/**
 * All settings variable are here
 *
 * @private
 * @type {Object}
 */
CodiceFiscale.prototype.__settings = {
    /** @type {Number} The number of max chars on italian tax code */
    maxChar: 15,
    /** @type {Array} The array of month in char */
    monthCodes: [
        /** Jan - Feb - Mar */
        'A', 'B', 'C',
        /** Apr - May - Jun */
        'D', 'E', 'H',
        /** Jul - Aug - Sep */
        'L', 'M', 'P',
        /** Oct - Nov - Dec */
        'R', 'S', 'T',
    ],
    /** @type {String} Char to control */
    controlChars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
    /** @type {Object} Table of association of char to control */
    charsControlValue: {
        'even': {
            0: 0,
            1: 1,
            2: 2,
            3: 3,
            4: 4,
            5: 5,
            6: 6,
            7: 7,
            8: 8,
            9: 9,
            A: 0,
            B: 1,
            C: 2,
            D: 3,
            E: 4,
            F: 5,
            G: 6,
            H: 7,
            I: 8,
            J: 9,
            K: 10,
            L: 11,
            M: 12,
            N: 13,
            O: 14,
            P: 15,
            Q: 16,
            R: 17,
            S: 18,
            T: 19,
            U: 20,
            V: 21,
            W: 22,
            X: 23,
            Y: 24,
            Z: 25
        },
        'odd': {
            0: 1,
            1: 0,
            2: 5,
            3: 7,
            4: 9,
            5: 13,
            6: 15,
            7: 17,
            8: 19,
            9: 21,
            A: 1,
            B: 0,
            C: 5,
            D: 7,
            E: 9,
            F: 13,
            G: 15,
            H: 17,
            I: 19,
            J: 21,
            K: 2,
            L: 4,
            M: 18,
            N: 20,
            O: 11,
            P: 3,
            Q: 6,
            R: 8,
            S: 12,
            T: 14,
            U: 16,
            V: 10,
            W: 22,
            X: 25,
            Y: 24,
            Z: 23
        },
    },
    /** @type {JSON} Defined in CodiceFiscale.cadastralCodes.js */
    cadastralCodes: {},
};

/**
 * Return the tax code
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.taxCode = function () {
    var lastnameCode = this.lastnameCode(),
        nameCode = this.nameCode(),
        dateCode = this.dateCode(),
        communeCode = this.communeCode(),
        taxCode = '';

    taxCode = lastnameCode + nameCode + dateCode + communeCode;
    taxCode += this.controlChar();

    return taxCode;
};

/**
 * Return the lastname code [3 chars in uppercase]
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.lastnameCode = function () {
    var lastname = this.generality('lastname'),
        lastnameCode = '';

    lastnameCode = this.__consonants(lastname);
    lastnameCode += this.__vowels(lastname);
    lastnameCode += 'XXX';
    lastnameCode = lastnameCode.substr(0, 3);

    return lastnameCode.toUpperCase();
};

/**
 * Return the name code [3 chars in uppercase]
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.nameCode = function () {
    var name = this.generality('name'),
        nameCode = '';

    nameCode = this.__consonants(name);
    if (nameCode.length >= 4) {
        nameCode = nameCode.charAt(0) + nameCode.charAt(2) + nameCode.charAt(3);
    }
    else {
        nameCode += this.__vowels(name);
        nameCode += 'XXX';
        nameCode = nameCode.substr(0, 3);
    }

    return nameCode.toUpperCase();
};

/**
 * Return the date code
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.dateCode = function () {
    var stringedYear = this.yearCode(),
        stringedMonth = this.monthCode(),
        stringedDay = this.dayCode();

    return '' + stringedYear + stringedMonth + stringedDay;
};

/**
 * Return the year code
 *
 * @public
 * @param  {Number} month The year
 * @return
 */
CodiceFiscale.prototype.yearCode = function () {
    year = this.generality('year').toString();

    return year.substr(year.length - 2, 2);
};

/**
 * Return the month code
 *
 * @public
 * @param  {Number} month The month
 * @return
 */
CodiceFiscale.prototype.monthCode = function () {
    var month = parseInt(this.generality('month') - 1);

    return this.setting('monthCodes')[month];
};

/**
 * Return the day code
 *
 * @public
 * @param  {Number} day The day
 * @return
 */
CodiceFiscale.prototype.dayCode = function () {
    var day = parseInt(this.generality('day'));

    day = (this.generality('isMale')) ? day : day + 40;
    day = ('00' + day.toString()).substring(day.toString().length);

    return day;
};

/**
 * Return the commune code
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.communeCode = function () {
    var communeName = this.generality('communeName'),
        stringToMatch = /^[A-Z]\d\d\d$/i;

    if (communeName.match(stringToMatch)) {
        return communeName;
    }

    return this._commune()[0][1];
};

/**
 * Return the control char of a taxcode
 *
 * @public
 * @return {String}
 */
CodiceFiscale.prototype.controlChar = function () {
    var i = 0,
        val = 0,
        indexChar = 0,
        maxChar = this.setting('maxChar'),
        controlChar = this.setting('controlChars'),
        lastnameCode = this.lastnameCode(),
        nameCode = this.nameCode(),
        dateCode = this.dateCode(),
        communeCode = this.communeCode(),
        partialTaxCode = '';

    // Get the partial tax code
    partialTaxCode = lastnameCode + nameCode + dateCode + communeCode;

    for (i = 0; i < maxChar; i++) {
        indexChar = partialTaxCode[i];
        if (i % 2) {
            val += this._controlValue('even', indexChar);
        }
        else {
            val += this._controlValue('odd', indexChar);
        }
    }

    val = val % controlChar.length;

    return controlChar.charAt(val);
};

/**
 * Get or set settings property
 * This is an interface to only settings
 *
 * @public
 * @param {String} propertyPath The property to set or get
 * @param {mixin}  dataToSet    Data to set, if not defined than return
 */
CodiceFiscale.prototype.setting = function (property, dataToSet) {
    return this.__property('__settings.' + property, dataToSet);
};

/**
 * Get or set generalities property
 * This is an interface to only generalities
 *
 * @public
 * @param {String} propertyPath The property to set or get
 * @param {mixin}  dataToSet    Data to set, if not defined than return
 */
CodiceFiscale.prototype.generality = function (property, dataToSet) {
    return this.__property('__generalities.' + property, dataToSet);
};

/**
 * Return the commune name and code
 *
 * @protected
 * @return {Array}
 */
CodiceFiscale.prototype._commune = function () {
    var communeName = this.generality('communeName'),
        code = [],
        commune = [],
        communeCodeToReturn = [],
        stringToReplace = /([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!<\>\|\:])/g,
        quoted = '',
        re = '',
        regex = '';

    quoted = communeName.replace(stringToReplace, '\\$1');
    regex = new RegExp('^' + quoted + '$', 'i');
    for (code in this.setting('cadastralCodes')) {
        commune = this._communeCadastralCode(code);
        if (commune.match(regex)) {
            communeCodeToReturn.push([commune, code]);
        }
    }

    return communeCodeToReturn;
};

/**
 * Return the cadastralCode selected
 *
 * @protected
 * @return {String}
 */
CodiceFiscale.prototype._communeCadastralCode = function (code) {
    return this.setting('cadastralCodes')[code];
};

/**
 * Return control value of even/odd char
 *
 * @protected
 * @param  {String} type 'even' or 'odd'
 * @param  {String} char The char to check
 * @return {Number}
 */
CodiceFiscale.prototype._controlValue = function (type, char) {
    return this.setting('charsControlValue')[type][char];
};

/**
 * Return the generality setted on Class call
 *
 * @protected
 * @param  {Object|Array} generality The generality passed
 * @return {Object}
 */
CodiceFiscale.prototype._options = function (generality) {
    var options = {
        name: generality.name || generality[0],
        lastname: generality.lastname || generality[1],
        day: generality.day || generality[2],
        month: generality.month || generality[3],
        year: generality.year || generality[4],
        isMale: generality.isMale || generality[5] || false,
        communeName: generality.communeName || generality[6],
    };

    return options;
};

/**
 * Return the cosonants of a string
 *
 * @private
 * @param  {String} string The string to parse
 * @return {String}
 */
CodiceFiscale.prototype.__consonants = function (string) {
    return string.replace(/[^BCDFGHJKLMNPQRSTVWXYZ]/gi, '');
};

/**
 * Return the vowels of a string
 *
 * @private
 * @param  {String} string The string to parse
 * @return {String}
 */
CodiceFiscale.prototype.__vowels = function (string) {
    return string.replace(/[^AEIOU]/gi, '');
};

/**
 * Get or Set the property
 *
 * @private
 * @param {String} propertyPath The property to set or get
 * @param {mixin}  dataToSet    Data to set, if not defined than return
 */
CodiceFiscale.prototype.__property = function (propertyPath, dataToSet) {
    return (function deepProp(self, path, data) {
        if (typeof path === 'string') {
            path = path.split('.');
        }

        if (path.length > 1) {
            var singlePath = path.shift();

            if (self[singlePath] === null || typeof self[singlePath] !== 'object') {
                self[singlePath] = {};
            }

            return deepProp(self[singlePath], path, data);
        }
        else {
            if (typeof data === 'undefined') {
                // Set global property variable
                return self[path[0]];
            }
            else {
                self[path[0]] = data;
            }
        }
    })(this, propertyPath, dataToSet);
};
<|endoftext|>


<commit_before>module.exports.hello = {
    handler: function (request, reply) {
        return reply({ result: 'Hello hapi!' });
    },
    id: 'root'
};

module.exports.restricted = {
    auth: 'jwt',
    handler: function (request, reply) {
        return reply({ result: 'Restricted!' });
    }
};

module.exports.notFound = {
    handler: function (request, reply) {
        return reply({ result: 'Oops, 404 Page!' }).code(404);
    }
};<commit_msg>update welcome message<commit_after>module.exports.hello = {
    handler: function (request, reply) {
        return reply({ result: 'Hello this is the ttrack server api' });
    },
    id: 'root'
};
<|endoftext|>


<commit_before>/**
	_moon.HighlightText_ is a control that displays an highlighted text.
	Identified string or chracter in content can be highlighted by onHighlight event.
	if content don't have any identical string, there is no change in display.

		{kind: "moon.HighlightText", content: "Hello World!"}

	Examples)

	_moon.HighlightText_ get event like below, then the "Hello" is highlighted.
		this.waterfall("onHighlight", {highlight: "Hello"});

	_moon.HighlightText_ get event like below, then the highlighted text is disapeared.
		this.waterfall("offHighlight");

    Not only can highlight directly using highlightOver highlightBlur function but also
    published variable for highlight.
*/
enyo.kind({
    name: "moon.HighlightText",
    published: {
        content: "",
        highlight: "",
        highlightClasses: "moon-highlight-text-highlighted"
    },
    handlers: {
        onHighlight: "onHighlightHandler",
        offHighlight: "offHighlightHandler"
    },
    //* @protected
    create: function() {
        this.inherited(arguments);
        this._content = this.content;
    },
    setContent: function(inValue) {
        this.inherited(arguments);
        this._content = inValue;
    },
    _setContent: function(inValue) {
        this.content = inValue;
        this.contentChanged();
    },
    getContent:function() {
        return this._content;
    },
    highlightChanged: function(inValue) {
        if(inValue==="") {
            this.highlightBlur();
        } else {
            this.highlightOver(inValue);
        }
    },
    onHighlightHandler: function(inSender, inEvent) {
        this.highlightOver(inEvent.highlight);
        return true;
    },
    offHighlightHandler: function(inSender, inEvent) {
        this.highlightBlur();
        return true;
    },
    //* @public
    highlightOver: function(inText) {
        this.allowHtml = true;
        var output = "",
            hlt = inText,
            ort = this.getContent(),
            sIdx = 0,
            eIdx = ort.length
        ;
        while(sIdx !== -1) {
            sIdx = ort.search(hlt);
            if(sIdx !== -1) {
                output += ort.slice(0, sIdx) + "";
                output += ort.slice(sIdx, sIdx+hlt.length) + "";
                sIdx = sIdx+hlt.length;
                ort = ort.slice(sIdx, eIdx);
            }
        }
        output += ort;
        this._setContent(output);
    },
    highlightBlur: function() {
        this.allowHtml = false;
        this.setContent(this._content);
        this.render();
    }
});<commit_msg>Correct Event and API<commit_after>/**
	_moon.HighlightText_ is a control that displays an highlighted text.
	Identified string or chracter in content can be highlighted by onHighlight event.
	if content don't have any identical string, there is no change in display.

		{kind: "moon.HighlightText", content: "Hello World!"}

	Examples)

	_moon.HighlightText_ get event like below, then the "Hello" is highlighted.
		this.waterfall("onHighlight", {highlight: "Hello"});

	_moon.HighlightText_ get event like below, then the highlighted text is disapeared.
		this.waterfall("offHighlight");

    Not only can highlight directly using highlightOver highlightBlur function but also
    published variable for highlight.
*/
enyo.kind({
    name: "moon.HighlightText",
    published: {
        content: "",
        highlight: false,
        highlightClasses: "moon-highlight-text-highlighted"
    },
    handlers: {
        onHighlight: "onHighlightHandler",
        onUnHighlight: "unHighlightHandler"
    },
    create: function() {
        this.inherited(arguments);
        this._content = this.content;
    },
    //* @public
    setContent: function(inValue) {
        this.inherited(arguments);
        this._content = inValue;
    },
    getContent:function() {
        return this._content;
    },
    //* @protected
    highlightBlur: function() {
        this.allowHtml = false;
        this.setContent(this._content);
        this.render();
    },
    //* @protected
    highlightOver: function(inText) {
        this.allowHtml = true;
        var output = "",
            hlt = inText,
            ort = this.getContent(),
            sIdx = 0,
            eIdx = ort.length
        ;
        while(sIdx !== -1) {
            sIdx = ort.search(hlt);
            if(sIdx !== -1) {
                output += ort.slice(0, sIdx) + "";
                output += ort.slice(sIdx, sIdx+hlt.length) + "";
                sIdx = sIdx+hlt.length;
                ort = ort.slice(sIdx, eIdx);
            }
        }
        output += ort;
        this._setContent(output);
    },
    //* @protected
    highlightChanged: function() {
        if(this.highlight===false || this.highlight ==="") {
            this.highlightBlur();
        } else {
            this.highlightOver(this.highlight);
        }
    },
    //* @protected
    _setContent: function(inValue) {
        this.content = inValue;
        this.contentChanged();
    },
    //* @protected
    onHighlightHandler: function(inSender, inEvent) {
        this.setHighlight(inEvent.highlight);
        return true;
    },
    //* @protected
    unHighlightHandler: function(inSender, inEvent) {
        this.setHighlight(false);
        return true;
    }
});<|endoftext|>


<commit_before>$("document").ready( function () {
    $("#search-login").autocomplete({
        source: $("#search-login").data('link')
    });
});
<commit_msg>[jelix] Remove unwanted file added for lizmap 3.3<commit_after><|endoftext|>


<commit_before>/* accordion.js v1.1.0 | MIT License | https://github.com/joaomosantos/accordion.js */
;(function($) {

	$.fn.accordion = function(options) {
		var previous = null;

		var defaults = {
			controlElement: $('.accordion-control'),
			contentElement: $('.accordion-content'),
			transitionSpeed: 400,
			ease: 'swing',
			multipleCollapse: true,
			onOpened: function(el) {},
			onClosed: function(el) {}
		};

		var settings = $.extend(defaults, options);

		$.extend($.easing, {
			back: function (x, t, b, c, d, s) {
				if (s == undefined) s = 1.70158;
				if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) +1) * t - s)) + b;
				return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
			},
			bounce: function (x, t, b, c, d) {
				if ((t /= d) < (1 / 2.75)) {
					return c * (7.5625 * t * t) + b;
				} else if (t < (2 / 2.75)) {
					return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
				} else if (t < (2.5/2.75)) {
					return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
				} else {
					return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
				}
			},
			circ: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
				return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
			},
			cubic: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
				return c / 2 * ((t -= 2) * t * t + 2) + b;
			},
			elastic: function (x, t, b, c, d) {
				var s = 1.70158; var p = 0; var a = c;
				if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (!p) p = d * (.3 * 1.5);
				if (a < Math.abs(c)) { a = c; var s = p / 4; }
				else var s = p / (2 * Math.PI) * Math.asin (c / a);
				if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p )) + b;
				return a * Math.pow(2, -10 * (t -=1 )) * Math.sin((t * d - s) * (2 * Math.PI) / p ) * .5 + c + b;
			},
			expo: function (x, t, b, c, d) {
				if (t == 0) return b;
				if (t == d) return b + c;
				if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
				return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
			},
			quad: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t + b;
				return -c / 2 * ((--t) * (t - 2) - 1) + b;
			},
			quart: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
				return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
			},
			quint: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
				return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
			},
			sine: function (x, t, b, c, d) {
				return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
			}
		});

		var collapse = function(elementCurrent, elementPrevious) {
			var isOpened = elementCurrent.hasClass('opened');
			if(isOpened) {
				elementCurrent.next().stop().slideUp(settings.transitionSpeed, settings.ease, function() {
					elementCurrent.removeClass('opened');
					settings.onClosed(elementCurrent);
				});
			} else {
				if(!settings.multipleCollapse && elementPrevious !== null) {
					elementPrevious.next().stop().slideUp(settings.transitionSpeed, settings.ease, function() {
						elementPrevious.removeClass('opened');
					});
				}
				elementCurrent.next().stop().slideDown(settings.transitionSpeed, settings.ease, function() {
					elementCurrent.addClass('opened');
					settings.onOpened(elementCurrent);
				});
			}
		};

		return this.each(function() {
			$(this).find(settings.contentElement).hide();
			$(this).find(settings.controlElement).click(function(event) {
				event.preventDefault();
				collapse($(this), previous);
				previous = $(this);
			});
		});
	};

}(jQuery));<commit_msg>Ajustando nome variavel<commit_after>/* accordion.js v1.1.0 | MIT License | https://github.com/joaomosantos/accordion.js */
;(function($) {

	$.fn.accordion = function(options) {
		var previous = null;

		var defaults = {
			controlElement: $('.accordion-control'),
			contentElement: $('.accordion-content'),
			transitionSpeed: 400,
			ease: 'swing',
			multipleCollapse: true,
			onOpened: function(el) {},
			onClosed: function(el) {}
		};

		var settings = $.extend(defaults, options);

		$.extend($.easing, {
			back: function (x, t, b, c, d, s) {
				if (s == undefined) s = 1.70158;
				if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) +1) * t - s)) + b;
				return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
			},
			bounce: function (x, t, b, c, d) {
				if ((t /= d) < (1 / 2.75)) {
					return c * (7.5625 * t * t) + b;
				} else if (t < (2 / 2.75)) {
					return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
				} else if (t < (2.5/2.75)) {
					return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
				} else {
					return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
				}
			},
			circ: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
				return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
			},
			cubic: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
				return c / 2 * ((t -= 2) * t * t + 2) + b;
			},
			elastic: function (x, t, b, c, d) {
				var s = 1.70158; var p = 0; var a = c;
				if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (!p) p = d * (.3 * 1.5);
				if (a < Math.abs(c)) { a = c; var s = p / 4; }
				else var s = p / (2 * Math.PI) * Math.asin (c / a);
				if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p )) + b;
				return a * Math.pow(2, -10 * (t -=1 )) * Math.sin((t * d - s) * (2 * Math.PI) / p ) * .5 + c + b;
			},
			expo: function (x, t, b, c, d) {
				if (t == 0) return b;
				if (t == d) return b + c;
				if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
				return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
			},
			quad: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t + b;
				return -c / 2 * ((--t) * (t - 2) - 1) + b;
			},
			quart: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
				return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
			},
			quint: function (x, t, b, c, d) {
				if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
				return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
			},
			sine: function (x, t, b, c, d) {
				return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
			}
		});

		var collapse = function(elementCurrent, elementPrevious) {
			var isOpen = elementCurrent.hasClass('opened');
			if(isOpen) {
				elementCurrent.next().stop().slideUp(settings.transitionSpeed, settings.ease, function() {
					elementCurrent.removeClass('opened');
					settings.onClosed(elementCurrent);
				});
			} else {
				if(!settings.multipleCollapse && elementPrevious !== null) {
					elementPrevious.next().stop().slideUp(settings.transitionSpeed, settings.ease, function() {
						elementPrevious.removeClass('opened');
					});
				}
				elementCurrent.next().stop().slideDown(settings.transitionSpeed, settings.ease, function() {
					elementCurrent.addClass('opened');
					settings.onOpened(elementCurrent);
				});
			}
		};

		return this.each(function() {
			$(this).find(settings.contentElement).hide();
			$(this).find(settings.controlElement).click(function(event) {
				event.preventDefault();
				collapse($(this), previous);
				previous = $(this);
			});
		});
	};

}(jQuery));
<|endoftext|>


<commit_before>import { ATTR_KEY } from '../constants';
import { memoize } from '../util';
import { ensureNodeData, getNodeType, getRawNodeAttributes } from '.';

/** DOM node pool, keyed on nodeName. */

let nodes = {};

let normalizeName = memoize(name => name.toUpperCase());

export function collectNode(node) {
	cleanNode(node);
	let name = normalizeName(node.nodeName),
		list = nodes[name];
	if (list) list.push(node);
	else nodes[name] = [node];
}

export function createNode(nodeName) {
	let name = normalizeName(nodeName),
		list = nodes[name],
		node = list && list.pop() || document.createElement(nodeName);
	ensureNodeData(node);
	return node;
}

function cleanNode(node) {
	let p = node.parentNode;
	if (p) p.removeChild(node);

	if (getNodeType(node)===3) return;

	// When reclaiming externally created nodes, seed the attribute cache: (Issue #97)
	if (!node[ATTR_KEY]) {
		node[ATTR_KEY] = getRawNodeAttributes(node);
	}

	node._component = node._componentConstructor = null;

	// if (node.childNodes.length>0) {
	// 	console.trace(`Warning: Recycler collecting <${node.nodeName}> with ${node.childNodes.length} children.`);
	// 	for (let i=node.childNodes.length; i--; ) collectNode(node.childNodes[i]);
	// }
}
<commit_msg>Update recycler.js<commit_after>import { ATTR_KEY } from '../constants';
import { memoize,removeNode } from '../util';
import { ensureNodeData, getNodeType, getRawNodeAttributes } from '.';

/** DOM node pool, keyed on nodeName. */

let nodes = {};

let normalizeName = memoize(name => name.toUpperCase());

export function collectNode(node) {
	cleanNode(node);
	let name = normalizeName(node.nodeName),
		list = nodes[name];
	if (list) list.push(node);
	else nodes[name] = [node];
}

export function createNode(nodeName) {
	let name = normalizeName(nodeName),
		list = nodes[name],
		node = list && list.pop() || document.createElement(nodeName);
	ensureNodeData(node);
	return node;
}

function cleanNode(node) {
	removeNode(node);

	if (getNodeType(node)===3) return;

	// When reclaiming externally created nodes, seed the attribute cache: (Issue #97)
	if (!node[ATTR_KEY]) {
		node[ATTR_KEY] = getRawNodeAttributes(node);
	}

	node._component = node._componentConstructor = null;

	// if (node.childNodes.length>0) {
	// 	console.trace(`Warning: Recycler collecting <${node.nodeName}> with ${node.childNodes.length} children.`);
	// 	for (let i=node.childNodes.length; i--; ) collectNode(node.childNodes[i]);
	// }
}
<|endoftext|>


<commit_before>module.exports = function ($editableElement) {
  $editableElement.css({
    'min-height': '1em',
    border: '2px dotted pink'
  })
}
<commit_msg>testbench style changes to editable elements<commit_after>module.exports = function ($editableElement) {
  $editableElement.css({
    'min-height': '1.618em',
    'min-width': '16.18em',
    'display': 'block',
    border: '2px dotted pink'
  })
}
<|endoftext|>