echarts.js 25.1 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 17
    var scaleClasses = require('./scale/scale');

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
    /**
     * @module echarts~ECharts
     */
L
lang 已提交
34
    function ECharts (dom, theme, opts) {
L
lang 已提交
35
        opts = opts || {};
L
lang 已提交
36

L
lang 已提交
37 38 39 40 41 42 43 44 45
        /**
         * @type {string}
         */
        this.id;
        /**
         * Group id
         * @type {string}
         */
        this.group;
L
lang 已提交
46 47 48 49 50
        /**
         * @type {HTMLDomElement}
         * @private
         */
        this._dom = dom;
L
lang 已提交
51 52 53 54
        /**
         * @type {module:zrender/ZRender}
         * @private
         */
L
lang 已提交
55 56 57
        this._zr = zrender.init(dom, {
            renderer: opts.renderer || 'canvas'
        });
L
lang 已提交
58

L
lang 已提交
59 60 61 62
        /**
         * @type {Object}
         * @private
         */
L
lang 已提交
63
        this._theme = zrUtil.clone(theme);
L
lang 已提交
64

L
lang 已提交
65 66 67 68
        /**
         * @type {Array.<module:echarts/view/Chart>}
         * @private
         */
L
lang 已提交
69
        this._chartsList = [];
L
lang 已提交
70 71 72 73 74

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

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

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

L
lang 已提交
89
        /**
L
lang 已提交
90
         * @type {module:echarts/ExtensionAPI}
L
lang 已提交
91 92
         * @private
         */
93
        this._api = new ExtensionAPI(this);
L
lang 已提交
94

L
lang 已提交
95 96 97 98
        /**
         * @type {module:echarts/CoordinateSystem}
         * @private
         */
L
lang 已提交
99
        this._coordinateSystem = new CoordinateSystemManager();
L
lang 已提交
100

L
lang 已提交
101 102 103 104
        Eventful.call(this);

        // Init mouse events
        this._initEvents();
L
Resize  
lang 已提交
105 106 107

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

L
tweak  
lang 已提交
110
    var echartsProto = ECharts.prototype;
L
lang 已提交
111

112 113 114
    /**
     * @return {HTMLDomElement}
     */
L
tweak  
lang 已提交
115 116 117
    echartsProto.getDom = function () {
        return this._dom;
    };
L
lang 已提交
118

119 120 121
    /**
     * @return {module:zrender~ZRender}
     */
L
tweak  
lang 已提交
122 123 124
    echartsProto.getZr = function () {
        return this._zr;
    };
L
lang 已提交
125

126 127 128 129 130 131
    /**
     * @param {Object} option
     * @param {boolean} notMerge
     * @param {boolean} [notRefreshImmediately=false]
     */
    echartsProto.setOption = function (option, notMerge, notRefreshImmediately) {
L
tweak  
lang 已提交
132 133
        // PENDING
        option = zrUtil.clone(option, true);
134

L
tweak  
lang 已提交
135 136 137
        each(optionPreprocessorFuncs, function (preProcess) {
            preProcess(option);
        });
L
lang 已提交
138

L
tweak  
lang 已提交
139 140 141 142 143 144 145 146 147
        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 已提交
148

L
tweak  
lang 已提交
149
        this._prepareComponents(ecModel);
L
lang 已提交
150

L
tweak  
lang 已提交
151
        this._prepareCharts(ecModel);
L
lang 已提交
152

L
tweak  
lang 已提交
153
        this._update();
L
lang 已提交
154

155
        !notRefreshImmediately && this._zr.refreshImmediately();
L
tweak  
lang 已提交
156
    };
L
lang 已提交
157

L
tweak  
lang 已提交
158 159 160 161 162 163
    /**
     * @return {module:echarts/model/Global}
     */
    echartsProto.getModel = function () {
        return this._model;
    };
L
lang 已提交
164

L
tweak  
lang 已提交
165 166 167 168 169 170
    /**
     * @return {number}
     */
    echartsProto.getWidth = function () {
        return this._zr.getWidth();
    };
L
lang 已提交
171

L
tweak  
lang 已提交
172 173 174 175 176 177
    /**
     * @return {number}
     */
    echartsProto.getHeight = function () {
        return this._zr.getHeight();
    };
L
lang 已提交
178

L
tweak  
lang 已提交
179 180
    /**
     * @param {Object} payload
L
tweak  
lang 已提交
181
     * @private
L
tweak  
lang 已提交
182
     */
L
tweak  
lang 已提交
183
    echartsProto._update = function (payload) {
L
lang 已提交
184
        console.time && console.time('update');
185

L
tweak  
lang 已提交
186
        var ecModel = this._model;
L
lang 已提交
187

L
tweak  
lang 已提交
188
        ecModel.restoreData();
L
lang 已提交
189

L
tweak  
lang 已提交
190 191 192
        // 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 已提交
193

L
tweak  
lang 已提交
194
        this._processData(ecModel);
L
lang 已提交
195

L
tweak  
lang 已提交
196
        this._stackSeriesData(ecModel);
L
lang 已提交
197

198
        this._coordinateSystem.update(ecModel, this._api);
L
lang 已提交
199

L
tweak  
lang 已提交
200
        this._doLayout(ecModel, payload);
201

L
tweak  
lang 已提交
202
        this._doVisualCoding(ecModel, payload);
203

L
tweak  
lang 已提交
204
        this._doRender(ecModel, payload);
205

L
tweak  
lang 已提交
206 207 208 209 210 211 212 213
        // 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 已提交
214
            }
L
tweak  
lang 已提交
215 216
        }
        backgroundColor && (this._dom.style.backgroundColor = backgroundColor);
L
lang 已提交
217

L
lang 已提交
218
        console.time && console.timeEnd('update');
L
tweak  
lang 已提交
219
    };
220

L
tweak  
lang 已提交
221 222 223
    // PENDING
    /**
     * @param {Object} payload
L
tweak  
lang 已提交
224
     * @private
L
tweak  
lang 已提交
225
     */
L
tweak  
lang 已提交
226
    echartsProto._updateView = function (payload) {
L
tweak  
lang 已提交
227
        var ecModel = this._model;
228

L
tweak  
lang 已提交
229
        this._doLayout(ecModel, payload);
230

L
tweak  
lang 已提交
231
        this._doVisualCoding(ecModel, payload);
232

L
tweak  
lang 已提交
233 234
        this._invokeUpdateMethod('updateView', ecModel, payload);
    };
235

L
tweak  
lang 已提交
236 237
    /**
     * @param {Object} payload
L
tweak  
lang 已提交
238
     * @private
L
tweak  
lang 已提交
239
     */
L
tweak  
lang 已提交
240
    echartsProto._updateVisual = function (payload) {
L
tweak  
lang 已提交
241
        var ecModel = this._model;
242

L
tweak  
lang 已提交
243
        this._doVisualCoding(ecModel, payload);
244

L
tweak  
lang 已提交
245 246
        this._invokeUpdateMethod('updateVisual', ecModel, payload);
    };
247

L
tweak  
lang 已提交
248 249
    /**
     * @param {Object} payload
L
tweak  
lang 已提交
250
     * @private
L
tweak  
lang 已提交
251
     */
L
tweak  
lang 已提交
252
    echartsProto._updateLayout = function (payload) {
L
tweak  
lang 已提交
253
        var ecModel = this._model;
254

L
tweak  
lang 已提交
255
        this._doLayout(ecModel, payload);
256

L
tweak  
lang 已提交
257 258
        this._invokeUpdateMethod('updateLayout', ecModel, payload);
    };
L
lang 已提交
259

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
    /**
     * @param {Object} payload
     * @private
     */
    echartsProto._highlight = function (payload) {
        this._toggleHighlight('highlight', payload);
    };

    /**
     * @param {Object} payload
     * @private
     */
    echartsProto._downplay = function (payload) {
        this._toggleHighlight('downplay', payload);
    };

    /**
     * @param {Object} payload
     * @private
     */
    echartsProto._toggleHighlight = function (method, payload) {
        var ecModel = this._model;
        var seriesModel;
        if (payload.seriesIndex) {
            seriesModel = ecModel.getSeriesByIndex(payload.seriesIndex, true);
        }
        else if (payload.seriesName) {
            seriesModel = ecModel.getSeriesByName(payload.seriesName, true);
        }
        if (seriesModel) {
            var chartView = this._chartsMap[seriesModel.getId()];
            if (chartView) {
                chartView[method](seriesModel, ecModel, this._api, payload);
            }
        }
    };

L
Resize  
lang 已提交
297 298 299
    /**
     * Resize the chart
     */
L
tweak  
lang 已提交
300
    echartsProto.resize = function () {
L
Resize  
lang 已提交
301
        this._zr.resize();
L
tweak  
lang 已提交
302
        this._update();
L
tweak  
lang 已提交
303
    };
P
pah100 已提交
304

L
lang 已提交
305
    /**
L
Resize  
lang 已提交
306 307
     * @param {Object} eventObj
     * @return {Object}
L
lang 已提交
308 309 310 311 312 313 314
     */
    echartsProto.makeActionFromEvent = function (eventObj) {
        var payload = zrUtil.extend({}, eventObj);
        payload.type = eventActionMap[eventObj.type];
        return payload;
    };

L
tweak  
lang 已提交
315 316 317 318
    /**
     * @pubilc
     * @param {Object} payload
     * @param {string} [payload.type] Action type
P
pah100 已提交
319
     * @param {boolean} [silent=false] Whether trigger event.
L
tweak  
lang 已提交
320 321
     * @param {number} [payload.from] From uid
     */
P
pah100 已提交
322
    echartsProto.dispatch = function (payload, silent) {
L
tweak  
lang 已提交
323 324
        var actionWrap = actions[payload.type];
        if (actionWrap) {
L
lang 已提交
325 326
            var actionInfo = actionWrap.actionInfo;
            var updateMethod = actionInfo.update || 'update';
L
tweak  
lang 已提交
327
            actionWrap.action(payload, this._model);
L
tweak  
lang 已提交
328
            updateMethod !== 'none' && this['_' + updateMethod](payload);
L
lang 已提交
329

P
pah100 已提交
330 331 332 333 334 335 336
            if (!silent) {
                // Emit event outside
                // Convert type to eventType
                var eventObj = zrUtil.extend({}, payload);
                eventObj.type = actionInfo.event || eventObj.type;
                this.trigger(eventObj.type, eventObj);
            }
L
tweak  
lang 已提交
337 338
        }
    };
339

L
tweak  
lang 已提交
340 341 342 343 344
    /**
     * @param {string} methodName
     * @private
     */
    echartsProto._invokeUpdateMethod = function (methodName, ecModel, payload) {
345
        var api = this._api;
L
lang 已提交
346

L
tweak  
lang 已提交
347 348 349 350
        // Update all components
        each(this._componentsList, function (component) {
            var componentModel = component.__model;
            component[methodName](componentModel, ecModel, api, payload);
351

L
tweak  
lang 已提交
352 353
            updateZ(componentModel, component);
        }, this);
L
lang 已提交
354

L
tweak  
lang 已提交
355 356
        // Upate all charts
        ecModel.eachSeries(function (seriesModel, idx) {
357
            var chart = this._chartsMap[seriesModel.getId()];
L
tweak  
lang 已提交
358
            chart[methodName](seriesModel, ecModel, api, payload);
359

L
tweak  
lang 已提交
360 361
            updateZ(seriesModel, chart);
        }, this);
362

L
tweak  
lang 已提交
363
    };
L
lang 已提交
364

L
lang 已提交
365 366 367 368 369
    /**
     * Prepare charts view instances
     * @param  {module:echarts/model/Global} ecModel
     * @private
     */
L
tweak  
lang 已提交
370
    echartsProto._prepareCharts = function (ecModel) {
L
lang 已提交
371

L
tweak  
lang 已提交
372 373 374
        var chartsList = this._chartsList;
        var chartsMap = this._chartsMap;
        var zr = this._zr;
L
lang 已提交
375

L
tweak  
lang 已提交
376 377 378
        for (var i = 0; i < chartsList.length; i++) {
            chartsList[i].__keepAlive = false;
        }
L
lang 已提交
379

L
tweak  
lang 已提交
380
        ecModel.eachSeries(function (seriesModel, idx) {
381
            var id = seriesModel.getId();
L
tweak  
lang 已提交
382 383 384 385 386 387 388 389

            var chart = chartsMap[id];
            if (!chart) {
                var Clazz = ChartView.getClass(
                    ComponentModel.parseComponentType(seriesModel.type).sub
                );
                if (Clazz) {
                    chart = new Clazz();
390
                    chart.init(ecModel, this._api);
L
tweak  
lang 已提交
391 392 393
                    chartsMap[id] = chart;
                    chartsList.push(chart);
                    zr.add(chart.group);
L
lang 已提交
394 395
                }
                else {
L
tweak  
lang 已提交
396
                    // Error
L
lang 已提交
397
                }
398
            }
L
lang 已提交
399

L
tweak  
lang 已提交
400 401 402 403 404 405 406 407
            chart.__keepAlive = true;
            chart.__id = id;
        }, this);

        for (var i = 0; i < chartsList.length;) {
            var chart = chartsList[i];
            if (!chart.__keepAlive) {
                zr.remove(chart.group);
408
                chart.dispose(this._api);
L
tweak  
lang 已提交
409 410 411 412 413 414 415 416
                chartsList.splice(i, 1);
                delete chartsMap[chart.__id];
            }
            else {
                i++;
            }
        }
    };
L
lang 已提交
417

L
lang 已提交
418 419 420 421 422
    /**
     * Prepare component view instances
     * @param  {module:echarts/model/Global} ecModel
     * @private
     */
L
tweak  
lang 已提交
423
    echartsProto._prepareComponents = function (ecModel) {
L
lang 已提交
424

L
tweak  
lang 已提交
425 426
        var componentsMap = this._componentsMap;
        var componentsList = this._componentsList;
L
lang 已提交
427

L
tweak  
lang 已提交
428 429 430
        for (var i = 0; i < componentsList.length; i++) {
            componentsList[i].__keepAlive = true;
        }
431

L
tweak  
lang 已提交
432 433 434 435 436
        ecModel.eachComponent(function (componentType, componentModel) {
            if (componentType === 'series') {
                return;
            }

437
            var id = componentModel.getId();
L
tweak  
lang 已提交
438 439 440 441 442 443 444 445 446
            var component = componentsMap[id];
            if (!component) {
                // Create and add component
                var Clazz = ComponentView.getClass(
                    componentType, componentModel.option.type
                );

                if (Clazz) {
                    component = new Clazz();
447
                    component.init(ecModel, this._api);
L
tweak  
lang 已提交
448 449 450 451
                    componentsMap[id] = component;
                    componentsList.push(component);

                    this._zr.add(component.group);
L
lang 已提交
452
                }
453
            }
L
tweak  
lang 已提交
454 455 456 457 458 459 460 461 462 463
            component.__id = id;
            component.__keepAlive = true;
            // Used in rendering
            component.__model = componentModel;
        }, this);

        for (var i = 0; i < componentsList.length;) {
            var component = componentsList[i];
            if (!component.__keepAlive) {
                this._zr.remove(component.group);
464
                component.dispose(this._api);
L
tweak  
lang 已提交
465 466 467 468 469 470 471 472
                componentsList.splice(i, 1);
                delete componentsMap[component.__id];
            }
            else {
                i++;
            }
        }
    };
L
lang 已提交
473

L
tweak  
lang 已提交
474 475 476 477 478 479 480 481 482 483
    /**
     * Processor data in each series
     *
     * @param {module:echarts/model/Global} ecModel
     * @private
     */
    echartsProto._processData = function (ecModel) {
        each(PROCESSOR_STAGES, function (stage) {
            each(dataProcessorFuncs[stage] || [], function (process) {
                process(ecModel);
L
lang 已提交
484
            });
L
tweak  
lang 已提交
485 486
        });
    };
L
lang 已提交
487

L
tweak  
lang 已提交
488 489 490 491 492 493 494 495 496 497 498 499
    /**
     * @private
     */
    echartsProto._stackSeriesData = function (ecModel) {
        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 已提交
500
                }
L
tweak  
lang 已提交
501 502 503 504
                stackedDataMap[stack] = data;
            }
        });
    };
L
lang 已提交
505

L
tweak  
lang 已提交
506
    /**
L
lang 已提交
507
     * Layout before each chart render there series, after visual coding and data processing
L
tweak  
lang 已提交
508 509 510 511 512
     *
     * @param {module:echarts/model/Global} ecModel
     * @private
     */
    echartsProto._doLayout = function (ecModel, payload) {
513
        var api = this._api;
L
tweak  
lang 已提交
514 515 516 517
        each(layoutFuncs, function (layout) {
            layout(ecModel, api, payload);
        });
    };
L
lang 已提交
518

L
tweak  
lang 已提交
519 520 521 522 523 524 525 526 527 528
    /**
     * Code visual infomation from data after data processing
     *
     * @param {module:echarts/model/Global} ecModel
     * @private
     */
    echartsProto._doVisualCoding = function (ecModel, payload) {
        each(VISUAL_CODING_STAGES, function (stage) {
            each(visualCodingFuncs[stage] || [], function (visualCoding) {
                visualCoding(ecModel, payload);
L
lang 已提交
529
            });
L
tweak  
lang 已提交
530 531
        });
    };
L
lang 已提交
532

L
tweak  
lang 已提交
533 534 535 536 537
    /**
     * Render each chart and component
     * @private
     */
    echartsProto._doRender = function (ecModel, payload) {
538
        var api = this._api;
L
tweak  
lang 已提交
539 540 541 542 543 544 545 546 547 548 549 550 551 552
        // 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) {
553
            var chart = this._chartsMap[seriesModel.getId()];
L
tweak  
lang 已提交
554 555 556 557 558 559
            chart.__keepAlive = true;
            chart.render(seriesModel, ecModel, api, payload);

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

L
lang 已提交
560
        // Remove groups of unrendered charts
L
tweak  
lang 已提交
561 562 563 564 565 566
        each(this._chartsList, function (chart) {
            if (!chart.__keepAlive) {
                chart.remove(ecModel, api);
            }
        }, this);
    };
L
lang 已提交
567

L
lang 已提交
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
    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) {
                    var hostModel = el.hostModel || ecModel.getSeriesByIndex(
                        el.seriesIndex, true
                    );
                    var params = hostModel && hostModel.getDataParams(el.dataIndex) || {};
                    params.event = e;
                    params.type = eveName;
                    this.trigger(eveName, params);
                }
            }, this);
        }, this);
    };

L
lang 已提交
593 594 595 596 597 598 599 600 601
    /**
     * @return {boolean]
     */
    echartsProto.isDisposed = function () {
        return this._disposed;
    };
    /**
     * Dispose instance
     */
L
tweak  
lang 已提交
602
    echartsProto.dispose = function () {
L
lang 已提交
603 604
        this._disposed = true;

L
tweak  
lang 已提交
605 606 607 608 609 610
        each(this._components, function (component) {
            component.dispose();
        });
        each(this._charts, function (chart) {
            chart.dispose();
        });
L
lang 已提交
611

L
tweak  
lang 已提交
612
        this.zr.dispose();
L
lang 已提交
613 614

        instances[this.id] = null;
L
lang 已提交
615 616
    };

L
lang 已提交
617 618
    zrUtil.mixin(ECharts, Eventful);

L
lang 已提交
619 620 621 622 623 624 625 626 627 628 629 630 631 632
    /**
     * @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 已提交
633 634 635 636
    /**
     * @type {Array.<Function>}
     * @inner
     */
P
pah100 已提交
637 638
    var actions = [];

L
lang 已提交
639
    /**
L
lang 已提交
640
     * Map eventType to actionType
L
lang 已提交
641 642 643 644
     * @type {Object}
     */
    var eventActionMap = {};

L
lang 已提交
645 646 647 648
    /**
     * @type {Array.<Function>}
     * @inner
     */
649 650
    var layoutFuncs = [];

L
lang 已提交
651 652 653 654 655 656 657
    /**
     * Data processor functions of each stage
     * @type {Array.<Object.<string, Function>>}
     * @inner
     */
    var dataProcessorFuncs = {};

658 659 660 661 662 663
    /**
     * @type {Array.<Function>}
     * @inner
     */
    var optionPreprocessorFuncs = [];

L
lang 已提交
664 665 666 667 668
    /**
     * Visual coding functions of each stage
     * @type {Array.<Object.<string, Function>>}
     * @inner
     */
669
    var visualCodingFuncs = {};
L
lang 已提交
670

L
lang 已提交
671 672 673 674 675 676
    var instances = {};
    var connectedGroups = {};

    var idBase = new Date() - 0;
    var groupIdBase = new Date() - 0;
    var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
L
lang 已提交
677
    /**
L
lang 已提交
678
     * @alias module:echarts
L
lang 已提交
679
     */
L
lang 已提交
680 681 682 683 684 685 686 687 688
    var echarts = {
        /**
         * @type {number}
         */
        version: '3.0.0',
        dependencies: {
            zrender: '3.0.0'
        }
    };
L
lang 已提交
689

L
tweak  
lang 已提交
690 691 692 693 694 695
    /**
     * @param {HTMLDomElement} dom
     * @param {Object} [theme]
     * @param {Object} opts
     */
    echarts.init = function (dom, theme, opts) {
L
lang 已提交
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
        // 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) {
            chart.on(eventType, function (event) {
                if (connectedGroups[chart.group]) {
                    chart.__connectedActionDispatching = true;
                    for (var id in instances) {
L
tweak  
lang 已提交
716
                        var action = chart.makeActionFromEvent(event);
L
lang 已提交
717 718
                        var otherChart = instances[id];
                        if (otherChart !== chart && otherChart.group === chart.group) {
L
tweak  
lang 已提交
719 720 721
                            if (!otherChart.__connectedActionDispatching) {
                                otherChart.dispatch(action);
                            }
L
lang 已提交
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 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
                        }
                    }
                    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 已提交
792
    };
L
lang 已提交
793

L
tweak  
lang 已提交
794 795 796 797 798 799 800
    /**
     * Register option preprocessor
     * @param {Function} preprocessorFunc
     */
    echarts.registerPreprocessor = function (preprocessorFunc) {
        optionPreprocessorFuncs.push(preprocessorFunc);
    };
801

L
tweak  
lang 已提交
802 803 804 805 806 807 808 809 810 811 812
    /**
     * @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 已提交
813

L
tweak  
lang 已提交
814 815 816 817 818 819 820 821 822 823 824
    /**
     * 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 已提交
825 826 827 828
     * @param {string} [actionInfo.event]
     * @param {string} [actionInfo.update]
     * @param {string} [eventName]
     * @param {Function} action
L
tweak  
lang 已提交
829
     */
L
lang 已提交
830 831 832 833 834
    echarts.registerAction = function (actionInfo, eventName, action) {
        if (typeof eventName === 'function') {
            action = eventName;
            eventName = '';
        }
L
tweak  
lang 已提交
835 836
        var actionType = zrUtil.isObject(actionInfo)
            ? actionInfo.type
L
lang 已提交
837 838 839
            : ([actionInfo, actionInfo = {
                event: eventName
            }][0]);
L
lang 已提交
840 841

        actionInfo.event = actionInfo.event || actionType;
L
lang 已提交
842
        eventName = actionInfo.event;
843

L
tweak  
lang 已提交
844 845 846
        if (!actions[actionType]) {
            actions[actionType] = {action: action, actionInfo: actionInfo};
        }
L
lang 已提交
847
        eventActionMap[eventName] = actionType;
L
tweak  
lang 已提交
848
    };
P
pah100 已提交
849

L
tweak  
lang 已提交
850 851 852 853 854 855 856
    /**
     * @param {string} type
     * @param {*} CoordinateSystem
     */
    echarts.registerCoordinateSystem = function (type, CoordinateSystem) {
        CoordinateSystemManager.register(type, CoordinateSystem);
    };
L
lang 已提交
857

L
tweak  
lang 已提交
858 859 860
    /**
     * @param {*} layout
     */
L
lang 已提交
861
    echarts.registerLayout = function (layout) {
L
tweak  
lang 已提交
862
        // PENDING All functions ?
863 864
        if (zrUtil.indexOf(layoutFuncs, layout) < 0) {
            layoutFuncs.push(layout);
L
tweak  
lang 已提交
865 866
        }
    };
L
lang 已提交
867

L
tweak  
lang 已提交
868 869 870 871 872 873 874 875 876 877 878
    /**
     * @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 已提交
879

L
tweak  
lang 已提交
880
    /**
L
lang 已提交
881
     * @param {echarts/scale/*} scale
L
tweak  
lang 已提交
882 883 884 885
     */
    echarts.registerScale = function (scale) {
        scaleClasses.register(scale);
    };
L
lang 已提交
886

L
tweak  
lang 已提交
887 888 889 890 891 892
    /**
     * @param {Object} opts
     */
    echarts.extendChartView = function (opts) {
        return ChartView.extend(opts);
    };
L
Update  
lang 已提交
893

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

L
tweak  
lang 已提交
901 902 903 904 905 906
    /**
     * @param {Object} opts
     */
    echarts.extendSeriesModel = function (opts) {
        return SeriesModel.extend(opts);
    };
P
pah100 已提交
907

L
tweak  
lang 已提交
908 909 910 911 912
    /**
     * @param {Object} opts
     */
    echarts.extendComponentView = function (opts) {
        return ComponentView.extend(opts);
L
lang 已提交
913 914
    };

L
lang 已提交
915
    echarts.registerVisualCoding('echarts', require('./visual/seriesColor'));
916 917
    echarts.registerPreprocessor(require('./preprocessor/backwardCompat'));

918 919 920 921 922 923 924 925 926 927 928 929
    // Default action
    echarts.registerAction({
        type: 'highlight',
        event: 'highlight',
        update: 'highlight'
    }, zrUtil.noop);
    echarts.registerAction({
        type: 'downplay',
        event: 'downplay',
        update: 'downplay'
    }, zrUtil.noop);

L
lang 已提交
930 931
    return echarts;
});