echarts.js 24.7 KB
Newer Older
L
lang 已提交
1
/**
L
lang 已提交
2
 * @module echarts
L
lang 已提交
3
 */
L
lang 已提交
4 5
define(function (require) {

L
lang 已提交
6
    var GlobalModel = require('./model/Global');
L
lang 已提交
7
    var ExtensionAPI = require('./ExtensionAPI');
L
lang 已提交
8
    var CoordinateSystemManager = require('./CoordinateSystem');
L
lang 已提交
9

L
Update  
lang 已提交
10 11 12 13 14 15
    var ComponentModel = require('./model/Component');
    var SeriesModel = require('./model/Series');

    var ComponentView = require('./view/Component');
    var ChartView = require('./view/Chart');

L
lang 已提交
16
    // var Scale = require('./scale/Scale');
L
lang 已提交
17

L
lang 已提交
18
    var zrender = require('zrender');
L
lang 已提交
19
    var zrUtil = require('zrender/core/util');
L
lang 已提交
20 21
    var colorTool = require('zrender/tool/color');
    var env = require('zrender/core/env');
L
lang 已提交
22
    var Eventful = require('zrender/mixin/Eventful');
L
lang 已提交
23

24 25
    var each = zrUtil.each;

26 27
    var VISUAL_CODING_STAGES = ['echarts', 'chart', 'component'];

L
lang 已提交
28
    // TODO Transform first or filter first
L
lang 已提交
29 30
    var PROCESSOR_STAGES = ['transform', 'filter', 'statistic'];

L
lang 已提交
31 32 33 34 35 36 37
    /**
     * @module echarts~MessageCenter
     */
    function MessageCenter() {
        Eventful.call(this);
    }
    zrUtil.mixin(MessageCenter, Eventful);
L
lang 已提交
38 39 40
    /**
     * @module echarts~ECharts
     */
L
lang 已提交
41
    function ECharts (dom, theme, opts) {
L
lang 已提交
42
        opts = opts || {};
L
lang 已提交
43

L
lang 已提交
44 45 46 47 48
        if (theme) {
            each(optionPreprocessorFuncs, function (preProcess) {
                preProcess(theme);
            });
        }
L
lang 已提交
49 50 51 52 53 54 55 56 57
        /**
         * @type {string}
         */
        this.id;
        /**
         * Group id
         * @type {string}
         */
        this.group;
L
lang 已提交
58 59 60 61 62
        /**
         * @type {HTMLDomElement}
         * @private
         */
        this._dom = dom;
L
lang 已提交
63 64 65 66
        /**
         * @type {module:zrender/ZRender}
         * @private
         */
L
lang 已提交
67 68 69
        this._zr = zrender.init(dom, {
            renderer: opts.renderer || 'canvas'
        });
L
lang 已提交
70

L
lang 已提交
71 72 73 74
        /**
         * @type {Object}
         * @private
         */
L
lang 已提交
75
        this._theme = zrUtil.clone(theme, true);
L
lang 已提交
76

L
lang 已提交
77 78 79 80
        /**
         * @type {Array.<module:echarts/view/Chart>}
         * @private
         */
L
lang 已提交
81
        this._chartsList = [];
L
lang 已提交
82 83 84 85 86

        /**
         * @type {Object.<string, module:echarts/view/Chart>}
         * @private
         */
L
lang 已提交
87 88
        this._chartsMap = {};

L
lang 已提交
89 90 91 92
        /**
         * @type {Array.<module:echarts/view/Component>}
         * @private
         */
L
lang 已提交
93
        this._componentsList = [];
L
lang 已提交
94 95 96 97 98

        /**
         * @type {Object.<string, module:echarts/view/Component>}
         * @private
         */
L
lang 已提交
99 100
        this._componentsMap = {};

L
lang 已提交
101
        /**
L
lang 已提交
102
         * @type {module:echarts/ExtensionAPI}
L
lang 已提交
103 104
         * @private
         */
105
        this._api = new ExtensionAPI(this);
L
lang 已提交
106

L
lang 已提交
107 108 109 110
        /**
         * @type {module:echarts/CoordinateSystem}
         * @private
         */
L
lang 已提交
111
        this._coordinateSystem = new CoordinateSystemManager();
L
lang 已提交
112

L
lang 已提交
113 114
        Eventful.call(this);

L
lang 已提交
115 116 117 118 119 120
        /**
         * @type {module:echarts~MessageCenter}
         * @private
         */
        this._messageCenter = new MessageCenter();

L
lang 已提交
121 122
        // Init mouse events
        this._initEvents();
L
Resize  
lang 已提交
123 124 125

        // In case some people write `window.onresize = chart.resize`
        this.resize = zrUtil.bind(this.resize, this);
L
lang 已提交
126
    }
L
lang 已提交
127

L
tweak  
lang 已提交
128
    var echartsProto = ECharts.prototype;
L
lang 已提交
129

130 131 132
    /**
     * @return {HTMLDomElement}
     */
L
tweak  
lang 已提交
133 134 135
    echartsProto.getDom = function () {
        return this._dom;
    };
L
lang 已提交
136

137 138 139
    /**
     * @return {module:zrender~ZRender}
     */
L
tweak  
lang 已提交
140 141 142
    echartsProto.getZr = function () {
        return this._zr;
    };
L
lang 已提交
143

144 145 146 147 148 149
    /**
     * @param {Object} option
     * @param {boolean} notMerge
     * @param {boolean} [notRefreshImmediately=false]
     */
    echartsProto.setOption = function (option, notMerge, notRefreshImmediately) {
L
tweak  
lang 已提交
150 151
        // PENDING
        option = zrUtil.clone(option, true);
152

L
tweak  
lang 已提交
153 154 155
        each(optionPreprocessorFuncs, function (preProcess) {
            preProcess(option);
        });
L
lang 已提交
156

L
tweak  
lang 已提交
157 158 159 160 161 162 163 164 165
        var ecModel = this._model;
        if (!ecModel || notMerge) {
            ecModel = new GlobalModel(option, null, this._theme);
            this._model = ecModel;
        }
        else {
            ecModel.restoreData();
            ecModel.mergeOption(option);
        }
L
lang 已提交
166

167
        prepareView.call(this, 'component', ecModel);
L
lang 已提交
168

169
        prepareView.call(this, 'chart', ecModel);
L
lang 已提交
170

171
        updateMethods.update.call(this);
L
lang 已提交
172

173
        !notRefreshImmediately && this._zr.refreshImmediately();
L
tweak  
lang 已提交
174
    };
L
lang 已提交
175

L
Tweak  
lang 已提交
176 177 178 179 180 181
    /**
     * @DEPRECATED
     */
    echartsProto.setTheme = function () {
        console.log('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
    };
L
tweak  
lang 已提交
182 183 184 185 186 187
    /**
     * @return {module:echarts/model/Global}
     */
    echartsProto.getModel = function () {
        return this._model;
    };
L
lang 已提交
188

L
tweak  
lang 已提交
189 190 191 192 193 194
    /**
     * @return {number}
     */
    echartsProto.getWidth = function () {
        return this._zr.getWidth();
    };
L
lang 已提交
195

L
tweak  
lang 已提交
196 197 198 199 200 201
    /**
     * @return {number}
     */
    echartsProto.getHeight = function () {
        return this._zr.getHeight();
    };
L
lang 已提交
202

203

204 205 206 207 208 209 210 211
    var updateMethods = {

        /**
         * @param {Object} payload
         * @private
         */
        update: function (payload) {
            console.time && console.time('update');
L
lang 已提交
212

213
            var ecModel = this._model;
L
lang 已提交
214

215 216 217 218 219
            ecModel.restoreData();

            // TODO
            // Save total ecModel here for undo/redo (after restoring data and before processing data).
            // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
P
pah100 已提交
220

221
            processData.call(this, ecModel);
L
lang 已提交
222

223
            stackSeriesData.call(this, ecModel);
L
lang 已提交
224

225
            this._coordinateSystem.update(ecModel, this._api);
L
lang 已提交
226

227
            doLayout.call(this, ecModel, payload);
228

229
            doVisualCoding.call(this, ecModel, payload);
230

231
            doRender.call(this, ecModel, payload);
232

233 234 235 236 237 238 239 240 241
            // Set background
            var backgroundColor = ecModel.get('backgroundColor');
            // In IE8
            if (!env.canvasSupported) {
                var colorArr = colorTool.parse(backgroundColor);
                backgroundColor = colorTool.stringify(colorArr, 'rgb');
                if (colorArr[3] === 0) {
                    backgroundColor = 'transparent';
                }
L
lang 已提交
242
            }
243
            backgroundColor && (this._dom.style.backgroundColor = backgroundColor);
L
lang 已提交
244

245 246
            console.time && console.timeEnd('update');
        },
247

248 249 250 251 252 253 254
        // PENDING
        /**
         * @param {Object} payload
         * @private
         */
        updateView: function (payload) {
            var ecModel = this._model;
255

256
            doLayout.call(this, ecModel, payload);
257

258
            doVisualCoding.call(this, ecModel, payload);
259

260 261
            invokeUpdateMethod.call(this, 'updateView', ecModel, payload);
        },
262

263 264 265 266 267 268
        /**
         * @param {Object} payload
         * @private
         */
        updateVisual: function (payload) {
            var ecModel = this._model;
269

270
            doVisualCoding.call(this, ecModel, payload);
271

272 273
            invokeUpdateMethod.call(this, 'updateVisual', ecModel, payload);
        },
274

275 276 277 278 279 280
        /**
         * @param {Object} payload
         * @private
         */
        updateLayout: function (payload) {
            var ecModel = this._model;
281

282
            doLayout.call(this, ecModel, payload);
283

284 285
            invokeUpdateMethod.call(this, 'updateLayout', ecModel, payload);
        },
L
lang 已提交
286

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
        /**
         * @param {Object} payload
         * @private
         */
        highlight: function (payload) {
            toggleHighlight.call(this, 'highlight', payload);
        },

        /**
         * @param {Object} payload
         * @private
         */
        downplay: function (payload) {
            toggleHighlight.call(this, 'downplay', payload);
        }
302 303 304 305 306 307 308

    };

    /**
     * @param {Object} payload
     * @private
     */
309
    function toggleHighlight(method, payload) {
310
        var ecModel = this._model;
311 312 313 314

        ecModel.eachComponent(
            {mainType: 'series', query: payload},
            function (seriesModel) {
P
tweak  
pah100 已提交
315
                var chartView = this._chartsMap[seriesModel.id];
316 317 318 319 320 321
                if (chartView) {
                    chartView[method](seriesModel, ecModel, this._api, payload);
                }
            },
            this
        );
322
    }
323

L
Resize  
lang 已提交
324 325 326
    /**
     * Resize the chart
     */
L
tweak  
lang 已提交
327
    echartsProto.resize = function () {
L
Resize  
lang 已提交
328
        this._zr.resize();
L
tweak  
lang 已提交
329
        this._update();
L
tweak  
lang 已提交
330
    };
P
pah100 已提交
331

L
lang 已提交
332
    /**
L
Resize  
lang 已提交
333 334
     * @param {Object} eventObj
     * @return {Object}
L
lang 已提交
335 336 337 338 339 340 341
     */
    echartsProto.makeActionFromEvent = function (eventObj) {
        var payload = zrUtil.extend({}, eventObj);
        payload.type = eventActionMap[eventObj.type];
        return payload;
    };

L
tweak  
lang 已提交
342 343 344 345
    /**
     * @pubilc
     * @param {Object} payload
     * @param {string} [payload.type] Action type
P
pah100 已提交
346
     * @param {boolean} [silent=false] Whether trigger event.
L
tweak  
lang 已提交
347 348
     * @param {number} [payload.from] From uid
     */
P
pah100 已提交
349
    echartsProto.dispatch = function (payload, silent) {
L
tweak  
lang 已提交
350 351
        var actionWrap = actions[payload.type];
        if (actionWrap) {
L
lang 已提交
352 353
            var actionInfo = actionWrap.actionInfo;
            var updateMethod = actionInfo.update || 'update';
L
tweak  
lang 已提交
354
            actionWrap.action(payload, this._model);
355
            updateMethod !== 'none' && updateMethods[updateMethod].call(this, payload);
L
lang 已提交
356

P
pah100 已提交
357 358 359 360 361
            if (!silent) {
                // Emit event outside
                // Convert type to eventType
                var eventObj = zrUtil.extend({}, payload);
                eventObj.type = actionInfo.event || eventObj.type;
L
lang 已提交
362
                this._messageCenter.trigger(eventObj.type, eventObj);
P
pah100 已提交
363
            }
L
tweak  
lang 已提交
364 365
        }
    };
366

L
tweak  
lang 已提交
367 368 369 370
    /**
     * @param {string} methodName
     * @private
     */
371
    function invokeUpdateMethod(methodName, ecModel, payload) {
372
        var api = this._api;
L
lang 已提交
373

L
tweak  
lang 已提交
374 375 376 377
        // Update all components
        each(this._componentsList, function (component) {
            var componentModel = component.__model;
            component[methodName](componentModel, ecModel, api, payload);
378

L
tweak  
lang 已提交
379 380
            updateZ(componentModel, component);
        }, this);
L
lang 已提交
381

L
tweak  
lang 已提交
382 383
        // Upate all charts
        ecModel.eachSeries(function (seriesModel, idx) {
P
tweak  
pah100 已提交
384
            var chart = this._chartsMap[seriesModel.id];
L
tweak  
lang 已提交
385
            chart[methodName](seriesModel, ecModel, api, payload);
386

L
tweak  
lang 已提交
387 388
            updateZ(seriesModel, chart);
        }, this);
389

390
    }
L
lang 已提交
391

L
lang 已提交
392
    /**
L
Tweak  
lang 已提交
393
     * Prepare view instances of charts and components
L
lang 已提交
394 395 396
     * @param  {module:echarts/model/Global} ecModel
     * @private
     */
397
    function prepareView(type, ecModel) {
L
Tweak  
lang 已提交
398 399 400
        var isComponent = type === 'component';
        var viewList = isComponent ? this._componentsList : this._chartsList;
        var viewMap = isComponent ? this._componentsMap : this._chartsMap;
L
tweak  
lang 已提交
401
        var zr = this._zr;
L
lang 已提交
402

L
Tweak  
lang 已提交
403 404
        for (var i = 0; i < viewList.length; i++) {
            viewList[i].__keepAlive = false;
L
tweak  
lang 已提交
405
        }
L
lang 已提交
406

L
Tweak  
lang 已提交
407 408 409 410
        ecModel[isComponent ? 'eachComponent' : 'eachSeries'](function (componentType, model) {
            if (isComponent) {
                if (componentType === 'series') {
                    return;
L
lang 已提交
411
                }
412
            }
L
tweak  
lang 已提交
413
            else {
L
Tweak  
lang 已提交
414
                model = componentType;
L
tweak  
lang 已提交
415 416
            }

P
tweak  
pah100 已提交
417
            var view = viewMap[model.id];
L
Tweak  
lang 已提交
418 419 420
            if (!view) {
                var classType = ComponentModel.parseClassType(model.type);
                var Clazz = isComponent
L
tweak  
lang 已提交
421
                    ? ComponentView.getClass(classType.main, classType.sub)
L
Tweak  
lang 已提交
422
                    : ChartView.getClass(classType.sub);
L
tweak  
lang 已提交
423
                if (Clazz) {
L
Tweak  
lang 已提交
424 425
                    view = new Clazz();
                    view.init(ecModel, this._api);
P
tweak  
pah100 已提交
426
                    viewMap[model.id] = view;
L
Tweak  
lang 已提交
427 428 429 430 431
                    viewList.push(view);
                    zr.add(view.group);
                }
                else {
                    // Error
L
lang 已提交
432
                }
433
            }
L
Tweak  
lang 已提交
434 435

            view.__keepAlive = true;
P
tweak  
pah100 已提交
436
            view.__id = model.id;
L
Tweak  
lang 已提交
437
            view.__model = model;
L
tweak  
lang 已提交
438 439
        }, this);

L
Tweak  
lang 已提交
440 441 442 443 444 445 446
        for (var i = 0; i < viewList.length;) {
            var view = viewList[i];
            if (!view.__keepAlive) {
                zr.remove(view.group);
                view.dispose(this._api);
                viewList.splice(i, 1);
                delete viewMap[view.__id];
L
tweak  
lang 已提交
447 448 449 450 451
            }
            else {
                i++;
            }
        }
452 453
    }

L
tweak  
lang 已提交
454 455 456 457 458 459
    /**
     * Processor data in each series
     *
     * @param {module:echarts/model/Global} ecModel
     * @private
     */
460
    function processData(ecModel) {
L
tweak  
lang 已提交
461 462 463
        each(PROCESSOR_STAGES, function (stage) {
            each(dataProcessorFuncs[stage] || [], function (process) {
                process(ecModel);
L
lang 已提交
464
            });
L
tweak  
lang 已提交
465
        });
466
    }
L
lang 已提交
467

L
tweak  
lang 已提交
468 469 470
    /**
     * @private
     */
471
    function stackSeriesData(ecModel) {
L
tweak  
lang 已提交
472 473 474 475 476 477 478 479
        var stackedDataMap = {};
        ecModel.eachSeries(function (series) {
            var stack = series.get('stack');
            var data = series.getData();
            if (stack && data.type === 'list') {
                var previousStack = stackedDataMap[stack];
                if (previousStack) {
                    data.stackedOn = previousStack;
L
lang 已提交
480
                }
L
tweak  
lang 已提交
481 482 483
                stackedDataMap[stack] = data;
            }
        });
484
    }
L
lang 已提交
485

L
tweak  
lang 已提交
486
    /**
L
lang 已提交
487
     * Layout before each chart render there series, after visual coding and data processing
L
tweak  
lang 已提交
488 489 490 491
     *
     * @param {module:echarts/model/Global} ecModel
     * @private
     */
492
    function doLayout(ecModel, payload) {
493
        var api = this._api;
L
tweak  
lang 已提交
494 495 496
        each(layoutFuncs, function (layout) {
            layout(ecModel, api, payload);
        });
497
    }
L
lang 已提交
498

L
tweak  
lang 已提交
499 500 501 502 503 504
    /**
     * Code visual infomation from data after data processing
     *
     * @param {module:echarts/model/Global} ecModel
     * @private
     */
505
    function doVisualCoding(ecModel, payload) {
L
tweak  
lang 已提交
506 507 508
        each(VISUAL_CODING_STAGES, function (stage) {
            each(visualCodingFuncs[stage] || [], function (visualCoding) {
                visualCoding(ecModel, payload);
L
lang 已提交
509
            });
L
tweak  
lang 已提交
510
        });
511
    }
L
lang 已提交
512

L
tweak  
lang 已提交
513 514 515 516
    /**
     * Render each chart and component
     * @private
     */
517
    function doRender(ecModel, payload) {
518
        var api = this._api;
L
tweak  
lang 已提交
519 520 521 522 523 524 525 526 527 528 529 530 531 532
        // Render all components
        each(this._componentsList, function (component) {
            var componentModel = component.__model;
            component.render(componentModel, ecModel, api, payload);

            updateZ(componentModel, component);
        }, this);

        each(this._chartsList, function (chart) {
            chart.__keepAlive = false;
        }, this);

        // Render all charts
        ecModel.eachSeries(function (seriesModel, idx) {
P
tweak  
pah100 已提交
533
            var chart = this._chartsMap[seriesModel.id];
L
tweak  
lang 已提交
534 535 536 537 538 539
            chart.__keepAlive = true;
            chart.render(seriesModel, ecModel, api, payload);

            updateZ(seriesModel, chart);
        }, this);

L
lang 已提交
540
        // Remove groups of unrendered charts
L
tweak  
lang 已提交
541 542 543 544 545
        each(this._chartsList, function (chart) {
            if (!chart.__keepAlive) {
                chart.remove(ecModel, api);
            }
        }, this);
546
    }
L
lang 已提交
547

L
lang 已提交
548 549 550 551 552 553 554 555 556 557 558 559 560
    var MOUSE_EVENT_NAMES = [
        'click', 'dblclick', 'mouseover', 'mouseout', 'globalout'
    ];
    /**
     * @private
     */
    echartsProto._initEvents = function () {
        var zr = this._zr;
        each(MOUSE_EVENT_NAMES, function (eveName) {
            zr.on(eveName, function (e) {
                var ecModel = this.getModel();
                var el = e.target;
                if (el && el.dataIndex != null) {
561
                    var hostModel = el.hostModel || ecModel.getSeriesByIndex(el.seriesIndex);
L
lang 已提交
562 563 564 565 566 567 568
                    var params = hostModel && hostModel.getDataParams(el.dataIndex) || {};
                    params.event = e;
                    params.type = eveName;
                    this.trigger(eveName, params);
                }
            }, this);
        }, this);
L
lang 已提交
569 570 571 572 573 574

        zrUtil.each(eventActionMap, function (actionType, eventType) {
            this._messageCenter.on(eventType, function (event) {
                this.trigger(eventType, event);
            }, this);
        }, this);
L
lang 已提交
575 576
    };

L
lang 已提交
577 578 579 580 581 582 583 584 585
    /**
     * @return {boolean]
     */
    echartsProto.isDisposed = function () {
        return this._disposed;
    };
    /**
     * Dispose instance
     */
L
tweak  
lang 已提交
586
    echartsProto.dispose = function () {
L
lang 已提交
587 588
        this._disposed = true;

L
tweak  
lang 已提交
589 590 591 592 593 594
        each(this._components, function (component) {
            component.dispose();
        });
        each(this._charts, function (chart) {
            chart.dispose();
        });
L
lang 已提交
595

L
Tweak  
lang 已提交
596
        this._zr.dispose();
L
lang 已提交
597 598

        instances[this.id] = null;
L
lang 已提交
599 600
    };

L
lang 已提交
601 602
    zrUtil.mixin(ECharts, Eventful);

L
lang 已提交
603 604 605 606 607 608 609 610 611 612 613 614 615 616
    /**
     * @param {module:echarts/model/Series|module:echarts/model/Component} model
     * @param {module:echarts/view/Component|module:echarts/view/Chart} view
     * @return {string}
     */
    function updateZ(model, view) {
        var z = model.get('z');
        var zlevel = model.get('zlevel');
        // Set z and zlevel
        view.group.traverse(function (el) {
            z != null && (el.z = z);
            zlevel != null && (el.zlevel = zlevel);
        });
    }
L
lang 已提交
617 618 619 620
    /**
     * @type {Array.<Function>}
     * @inner
     */
P
pah100 已提交
621 622
    var actions = [];

L
lang 已提交
623
    /**
L
lang 已提交
624
     * Map eventType to actionType
L
lang 已提交
625 626 627 628
     * @type {Object}
     */
    var eventActionMap = {};

L
lang 已提交
629 630 631 632
    /**
     * @type {Array.<Function>}
     * @inner
     */
633 634
    var layoutFuncs = [];

L
lang 已提交
635 636 637 638 639 640 641
    /**
     * Data processor functions of each stage
     * @type {Array.<Object.<string, Function>>}
     * @inner
     */
    var dataProcessorFuncs = {};

642 643 644 645 646 647
    /**
     * @type {Array.<Function>}
     * @inner
     */
    var optionPreprocessorFuncs = [];

L
lang 已提交
648 649 650 651 652
    /**
     * Visual coding functions of each stage
     * @type {Array.<Object.<string, Function>>}
     * @inner
     */
653
    var visualCodingFuncs = {};
L
lang 已提交
654

L
lang 已提交
655 656 657 658 659 660
    var instances = {};
    var connectedGroups = {};

    var idBase = new Date() - 0;
    var groupIdBase = new Date() - 0;
    var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
L
lang 已提交
661
    /**
L
lang 已提交
662
     * @alias module:echarts
L
lang 已提交
663
     */
L
lang 已提交
664 665 666 667 668 669 670 671 672
    var echarts = {
        /**
         * @type {number}
         */
        version: '3.0.0',
        dependencies: {
            zrender: '3.0.0'
        }
    };
L
lang 已提交
673

L
tweak  
lang 已提交
674 675 676 677 678 679
    /**
     * @param {HTMLDomElement} dom
     * @param {Object} [theme]
     * @param {Object} opts
     */
    echarts.init = function (dom, theme, opts) {
L
lang 已提交
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
        // Check version
        if ((zrender.version.replace('.', '') - 0) < (echarts.dependencies.zrender.replace('.', '') - 0)) {
            console.error(
                'ZRender ' + zrender.version
                + ' is too old for ECharts ' + echarts.version
                + '. Current version need ZRender '
                + echarts.dependencies.zrender + '+'
            );
        }

        var chart = new ECharts(dom, theme, opts);
        chart.id = idBase++;
        instances[chart.id] = chart;

        // Connecting
        zrUtil.each(eventActionMap, function (actionType, eventType) {
L
lang 已提交
696 697
            // FIXME
            chart._messageCenter.on(eventType, function (event) {
L
lang 已提交
698 699 700
                if (connectedGroups[chart.group]) {
                    chart.__connectedActionDispatching = true;
                    for (var id in instances) {
L
tweak  
lang 已提交
701
                        var action = chart.makeActionFromEvent(event);
L
lang 已提交
702 703
                        var otherChart = instances[id];
                        if (otherChart !== chart && otherChart.group === chart.group) {
L
tweak  
lang 已提交
704 705 706
                            if (!otherChart.__connectedActionDispatching) {
                                otherChart.dispatch(action);
                            }
L
lang 已提交
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
                        }
                    }
                    chart.__connectedActionDispatching = false;
                }
            });
        });

        return chart;
    };

    /**
     * @return {string|Array.<module:echarts~ECharts>} groupId
     */
    echarts.connect = function (groupId) {
        // Is array of charts
        if (zrUtil.isArray(groupId)) {
            var charts = groupId;
            groupId = null;
            // If any chart has group
            zrUtil.each(charts, function (chart) {
                if (chart.group != null) {
                    groupId = chart.group;
                }
            });
            groupId = groupId || groupIdBase++;
            zrUtil.each(charts, function (chart) {
                chart.group = groupId;
            });
        }
        connectedGroups[groupId] = true;
        return groupId;
    };

    /**
     * @return {string} groupId
     */
    echarts.disConnect = function (groupId) {
        connectedGroups[groupId] = false;
    };

    /**
     * Dispose a chart instance
     * @param  {module:echarts~ECharts|HTMLDomElement|string} chart
     */
    echarts.dispose = function (chart) {
        if (zrUtil.isDom(chart)) {
            chart = echarts.getInstanceByDom(chart);
        }
        else if (typeof chart === 'string') {
            chart = instances[chart];
        }
        if ((chart instanceof ECharts) && !chart.isDisposed()) {
            chart.dispose();
        }
    };

    /**
     * @param  {HTMLDomElement} dom
     * @return {echarts~ECharts}
     */
    echarts.getInstanceByDom = function (dom) {
        var key = dom.getAttribute(DOM_ATTRIBUTE_KEY);
        return instances[key];
    };
    /**
     * @param {string} key
     * @return {echarts~ECharts}
     */
    echarts.getInstanceById = function (key) {
        return instances[key];
L
tweak  
lang 已提交
777
    };
L
lang 已提交
778

L
tweak  
lang 已提交
779 780 781 782 783 784 785
    /**
     * Register option preprocessor
     * @param {Function} preprocessorFunc
     */
    echarts.registerPreprocessor = function (preprocessorFunc) {
        optionPreprocessorFuncs.push(preprocessorFunc);
    };
786

L
tweak  
lang 已提交
787 788 789 790 791 792 793 794 795 796 797
    /**
     * @param {string} stage
     * @param {Function} processorFunc
     */
    echarts.registerProcessor = function (stage, processorFunc) {
        if (zrUtil.indexOf(PROCESSOR_STAGES, stage) < 0) {
            throw new Error('stage should be one of ' + PROCESSOR_STAGES);
        }
        var funcs = dataProcessorFuncs[stage] || (dataProcessorFuncs[stage] = []);
        funcs.push(processorFunc);
    };
L
lang 已提交
798

L
tweak  
lang 已提交
799 800 801 802 803 804 805 806 807 808 809
    /**
     * Usage:
     * registerAction('someAction', 'someEvent', function () { ... });
     * registerAction('someAction', function () { ... });
     * registerAction(
     *     {type: 'someAction', event: 'someEvent', update: 'updateView'},
     *     function () { ... }
     * );
     *
     * @param {(string|Object)} actionInfo
     * @param {string} actionInfo.type
L
lang 已提交
810 811 812 813
     * @param {string} [actionInfo.event]
     * @param {string} [actionInfo.update]
     * @param {string} [eventName]
     * @param {Function} action
L
tweak  
lang 已提交
814
     */
L
lang 已提交
815 816 817 818 819
    echarts.registerAction = function (actionInfo, eventName, action) {
        if (typeof eventName === 'function') {
            action = eventName;
            eventName = '';
        }
L
tweak  
lang 已提交
820 821
        var actionType = zrUtil.isObject(actionInfo)
            ? actionInfo.type
L
lang 已提交
822 823 824
            : ([actionInfo, actionInfo = {
                event: eventName
            }][0]);
L
lang 已提交
825 826

        actionInfo.event = actionInfo.event || actionType;
L
lang 已提交
827
        eventName = actionInfo.event;
828

L
tweak  
lang 已提交
829 830 831
        if (!actions[actionType]) {
            actions[actionType] = {action: action, actionInfo: actionInfo};
        }
L
lang 已提交
832
        eventActionMap[eventName] = actionType;
L
tweak  
lang 已提交
833
    };
P
pah100 已提交
834

L
tweak  
lang 已提交
835 836 837 838 839 840 841
    /**
     * @param {string} type
     * @param {*} CoordinateSystem
     */
    echarts.registerCoordinateSystem = function (type, CoordinateSystem) {
        CoordinateSystemManager.register(type, CoordinateSystem);
    };
L
lang 已提交
842

L
tweak  
lang 已提交
843 844 845
    /**
     * @param {*} layout
     */
L
lang 已提交
846
    echarts.registerLayout = function (layout) {
L
tweak  
lang 已提交
847
        // PENDING All functions ?
848 849
        if (zrUtil.indexOf(layoutFuncs, layout) < 0) {
            layoutFuncs.push(layout);
L
tweak  
lang 已提交
850 851
        }
    };
L
lang 已提交
852

L
tweak  
lang 已提交
853 854 855 856 857 858 859 860 861 862 863
    /**
     * @param {string} stage
     * @param {Function} visualCodingFunc
     */
    echarts.registerVisualCoding = function (stage, visualCodingFunc) {
        if (zrUtil.indexOf(VISUAL_CODING_STAGES, stage) < 0) {
            throw new Error('stage should be one of ' + VISUAL_CODING_STAGES);
        }
        var funcs = visualCodingFuncs[stage] || (visualCodingFuncs[stage] = []);
        funcs.push(visualCodingFunc);
    };
L
Update  
lang 已提交
864

L
tweak  
lang 已提交
865
    /**
L
lang 已提交
866
     * @param {echarts/scale/*} scale
L
tweak  
lang 已提交
867
     */
L
Tweak  
lang 已提交
868 869 870
    // echarts.extendScale = function (opts) {
    //     return Scale.extend(opts);
    // };
L
lang 已提交
871

L
tweak  
lang 已提交
872 873 874 875 876 877
    /**
     * @param {Object} opts
     */
    echarts.extendChartView = function (opts) {
        return ChartView.extend(opts);
    };
L
Update  
lang 已提交
878

L
tweak  
lang 已提交
879 880 881 882 883 884
    /**
     * @param {Object} opts
     */
    echarts.extendComponentModel = function (opts) {
        return ComponentModel.extend(opts);
    };
L
Update  
lang 已提交
885

L
tweak  
lang 已提交
886 887 888 889 890 891
    /**
     * @param {Object} opts
     */
    echarts.extendSeriesModel = function (opts) {
        return SeriesModel.extend(opts);
    };
P
pah100 已提交
892

L
tweak  
lang 已提交
893 894 895 896 897
    /**
     * @param {Object} opts
     */
    echarts.extendComponentView = function (opts) {
        return ComponentView.extend(opts);
L
lang 已提交
898 899
    };

L
lang 已提交
900
    echarts.registerVisualCoding('echarts', require('./visual/seriesColor'));
901 902
    echarts.registerPreprocessor(require('./preprocessor/backwardCompat'));

903 904 905 906 907 908 909 910 911 912 913 914
    // Default action
    echarts.registerAction({
        type: 'highlight',
        event: 'highlight',
        update: 'highlight'
    }, zrUtil.noop);
    echarts.registerAction({
        type: 'downplay',
        event: 'downplay',
        update: 'downplay'
    }, zrUtil.noop);

L
lang 已提交
915 916
    return echarts;
});