Global.js 9.5 KB
Newer Older
L
lang 已提交
1 2 3 4 5 6
/**
 * ECharts global model
 *
 * @module {echarts/model/Global}
 */

L
lang 已提交
7 8 9 10 11
define(function (require) {

    var zrUtil = require('zrender/core/util');
    var Model = require('./Model');

L
lang 已提交
12
    var ComponentModel = require('./Component');
L
lang 已提交
13

L
lang 已提交
14 15
    var globalDefault = require('./globalDefault');

L
lang 已提交
16 17
    /**
     * @alias module:echarts/model/Global
L
lang 已提交
18 19 20 21
     *
     * @param {Object} option
     * @param {module:echarts/model/Model} parentModel
     * @param {Object} theme
L
lang 已提交
22
     */
L
lang 已提交
23 24 25 26
    var GlobalModel = Model.extend({

        constructor: GlobalModel,

L
lang 已提交
27
        init: function (option, parentModel, theme) {
L
lang 已提交
28

L
lang 已提交
29 30
            theme = theme || {};

L
lang 已提交
31 32
            this.option = {};

L
lang 已提交
33 34 35 36 37 38
            /**
             * @type {Array.<module:echarts/model/Model}
             * @private
             */
            this._components = [];

L
lang 已提交
39 40 41 42
            /**
             * @type {Object.<string, module:echarts/model/Model>}
             * @private
             */
L
lang 已提交
43
            this._componentsMap = {};
L
lang 已提交
44

P
pah100 已提交
45 46 47 48 49 50
            /**
             * @type {Object.<string, module:echarts/model/Model>}
             * @private
             */
            this._componentsMapBeforeProcessing = {};

L
lang 已提交
51 52 53 54
            /**
             * @type {module:echarts/model/Model}
             * @private
             */
L
lang 已提交
55
            this._theme = new Model(theme);
L
lang 已提交
56

L
lang 已提交
57 58
            this._mergeTheme(option, theme);

L
lang 已提交
59
            // TODO Needs clone when merging to the unexisted property
L
lang 已提交
60 61
            zrUtil.merge(option, globalDefault, false);

L
lang 已提交
62 63 64
            this.mergeOption(option);
        },

L
lang 已提交
65 66 67 68 69 70 71 72
        /**
         * @private
         */
        _mergeTheme: function (option, theme) {
            for (var name in theme) {
                // 如果有 component model 则把具体的 merge 逻辑交给该 model 处理
                if (! ComponentModel.has[name]) {
                    if (typeof theme[name] === 'object') {
L
lang 已提交
73 74 75
                        option[name] = option[name]
                            ? zrUtil.clone(theme[name])
                            : zrUtil.merge(option[name], theme[name]);
L
lang 已提交
76 77 78 79 80 81 82 83 84 85 86
                    }
                    else {
                        option[name] = theme[name];
                    }
                }
            }
        },

        /**
         * @protected
         */
L
lang 已提交
87
        mergeOption: function (newOption) {
L
lang 已提交
88 89

            var option = this.option;
L
lang 已提交
90
            var componentsMap = this._componentsMap;
L
lang 已提交
91
            var components = this._components;
92
            var componentTypes = [];
P
pah100 已提交
93 94

            // 如果不存在对应的 component model 则直接 merge
95 96
            zrUtil.each(newOption, function (componentOption, componentType) {
                if (!ComponentModel.has(componentType)) {
P
pah100 已提交
97
                    if (componentOption && typeof componentOption === 'object') {
98
                        option[componentType] = option[componentType] == null
L
lang 已提交
99
                            ? zrUtil.clone(componentOption)
100
                            : zrUtil.merge(option[componentType], componentOption);
L
lang 已提交
101 102
                    }
                    else {
103
                        option[componentType] = componentOption;
L
lang 已提交
104
                    }
L
lang 已提交
105 106
                }
                else {
107
                    componentTypes.push(componentType);
P
pah100 已提交
108 109 110
                }
            });

L
lang 已提交
111 112
            // FIXME 这里 componentTypes 是新的 Option,在依赖处理上是否会有问题
            // FIXME OPTION 同步是否要改回原来的
113 114
            ComponentModel.topologicalTravel(componentTypes, function (componentType, dependencies) {
                var componentOption = newOption[componentType];
P
pah100 已提交
115 116

                // Normalize
117
                if (!(zrUtil.isArray(componentOption))) {
P
pah100 已提交
118 119
                    componentOption = [componentOption];
                }
120 121
                if (!componentsMap[componentType]) {
                    componentsMap[componentType] = [];
P
pah100 已提交
122 123 124
                }

                for (var i = 0; i < componentOption.length; i++) {
125 126 127 128 129
                    var componentModel = componentsMap[componentType][i];
                    var ComponentModelClass = ComponentModel.getComponentModelClass(
                        componentType, componentOption[i]
                    );

L
lang 已提交
130 131 132 133
                    if (! ComponentModelClass) {
                        throw new Error('Component ' + componentType + ' not exists');
                    }

134 135
                    if (componentModel && componentModel instanceof ComponentModelClass) {
                        componentModel.mergeOption(componentOption[i], this);
L
lang 已提交
136
                    }
P
pah100 已提交
137
                    else {
138 139 140
                        componentModel = new ComponentModelClass(
                            componentOption[i], null, this,
                            this._getComponentsByTypes(dependencies), i
P
pah100 已提交
141
                        );
142
                        componentsMap[componentType][i] = componentModel;
P
pah100 已提交
143
                        components.push(componentModel);
L
lang 已提交
144
                    }
L
lang 已提交
145
                }
P
pah100 已提交
146
            }, this);
P
pah100 已提交
147 148 149 150 151

            // Backup data
            zrUtil.each(componentsMap, function (components, componentType) {
                this._componentsMapBeforeProcessing[componentType] = components.slice();
            }, this);
L
lang 已提交
152 153
        },

L
lang 已提交
154 155 156
        /**
         * @return {module:echarts/model/Model}
         */
L
lang 已提交
157 158 159 160
        getTheme: function () {
            return this._theme;
        },

L
lang 已提交
161 162 163
        /**
         * @return {module:echarts/model/Component}
         */
L
lang 已提交
164
        getComponent: function (type, idx) {
L
lang 已提交
165
            var list = this._componentsMap[type];
L
lang 已提交
166 167 168 169 170
            if (list) {
                return list[idx || 0];
            }
        },

L
lang 已提交
171 172 173 174 175
        /**
         * @param {string} type
         * @param {Function} cb
         * @param {*} context
         */
L
lang 已提交
176
        eachComponent: function (type, cb, context) {
L
lang 已提交
177
            zrUtil.each(this._componentsMap[type], cb, context);
L
lang 已提交
178 179
        },

L
lang 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
        /**
         * @param {string} type
         * @param {Function} cb
         * @param {*} context
         * @return {module:echarts/model/Component}
         */
        findComponent: function (type, cb, context) {
            var components = this._componentsMap[type];
            if (components) {
                for (var i = 0, len = components.length; i < len; i++) {
                    if (cb.call(context, components[i], i)) {
                        // Return first found
                        return components[i];
                    }
                }
            }
        },

L
lang 已提交
198 199
        /**
         * @param {string} name
P
pah100 已提交
200
         * @param {boolean} beforeProcessing
201
         * @return {module:echarts/model/Series}
L
lang 已提交
202
         */
P
pah100 已提交
203 204 205 206
        getSeriesByName: function (name, beforeProcessing) {
            var series = beforeProcessing
                ? this._componentsMapBeforeProcessing.series
                : this._componentsMap.series;
207 208 209 210 211 212
            for (var i = 0, len = series.length; i < len; i++) {
                // name should be unique.
                if (series[i].name === name) {
                    return series[i];
                }
            }
L
lang 已提交
213 214
        },

L
lang 已提交
215 216 217 218
        /**
         * @param {string} type
         * @return {Array.<module:echarts/model/Series>}
         */
L
lang 已提交
219
        getSeriesByType: function (type) {
220 221
            return zrUtil.filter(this._componentsMap.series, function (series) {
                return ComponentModel.parseComponentType(series.type).sub === type;
L
lang 已提交
222 223 224
            });
        },

L
lang 已提交
225 226 227 228 229
        /**
         * @param {number} seriesIndex
         * @return {module:echarts/model/Series}
         */
        getSeries: function (seriesIndex) {
230
            return this._componentsMap.series[seriesIndex];
L
lang 已提交
231 232
        },

L
lang 已提交
233 234 235 236
        /**
         * @return {Array.<module:echarts/model/Series>}
         */
        getSeriesAll: function () {
237
            return this._componentsMap.series.slice();
L
lang 已提交
238 239
        },

L
lang 已提交
240 241 242 243
        /**
         * @param {Function} cb
         * @param {*} context
         */
L
lang 已提交
244
        eachSeries: function (cb, context) {
245
            zrUtil.each(this._componentsMap.series, cb, context);
L
lang 已提交
246 247
        },

L
lang 已提交
248 249 250 251 252
        /**
         * @parma {string} type
         * @param {Function} cb
         * @param {*} context
         */
253 254 255 256
        eachSeriesByType: function (type, cb, context) {
            return zrUtil.each(this.getSeriesByType(type), cb, context);
        },

L
lang 已提交
257 258 259 260
        /**
         * @param {Function} cb
         * @param {*} context
         */
L
lang 已提交
261
        filterSeries: function (cb, context) {
262 263 264
            this._componentsMap.series = zrUtil.filter(
                this._componentsMap.series, cb, context
            );
L
lang 已提交
265 266
        },

P
pah100 已提交
267 268 269
        restoreData: function () {
            var componentsMap = this._componentsMap;
            var componentTypes = [];
L
lang 已提交
270

P
pah100 已提交
271 272 273 274
            zrUtil.each(this._componentsMapBeforeProcessing, function (components, componentType) {
                componentsMap[componentType] = components.slice();
                componentTypes.push(componentType);
            });
L
lang 已提交
275

P
pah100 已提交
276 277 278 279 280
            ComponentModel.topologicalTravel(componentTypes, function (componentType, dependencies) {
                zrUtil.each(componentsMap[componentType], function (component) {
                    component.restoreData();
                });
            });
P
pah100 已提交
281 282 283 284 285 286 287 288
        },

        /**
         * @private
         * @param {Array.<string>|string} types model types
         * @return {Object} key: {string} type, value: {Array.<Object>} models
         */
        _getComponentsByTypes: function (types) {
289
            if (!zrUtil.isArray(types)) {
P
pah100 已提交
290 291 292 293 294 295 296 297 298
                types = types ? [types] : [];
            }

            var ret = {};
            zrUtil.each(types, function (type) {
                ret[type] = (this._componentsMap[type] || []).slice();
            }, this);

            return ret;
L
lang 已提交
299 300 301 302 303
        }
    });

    return GlobalModel;
});