ag-grid
Version: 
Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components
189 lines (188 loc) • 9.1 kB
JavaScript
/**
 * ag-grid - Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components
 * @version v18.1.2
 * @link http://www.ag-grid.com/
 * @license MIT
 */
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
var logger_1 = require("./logger");
var utils_1 = require("./utils");
var context_1 = require("./context/context");
var context_2 = require("./context/context");
var gridOptionsWrapper_1 = require("./gridOptionsWrapper");
var EventService = (function () {
    function EventService() {
        this.allSyncListeners = {};
        this.allAsyncListeners = {};
        this.globalSyncListeners = [];
        this.globalAsyncListeners = [];
        this.asyncFunctionsQueue = [];
        this.scheduled = false;
    }
    EventService_1 = EventService;
    // because this class is used both inside the context and outside the context, we do not
    // use autowired attributes, as that would be confusing, as sometimes the attributes
    // would be wired, and sometimes not.
    //
    // the global event servers used by ag-Grid is autowired by the context once, and this
    // setBeans method gets called once.
    //
    // the times when this class is used outside of the context (eg RowNode has an instance of this
    // class) then it is not a bean, and this setBeans method is not called.
    EventService.prototype.setBeans = function (loggerFactory, gridOptionsWrapper, globalEventListener) {
        if (globalEventListener === void 0) { globalEventListener = null; }
        this.logger = loggerFactory.create('EventService');
        if (globalEventListener) {
            var async = gridOptionsWrapper.useAsyncEvents();
            this.addGlobalListener(globalEventListener, async);
        }
    };
    EventService.prototype.getListenerList = function (eventType, async) {
        var listenerMap = async ? this.allAsyncListeners : this.allSyncListeners;
        var listenerList = listenerMap[eventType];
        if (!listenerList) {
            listenerList = [];
            listenerMap[eventType] = listenerList;
        }
        return listenerList;
    };
    EventService.prototype.addEventListener = function (eventType, listener, async) {
        if (async === void 0) { async = false; }
        var listenerList = this.getListenerList(eventType, async);
        if (listenerList.indexOf(listener) < 0) {
            listenerList.push(listener);
        }
    };
    // for some events, it's important that the model gets to hear about them before the view,
    // as the model may need to update before the view works on the info. if you register
    // via this method, you get notified before the view parts
    EventService.prototype.addModalPriorityEventListener = function (eventType, listener, async) {
        if (async === void 0) { async = false; }
        this.addEventListener(eventType + EventService_1.PRIORITY, listener, async);
    };
    EventService.prototype.addGlobalListener = function (listener, async) {
        if (async === void 0) { async = false; }
        if (async) {
            this.globalAsyncListeners.push(listener);
        }
        else {
            this.globalSyncListeners.push(listener);
        }
    };
    EventService.prototype.removeEventListener = function (eventType, listener, async) {
        if (async === void 0) { async = false; }
        var listenerList = this.getListenerList(eventType, async);
        utils_1.Utils.removeFromArray(listenerList, listener);
    };
    EventService.prototype.removeGlobalListener = function (listener, async) {
        if (async === void 0) { async = false; }
        if (async) {
            utils_1.Utils.removeFromArray(this.globalAsyncListeners, listener);
        }
        else {
            utils_1.Utils.removeFromArray(this.globalSyncListeners, listener);
        }
    };
    // why do we pass the type here? the type is in ColumnChangeEvent, so unless the
    // type is not in other types of events???
    EventService.prototype.dispatchEvent = function (event) {
        // console.log(`dispatching ${eventType}: ${event}`);
        this.dispatchToListeners(event, true);
        this.dispatchToListeners(event, false);
    };
    EventService.prototype.dispatchToListeners = function (event, async) {
        var _this = this;
        var globalListeners = async ? this.globalAsyncListeners : this.globalSyncListeners;
        var eventType = event.type;
        // this allows the columnController to get events before anyone else
        var p1ListenerList = this.getListenerList(eventType + EventService_1.PRIORITY, async);
        utils_1.Utils.forEachSnapshotFirst(p1ListenerList, function (listener) {
            if (async) {
                _this.dispatchAsync(function () { return listener(event); });
            }
            else {
                listener(event);
            }
        });
        var listenerList = this.getListenerList(eventType, async);
        utils_1.Utils.forEachSnapshotFirst(listenerList, function (listener) {
            if (async) {
                _this.dispatchAsync(function () { return listener(event); });
            }
            else {
                listener(event);
            }
        });
        utils_1.Utils.forEachSnapshotFirst(globalListeners, function (listener) {
            if (async) {
                _this.dispatchAsync(function () { return listener(eventType, event); });
            }
            else {
                listener(eventType, event);
            }
        });
    };
    // this gets called inside the grid's thread, for each event that it
    // wants to set async. the grid then batches the events into one setTimeout()
    // because setTimeout() is an expensive operation. ideally we would have
    // each event in it's own setTimeout(), but we batch for performance.
    EventService.prototype.dispatchAsync = function (func) {
        // add to the queue for executing later in the next VM turn
        this.asyncFunctionsQueue.push(func);
        // check if timeout is already scheduled. the first time the grid calls
        // this within it's thread turn, this should be false, so it will schedule
        // the 'flush queue' method the first time it comes here. then the flag is
        // set to 'true' so it will know it's already scheduled for subsequent calls.
        if (!this.scheduled) {
            // if not scheduled, schedule one
            setTimeout(this.flushAsyncQueue.bind(this), 0);
            // mark that it is scheduled
            this.scheduled = true;
        }
    };
    // this happens in the next VM turn only, and empties the queue of events
    EventService.prototype.flushAsyncQueue = function () {
        this.scheduled = false;
        // we take a copy, because the event listener could be using
        // the grid, which would cause more events, which would be potentially
        // added to the queue, so safe to take a copy, the new events will
        // get executed in a later VM turn rather than risk updating the
        // queue as we are flushing it.
        var queueCopy = this.asyncFunctionsQueue.slice();
        this.asyncFunctionsQueue = [];
        // execute the queue
        queueCopy.forEach(function (func) { return func(); });
    };
    // this is an old idea niall had, should really take it out, was to do with ordering who gets to process
    // events first, to give model and service objects preference over the view
    EventService.PRIORITY = '-P1';
    __decorate([
        __param(0, context_2.Qualifier('loggerFactory')),
        __param(1, context_2.Qualifier('gridOptionsWrapper')),
        __param(2, context_2.Qualifier('globalEventListener')),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [logger_1.LoggerFactory,
            gridOptionsWrapper_1.GridOptionsWrapper,
            Function]),
        __metadata("design:returntype", void 0)
    ], EventService.prototype, "setBeans", null);
    EventService = EventService_1 = __decorate([
        context_1.Bean('eventService')
    ], EventService);
    return EventService;
    var EventService_1;
}());
exports.EventService = EventService;