function Dispatcher(config, vm) {
    var _this = this;

    _classCallCheck(this, Dispatcher);

    this.plugins = {};
    this.order = [];
    this.readySync = false;
    this.zIndexMap = {
      inner: [],
      outer: []
    };
    this.changeWatchable = true;
    this.kernelEventHandlerList = [];

    if (!chimeeHelper.isObject(config)) throw new TypeError('UserConfig must be an Object, but not "' + config + '" in ' + (typeof config === 'undefined' ? 'undefined' : _typeof(config)));
    /**
     * dom Manager
     * @type {Dom}
     */
    this.dom = new Dom(config, this);
    /**
     * Chimee's referrence
     * @type {[type]}
     */
    this.vm = vm;
    /**
     * tell user have Chimee installed finished
     * @type {Promises}
     */
    this.videoConfigReady = false;
    // create the videoconfig
    this.videoConfig = new VideoConfig(this, config);
    // support both plugin and plugins here as people often cofuse both
    // $FlowFixMe: we support plugins here, which should be illegal
    if (chimeeHelper.isArray(config.plugins) && !chimeeHelper.isArray(config.plugin)) {
      config.plugin = config.plugins;
      delete config.plugins;
    }
    this.binder = new Binder(this);
    this.binder.listenOnMouseMoveEvent(this.dom.videoElement);
    // use the plugin user want to use
    this._initUserPlugin(config.plugin);
    // add default config for container
    var containerConfig = chimeeHelper.deepAssign({}, defaultContainerConfig, config.container || {});
    // trigger the init life hook of plugin
    this.order.forEach(function (key) {
      return _this.plugins[key].__init(_this.videoConfig, containerConfig);
    });
    this.videoConfigReady = true;
    this.videoConfig.init();
    this.containerConfig = new Vessel(this, 'container', containerConfig);
    /**
     * video kernel
     * @type {Kernel}
     */
    this.kernel = this._createKernel(this.dom.videoElement, this.videoConfig);
    this.binder.applyPendingEvents('kernel');
    if (config.noDefaultContextMenu) {
      var noDefaultContextMenu = config.noDefaultContextMenu;

      var target = noDefaultContextMenu === 'container' || noDefaultContextMenu === 'wrapper' ? noDefaultContextMenu : 'video-dom';
      this.binder.on({
        target: target,
        id: '_vm',
        name: 'contextmenu',
        fn: function fn(evt) {
          return evt.preventDefault();
        },
        stage: 'main'
      });
    }
    // trigger auto load event
    var asyncInitedTasks = [];
    this.order.forEach(function (key) {
      var ready = _this.plugins[key].__inited();
      if (chimeeHelper.isPromise(ready)) {
        asyncInitedTasks.push(ready);
      }
    });
    this.readySync = asyncInitedTasks.length === 0;
    // tell them we have inited the whold player
    this.ready = this.readySync ? _Promise.resolve() : _Promise.all(asyncInitedTasks).then(function () {
      _this.readySync = true;
      _this.onReady();
    });
    if (this.readySync) this.onReady();
  }
function Dispatcher(config, vm) {
    var _this = this;

    _classCallCheck(this, Dispatcher);

    this.plugins = {};
    this.order = [];
    this.readySync = false;
    this.zIndexMap = {
      inner: [],
      outer: []
    };
    this.changeWatchable = true;
    this.kernelEventHandlerList = [];

    if (!chimeeHelper.isObject(config)) throw new TypeError('UserConfig must be an Object, but not "' + config + '" in ' + (typeof config === 'undefined' ? 'undefined' : _typeof(config)));
    
    this.dom = new Dom(config, this);
    
    this.vm = vm;
    
    this.videoConfigReady = false;
    
    this.videoConfig = new VideoConfig(this, config);
    
    
    if (chimeeHelper.isArray(config.plugins) && !chimeeHelper.isArray(config.plugin)) {
      config.plugin = config.plugins;
      delete config.plugins;
    }
    this.binder = new Binder(this);
    this.binder.listenOnMouseMoveEvent(this.dom.videoElement);
    
    this._initUserPlugin(config.plugin);
    
    var containerConfig = chimeeHelper.deepAssign({}, defaultContainerConfig, config.container || {});
    
    this.order.forEach(function (key) {
      return _this.plugins[key].__init(_this.videoConfig, containerConfig);
    });
    this.videoConfigReady = true;
    this.videoConfig.init();
    this.containerConfig = new Vessel(this, 'container', containerConfig);
    
    this.kernel = this._createKernel(this.dom.videoElement, this.videoConfig);
    this.binder.applyPendingEvents('kernel');
    if (config.noDefaultContextMenu) {
      var noDefaultContextMenu = config.noDefaultContextMenu;

      var target = noDefaultContextMenu === 'container' || noDefaultContextMenu === 'wrapper' ? noDefaultContextMenu : 'video-dom';
      this.binder.on({
        target: target,
        id: '_vm',
        name: 'contextmenu',
        fn: function fn(evt) {
          return evt.preventDefault();
        },
        stage: 'main'
      });
    }
    
    var asyncInitedTasks = [];
    this.order.forEach(function (key) {
      var ready = _this.plugins[key].__inited();
      if (chimeeHelper.isPromise(ready)) {
        asyncInitedTasks.push(ready);
      }
    });
    this.readySync = asyncInitedTasks.length === 0;
    
    this.ready = this.readySync ? _Promise.resolve() : _Promise.all(asyncInitedTasks).then(function () {
      _this.readySync = true;
      _this.onReady();
    });
    if (this.readySync) this.onReady();
  }
function Dispatcher ( config , vm ) { var _this = this ; _classCallCheck ( this , Dispatcher ) ; this . plugins = { } ; this . order = [ ] ; this . readySync = false ; this . zIndexMap = { inner : [ ] , outer : [ ] } ; this . changeWatchable = true ; this . kernelEventHandlerList = [ ] ; if ( ! chimeeHelper . isObject ( config ) ) throw new TypeError ( 'UserConfig must be an Object, but not "' + config + '" in ' + ( typeof config === 'undefined' ? 'undefined' : _typeof ( config ) ) ) ; /**
     * dom Manager
     * @type {Dom}
     */ this . dom = new Dom ( config , this ) ; /**
     * Chimee's referrence
     * @type {[type]}
     */ this . vm = vm ; /**
     * tell user have Chimee installed finished
     * @type {Promises}
     */ this . videoConfigReady = false ; // create the videoconfig this . videoConfig = new VideoConfig ( this , config ) ; // support both plugin and plugins here as people often cofuse both // $FlowFixMe: we support plugins here, which should be illegal if ( chimeeHelper . isArray ( config . plugins ) && ! chimeeHelper . isArray ( config . plugin ) ) { config . plugin = config . plugins ; delete config . plugins ; } this . binder = new Binder ( this ) ; this . binder . listenOnMouseMoveEvent ( this . dom . videoElement ) ; // use the plugin user want to use this . _initUserPlugin ( config . plugin ) ; // add default config for container var containerConfig = chimeeHelper . deepAssign ( { } , defaultContainerConfig , config . container || { } ) ; // trigger the init life hook of plugin this . order . forEach ( function ( key ) { return _this . plugins [ key ] . __init ( _this . videoConfig , containerConfig ) ; } ) ; this . videoConfigReady = true ; this . videoConfig . init ( ) ; this . containerConfig = new Vessel ( this , 'container' , containerConfig ) ; /**
     * video kernel
     * @type {Kernel}
     */ this . kernel = this . _createKernel ( this . dom . videoElement , this . videoConfig ) ; this . binder . applyPendingEvents ( 'kernel' ) ; if ( config . noDefaultContextMenu ) { var noDefaultContextMenu = config . noDefaultContextMenu ; var target = noDefaultContextMenu === 'container' || noDefaultContextMenu === 'wrapper' ? noDefaultContextMenu : 'video-dom' ; this . binder . on ( { target : target , id : '_vm' , name : 'contextmenu' , fn : function fn ( evt ) { return evt . preventDefault ( ) ; } , stage : 'main' } ) ; } // trigger auto load event var asyncInitedTasks = [ ] ; this . order . forEach ( function ( key ) { var ready = _this . plugins [ key ] . __inited ( ) ; if ( chimeeHelper . isPromise ( ready ) ) { asyncInitedTasks . push ( ready ) ; } } ) ; this . readySync = asyncInitedTasks . length === 0 ; // tell them we have inited the whold player this . ready = this . readySync ? _Promise . resolve ( ) : _Promise . all ( asyncInitedTasks ) . then ( function ( ) { _this . readySync = true ; _this . onReady ( ) ; } ) ; if ( this . readySync ) this . onReady ( ) ; }
the synchronous ready flag
@type {boolean}
@member readySync
 
all plugins instance set
@type {Object}
@member plugins
the synchronous ready flag