diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..21a2210 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b877177 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..fe4156d --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,5406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + padding + LANGUAGE_CODE + footer + body.pn + language + siteurl + allow + '+ + 9090 + bing + SOurce + localhost + meas + + UT: + Date + date + searchLabelText + from + about + button + "Search + from y + buttonText + measure + text + 202 + addWorldMapLayers + reloadWorldMapSource + Hypermap:WorldMap + + + Baidu + BMap + baidu + la + plugin + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - -
- - + + + + + + + + + + +
+ + diff --git a/src/geonode-client/app/static/externals/gxp/examples/viewer/ux/RowExpander.js b/src/geonode-client/app/static/externals/gxp/examples/viewer/ux/RowExpander.js index 93464c5..77e200a 100644 --- a/src/geonode-client/app/static/externals/gxp/examples/viewer/ux/RowExpander.js +++ b/src/geonode-client/app/static/externals/gxp/examples/viewer/ux/RowExpander.js @@ -1,136 +1,136 @@ -/* - * Ext JS Library 2.2.1 - * Copyright(c) 2006-2009, Ext JS, LLC. - * licensing@extjs.com - * - * http://extjs.com/license - */ - -Ext.grid.RowExpander = function(config){ - Ext.apply(this, config); - - this.addEvents({ - beforeexpand : true, - expand: true, - beforecollapse: true, - collapse: true - }); - - Ext.grid.RowExpander.superclass.constructor.call(this); - - if(this.tpl){ - if(typeof this.tpl == 'string'){ - this.tpl = new Ext.Template(this.tpl); - } - this.tpl.compile(); - } - - this.state = {}; - this.bodyContent = {}; -}; - -Ext.extend(Ext.grid.RowExpander, Ext.util.Observable, { - header: "", - width: 20, - sortable: false, - fixed:true, - menuDisabled:true, - dataIndex: '', - id: 'expander', - lazyRender : true, - enableCaching: true, - - getRowClass : function(record, rowIndex, p, ds){ - p.cols = p.cols-1; - var content = this.bodyContent[record.id]; - if(!content && !this.lazyRender){ - content = this.getBodyContent(record, rowIndex); - } - if(content){ - p.body = content; - } - return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed'; - }, - - init : function(grid){ - this.grid = grid; - - var view = grid.getView(); - view.getRowClass = this.getRowClass.createDelegate(this); - - view.enableRowBody = true; - - grid.on('render', function(){ - view.mainBody.on('mousedown', this.onMouseDown, this); - }, this); - }, - - getBodyContent : function(record, index){ - if(!this.enableCaching){ - return this.tpl.apply(record.data); - } - var content = this.bodyContent[record.id]; - if(!content){ - content = this.tpl.apply(record.data); - this.bodyContent[record.id] = content; - } - return content; - }, - - onMouseDown : function(e, t){ - if(t.className == 'x-grid3-row-expander'){ - e.stopEvent(); - var row = e.getTarget('.x-grid3-row'); - this.toggleRow(row); - } - }, - - renderer : function(v, p, record){ - p.cellAttr = 'rowspan="2"'; - return '
 
'; - }, - - beforeExpand : function(record, body, rowIndex){ - if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){ - if(this.tpl && this.lazyRender){ - body.innerHTML = this.getBodyContent(record, rowIndex); - } - return true; - }else{ - return false; - } - }, - - toggleRow : function(row){ - if(typeof row == 'number'){ - row = this.grid.view.getRow(row); - } - this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row); - }, - - expandRow : function(row){ - if(typeof row == 'number'){ - row = this.grid.view.getRow(row); - } - var record = this.grid.store.getAt(row.rowIndex); - var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row); - if(this.beforeExpand(record, body, row.rowIndex)){ - this.state[record.id] = true; - Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded'); - this.fireEvent('expand', this, record, body, row.rowIndex); - } - }, - - collapseRow : function(row){ - if(typeof row == 'number'){ - row = this.grid.view.getRow(row); - } - var record = this.grid.store.getAt(row.rowIndex); - var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true); - if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){ - this.state[record.id] = false; - Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed'); - this.fireEvent('collapse', this, record, body, row.rowIndex); - } - } -}); +/* + * Ext JS Library 2.2.1 + * Copyright(c) 2006-2009, Ext JS, LLC. + * licensing@extjs.com + * + * http://extjs.com/license + */ + +Ext.grid.RowExpander = function(config){ + Ext.apply(this, config); + + this.addEvents({ + beforeexpand : true, + expand: true, + beforecollapse: true, + collapse: true + }); + + Ext.grid.RowExpander.superclass.constructor.call(this); + + if(this.tpl){ + if(typeof this.tpl == 'string'){ + this.tpl = new Ext.Template(this.tpl); + } + this.tpl.compile(); + } + + this.state = {}; + this.bodyContent = {}; +}; + +Ext.extend(Ext.grid.RowExpander, Ext.util.Observable, { + header: "", + width: 20, + sortable: false, + fixed:true, + menuDisabled:true, + dataIndex: '', + id: 'expander', + lazyRender : true, + enableCaching: true, + + getRowClass : function(record, rowIndex, p, ds){ + p.cols = p.cols-1; + var content = this.bodyContent[record.id]; + if(!content && !this.lazyRender){ + content = this.getBodyContent(record, rowIndex); + } + if(content){ + p.body = content; + } + return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed'; + }, + + init : function(grid){ + this.grid = grid; + + var view = grid.getView(); + view.getRowClass = this.getRowClass.createDelegate(this); + + view.enableRowBody = true; + + grid.on('render', function(){ + view.mainBody.on('mousedown', this.onMouseDown, this); + }, this); + }, + + getBodyContent : function(record, index){ + if(!this.enableCaching){ + return this.tpl.apply(record.data); + } + var content = this.bodyContent[record.id]; + if(!content){ + content = this.tpl.apply(record.data); + this.bodyContent[record.id] = content; + } + return content; + }, + + onMouseDown : function(e, t){ + if(t.className == 'x-grid3-row-expander'){ + e.stopEvent(); + var row = e.getTarget('.x-grid3-row'); + this.toggleRow(row); + } + }, + + renderer : function(v, p, record){ + p.cellAttr = 'rowspan="2"'; + return '
 
'; + }, + + beforeExpand : function(record, body, rowIndex){ + if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){ + if(this.tpl && this.lazyRender){ + body.innerHTML = this.getBodyContent(record, rowIndex); + } + return true; + }else{ + return false; + } + }, + + toggleRow : function(row){ + if(typeof row == 'number'){ + row = this.grid.view.getRow(row); + } + this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row); + }, + + expandRow : function(row){ + if(typeof row == 'number'){ + row = this.grid.view.getRow(row); + } + var record = this.grid.store.getAt(row.rowIndex); + var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row); + if(this.beforeExpand(record, body, row.rowIndex)){ + this.state[record.id] = true; + Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded'); + this.fireEvent('expand', this, record, body, row.rowIndex); + } + }, + + collapseRow : function(row){ + if(typeof row == 'number'){ + row = this.grid.view.getRow(row); + } + var record = this.grid.store.getAt(row.rowIndex); + var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true); + if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){ + this.state[record.id] = false; + Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed'); + this.fireEvent('collapse', this, record, body, row.rowIndex); + } + } +}); diff --git a/src/geonode-client/app/static/externals/gxp/src/script/loader.js b/src/geonode-client/app/static/externals/gxp/src/script/loader.js index 93b6bfc..ce82575 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/loader.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/loader.js @@ -61,6 +61,7 @@ "plugins/WMSCSource.js", "plugins/OSMSource.js", "plugins/GoogleSource.js", + "plugins/TiandituSource.js", "plugins/OLSource.js", "plugins/MapBoxSource.js", "plugins/MapQuestSource.js", @@ -105,8 +106,17 @@ "plugins/Print.js", "plugins/LoadingIndicator.js", "plugins/Playback.js", + "locale/ca.js", + "locale/de.js", + "locale/el.js", + "locale/en.js", "locale/es.js", - "locale/ca.js" + "locale/fr.js", + "locale/id.js", + "locale/nl.js", + "locale/pl.js", + "locale/zh.js", + "locale/zh-cn.js" ); var scripts = document.getElementsByTagName("script"); diff --git a/src/geonode-client/app/static/externals/gxp/src/script/locale/en.js b/src/geonode-client/app/static/externals/gxp/src/script/locale/en.js index 05477f2..c6722dd 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/locale/en.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/locale/en.js @@ -2,7 +2,7 @@ * @requires GeoExt/Lang.js */ -GeoExt.Lang.add("zh", { +GeoExt.Lang.add("en", { "gxp.menu.LayerMenu.prototype": { layerText: "Layer" diff --git a/src/geonode-client/app/static/externals/gxp/src/script/locale/zh-cn.js b/src/geonode-client/app/static/externals/gxp/src/script/locale/zh-cn.js new file mode 100644 index 0000000..d2f29ec --- /dev/null +++ b/src/geonode-client/app/static/externals/gxp/src/script/locale/zh-cn.js @@ -0,0 +1,613 @@ +/** + * @requires GeoExt/Lang.js + */ + +GeoExt.Lang.add("zh-cn", { + + "gxp.menu.LayerMenu.prototype": { + layerText: "图层" + }, + + "gxp.plugins.AddLayers.prototype": { + addActionMenuText: "添加图层", + addActionTip: "添加图层", + addServerText: "添加新的服务", + addButtonText: "添加图层", + untitledText: "未定义", + addLayerSourceErrorText: "错误:无法获取WMS ({msg})。\n请确认url并重试。", + availableLayersText: "可用图层", + expanderTemplateText: "

概述: {abstract}

", + panelTitleText: "标题", + layerSelectionText: "源:", + sourceSelectOrTypeText: "选择一个或输入其他服务URL", + doneText: "完成", + uploadText: "上传图层" + }, + + "gxp.plugins.BingSource.prototype": { + title: "Bing图层", + roadTitle: "Bing路网", + aerialTitle: "Bing天空", + labeledAerialTitle: "Bing Aerial With Labels" + }, + + "gxp.plugins.FeatureEditor.prototype": { + splitButtonText: "编辑", + createFeatureActionText: "创建", + editFeatureActionText: "修改", + createFeatureActionTip: "创建新的要素", + editFeatureActionTip: "编辑已有要素" + }, + + "gxp.plugins.FeatureGrid.prototype": { + displayFeatureText: "在地图上显示", + firstPageTip: "第一页", + previousPageTip: "上一页", + zoomPageExtentTip: "缩放到页面范围", + nextPageTip: "下一页Next page", + lastPageTip: "最后一页Last page", + totalMsg: "第{0}页的第{1}到{2}个要素" + }, + + "gxp.plugins.LayerProperties.prototype": { + menuText: "图层属性", + toolTip: "图层属性" + }, + + "gxp.plugins.LayerTree.prototype": { + shortTitle: "图层", + rootNodeText: "图层", + overlayNodeText: "覆盖图", + baseNodeText: "底图" + }, + + "gxp.plugins.Legend.prototype": { + menuText: "显示比例尺", + tooltip: "显示比例尺" + }, + + "gxp.plugins.LoadingIndicator.prototype": { + loadingMapMessage: "加载地图..." + }, + + "gxp.plugins.MapBoxSource.prototype": { + title: "MapBox图层", + blueMarbleTopoBathyJanTitle: "Blue Marble Topography & Bathymetry (January)", + blueMarbleTopoBathyJulTitle: "Blue Marble Topography & Bathymetry (July)", + blueMarbleTopoJanTitle: "Blue Marble Topography (January)", + blueMarbleTopoJulTitle: "Blue Marble Topography (July)", + controlRoomTitle: "Control Room", + geographyClassTitle: "Geography Class", + naturalEarthHypsoTitle: "Natural Earth Hypsometric", + naturalEarthHypsoBathyTitle: "Natural Earth Hypsometric & Bathymetry", + naturalEarth1Title: "Natural Earth I", + naturalEarth2Title: "Natural Earth II", + worldDarkTitle: "World Dark", + worldLightTitle: "World Light", + worldPrintTitle: "World Print" + }, + + "gxp.plugins.Measure.prototype": { + buttonText: "测量", + lengthMenuText: "长度", + areaMenuText: "面积", + lengthTooltip: "测量长度", + areaTooltip: "测量面积", + measureTooltip: "测量" + }, + + "gxp.plugins.Navigation.prototype": { + menuText: "浏览地图", + tooltip: "浏览地图" + }, + + "gxp.plugins.NavigationHistory.prototype": { + previousMenuText: "缩放到上一个范围", + nextMenuText: "缩放到下一个范围", + previousTooltip: "缩放到上一个范围", + nextTooltip: "缩放到下一个范围" + }, + + "gxp.plugins.OSMSource.prototype": { + title: "OpenStreetMap图层", + mapnikAttribution: "Data CC-By-SA by OpenStreetMap", + osmarenderAttribution: "Data CC-By-SA by OpenStreetMap" + }, + + "gxp.plugins.Print.prototype": { + buttonText:"打印", + menuText: "打印地图", + tooltip: "打印地图", + previewText: "打印预览", + notAllNotPrintableText: "并非所有图层都能打印", + nonePrintableText: "所有图层都无法打印" + }, + + "gxp.plugins.MapQuestSource.prototype": { + title: "MapQuest图层", + osmAttribution: "Tiles Courtesy of MapQuest ", + osmTitle: "MapQuest OpenStreetMap", + naipAttribution: "Tiles Courtesy of MapQuest ", + naipTitle: "MapQuest Imagery" + }, + + "gxp.plugins.QueryForm.prototype": { + queryActionText: "查询", + queryMenuText: "查询图层", + queryActionTip: "查询所选图层", + queryByLocationText: "通过地图范围查询", + queryByAttributesText: "通过属性查询", + queryMsg: "查询中...", + cancelButtonText: "取消", + noFeaturesTitle: "没有匹配项", + noFeaturesMessage: "您的查询未返回任何结果。" + }, + + "gxp.plugins.RemoveLayer.prototype": { + removeMenuText: "移除图层", + removeActionTip: "移除图层" + }, + + "gxp.plugins.Styler.prototype": { + menuText: "编辑样式", + tooltip: "管理图层样式" + + }, + + "gxp.plugins.WMSGetFeatureInfo.prototype": { + buttonText:"识别", + infoActionTip: "获取要素信息", + popupTitle: "要素信息" + }, + + "gxp.plugins.Zoom.prototype": { + zoomMenuText: "缩放框", + zoomInMenuText: "放大", + zoomOutMenuText: "缩小", + zoomTooltip: "缩放至所选框", + zoomInTooltip: "放大", + zoomOutTooltip: "缩小" + }, + + "gxp.plugins.ZoomToExtent.prototype": { + menuText: "缩放到最大范围", + tooltip: "缩放到最大范围" + }, + + + "gxp.plugins.ZoomToLayerExtent.prototype": { + menuText: "缩放至图层范围", + tooltip: "缩放至图层范围" + }, + + "gxp.plugins.ZoomToSelectedFeatures.prototype": { + menuText: "缩放至所选要素", + tooltip: "缩放至所选要素" + }, + + "gxp.FeatureEditPopup.prototype": { + closeMsgTitle: "保存更改?", + closeMsg: "该要素的更改未保存。需要保存这些更改吗?", + deleteMsgTitle: "删除要素?", + deleteMsg: "确定要删除该要素?", + editButtonText: "编辑", + editButtonTooltip: "使该要素可编辑", + deleteButtonText: "删除", + deleteButtonTooltip: "删除该要素", + cancelButtonText: "取消", + cancelButtonTooltip: "停止编辑并不保存", + saveButtonText: "保存", + saveButtonTooltip: "保存更改" + }, + + "gxp.FillSymbolizer.prototype": { + fillText: "填充", + colorText: "颜色", + opacityText: "不透明度" + }, + + "gxp.FilterBuilder.prototype": { + builderTypeNames: ["any", "all", "none", "not all"], + preComboText: "匹配", + postComboText: "下列:", + addConditionText: "添加条件", + addGroupText: "添加分组", + removeConditionText: "移除条件" + }, + + "gxp.grid.CapabilitiesGrid.prototype": { + nameHeaderText : "名称", + titleHeaderText : "标题", + queryableHeaderText : "可查询", + layerSelectionLabel: "查看可取数据:", + layerAdditionLabel: "或者添加新的服务。", + expanderTemplateText: "

概述: {abstract}

" + }, + + + + "gxp.QueryPanel.prototype": { + queryByLocationText: "通过位置查询", + currentTextText: "当前选项", + queryByAttributesText: "通过属性查询", + layerText: "图层" + }, + + "gxp.RulePanel.prototype": { + scaleSliderTemplate: "{scaleType} 缩放1:{scale}", + labelFeaturesText: "标签要素", + labelsText: "标签", + basicText: "原始的", + advancedText: "更新的", + limitByScaleText: "缩放限制", + limitByConditionText: "位置限制", + symbolText: "符号", + nameText: "名称" + }, + + "gxp.PointSymbolizer.prototype": { + graphicCircleText: "圆形", + graphicSquareText: "正方形", + graphicTriangleText: "三角形", + graphicStarText: "星形", + graphicCrossText: "交叉形", + graphicXText: "x形", + graphicExternalText: "外部", + urlText: "URL", + opacityText: "不透明度", + symbolText: "符号", + sizeText: "大小", + rotationText: "旋转" + }, + + "gxp.ScaleLimitPanel.prototype": { + scaleSliderTemplate: "{scaleType} 缩放1:{scale}", + minScaleLimitText: "最小缩放限制", + maxScaleLimitText: "最大缩放限制" + }, + + "gxp.StrokeSymbolizer.prototype": { + solidStrokeName: "实线", + dashStrokeName: "短线", + dotStrokeName: "点线", + titleText: "边界", + styleText: "样式", + colorText: "颜色", + widthText: "宽度", + opacityText: "不透明度" + }, + + "gxp.StylePropertiesDialog.prototype": { + titleText: "常规", + nameFieldText: "名称", + titleFieldText: "标题", + abstractFieldText: "概述" + }, + + "gxp.TextSymbolizer.prototype": { + labelValuesText: "标签属性", + haloText: "光环", + sizeText: "大小", + priorityText: "优先", + labelOptionsText: "标签选项", + autoWrapText: "自动换行", + followLineText: "走线", + maxDisplacementText: "最大偏移", + repeatText: "重复", + forceLeftToRightText: "强制从左到右", + graphicResizeText: "图像大小", + graphicMarginText: "图形", + graphicTitle: "图形", + fontColorTitle: "字体颜色和不透明度", + positioningText: "定位", + anchorPointText: "锚点", + displacementXText: "X向偏移", + displacementYText: "Y向偏移", + perpendicularOffsetText: "垂直偏移量", + priorityHelp: "指定字段的值越高,标签将越快被绘制(从而在解决冲突中获利)", + autoWrapHelp: "包装超过一定长度的标签", + followLineHelp: "标签是否应该遵循直线的几何形状?", + maxDisplacementHelp: "如果标签位置占线则采用像素的最大偏移", + repeatHelp: "在一定数量的像素之后重复标签", + forceLeftToRightHelp: "标签通常会被翻转,以使其更易读。如果这个字符恰好是一个方向箭头那么这是不可取的", + graphic_resizeHelp: "指定调整标签图形(如高速公路护栏),以适应标签文本的模式。默认模式“none”从不修改标签图形。在拉伸模式下,GeoServer将调整图形以精确地包围标签文本,可能会修改图像的纵横比。在比例模式下,GeoServer将把图像扩展到足够大的位置,以使文本围绕文本,同时保持其原始的长宽比。", + graphic_marginHelp: "类似于保证金简写属性在HTML,CSS的解释取决于提供了多少边缘值:1 =使用保证金在长度的标签。2 =使用顶部和底部边缘的第一和第二个左和右的利润率。3 =使用第一个顶部边缘,第二个为左和右边缘,第三个为底部边缘。4 =使用第一个,第二个为右,第三个为底部边缘,第四个为左边缘。" + }, + "gxp.WMSLayerPanel.prototype": { + aboutText: "关于", + titleText: "标题", + nameText: "名称", + descriptionText: "描述", + displayText: "显示", + opacityText: "不透明度", + formatText: "格式", + transparentText: "透明度", + cacheText: "隐藏", + cacheFieldText: "使用隐藏版本", + stylesText: "样式", + infoFormatText: "信息格式", + infoFormatEmptyText: "选择一个格式" + }, + + "gxp.EmbedMapDialog.prototype": { + publishMessage: "您的地图已准备好发布到Web上!只需在您的网站上复制以下HTML加载地图:", + heightLabel: '高度', + widthLabel: '宽度', + mapSizeLabel: '地图大小', + miniSizeLabel: '最小', + smallSizeLabel: '小', + premiumSizeLabel: '额外', + largeSizeLabel: '大' + }, + + "gxp.WMSStylesDialog.prototype": { + addStyleText: "添加", + addStyleTip: "添加新的样式", + chooseStyleText: "选择样式", + classifyStyleText:"分类", + classifyStyleTip:"基于属性进行分类", + deleteStyleText: "移除", + deleteStyleTip: "删除所选样式", + editStyleText: "编辑", + editStyleTip: "编辑所选样式", + duplicateStyleText: "拷贝", + duplicateStyleTip: "拷贝所选样式", + addRuleText: "添加", + addRuleTip: "添加新规则", + newRuleText: "新规则", + deleteRuleText: "移除", + deleteRuleTip: "删除所选规则", + editRuleText: "编辑", + editRuleTip: "编辑所选规则", + duplicateRuleText: "拷贝", + duplicateRuleTip: "拷贝所选规则", + cancelText: "取消", + saveText: "保存", + styleWindowTitle: "用户样式:{0}", + ruleWindowTitle: "样式规则:{0}", + stylesFieldsetTitle: "样式", + rulesFieldsetTitle: "规则" + }, + + "gxp.ClassificationPanel.prototype": { + classifyText: "分类", + rampBlueText: "蓝色", + rampRedText: "红色", + rampOrangeText: "橙色", + rampJetText: "蓝-红", + rampGrayText: "灰色", + rampRandomText: "随机", + rampCustomText: "自定义", + selectColorText: "选择颜色", + colorStartText: "起始颜色", + colorEndText: "终止颜色", + methodUniqueText: "唯一值", + methodQuantileText: "等量", + methodEqualText: "等距", + methodJenksText: "Jenks自然间断点", + standardDeviationText: "标准差", + attributeText: "属性", + selectAttributeText: "选择属性", + startColor: "#FEE5D9", + endColor: "#A50F15", + generateRulesText: "应用", + reverseColorsText: "反转颜色", + methodText: "方法", + classesText: "数量", + colorrampText: "颜色梯度", + selectMethodText: "选择方法" + }, + + "gxp.LayerUploadPanel.prototype": { + titleLabel: "标题", + titleEmptyText: "图层标题", + abstractLabel: "描述", + abstractEmptyText: "图层描述", + fileLabel: "数据", + fieldEmptyText: "浏览数据归档...", + uploadText: "上传", + waitMsgText: "上传你的数据..", + invalidFileExtensionText: "文件扩展名必须是以下格式:", + optionsText: "选项", + workspaceLabel: "工作空间", + workspaceEmptyText: "默认工作空间", + dataStoreLabel: "仓库", + dataStoreEmptyText: "创建新的仓库", + defaultDataStoreEmptyText: "默认数据仓库" + }, + + "gxp.NewSourceDialog.prototype": { + title: "添加新的服务...", + cancelText: "取消", + addServerText: "添加服务", + invalidURLText: "通过正确的URL进入WMS端点 (e.g. http://example.com/geoserver/wms)", + contactingServerText: "连接服务器..." + }, + + "gxp.ScaleOverlay.prototype": { + zoomLevelText: "缩放等级" + }, + + "gxp.plugins.ArcGISCacheSource.prototype": { + noLayersTitle: "没有ArcGIS图层", + noLayersText: "无法找到拥有兼容投影(墨卡托)的任何图层,位置:" + }, + + "gxp.plugins.ArcRestSource.prototype": { + noLayersTitle: "没有ArcGIS图层", + noLayersText: "无法找到拥有兼容投影(墨卡托)的任何图层,位置:" + }, + + "gxp.plugins.MapShare.prototype": { + text: "分享地图", + toolTip: "地图信息和下载链接" + }, + + "gxp.plugins.AnnotationTool.prototype": { + errorTitle: "注释创建失败", + noteText: "注释", + notesText: "注释", + showNotesText: "显示注释", + editNotesText: "编辑注释", + addNoteText: "添加注释", + newNoteText: "新的注释", + projection: "EPSG:4326", + pointText: "点", + lineText: "线", + polygonText: "形状", + saveFailTitle: "无法保存注释", + saveFailText: "编辑失败,您未拥有保存改注释的权限", + saveText: "保存", + editText: "编辑", + deleteText: "删除", + cancelText: "取消", + titleText: "标题" + }, + + + + "gxp.SearchBar.prototype": { + emptyText: '正在检索...', + searchText: '检索', + noSearchableLayersTitle: '未检索到图层', + noSearchableLayersMsg: '目前地图上没有可搜索图层。您必须在地图上至少拥有一个有可检索字段的可见图层。', + searchTermTitle: "所需检索项", + searchTermText: "请输入检索项", + resetText: "重置" + }, + + "gxp.plugins.PrintPage.prototype": { + menuText: "打印地图", + tooltip: "打印地图", + buttonText: "打印" + }, + + "gxp.plugins.CoordinateTool.prototype": { + title: "地图坐标 (经度,纬度)", + infoActionTip: "获取鼠标位置的坐标信息", + coordinatePositionText: "坐标位置" + }, + + "gxp.plugins.FeedSource.prototype": { + title: 'Feed Source' + }, + + "gxp.plugins.HGLSource.prototype": { + title: 'Harvard Geospatial Library Source' + }, + + "gxp.plugins.HGLFeedSource.prototype" : { + title: 'HGL Feed Source' + }, + + "gxp.plugins.PicasaFeedSource.prototype" : { + title: 'Picasa Source' + }, + + "gxp.plugins.YouTubeFeedSource.prototype" : { + title: 'YouTube Source' + }, + + "gxp.plugins.GeoLocator.prototype": { + infoActionTip: "获取我的位置", + locationFailedText: "位置检测失败" + }, + + "gxp.plugins.LayerShare.prototype": { + menuText: "分享图层", + toolTip: "图层信息和下载链接" + }, + + "gxp.plugins.MapShare.prototype": { + text: "分享我的地图", + toolTip: "地图信息和下载链接" + }, + + "gxp.plugins.AddCategory.prototype": { + addCategoryMenuText:"添加分类", + addCategoryActionTipText:"向图层树添加分类", + categoryNameText: "分类名:" + }, + + "gxp.plugins.RemoveCategory.prototype": { + removeCategoryActionText:"移除分类", + removeCategoryActionTipText: "移除分类以及其内所有图层", + cannotRemoveText: "该分类不能被移除" + }, + + "gxp.plugins.RenameCategory.prototype": { + renameCategoryActionText:"重命名分类", + renameCategoryActionTipText:"为该分类创建新的名字", + cannotRenameText: "该分类不能被重命名" + }, + + "gxp.LinkEmbedMapDialog.prototype": { + linkMessage: '拷贝以下链接到email或者IM:', + publishMessage: '拷贝以下HTML嵌入到前端:' + }, + + "gxp.plugins.GeoNodeQueryTool.prototype" : { + infoActionTip: "获取要素信息", + popupTitle: "要素信息", + resetTitle: "重置", + resetToolTipText: "清空所有要素" + }, + + "gxp.plugins.MapRevisionTool.prototype" : { + infoActionTip: "查看地图修订列表", + toolText: "修订", + windowTitle: "地图修订历史记录" + }, + + "gxp.plugins.GazetteerTool.prototype" : { + infoActionTip: '输入要搜索的地名', + toolText: '地名索引', + searchingText: '检索中...', + fromText: '起始: YYYY-MM-DD', + toText: '终止: YYYY-MM-DD', + datesText: '日期', + geocodersText: '地理编码', + advancedText: '高级设置', + sourceText: '源', + startDateText: '开始日期', + endDateText: '结束日期', + placenameText: '地名', + coordinatesText: '坐标系', + searchText: '检索' + }, + + 'gxp.FeedSourceDialog.prototype': { + addPicasaText: 'Picasa Photos', + addFlickrText: 'Add Flickr Photos', + addYouTubeText: 'YouTube Videos', + addHGLText: 'Harvard Geospatial Library', + addRSSText: '其他GeoRSS Feed', + addFeedText: '添加到地图', + titleText: 'Feed标题', + keywordText: '关键字', + typeText: '类型', + urlText: 'URL', + maxResultsText: '最大 # Results', + chooseNumberText: '选择数量...', + georssfeedsText: 'GeoRSS Feeds' + }, + + + 'gxp.plugins.MapShare.prototype': { + text: "分享地图", + toolTip: "地图信息以及下载链接" + }, + + + 'gxp.plugins.LayerManager.prototype': { + baseNodeText: "底图" + }, + + 'gxp.plugins.LayerTree.prototype': { + overlayNodeText: '覆盖图', + baseNodeText: '底图', + addCategoryActionText: '添加分类', + addCategoryActionTipText: '添加分类' + } + +}); diff --git a/src/geonode-client/app/static/externals/gxp/src/script/locale/zh.js b/src/geonode-client/app/static/externals/gxp/src/script/locale/zh.js index 05477f2..1444382 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/locale/zh.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/locale/zh.js @@ -532,7 +532,8 @@ GeoExt.Lang.add("zh", { startDateText: 'Start Date', endDateText: 'End Date', placenameText: 'Place name', - coordinatesText: 'Coordinates' + coordinatesText: 'Coordinates', + searchText: 'Search' }, "gxp.plugins.StreetViewTool.js" : { diff --git a/src/geonode-client/app/static/externals/gxp/src/script/plugins/GazetteerTool.js b/src/geonode-client/app/static/externals/gxp/src/script/plugins/GazetteerTool.js index 890cdbf..622f98a 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/plugins/GazetteerTool.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/plugins/GazetteerTool.js @@ -54,7 +54,7 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { /** api: config[services] * ``String`` Default gazetteer services to search */ - services: 'worldmap,google', + services: 'nominatim', /** api: config[searchingText] * ``String`` Text to show when search is taking place @@ -62,7 +62,17 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { searchingText: 'Searching...', firstLoad: true, - + fromText: 'From: YYYY-MM-DD', + toText: 'To: YYYY-MM-DD', + datesText: 'Dates', + geocodersText: 'Geocoders', + advancedText: 'Advanced', + sourceText: 'Source', + startDateText: 'Start Date', + endDateText: 'End Date', + placenameText: 'Place name', + coordinatesText: 'CoTEXTordinates', + searchText: 'Search', /** api: method[addActions] * Creates the gazetteer interface, functionality, etc. */ @@ -72,7 +82,7 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { this.searchTB = new Ext.form.TextField({ id:'search-tb', width:150, - emptyText:'Place name:', + emptyText:this.placenameText + ':', handleMouseEvents: true, enableKeyEvents: true, listeners: { @@ -91,7 +101,7 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { // Button to initiate search this.searchBtn = new Ext.Button({ - text:'Search', + text:''+ this.searchText + '', handler: function() { this.performSearch(); }, @@ -110,24 +120,24 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { }; // Gazetteer/Geocoder service options - var geocoderWorldMap = {text: 'WorldMap', id: 'worldmap', checked: true, disabled: false, hideOnClick: false, checkHandler: serviceCheck}; - var geocoderGoogle = {text: 'Google', id: 'google', checked: true, hideOnClick: false, checkHandler: serviceCheck}; - var geocoderNominatim = {text: 'Nominatim', id: 'nominatim', checked: false, hideOnClick: false, checkHandler: serviceCheck}; + var geocoderWorldMap = {text: 'WorldMap', id: 'worldmap', checked: false, hideOnClick: false, checkHandler: serviceCheck}; + //var geocoderGoogle = {text: 'Google', id: 'google', checked: true, hideOnClick: false, checkHandler: serviceCheck}; + var geocoderNominatim = {text: 'Nominatim', id: 'nominatim', checked: true, disabled: false, hideOnClick: false, checkHandler: serviceCheck}; var geocoderGeonames = {text: 'GeoNames', id: 'geonames', checked: false, hideOnClick: false, checkHandler: serviceCheck}; //Optional start date filter this.startDateField = new Ext.form.TextField({ - emptyText: 'From: YYYY-MM-DD' + emptyText: this.fromText }); //Optional end date filter this.endDateField = new Ext.form.TextField({ - emptyText: 'To: YYYY-MM-DD' + emptyText: this.toText }); //menu for date filters this.dateOptions = { - text: "Dates", + text: this.datesText, menu: { xtype: 'menu', hideOnClick: false, @@ -140,13 +150,13 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { //menu for service options this.geocoderOptions = { - text: "Geocoders", + text: this.geocodersText, menu: { xtype: 'menu', hideOnClick: false, items: [ geocoderWorldMap, - geocoderGoogle, + //geocoderGoogle, geocoderNominatim, geocoderGeonames ] @@ -155,7 +165,7 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { //menu for filter options this.advancedOptions = new Ext.Button({ - text:"Advanced", + text:this.advancedText, menu: { items: [ this.geocoderOptions, @@ -219,11 +229,11 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { lonlat, new OpenLayers.Size(100,100), "

"+ record.get("placename") + "

" + - "Source: " + record.get("source") + '
' + + this.sourceText + ": " + record.get("source") + '
' + (startDate != "N/A" ? - "Start Date: " + startDate + "
" : "") + + this.startDateText + ": " + startDate + "
" : "") + (endDate != "N/A" ? - "End Date: " + endDate + "
" : ""), + this.endDateText + ": " + endDate + "
" : ""), null, true, onPopupClose); map.addPopup(this.popup, true); }; @@ -258,8 +268,8 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { store: this.gazetteerDataStore, width: 700, columns: [ - {header: 'Place Name', width:200, dataIndex: 'placename', sortable: true}, - {header: 'Coordinates', width:100, dataIndex: 'coordinates', sortable: false, + {header: this.placenameText, width:200, dataIndex: 'placename', sortable: true}, + {header: this.coordinatesText, width:100, dataIndex: 'coordinates', sortable: false, renderer: function(value) { if (value.lat) return value.lat.toFixed(2) + ', ' + value.lon.toFixed(2); @@ -267,9 +277,9 @@ gxp.plugins.GazetteerTool = Ext.extend(gxp.plugins.Tool, { return value[0].toFixed(2) + ', ' + value[1].toFixed(2); } }, - {header: 'Source', width:200, dataIndex: 'source', sortable: true}, - {header: 'Start Date', width:100, dataIndex: 'start_date', sortable: true}, - {header: 'End Date', width:100, dataIndex: 'end_date', sortable: true} + {header: this.sourceText, width:200, dataIndex: 'source', sortable: true}, + {header: this.startDateText, width:100, dataIndex: 'start_date', sortable: true}, + {header: this.endDateText, width:100, dataIndex: 'end_date', sortable: true} //{header: 'ID', width:100, dataIndex: 'gazetteer_id', sortable: true} ], listeners: diff --git a/src/geonode-client/app/static/externals/gxp/src/script/plugins/MapShare.js b/src/geonode-client/app/static/externals/gxp/src/script/plugins/MapShare.js index 8a94b33..fb95822 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/plugins/MapShare.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/plugins/MapShare.js @@ -48,7 +48,7 @@ gxp.plugins.MapShare = Ext.extend(gxp.plugins.Tool, { linkPrefix: "/maps/", - linkSuffix: "/view", + linkSuffix: "", iconCls: "gxp-icon-link", @@ -60,7 +60,7 @@ gxp.plugins.MapShare = Ext.extend(gxp.plugins.Tool, { iconCls: this.iconCls, text: this.text, tooltip: this.toolTip, - disabled: this.target.mapID == null, + disabled: this.target.mapID == null || this.target.mapID == 0, handler: function() { window.open(link); }, diff --git a/src/geonode-client/app/static/externals/gxp/src/script/plugins/Measure.js b/src/geonode-client/app/static/externals/gxp/src/script/plugins/Measure.js index a7de26d..e83a46f 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/plugins/Measure.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/plugins/Measure.js @@ -201,8 +201,8 @@ gxp.plugins.Measure = Ext.extend(gxp.plugins.Tool, { this.activeIndex = 0; this.button = new Ext.SplitButton({ iconCls: "gxp-icon-measure-length", - text: "Measure", tooltip: this.measureTooltip, + text:this.buttonText, buttonText: this.buttonText, enableToggle: true, toggleGroup: this.toggleGroup, diff --git a/src/geonode-client/app/static/externals/gxp/src/script/plugins/Styler.js b/src/geonode-client/app/static/externals/gxp/src/script/plugins/Styler.js index 893a300..0c6c637 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/plugins/Styler.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/plugins/Styler.js @@ -99,7 +99,7 @@ gxp.plugins.Styler = Ext.extend(gxp.plugins.Tool, { /** private: method[destroy] */ destroy: function() { - this.target.on("authorizationchange", this.enableOrDisable, this); + this.target.un("authorizationchange", this.enableOrDisable, this); gxp.plugins.Styler.superclass.destroy.apply(this, arguments); }, diff --git a/src/geonode-client/app/static/externals/gxp/src/script/plugins/TiandituSource.js b/src/geonode-client/app/static/externals/gxp/src/script/plugins/TiandituSource.js new file mode 100644 index 0000000..6a88ce9 --- /dev/null +++ b/src/geonode-client/app/static/externals/gxp/src/script/plugins/TiandituSource.js @@ -0,0 +1,201 @@ +/** + * Copyright (c) 2008-2011 The Open Planning Project + * + * Published under the GPL license. + * See https://github.com/opengeo/gxp/raw/master/license.txt for the full text + * of the license. + */ + +/** + * @requires plugins/LayerSource.js + * @requires OpenLayers/Layer/Tianditu/v3.js + */ + +/** api: (define) + * module = gxp.plugins + * class = TiandituSource + */ + +/** api: (extends) + * plugins/LayerSource.js + */ +Ext.namespace("gxp.plugins"); + +/** api: constructor + * .. class:: TiandituSource(config) + * + * Plugin for using Tianditu layers with :class:`gxp.Viewer` instances. The + * plugin uses the BMaps v3 API and also takes care of loading the + * required Tianditu resources. + * + * Available layer names for this source are "ROADMAP", "SATELLITE", + * "HYBRID" and "TERRAIN" + */ +/** api: example + * The configuration in the ``sources`` property of the :class:`gxp.Viewer` is + * straightforward: + * + * .. code-block:: javascript + * + * "tianditu": { + * ptype: "gxp_tianditu" + * } + * + * A typical configuration for a layer from this source (in the ``layers`` + * array of the viewer's ``map`` config option would look like this: + * + * .. code-block:: javascript + * + * { + * source: "tianditu", + * name: "TERRAIN" + * } + * + */ +gxp.plugins.TiandituSource = Ext.extend(gxp.plugins.LayerSource, { + + /** api: ptype = gxp_tianditusource */ + ptype: "gxp_tianditusource", + + /** config: config[timeout] + * ``Number`` + * The time (in milliseconds) to wait before giving up on the Tianditu Maps + * script loading. This layer source will not be availble if the script + * does not load within the given timeout. Default is 7000 (seven seconds). + */ + timeout: 7000, + + /** api: property[store] + * ``GeoExt.data.LayerStore`` containing records with "ROADMAP", + * "SATELLITE", "HYBRID" and "TERRAIN" name fields. + */ + + /** api: config[title] + * ``String`` + * A descriptive title for this layer source (i18n). + */ + title: "Tianditu Layers", + tiandituroadAbstract: "Show tiandituRoad", + tiandituimageAbstract: "Show tiandituImage", + tiandituterrainAbstract: "Show tiandituTerrain", + tiandituannotationAbstract: "Show tiandituAnnotation", + tiandituroadTitle: "Tianditu Road", + tiandituimageTitle: "Tianditu Image", + tiandituterrainTitle: "Tianditu Terrain", + tiandituannotationTitle: "Tianditu Annotation", + tiandituroadURL: "http://t4.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", + tiandituimageURL: "http://t4.tianditu.com/DataServer?T=img_w&X=${x}&Y=${y}&L=${z}", + tiandituterrainURL: "http://t4.tianditu.com/DataServer?T=ter_w&X=${x}&Y=${y}&L=${z}", + tiandituannotationURL: "http://t4.tianditu.com/DataServer?T=cia_w&X=${x}&Y=${y}&L=${z}", + /** api: config[otherParams] + * ``String`` + * Additional parameters to be sent to Tianditu, + * default is "sensore=false" + */ + otherParams: "sensor=false", + + constructor: function(config) { + this.config = config; + gxp.plugins.TiandituSource.superclass.constructor.apply(this, arguments); + }, + + /** api: method[createStore] + * + * Creates a store of layer records. Fires "ready" when store is loaded. + */ + + createStore: function() { + var mapTypes = { + "TIANDITUROAD": {"abstract": this.tiandituroadAbstract, "title": this.tiandituroadTitle, + "url":this.tiandituroadURL, "isbaselayer":true, "displayswitch":true}, + "TIANDITUIMAGE": {"abstract": this.tiandituimageAbstract, "title": this.tiandituimageTitle, + "url":this.tiandituimageURL, "isbaselayer":true, "displayswitch":true}, + "TIANDITUTERRAIN": {"abstract": this.tiandituterrainAbstract, "title": this.tiandituterrainTitle, + "url":this.tiandituterrainURL, "isbaselayer":true, "displayswitch":true}, + "TIANDITUANNOTATION": {"abstract": this.tiandituannotationAbstract, "title": this.tiandituannotationTitle, + "url":this.tiandituannotationURL, "isbaselayer":false, "displayswitch":false} + }; + + var layers = []; + var name, mapType; + for (name in mapTypes) { + layers.push(new OpenLayers.Layer.XYZ( + mapTypes[name]["title"], + [ + mapTypes[name]["url"], + mapTypes[name]["url"], + mapTypes[name]["url"], + mapTypes[name]["url"], + mapTypes[name]["url"], + mapTypes[name]["url"], + mapTypes[name]["url"], + mapTypes[name]["url"] + ], + { + mapType: name, + isBaseLayer: mapTypes[name]["isbaselayer"] + //visibility: true, + //displayInLayerSwitcher: mapTypes[name]["displayswitch"] + } + )); + } + this.store = new GeoExt.data.LayerStore({ + layers: layers, + fields: [ + {name: "source", type: "string"}, + {name: "name", type: "string", mapping: "mapType"}, + {name: "abstract", type: "string"}, + {name: "group", type: "string", defaultValue: "background"}, + {name: "fixed", type: "boolean", defaultValue: true}, + {name: "selected", type: "boolean"} + ] + }); + this.fireEvent("ready", this); + }, + + /** api: method[createLayerRecord] + * :arg config: ``Object`` The application config for this layer. + * :returns: ``GeoExt.data.LayerRecord`` + * + * Create a layer record given the config. + */ + createLayerRecord: function(config) { + var record; + var cmp = function(l) { + return l.get("name") === config.name; + }; + // only return layer if app does not have it already + if (this.target.mapPanel.layers.findBy(cmp) == -1) { + // records can be in only one store + record = this.store.getAt(this.store.findBy(cmp)).clone(); + var layer = record.getLayer(); + // set layer title from config + if (config.title) { + /** + * Because the layer title data is duplicated, we have + * to set it in both places. After records have been + * added to the store, the store handles this + * synchronization. + */ + layer.setName(config.title); + record.set("title", config.title); + } + // set visibility from config + if ("visibility" in config) { + layer.visibility = config.visibility; + } + + record.set("selected", config.selected || false); + record.set("source", config.source); + record.set("name", config.name); + if ("group" in config) { + record.set("group", config.group); + } + record.commit(); + } + return record; + } + +}); + +Ext.preg(gxp.plugins.TiandituSource.prototype.ptype, gxp.plugins.TiandituSource); diff --git a/src/geonode-client/app/static/externals/gxp/src/script/widgets/ClassificationPanel.js b/src/geonode-client/app/static/externals/gxp/src/script/widgets/ClassificationPanel.js index 22bd2b3..307be7b 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/widgets/ClassificationPanel.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/widgets/ClassificationPanel.js @@ -36,7 +36,10 @@ gxp.ClassificationPanel = Ext.extend(Ext.Panel, { endColor: "#A50F15", generateRulesText: "Apply", reverseColorsText: "Reverse colors", - + methodText: "Color Ramp", + classesText: "Classes", + colorrampText: "Color Ramp", + selectMethodText: "Select method", initComponent: function() { var colorFieldPlugins; @@ -95,7 +98,7 @@ gxp.ClassificationPanel = Ext.extend(Ext.Panel, { var classNumSelector = new Ext.ux.form.SpinnerField({ - fieldLabel: 'Classes', + fieldLabel: this.classesText, id: "choropleth_classes", minValue: 2, name: 'intervals', @@ -115,7 +118,7 @@ gxp.ClassificationPanel = Ext.extend(Ext.Panel, { var colorDropdown = new Ext.form.ComboBox({ id: 'choropleth_colorramp', name: 'ramp', - fieldLabel: 'Color Ramp', + fieldLabel: this.colorrampText, store: new Ext.data.ArrayStore({ id: 0, fields: [ @@ -183,7 +186,7 @@ gxp.ClassificationPanel = Ext.extend(Ext.Panel, { var methodDropdown = new Ext.form.ComboBox({ id: 'choropleth_method', name: 'method', - fieldLabel: 'Method', + fieldLabel: this.methodText, store: new Ext.data.ArrayStore({ id: 0, mode: 'local', @@ -204,7 +207,7 @@ gxp.ClassificationPanel = Ext.extend(Ext.Panel, { mode: 'local', width: 110, editable: false, - emptyText: 'Select method', + emptyText: this.selectMethodText, triggerAction: 'all', disabled: false, listeners: { diff --git a/src/geonode-client/app/static/externals/gxp/src/script/widgets/FilterBuilder.js b/src/geonode-client/app/static/externals/gxp/src/script/widgets/FilterBuilder.js index 1b48a2d..cd748b4 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/widgets/FilterBuilder.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/widgets/FilterBuilder.js @@ -1,604 +1,604 @@ -/** - * Copyright (c) 2008-2011 The Open Planning Project - * - * Published under the GPL license. - * See https://github.com/opengeo/gxp/raw/master/license.txt for the full text - * of the license. - */ - -/** - * @include widgets/form/FilterField.js - */ - -/** api: (define) - * module = gxp - * class = FilterBuilder - * base_link = `Ext.Panel `_ - */ -Ext.namespace("gxp"); - -/** api: constructor - * .. class:: FilterBuilder(config) - * - * Create a panel for assembling a filter. - */ -gxp.FilterBuilder = Ext.extend(Ext.Container, { - - /** api: config[builderTypeNames] - * ``Array`` - * A list of labels that correspond to builder type constants. - * These will be the option names available in the builder type combo. - * Default is ``["any", "all", "none", "not all"]``. - */ - builderTypeNames: ["any", "all", "none", "not all"], - - /** api: config[allowedBuilderTypes] - * ``Array`` - * List of builder type constants. Default is - * ``[ANY_OF, ALL_OF, NONE_OF]``. - */ - allowedBuilderTypes: null, - - /** api: config[allowBlank] - * ``Boolean`` Do we allow blank FilterFields? It is safe to say true - * here, but for compatibility reasons with old applications, the default - * is false. - */ - allowBlank: false, - - /** api: config[preComboText] - * ``String`` - * String to display before filter type combo. Default is ``"Match"``. - */ - preComboText: "Match", - - /** api: config[postComboText] - * ``String`` - * String to display after filter type combo. Default is - * ``"of the following:"``. - */ - postComboText: "of the following:", - - /** api: config[cls] - * ``String`` - * The CSS class to be added to this panel's element (defaults to - * ``"gxp-filterbuilder"``). - */ - cls: "gxp-filterbuilder", - - /** api: config[filter] - * ``OpenLayers.Filter`` - * Filter to initialize the component with - */ - - /** private: property[builderType] - */ - builderType: null, - - /** private: property[childFilterContainer] - */ - childFilterContainer: null, - - /** private: property[customizeFilterOnInit] - */ - customizeFilterOnInit: true, - - /** i18n */ - addConditionText: "add condition", - addGroupText: "add group", - removeConditionText: "remove condition", - - /** api: config[allowGroups] - * ``Boolean`` - * Allow groups of conditions to be added. Default is ``true``. - * If ``false``, only individual conditions (non-logical filters) can - * be added. - */ - allowGroups: true, - - initComponent: function() { - var defConfig = { - defaultBuilderType: gxp.FilterBuilder.ANY_OF - }; - Ext.applyIf(this, defConfig); - - if(this.customizeFilterOnInit) { - this.filter = this.customizeFilter(this.filter); - } - - this.builderType = this.getBuilderType(); - - this.items = [{ - xtype: "container", - layout: "form", - ref: "form", - defaults: {anchor: "100%"}, - hideLabels: true, - items: [{ - xtype: "compositefield", - style: "padding-left: 2px", - items: [{ - xtype: "label", - style: "padding-top: 0.3em", - text: this.preComboText - }, this.createBuilderTypeCombo(), { - xtype: "label", - style: "padding-top: 0.3em", - text: this.postComboText - }] - }, this.createChildFiltersPanel(), { - xtype: "toolbar", - items: this.createToolBar() - }] - - }]; - - this.addEvents( - /** - * Event: change - * Fires when the filter changes. - * - * Listener arguments: - * builder - {gxp.FilterBuilder} This filter builder. Call - * ``getFilter`` to get the updated filter. - */ - "change" - ); - - gxp.FilterBuilder.superclass.initComponent.call(this); - }, - - /** private: method[createToolBar] - */ - createToolBar: function() { - var bar = [{ - text: this.addConditionText, - iconCls: "add", - handler: function() { - this.addCondition(); - }, - scope: this - }]; - if(this.allowGroups) { - bar.push({ - text: this.addGroupText, - iconCls: "add", - handler: function() { - this.addCondition(true); - }, - scope: this - }); - } - return bar; - }, - - /** api: method[getFilter] - * :return: ``OpenLayers.Filter`` - * - * Returns a filter that fits the model in the Filter Encoding - * specification. Use this method instead of directly accessing - * the ``filter`` property. Return will be ``false`` if any child - * filter does not have a type, property, or value. - */ - getFilter: function() { - var filter; - if(this.filter) { - filter = this.filter.clone(); - if(filter instanceof OpenLayers.Filter.Logical) { - filter = this.cleanFilter(filter); - } - } - return filter; - }, - - /** private: method[cleanFilter] - * :arg filter: ``OpenLayers.Filter.Logical`` - * :return: ``OpenLayers.Filter`` An equivalent filter to the input, where - * all binary logical filters have more than one child filter. Returns - * false if a filter doesn't have non-null type, property, or value. - * - * Ensures that binary logical filters have more than one child. - */ - cleanFilter: function(filter) { - if(filter instanceof OpenLayers.Filter.Logical) { - if(filter.type !== OpenLayers.Filter.Logical.NOT && - filter.filters.length === 1) { - filter = this.cleanFilter(filter.filters[0]); - } else { - var child; - for(var i=0, len=filter.filters.length; i method to return a - * filter that meets the encoding spec. - */ - customizeFilter: function(filter) { - if(!filter) { - filter = this.wrapFilter(this.createDefaultFilter()); - } else { - filter = this.cleanFilter(filter); - var child, i, len; - switch(filter.type) { - case OpenLayers.Filter.Logical.AND: - case OpenLayers.Filter.Logical.OR: - if(!filter.filters || filter.filters.length === 0) { - // give the filter children if it has none - filter.filters = [this.createDefaultFilter()]; - } else { - for(i=0, len=filter.filters.length; i 0) { - filter = this.customizeFilter(child.filters[0]); - } else { - filter = this.wrapFilter(this.createDefaultFilter()); - } - } - } else { - // non-logical child of NOT should be wrapped - var type; - if(this.defaultBuilderType === gxp.FilterBuilder.NOT_ALL_OF) { - type = OpenLayers.Filter.Logical.AND; - } else { - type = OpenLayers.Filter.Logical.OR; - } - filter.filters = [ - new OpenLayers.Filter.Logical({ - type: type, - filters: [child] - }) - ]; - } - } - break; - default: - // non-logical filters get wrapped - filter = this.wrapFilter(filter); - break; - } - } - return filter; - }, - - createDefaultFilter: function() { - return new OpenLayers.Filter.Comparison(); - }, - - /** private: method[wrapFilter] - * :arg filter: ``OpenLayers.Filter`` A non-logical filter. - * :return: ``OpenLayers.Filter`` A wrapped version of the input filter. - * - * Given a non-logical filter, this creates parent filters depending on - * the ``defaultBuilderType``. - */ - wrapFilter: function(filter) { - var type; - if(this.defaultBuilderType === gxp.FilterBuilder.ALL_OF) { - type = OpenLayers.Filter.Logical.AND; - } else { - type = OpenLayers.Filter.Logical.OR; - } - return new OpenLayers.Filter.Logical({ - type: OpenLayers.Filter.Logical.OR, - filters: [ - new OpenLayers.Filter.Logical({ - type: type, filters: [filter] - }) - ] - }); - }, - - /** private: method[addCondition] - * Add a new condition or group of conditions to the builder. This - * modifies the filter and adds a panel representing the new condition - * or group of conditions. - */ - addCondition: function(group) { - var filter, type; - if(group) { - type = "gxp_filterbuilder"; - filter = this.wrapFilter(this.createDefaultFilter()); - } else { - type = "gxp_filterfield"; - filter = this.createDefaultFilter(); - } - var newChild = this.newRow({ - xtype: type, - filter: filter, - columnWidth: 1, - attributes: this.attributes, - allowBlank: group ? undefined : this.allowBlank, - customizeFilterOnInit: group && false, - listeners: { - change: function() { - this.fireEvent("change", this); - }, - scope: this - } - }); - this.childFilterContainer.add(newChild); - this.filter.filters[0].filters.push(filter); - this.childFilterContainer.doLayout(); - }, - - /** private: method[removeCondition] - * Remove a condition or group of conditions from the builder. This - * modifies the filter and removes the panel representing the condition - * or group of conditions. - */ - removeCondition: function(item, filter) { - var parent = this.filter.filters[0].filters; - if(parent.length > 0) { - parent.remove(filter); - this.childFilterContainer.remove(item, true); - } - if(parent.length === 0) { - this.addCondition(); - } - this.fireEvent("change", this); - }, - - createBuilderTypeCombo: function() { - var types = this.allowedBuilderTypes || [ - gxp.FilterBuilder.ANY_OF, gxp.FilterBuilder.ALL_OF, - gxp.FilterBuilder.NONE_OF - ]; - var numTypes = types.length; - var data = new Array(numTypes); - var type; - for(var i=0; i`_ + */ +Ext.namespace("gxp"); + +/** api: constructor + * .. class:: FilterBuilder(config) + * + * Create a panel for assembling a filter. + */ +gxp.FilterBuilder = Ext.extend(Ext.Container, { + + /** api: config[builderTypeNames] + * ``Array`` + * A list of labels that correspond to builder type constants. + * These will be the option names available in the builder type combo. + * Default is ``["any", "all", "none", "not all"]``. + */ + builderTypeNames: ["any", "all", "none", "not all"], + + /** api: config[allowedBuilderTypes] + * ``Array`` + * List of builder type constants. Default is + * ``[ANY_OF, ALL_OF, NONE_OF]``. + */ + allowedBuilderTypes: null, + + /** api: config[allowBlank] + * ``Boolean`` Do we allow blank FilterFields? It is safe to say true + * here, but for compatibility reasons with old applications, the default + * is false. + */ + allowBlank: false, + + /** api: config[preComboText] + * ``String`` + * String to display before filter type combo. Default is ``"Match"``. + */ + preComboText: "Match", + + /** api: config[postComboText] + * ``String`` + * String to display after filter type combo. Default is + * ``"of the following:"``. + */ + postComboText: "of the following:", + + /** api: config[cls] + * ``String`` + * The CSS class to be added to this panel's element (defaults to + * ``"gxp-filterbuilder"``). + */ + cls: "gxp-filterbuilder", + + /** api: config[filter] + * ``OpenLayers.Filter`` + * Filter to initialize the component with + */ + + /** private: property[builderType] + */ + builderType: null, + + /** private: property[childFilterContainer] + */ + childFilterContainer: null, + + /** private: property[customizeFilterOnInit] + */ + customizeFilterOnInit: true, + + /** i18n */ + addConditionText: "add condition", + addGroupText: "add group", + removeConditionText: "remove condition", + + /** api: config[allowGroups] + * ``Boolean`` + * Allow groups of conditions to be added. Default is ``true``. + * If ``false``, only individual conditions (non-logical filters) can + * be added. + */ + allowGroups: true, + + initComponent: function() { + var defConfig = { + defaultBuilderType: gxp.FilterBuilder.ANY_OF + }; + Ext.applyIf(this, defConfig); + + if(this.customizeFilterOnInit) { + this.filter = this.customizeFilter(this.filter); + } + + this.builderType = this.getBuilderType(); + + this.items = [{ + xtype: "container", + layout: "form", + ref: "form", + defaults: {anchor: "100%"}, + hideLabels: true, + items: [{ + xtype: "compositefield", + style: "padding-left: 2px", + items: [{ + xtype: "label", + style: "padding-top: 0.3em", + text: this.preComboText + }, this.createBuilderTypeCombo(), { + xtype: "label", + style: "padding-top: 0.3em", + text: this.postComboText + }] + }, this.createChildFiltersPanel(), { + xtype: "toolbar", + items: this.createToolBar() + }] + + }]; + + this.addEvents( + /** + * Event: change + * Fires when the filter changes. + * + * Listener arguments: + * builder - {gxp.FilterBuilder} This filter builder. Call + * ``getFilter`` to get the updated filter. + */ + "change" + ); + + gxp.FilterBuilder.superclass.initComponent.call(this); + }, + + /** private: method[createToolBar] + */ + createToolBar: function() { + var bar = [{ + text: this.addConditionText, + iconCls: "add", + handler: function() { + this.addCondition(); + }, + scope: this + }]; + if(this.allowGroups) { + bar.push({ + text: this.addGroupText, + iconCls: "add", + handler: function() { + this.addCondition(true); + }, + scope: this + }); + } + return bar; + }, + + /** api: method[getFilter] + * :return: ``OpenLayers.Filter`` + * + * Returns a filter that fits the model in the Filter Encoding + * specification. Use this method instead of directly accessing + * the ``filter`` property. Return will be ``false`` if any child + * filter does not have a type, property, or value. + */ + getFilter: function() { + var filter; + if(this.filter) { + filter = this.filter.clone(); + if(filter instanceof OpenLayers.Filter.Logical) { + filter = this.cleanFilter(filter); + } + } + return filter; + }, + + /** private: method[cleanFilter] + * :arg filter: ``OpenLayers.Filter.Logical`` + * :return: ``OpenLayers.Filter`` An equivalent filter to the input, where + * all binary logical filters have more than one child filter. Returns + * false if a filter doesn't have non-null type, property, or value. + * + * Ensures that binary logical filters have more than one child. + */ + cleanFilter: function(filter) { + if(filter instanceof OpenLayers.Filter.Logical) { + if(filter.type !== OpenLayers.Filter.Logical.NOT && + filter.filters.length === 1) { + filter = this.cleanFilter(filter.filters[0]); + } else { + var child; + for(var i=0, len=filter.filters.length; i method to return a + * filter that meets the encoding spec. + */ + customizeFilter: function(filter) { + if(!filter) { + filter = this.wrapFilter(this.createDefaultFilter()); + } else { + filter = this.cleanFilter(filter); + var child, i, len; + switch(filter.type) { + case OpenLayers.Filter.Logical.AND: + case OpenLayers.Filter.Logical.OR: + if(!filter.filters || filter.filters.length === 0) { + // give the filter children if it has none + filter.filters = [this.createDefaultFilter()]; + } else { + for(i=0, len=filter.filters.length; i 0) { + filter = this.customizeFilter(child.filters[0]); + } else { + filter = this.wrapFilter(this.createDefaultFilter()); + } + } + } else { + // non-logical child of NOT should be wrapped + var type; + if(this.defaultBuilderType === gxp.FilterBuilder.NOT_ALL_OF) { + type = OpenLayers.Filter.Logical.AND; + } else { + type = OpenLayers.Filter.Logical.OR; + } + filter.filters = [ + new OpenLayers.Filter.Logical({ + type: type, + filters: [child] + }) + ]; + } + } + break; + default: + // non-logical filters get wrapped + filter = this.wrapFilter(filter); + break; + } + } + return filter; + }, + + createDefaultFilter: function() { + return new OpenLayers.Filter.Comparison(); + }, + + /** private: method[wrapFilter] + * :arg filter: ``OpenLayers.Filter`` A non-logical filter. + * :return: ``OpenLayers.Filter`` A wrapped version of the input filter. + * + * Given a non-logical filter, this creates parent filters depending on + * the ``defaultBuilderType``. + */ + wrapFilter: function(filter) { + var type; + if(this.defaultBuilderType === gxp.FilterBuilder.ALL_OF) { + type = OpenLayers.Filter.Logical.AND; + } else { + type = OpenLayers.Filter.Logical.OR; + } + return new OpenLayers.Filter.Logical({ + type: OpenLayers.Filter.Logical.OR, + filters: [ + new OpenLayers.Filter.Logical({ + type: type, filters: [filter] + }) + ] + }); + }, + + /** private: method[addCondition] + * Add a new condition or group of conditions to the builder. This + * modifies the filter and adds a panel representing the new condition + * or group of conditions. + */ + addCondition: function(group) { + var filter, type; + if(group) { + type = "gxp_filterbuilder"; + filter = this.wrapFilter(this.createDefaultFilter()); + } else { + type = "gxp_filterfield"; + filter = this.createDefaultFilter(); + } + var newChild = this.newRow({ + xtype: type, + filter: filter, + columnWidth: 1, + attributes: this.attributes, + allowBlank: group ? undefined : this.allowBlank, + customizeFilterOnInit: group && false, + listeners: { + change: function() { + this.fireEvent("change", this); + }, + scope: this + } + }); + this.childFilterContainer.add(newChild); + this.filter.filters[0].filters.push(filter); + this.childFilterContainer.doLayout(); + }, + + /** private: method[removeCondition] + * Remove a condition or group of conditions from the builder. This + * modifies the filter and removes the panel representing the condition + * or group of conditions. + */ + removeCondition: function(item, filter) { + var parent = this.filter.filters[0].filters; + if(parent.length > 0) { + parent.remove(filter); + this.childFilterContainer.remove(item, true); + } + if(parent.length === 0) { + this.addCondition(); + } + this.fireEvent("change", this); + }, + + createBuilderTypeCombo: function() { + var types = this.allowedBuilderTypes || [ + gxp.FilterBuilder.ANY_OF, gxp.FilterBuilder.ALL_OF, + gxp.FilterBuilder.NONE_OF + ]; + var numTypes = types.length; + var data = new Array(numTypes); + var type; + for(var i=0; iPaste link in email or IM:', + publishMessage: 'Paste HTML to embed in website:', /** private: method[initComponent] */ @@ -57,16 +58,16 @@ gxp.LinkEmbedMapDialog = Ext.extend(gxp.EmbedMapDialog, { '" width="' + this.widthField.getValue() +'" src="' + gxp.util.getAbsoluteUrl(this.url) + '">' ); - this.linkBox.focus(true, 100); - + this.linkBox.focus(true, 100); + }, /** private: method[getConfig] */ getConfig: function() { - - var absoluteUrl = gxp.util.getAbsoluteUrl(this.linkUrl); - + + var absoluteUrl = gxp.util.getAbsoluteUrl(this.linkUrl); + this.snippetArea = new Ext.form.TextArea({ height: 70, selectOnFocus: true, @@ -93,12 +94,12 @@ gxp.LinkEmbedMapDialog = Ext.extend(gxp.EmbedMapDialog, { }); this.linkBox = new Ext.form.TextField({ - value: absoluteUrl, - listeners: { - "focus": function() { - this.selectText(); - } - } + value: absoluteUrl, + listeners: { + "focus": function() { + this.selectText(); + } + } }); var adjustments = new Ext.Container({ @@ -158,7 +159,7 @@ gxp.LinkEmbedMapDialog = Ext.extend(gxp.EmbedMapDialog, { html: this.linkMessage } },{ - items: [this.linkBox] + items: [this.linkBox] }, { xtype: "box", autoEl: { diff --git a/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSLayerPanel.js b/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSLayerPanel.js index eaa86df..e0824f3 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSLayerPanel.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSLayerPanel.js @@ -1,604 +1,604 @@ -/** - * Copyright (c) 2008-2011 The Open Planning Project - * - * Published under the GPL license. - * See https://github.com/opengeo/gxp/raw/master/license.txt for the full text - * of the license. - */ - -//TODO remove the WMSStylesDialog and GeoServerStyleWriter includes -/** - * @include widgets/WMSStylesDialog.js - * @include plugins/GeoServerStyleWriter.js - * @include GeoExt/widgets/LayerOpacitySlider.js - * @require OpenLayers/Format/CQL.js - * @require widgets/FilterBuilder.js - */ - -/** api: (define) - * module = gxp - * class = WMSLayerPanel - * base_link = `Ext.TabPanel `_ - */ -Ext.namespace("gxp"); - -/** api: constructor - * .. class:: WMSLayerPanel(config) - * - * Create a dialog for setting WMS layer properties like title, abstract, - * opacity, transparency and image format. - */ -gxp.WMSLayerPanel = Ext.extend(Ext.TabPanel, { - - /** api: config[layerRecord] - * ``GeoExt.data.LayerRecord`` - * Show properties for this layer record. - */ - layerRecord: null, - - /** api: config[source] - * ``gxp.plugins.LayerSource`` - * Source for the layer. Optional. If not provided, ``sameOriginStyling`` - * will be ignored. - */ - source: null, - - /** api: config[styling] - * ``Boolean`` - * Show a "Styles" tab. Default is true. - */ - styling: true, - - /** api: config[sameOriginStyling] - * ``Boolean`` - * Only allow editing of styles for layers whose sources have a URL that - * matches the origin of this application. It is strongly discouraged to - * do styling through the proxy as all authorization headers and cookies - * are shared with all remotesources. Default is ``true``. - */ - sameOriginStyling: true, - - /** api: config[rasterStyling] - * ``Boolean`` If set to true, single-band raster styling will be - * supported. Default is ``false``. - */ - rasterStyling: false, - - /** private: property[transparent] - * ``Boolean`` - * Used to store the previous state of the transparent checkbox before - * changing the image format to jpeg (and automagically changing - * the checkbox to disabled and unchecked). - */ - transparent: null, - - /** private: property[editableStyles] - * ``Boolean`` - */ - editableStyles: false, - - /** api: config[activeTab] - * ``String or Number`` - * A string id or the numeric index of the tab that should be initially - * activated on render. Defaults to ``0``. - */ - activeTab: 0, - - /** api: config[border] - * ``Boolean`` - * Display a border around the panel. Defaults to ``false``. - */ - border: false, - - /** api: config[imageFormats] - * ``RegEx`` Regular expression used to test browser friendly formats for - * GetMap requests. The formats displayed will those from the record that - * match this expression. Default is ``/png|gif|jpe?g/i``. - */ - imageFormats: /png|gif|jpe?g/i, - - /** i18n */ - aboutText: "About", - titleText: "Title", - nameText: "Name", - descriptionText: "Description", - displayText: "Display", - opacityText: "Opacity", - formatText: "Tile format", - infoFormatText: "Info format", - infoFormatEmptyText: "Select a format", - transparentText: "Transparent", - cacheText: "Caching", - cacheFieldText: "Use cached tiles", - stylesText: "Styles", - displayOptionsText: "Display options", - queryText: "Limit with filters", - scaleText: "Limit by scale", - minScaleText: "Min scale", - maxScaleText: "Max scale", - switchToFilterBuilderText: "Switch back to filter builder", - cqlPrefixText: "or ", - cqlText: "use CQL filter instead", - - initComponent: function() { - this.cqlFormat = new OpenLayers.Format.CQL(); - if (this.source) { - this.source.getSchema(this.layerRecord, function(attributeStore) { - if (attributeStore !== false) { - var filter = this.layerRecord.getLayer().params.CQL_FILTER; - this.filterBuilder = new gxp.FilterBuilder({ - filter: filter && this.cqlFormat.read(filter), - allowGroups: false, - listeners: { - afterrender: function() { - this.filterBuilder.cascade(function(item) { - if (item.getXType() === "toolbar") { - item.addText(this.cqlPrefixText); - item.addButton({ - text: this.cqlText, - handler: this.switchToCQL, - scope: this - }); - } - }, this); - }, - change: function(builder) { - var filter = builder.getFilter(); - var cql = null; - if (filter !== false) { - cql = this.cqlFormat.write(filter); - } - this.layerRecord.getLayer().mergeNewParams({ - CQL_FILTER: cql - }); - }, - scope: this - }, - attributes: attributeStore - }); - this.filterFieldset.add(this.filterBuilder); - this.filterFieldset.doLayout(); - } - }, this); - } - this.addEvents( - /** api: event[change] - * Fires when the ``layerRecord`` is changed using this dialog. - */ - "change" - ); - this.items = [ - this.createAboutPanel(), - this.createDisplayPanel() - ]; - - // only add the Styles panel if we know for sure that we have styles - if (this.styling && gxp.WMSStylesDialog && this.layerRecord.get("styles")) { - // TODO: revisit this - var url = this.layerRecord.get("restUrl"); - if (!url) { - url = (this.source || this.layerRecord.get("layer")).url.split( - "?").shift().replace(/\/(wms|ows)\/?$/, "/rest"); - } - if (this.sameOriginStyling) { - // this could be made more robust - // for now, only style for sources with relative url - this.editableStyles = url.charAt(0) === "/"; - } else { - this.editableStyles = true; - } - this.items.push(this.createStylesPanel(url)); - } - - gxp.WMSLayerPanel.superclass.initComponent.call(this); - }, - - /** private: method[switchToCQL] - * Switch from filter builder to CQL. - */ - switchToCQL: function() { - var filter = this.filterBuilder.getFilter(); - var CQL = ""; - if (filter !== false) { - CQL = this.cqlFormat.write(filter); - } - this.filterBuilder.hide(); - this.cqlField.setValue(CQL); - this.cqlField.show(); - this.cqlToolbar.show(); - }, - - /** private: method[switchToFilterBuilder] - * Switch from CQL field to filter builder. - */ - switchToFilterBuilder: function() { - var filter = null; - // when parsing fails, we keep the previous filter in the filter builder - try { - filter = this.cqlFormat.read(this.cqlField.getValue()); - } catch(e) { - } - this.cqlField.hide(); - this.cqlToolbar.hide(); - this.filterBuilder.show(); - if (filter !== null) { - this.filterBuilder.setFilter(filter); - } - }, - - /** private: method[createStylesPanel] - * :arg url: ``String`` url to save styles to - * - * Creates the Styles panel. - */ - createStylesPanel: function(url) { - var config = gxp.WMSStylesDialog.createGeoServerStylerConfig( - this.layerRecord, url - ); - if (this.rasterStyling === true) { - config.plugins.push({ - ptype: "gxp_wmsrasterstylesdialog" - }); - } - var ownerCt = this.ownerCt; - if (!(ownerCt.ownerCt instanceof Ext.Window)) { - config.dialogCls = Ext.Panel; - config.showDlg = function(dlg) { - dlg.layout = "fit"; - dlg.autoHeight = false; - ownerCt.add(dlg); - }; - } - return Ext.apply(config, { - title: this.stylesText, - style: "padding: 10px", - editable: false, - listeners: Ext.apply(config.listeners, { - "beforerender": { - fn: function(cmp) { - var render = !this.editableStyles; - if (!render) { - if (typeof this.authorized == 'boolean') { - cmp.editable = this.authorized; - cmp.ownerCt.doLayout(); - } else { - Ext.Ajax.request({ - method: "PUT", - url: url + "/styles", - callback: function(options, success, response) { - // we expect a 405 error code here if we are dealing with - // GeoServer and have write access. Otherwise we will - // create the panel in readonly mode. - cmp.editable = (response.status == 405); - cmp.ownerCt.doLayout(); - } - }); - } - } - return render; - }, - scope: this, - single: true - } - }) - }); - }, - - /** private: method[createAboutPanel] - * Creates the about panel. - */ - createAboutPanel: function() { - return { - title: this.aboutText, - bodyStyle: {"padding": "10px"}, - defaults: { - border: false - }, - items: [{ - layout: "form", - labelWidth: 70, - items: [{ - xtype: "textfield", - fieldLabel: this.titleText, - anchor: "99%", - value: this.layerRecord.get("title"), - listeners: { - change: function(field) { - this.layerRecord.set("title", field.getValue()); - //TODO revisit when discussion on - // http://trac.geoext.org/ticket/110 is complete - this.layerRecord.commit(); - this.fireEvent("change"); - }, - scope: this - } - }, { - xtype: "textfield", - fieldLabel: this.nameText, - anchor: "99%", - value: this.layerRecord.get("name"), - readOnly: true - }] - }, { - layout: "form", - labelAlign: "top", - items: [{ - xtype: "textarea", - fieldLabel: this.descriptionText, - grow: true, - growMax: 150, - anchor: "99%", - value: this.layerRecord.get("abstract"), - readOnly: true - }] - }] - }; - }, - - /** private: method[onFormatChange] - * Handler for when the image format is changed. - */ - onFormatChange: function(combo) { - var layer = this.layerRecord.getLayer(); - var format = combo.getValue(); - layer.mergeNewParams({ - format: format - }); - var cb = this.transparentCb; - if (format == "image/jpeg") { - this.transparent = cb.getValue(); - cb.setValue(false); - } else if (this.transparent !== null) { - cb.setValue(this.transparent); - this.transparent = null; - } - cb.setDisabled(format == "image/jpeg"); - this.fireEvent("change"); - }, - - /** private: method[addScaleOptions] - * :arg layer: ``OpenLayers.Layer.WMS`` - * :arg options: ``Object`` - * - * Apply the scale options to the layer and redraw. - */ - addScaleOptions: function(layer, options) { - // work around for https://github.com/openlayers/openlayers/issues/407 - layer.alwaysInRange = null; - layer.addOptions(options); - layer.display(); - layer.redraw(); - }, - - /** private: method[createDisplayPanel] - * Creates the display panel. - */ - createDisplayPanel: function() { - var record = this.layerRecord; - var layer = record.getLayer(); - var opacity = layer.opacity; - if(opacity == null) { - opacity = 1; - } - var formats = []; - var currentFormat = layer.params["FORMAT"].toLowerCase(); - Ext.each(record.get("formats"), function(format) { - if(this.imageFormats.test(format)) { - formats.push(format.toLowerCase()); - } - }, this); - if(formats.indexOf(currentFormat) === -1) { - formats.push(currentFormat); - } - var transparent = layer.params["TRANSPARENT"]; - transparent = (transparent === "true" || transparent === true); - - return { - title: this.displayText, - layout: 'form', - bodyStyle: {"padding": "10px"}, - defaults: { - labelWidth: 70 - }, - items: [{ - xtype: "fieldset", - title: this.displayOptionsText, - items: [{ - xtype: "gx_opacityslider", - name: "opacity", - anchor: "99%", - isFormField: true, - fieldLabel: this.opacityText, - listeners: { - change: function() { - this.fireEvent("change"); - }, - scope: this - }, - layer: this.layerRecord - }, { - xtype: "compositefield", - fieldLabel: this.formatText, - anchor: "99%", - items: [{ - xtype: "combo", - width: 90, - listWidth: 150, - store: formats, - value: currentFormat, - mode: "local", - triggerAction: "all", - editable: false, - listeners: { - select: this.onFormatChange, - scope: this - } - }, { - xtype: "checkbox", - ref: '../../../transparentCb', - checked: transparent, - listeners: { - check: function(checkbox, checked) { - layer.mergeNewParams({ - transparent: checked ? "true" : "false" - }); - this.fireEvent("change"); - }, - scope: this - } - }, { - xtype: "label", - cls: "gxp-layerproperties-label", - text: this.transparentText - }] - }, { - xtype: "compositefield", - anchor: "99%", - hidden: this.layerRecord.get("layer").params.TILED == null, - fieldLabel: this.cacheText, - items: [{ - xtype: "checkbox", - checked: (this.layerRecord.get("layer").params.TILED === true), - listeners: { - check: function(checkbox, checked) { - var layer = this.layerRecord.get("layer"); - layer.mergeNewParams({ - TILED: checked - }); - this.fireEvent("change"); - }, - scope: this - } - }, { - xtype: "label", - cls: "gxp-layerproperties-label", - text: this.cacheFieldText - }] - }, { - xtype: "combo", - fieldLabel: this.infoFormatText, - emptyText: this.infoFormatEmptyText, - store: record.get("infoFormats"), - value: record.get("infoFormat"), - hidden: (record.get("infoFormats") === undefined), - mode: 'local', - listWidth: 150, - triggerAction: "all", - editable: false, - anchor: "99%", - listeners: { - select: function(combo) { - var infoFormat = combo.getValue(); - record.set("infoFormat", infoFormat); - this.fireEvent("change"); - } - }, - scope: this - }] - }, { - xtype: "fieldset", - title: this.queryText, - hideLabels: true, - ref: "../filterFieldset", - listeners: { - expand: function() { - this.layerRecord.getLayer().mergeNewParams({CQL_FILTER: this.cqlFilter}); - }, - collapse: function() { - this.cqlFilter = this.layerRecord.getLayer().params.CQL_FILTER; - this.layerRecord.getLayer().mergeNewParams({CQL_FILTER: null}); - }, - scope: this - }, - hidden: this.source === null, - checkboxToggle: true, - items: [{ - xtype: "textarea", - value: this.layerRecord.getLayer().params.CQL_FILTER, - grow: true, - anchor: '99%', - width: '100%', - growMax: 100, - ref: "../../cqlField", - hidden: true - }], - buttons: [{ - ref: "../../../cqlToolbar", - hidden: true, - text: this.switchToFilterBuilderText, - handler: this.switchToFilterBuilder, - scope: this - }] - }, { - xtype: "fieldset", - title: this.scaleText, - listeners: { - expand: function() { - var layer = this.layerRecord.getLayer(); - if (this.minScale !== undefined || this.maxScale !== undefined) { - this.addScaleOptions(layer, {minScale: this.maxScale, maxScale: this.minScale}); - } - }, - collapse: function() { - var layer = this.layerRecord.getLayer(); - this.minScale = layer.options.maxScale; - this.maxScale = layer.options.minScale; - this.addScaleOptions(layer, {minScale: null, maxScale: null}); - }, - scope: this - }, - checkboxToggle: true, - items: [{ - xtype: "compositefield", - fieldLabel: this.minScaleText, - items: [{ - xtype: "label", - text: "1:", - cls: "gxp-layerproperties-label" - }, { - xtype: "numberfield", - anchor: '99%', - width: '85%', - listeners: { - 'change': function(field) { - var options = { - maxScale: parseInt(field.getValue()) - }; - var layer = this.layerRecord.getLayer(); - this.addScaleOptions(layer, options); - }, - scope: this - }, - value: this.layerRecord.getLayer().options.maxScale - }] - }, { - xtype: "compositefield", - fieldLabel: this.maxScaleText, - items: [{ - xtype: "label", - text: "1:", - cls: "gxp-layerproperties-label" - }, { - xtype: "numberfield", - anchor: '99%', - width: '85%', - listeners: { - 'change': function(field) { - var options = { - minScale: parseInt(field.getValue()) - }; - var layer = this.layerRecord.getLayer(); - this.addScaleOptions(layer, options); - }, - scope: this - }, - value: this.layerRecord.getLayer().options.minScale - }] - }] - }] - }; - } - -}); - -Ext.reg('gxp_wmslayerpanel', gxp.WMSLayerPanel); +/** + * Copyright (c) 2008-2011 The Open Planning Project + * + * Published under the GPL license. + * See https://github.com/opengeo/gxp/raw/master/license.txt for the full text + * of the license. + */ + +//TODO remove the WMSStylesDialog and GeoServerStyleWriter includes +/** + * @include widgets/WMSStylesDialog.js + * @include plugins/GeoServerStyleWriter.js + * @include GeoExt/widgets/LayerOpacitySlider.js + * @require OpenLayers/Format/CQL.js + * @require widgets/FilterBuilder.js + */ + +/** api: (define) + * module = gxp + * class = WMSLayerPanel + * base_link = `Ext.TabPanel `_ + */ +Ext.namespace("gxp"); + +/** api: constructor + * .. class:: WMSLayerPanel(config) + * + * Create a dialog for setting WMS layer properties like title, abstract, + * opacity, transparency and image format. + */ +gxp.WMSLayerPanel = Ext.extend(Ext.TabPanel, { + + /** api: config[layerRecord] + * ``GeoExt.data.LayerRecord`` + * Show properties for this layer record. + */ + layerRecord: null, + + /** api: config[source] + * ``gxp.plugins.LayerSource`` + * Source for the layer. Optional. If not provided, ``sameOriginStyling`` + * will be ignored. + */ + source: null, + + /** api: config[styling] + * ``Boolean`` + * Show a "Styles" tab. Default is true. + */ + styling: true, + + /** api: config[sameOriginStyling] + * ``Boolean`` + * Only allow editing of styles for layers whose sources have a URL that + * matches the origin of this application. It is strongly discouraged to + * do styling through the proxy as all authorization headers and cookies + * are shared with all remotesources. Default is ``true``. + */ + sameOriginStyling: true, + + /** api: config[rasterStyling] + * ``Boolean`` If set to true, single-band raster styling will be + * supported. Default is ``false``. + */ + rasterStyling: false, + + /** private: property[transparent] + * ``Boolean`` + * Used to store the previous state of the transparent checkbox before + * changing the image format to jpeg (and automagically changing + * the checkbox to disabled and unchecked). + */ + transparent: null, + + /** private: property[editableStyles] + * ``Boolean`` + */ + editableStyles: false, + + /** api: config[activeTab] + * ``String or Number`` + * A string id or the numeric index of the tab that should be initially + * activated on render. Defaults to ``0``. + */ + activeTab: 0, + + /** api: config[border] + * ``Boolean`` + * Display a border around the panel. Defaults to ``false``. + */ + border: false, + + /** api: config[imageFormats] + * ``RegEx`` Regular expression used to test browser friendly formats for + * GetMap requests. The formats displayed will those from the record that + * match this expression. Default is ``/png|gif|jpe?g/i``. + */ + imageFormats: /png|gif|jpe?g/i, + + /** i18n */ + aboutText: "About", + titleText: "Title", + nameText: "Name", + descriptionText: "Description", + displayText: "Display", + opacityText: "Opacity", + formatText: "Tile format", + infoFormatText: "Info format", + infoFormatEmptyText: "Select a format", + transparentText: "Transparent", + cacheText: "Caching", + cacheFieldText: "Use cached tiles", + stylesText: "Styles", + displayOptionsText: "Display options", + queryText: "Limit with filters", + scaleText: "Limit by scale", + minScaleText: "Min scale", + maxScaleText: "Max scale", + switchToFilterBuilderText: "Switch back to filter builder", + cqlPrefixText: "or ", + cqlText: "use CQL filter instead", + + initComponent: function() { + this.cqlFormat = new OpenLayers.Format.CQL(); + if (this.source) { + this.source.getSchema(this.layerRecord, function(attributeStore) { + if (attributeStore !== false) { + var filter = this.layerRecord.getLayer().params.CQL_FILTER; + this.filterBuilder = new gxp.FilterBuilder({ + filter: filter && this.cqlFormat.read(filter), + allowGroups: false, + listeners: { + afterrender: function() { + this.filterBuilder.cascade(function(item) { + if (item.getXType() === "toolbar") { + item.addText(this.cqlPrefixText); + item.addButton({ + text: this.cqlText, + handler: this.switchToCQL, + scope: this + }); + } + }, this); + }, + change: function(builder) { + var filter = builder.getFilter(); + var cql = null; + if (filter !== false) { + cql = this.cqlFormat.write(filter); + } + this.layerRecord.getLayer().mergeNewParams({ + CQL_FILTER: cql + }); + }, + scope: this + }, + attributes: attributeStore + }); + this.filterFieldset.add(this.filterBuilder); + this.filterFieldset.doLayout(); + } + }, this); + } + this.addEvents( + /** api: event[change] + * Fires when the ``layerRecord`` is changed using this dialog. + */ + "change" + ); + this.items = [ + this.createAboutPanel(), + this.createDisplayPanel() + ]; + + // only add the Styles panel if we know for sure that we have styles + if (this.styling && gxp.WMSStylesDialog && this.layerRecord.get("styles")) { + // TODO: revisit this + var url = this.layerRecord.get("restUrl"); + if (!url) { + url = (this.source || this.layerRecord.get("layer")).url.split( + "?").shift().replace(/\/(wms|ows)\/?$/, "/rest"); + } + if (this.sameOriginStyling) { + // this could be made more robust + // for now, only style for sources with relative url + this.editableStyles = url.charAt(0) === "/"; + } else { + this.editableStyles = true; + } + this.items.push(this.createStylesPanel(url)); + } + + gxp.WMSLayerPanel.superclass.initComponent.call(this); + }, + + /** private: method[switchToCQL] + * Switch from filter builder to CQL. + */ + switchToCQL: function() { + var filter = this.filterBuilder.getFilter(); + var CQL = ""; + if (filter !== false) { + CQL = this.cqlFormat.write(filter); + } + this.filterBuilder.hide(); + this.cqlField.setValue(CQL); + this.cqlField.show(); + this.cqlToolbar.show(); + }, + + /** private: method[switchToFilterBuilder] + * Switch from CQL field to filter builder. + */ + switchToFilterBuilder: function() { + var filter = null; + // when parsing fails, we keep the previous filter in the filter builder + try { + filter = this.cqlFormat.read(this.cqlField.getValue()); + } catch(e) { + } + this.cqlField.hide(); + this.cqlToolbar.hide(); + this.filterBuilder.show(); + if (filter !== null) { + this.filterBuilder.setFilter(filter); + } + }, + + /** private: method[createStylesPanel] + * :arg url: ``String`` url to save styles to + * + * Creates the Styles panel. + */ + createStylesPanel: function(url) { + var config = gxp.WMSStylesDialog.createGeoServerStylerConfig( + this.layerRecord, url + ); + if (this.rasterStyling === true) { + config.plugins.push({ + ptype: "gxp_wmsrasterstylesdialog" + }); + } + var ownerCt = this.ownerCt; + if (!(ownerCt.ownerCt instanceof Ext.Window)) { + config.dialogCls = Ext.Panel; + config.showDlg = function(dlg) { + dlg.layout = "fit"; + dlg.autoHeight = false; + ownerCt.add(dlg); + }; + } + return Ext.apply(config, { + title: this.stylesText, + style: "padding: 10px", + editable: false, + listeners: Ext.apply(config.listeners, { + "beforerender": { + fn: function(cmp) { + var render = !this.editableStyles; + if (!render) { + if (typeof this.authorized == 'boolean') { + cmp.editable = this.authorized; + cmp.ownerCt.doLayout(); + } else { + Ext.Ajax.request({ + method: "PUT", + url: url + "/styles", + callback: function(options, success, response) { + // we expect a 405 error code here if we are dealing with + // GeoServer and have write access. Otherwise we will + // create the panel in readonly mode. + cmp.editable = (response.status == 405); + cmp.ownerCt.doLayout(); + } + }); + } + } + return render; + }, + scope: this, + single: true + } + }) + }); + }, + + /** private: method[createAboutPanel] + * Creates the about panel. + */ + createAboutPanel: function() { + return { + title: this.aboutText, + bodyStyle: {"padding": "10px"}, + defaults: { + border: false + }, + items: [{ + layout: "form", + labelWidth: 70, + items: [{ + xtype: "textfield", + fieldLabel: this.titleText, + anchor: "99%", + value: this.layerRecord.get("title"), + listeners: { + change: function(field) { + this.layerRecord.set("title", field.getValue()); + //TODO revisit when discussion on + // http://trac.geoext.org/ticket/110 is complete + this.layerRecord.commit(); + this.fireEvent("change"); + }, + scope: this + } + }, { + xtype: "textfield", + fieldLabel: this.nameText, + anchor: "99%", + value: this.layerRecord.get("name"), + readOnly: true + }] + }, { + layout: "form", + labelAlign: "top", + items: [{ + xtype: "textarea", + fieldLabel: this.descriptionText, + grow: true, + growMax: 150, + anchor: "99%", + value: this.layerRecord.get("abstract"), + readOnly: true + }] + }] + }; + }, + + /** private: method[onFormatChange] + * Handler for when the image format is changed. + */ + onFormatChange: function(combo) { + var layer = this.layerRecord.getLayer(); + var format = combo.getValue(); + layer.mergeNewParams({ + format: format + }); + var cb = this.transparentCb; + if (format == "image/jpeg") { + this.transparent = cb.getValue(); + cb.setValue(false); + } else if (this.transparent !== null) { + cb.setValue(this.transparent); + this.transparent = null; + } + cb.setDisabled(format == "image/jpeg"); + this.fireEvent("change"); + }, + + /** private: method[addScaleOptions] + * :arg layer: ``OpenLayers.Layer.WMS`` + * :arg options: ``Object`` + * + * Apply the scale options to the layer and redraw. + */ + addScaleOptions: function(layer, options) { + // work around for https://github.com/openlayers/openlayers/issues/407 + layer.alwaysInRange = null; + layer.addOptions(options); + layer.display(); + layer.redraw(); + }, + + /** private: method[createDisplayPanel] + * Creates the display panel. + */ + createDisplayPanel: function() { + var record = this.layerRecord; + var layer = record.getLayer(); + var opacity = layer.opacity; + if(opacity == null) { + opacity = 1; + } + var formats = []; + var currentFormat = layer.params["FORMAT"].toLowerCase(); + Ext.each(record.get("formats"), function(format) { + if(this.imageFormats.test(format)) { + formats.push(format.toLowerCase()); + } + }, this); + if(formats.indexOf(currentFormat) === -1) { + formats.push(currentFormat); + } + var transparent = layer.params["TRANSPARENT"]; + transparent = (transparent === "true" || transparent === true); + + return { + title: this.displayText, + layout: 'form', + bodyStyle: {"padding": "10px"}, + defaults: { + labelWidth: 70 + }, + items: [{ + xtype: "fieldset", + title: this.displayOptionsText, + items: [{ + xtype: "gx_opacityslider", + name: "opacity", + anchor: "99%", + isFormField: true, + fieldLabel: this.opacityText, + listeners: { + change: function() { + this.fireEvent("change"); + }, + scope: this + }, + layer: this.layerRecord + }, { + xtype: "compositefield", + fieldLabel: this.formatText, + anchor: "99%", + items: [{ + xtype: "combo", + width: 90, + listWidth: 150, + store: formats, + value: currentFormat, + mode: "local", + triggerAction: "all", + editable: false, + listeners: { + select: this.onFormatChange, + scope: this + } + }, { + xtype: "checkbox", + ref: '../../../transparentCb', + checked: transparent, + listeners: { + check: function(checkbox, checked) { + layer.mergeNewParams({ + transparent: checked ? "true" : "false" + }); + this.fireEvent("change"); + }, + scope: this + } + }, { + xtype: "label", + cls: "gxp-layerproperties-label", + text: this.transparentText + }] + }, { + xtype: "compositefield", + anchor: "99%", + hidden: this.layerRecord.get("layer").params.TILED == null, + fieldLabel: this.cacheText, + items: [{ + xtype: "checkbox", + checked: (this.layerRecord.get("layer").params.TILED === true), + listeners: { + check: function(checkbox, checked) { + var layer = this.layerRecord.get("layer"); + layer.mergeNewParams({ + TILED: checked + }); + this.fireEvent("change"); + }, + scope: this + } + }, { + xtype: "label", + cls: "gxp-layerproperties-label", + text: this.cacheFieldText + }] + }, { + xtype: "combo", + fieldLabel: this.infoFormatText, + emptyText: this.infoFormatEmptyText, + store: record.get("infoFormats"), + value: record.get("infoFormat"), + hidden: (record.get("infoFormats") === undefined), + mode: 'local', + listWidth: 150, + triggerAction: "all", + editable: false, + anchor: "99%", + listeners: { + select: function(combo) { + var infoFormat = combo.getValue(); + record.set("infoFormat", infoFormat); + this.fireEvent("change"); + } + }, + scope: this + }] + }, { + xtype: "fieldset", + title: this.queryText, + hideLabels: true, + ref: "../filterFieldset", + listeners: { + expand: function() { + this.layerRecord.getLayer().mergeNewParams({CQL_FILTER: this.cqlFilter}); + }, + collapse: function() { + this.cqlFilter = this.layerRecord.getLayer().params.CQL_FILTER; + this.layerRecord.getLayer().mergeNewParams({CQL_FILTER: null}); + }, + scope: this + }, + hidden: this.source === null, + checkboxToggle: true, + items: [{ + xtype: "textarea", + value: this.layerRecord.getLayer().params.CQL_FILTER, + grow: true, + anchor: '99%', + width: '100%', + growMax: 100, + ref: "../../cqlField", + hidden: true + }], + buttons: [{ + ref: "../../../cqlToolbar", + hidden: true, + text: this.switchToFilterBuilderText, + handler: this.switchToFilterBuilder, + scope: this + }] + }, { + xtype: "fieldset", + title: this.scaleText, + listeners: { + expand: function() { + var layer = this.layerRecord.getLayer(); + if (this.minScale !== undefined || this.maxScale !== undefined) { + this.addScaleOptions(layer, {minScale: this.maxScale, maxScale: this.minScale}); + } + }, + collapse: function() { + var layer = this.layerRecord.getLayer(); + this.minScale = layer.options.maxScale; + this.maxScale = layer.options.minScale; + this.addScaleOptions(layer, {minScale: null, maxScale: null}); + }, + scope: this + }, + checkboxToggle: true, + items: [{ + xtype: "compositefield", + fieldLabel: this.minScaleText, + items: [{ + xtype: "label", + text: "1:", + cls: "gxp-layerproperties-label" + }, { + xtype: "numberfield", + anchor: '99%', + width: '85%', + listeners: { + 'change': function(field) { + var options = { + maxScale: parseInt(field.getValue()) + }; + var layer = this.layerRecord.getLayer(); + this.addScaleOptions(layer, options); + }, + scope: this + }, + value: this.layerRecord.getLayer().options.maxScale + }] + }, { + xtype: "compositefield", + fieldLabel: this.maxScaleText, + items: [{ + xtype: "label", + text: "1:", + cls: "gxp-layerproperties-label" + }, { + xtype: "numberfield", + anchor: '99%', + width: '85%', + listeners: { + 'change': function(field) { + var options = { + minScale: parseInt(field.getValue()) + }; + var layer = this.layerRecord.getLayer(); + this.addScaleOptions(layer, options); + }, + scope: this + }, + value: this.layerRecord.getLayer().options.minScale + }] + }] + }] + }; + } + +}); + +Ext.reg('gxp_wmslayerpanel', gxp.WMSLayerPanel); diff --git a/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSStylesDialog.js b/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSStylesDialog.js index 1173519..58c5c71 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSStylesDialog.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/widgets/WMSStylesDialog.js @@ -917,7 +917,7 @@ gxp.WMSStylesDialog = Ext.extend(Ext.Container, { // set the default style if no STYLES param is set on the layer if (!this.selectedStyle && (initialStyle === userStyle.name || - userStyle.isDefault === true )) { + !initialStyle && userStyle.isDefault === true )) { this.selectedStyle = record; } } diff --git a/src/geonode-client/app/static/externals/gxp/src/script/widgets/form/FilterField.js b/src/geonode-client/app/static/externals/gxp/src/script/widgets/form/FilterField.js index 37b7865..a476e12 100644 --- a/src/geonode-client/app/static/externals/gxp/src/script/widgets/form/FilterField.js +++ b/src/geonode-client/app/static/externals/gxp/src/script/widgets/form/FilterField.js @@ -1,303 +1,303 @@ -/** - * Copyright (c) 2008-2011 The Open Planning Project - * - * Published under the GPL license. - * See https://github.com/opengeo/gxp/raw/master/license.txt for the full text - * of the license. - */ - -/** - * @include widgets/form/ComparisonComboBox.js - * @requires GeoExt/data/AttributeStore.js - */ - -/** api: (define) - * module = gxp.form - * class = FilterField - * base_link = `Ext.form.CompositeField `_ - */ -Ext.namespace("gxp.form"); - -/** api: constructor - * .. class:: FilterField(config) - * - * A form field representing a comparison filter. - */ -gxp.form.FilterField = Ext.extend(Ext.form.CompositeField, { - - /** api:config[lowerBoundaryTip] - * ``String`` tooltip for the lower boundary textfield (i18n) - */ - lowerBoundaryTip: "lower boundary", - - /** api:config[upperBoundaryTip] - * ``String`` tooltip for the lower boundary textfield (i18n) - */ - upperBoundaryTip: "upper boundary", - - /** - * Property: filter - * {OpenLayers.Filter} Optional non-logical filter provided in the initial - * configuration. To retreive the filter, use instead - * of accessing this property directly. - */ - filter: null, - - /** - * Property: attributes - * {GeoExt.data.AttributeStore} A configured attributes store for use in - * the filter property combo. - */ - attributes: null, - - /** api:config[comparisonComboConfig] - * ``Object`` Config object for comparison combobox. - */ - - /** api:config[attributesComboConfig] - * ``Object`` Config object for attributes combobox. - */ - - /** - * Property: attributesComboConfig - * {Object} - */ - attributesComboConfig: null, - - initComponent: function() { - - if(!this.filter) { - this.filter = this.createDefaultFilter(); - } - // Maintain compatibility with QueryPanel, which relies on "remote" - // mode and the filterBy filter applied in it's attributeStore's load - // listener *after* the initial combo filtering. - //TODO Assume that the AttributeStore is already loaded and always - // create a new one without geometry fields. - var mode = "remote", attributes = new GeoExt.data.AttributeStore(); - if (this.attributes) { - if (this.attributes.getCount() != 0) { - mode = "local"; - this.attributes.each(function(r) { - var match = /gml:((Multi)?(Point|Line|Polygon|Curve|Surface|Geometry)).*/.exec(r.get("type")); - match || attributes.add([r]); - }); - } else { - attributes = this.attributes; - } - } - - var defAttributesComboConfig = { - xtype: "combo", - store: attributes, - editable: mode == "local", - typeAhead: true, - forceSelection: true, - mode: mode, - triggerAction: "all", - ref: "property", - allowBlank: this.allowBlank, - displayField: "name", - valueField: "name", - value: this.filter.property, - listeners: { - select: function(combo, record) { - this.items.get(1).enable(); - this.filter.property = record.get("name"); - this.fireEvent("change", this.filter, this); - }, - // workaround for select event not being fired when tab is hit - // after field was autocompleted with forceSelection - "blur": function(combo) { - var index = combo.store.findExact("name", combo.getValue()); - if (index != -1) { - combo.fireEvent("select", combo, combo.store.getAt(index)); - } else if (combo.startValue != null) { - combo.setValue(combo.startValue); - } - }, - scope: this - }, - width: 120 - }; - this.attributesComboConfig = this.attributesComboConfig || {}; - Ext.applyIf(this.attributesComboConfig, defAttributesComboConfig); - - this.items = this.createFilterItems(); - - this.addEvents( - /** - * Event: change - * Fires when the filter changes. - * - * Listener arguments: - * filter - {OpenLayers.Filter} This filter. - * this - {gxp.form.FilterField} (TODO change sequence of event parameters) - */ - "change" - ); - - gxp.form.FilterField.superclass.initComponent.call(this); - }, - - /** - * Method: validateValue - * Performs validation checks on the filter field. - * - * Returns: - * {Boolean} True if value is valid. - */ - validateValue: function(value, preventMark) { - if (this.filter.type === OpenLayers.Filter.Comparison.BETWEEN) { - return (this.filter.property !== null && this.filter.upperBoundary !== null && - this.filter.lowerBoundary !== null); - } else { - return (this.filter.property !== null && - this.filter.value !== null && this.filter.type !== null); - } - }, - - /** - * Method: createDefaultFilter - * May be overridden to change the default filter. - * - * Returns: - * {OpenLayers.Filter} By default, returns a comarison filter. - */ - createDefaultFilter: function() { - return new OpenLayers.Filter.Comparison(); - }, - - /** - * Method: createFilterItems - * Creates a panel config containing filter parts. - */ - createFilterItems: function() { - var isBetween = this.filter.type === OpenLayers.Filter.Comparison.BETWEEN; - return [ - this.attributesComboConfig, Ext.applyIf({ - xtype: "gxp_comparisoncombo", - ref: "type", - disabled: this.filter.property == null, - allowBlank: this.allowBlank, - value: this.filter.type, - listeners: { - select: function(combo, record) { - this.items.get(2).enable(); - this.items.get(3).enable(); - this.items.get(4).enable(); - this.setFilterType(record.get("value")); - this.fireEvent("change", this.filter, this); - }, - scope: this - } - }, this.comparisonComboConfig), { - xtype: "textfield", - disabled: this.filter.type == null, - hidden: isBetween, - ref: "value", - value: this.filter.value, - width: 50, - grow: true, - growMin: 50, - anchor: "100%", - allowBlank: this.allowBlank, - listeners: { - "change": function(field, value) { - this.filter.value = value; - this.fireEvent("change", this.filter, this); - }, - scope: this - } - }, { - xtype: "textfield", - disabled: this.filter.type == null, - hidden: !isBetween, - value: this.filter.lowerBoundary, - tooltip: this.lowerBoundaryTip, - grow: true, - growMin: 30, - ref: "lowerBoundary", - anchor: "100%", - allowBlank: this.allowBlank, - listeners: { - "change": function(field, value) { - this.filter.lowerBoundary = value; - this.fireEvent("change", this.filter, this); - }, - "render": function(c) { - Ext.QuickTips.register({ - target: c.getEl(), - text: this.lowerBoundaryTip - }); - }, - "autosize": function(field, width) { - field.setWidth(width); - field.ownerCt.doLayout(); - }, - scope: this - } - }, { - xtype: "textfield", - disabled: this.filter.type == null, - hidden: !isBetween, - grow: true, - growMin: 30, - ref: "upperBoundary", - value: this.filter.upperBoundary, - allowBlank: this.allowBlank, - listeners: { - "change": function(field, value) { - this.filter.upperBoundary = value; - this.fireEvent("change", this.filter, this); - }, - "render": function(c) { - Ext.QuickTips.register({ - target: c.getEl(), - text: this.upperBoundaryTip - }); - }, - scope: this - } - } - ]; - }, - - setFilterType: function(type) { - this.filter.type = type; - if (type === OpenLayers.Filter.Comparison.BETWEEN) { - this.items.get(2).hide(); - this.items.get(3).show(); - this.items.get(4).show(); - } else { - this.items.get(2).show(); - this.items.get(3).hide(); - this.items.get(4).hide(); - } - this.doLayout(); - }, - - /** api: method[setFilter] - * :arg filter: ``OpenLayers.Filter``` Change the filter object to be - * used. - */ - setFilter: function(filter) { - var previousType = this.filter.type; - this.filter = filter; - if (previousType !== filter.type) { - this.setFilterType(filter.type); - } - this['property'].setValue(filter.property); - this['type'].setValue(filter.type); - if (filter.type === OpenLayers.Filter.Comparison.BETWEEN) { - this['lowerBoundary'].setValue(filter.lowerBoundary); - this['upperBoundary'].setValue(filter.upperBoundary); - } else { - this['value'].setValue(filter.value); - } - this.fireEvent("change", this.filter, this); - } - -}); - -Ext.reg('gxp_filterfield', gxp.form.FilterField); +/** + * Copyright (c) 2008-2011 The Open Planning Project + * + * Published under the GPL license. + * See https://github.com/opengeo/gxp/raw/master/license.txt for the full text + * of the license. + */ + +/** + * @include widgets/form/ComparisonComboBox.js + * @requires GeoExt/data/AttributeStore.js + */ + +/** api: (define) + * module = gxp.form + * class = FilterField + * base_link = `Ext.form.CompositeField `_ + */ +Ext.namespace("gxp.form"); + +/** api: constructor + * .. class:: FilterField(config) + * + * A form field representing a comparison filter. + */ +gxp.form.FilterField = Ext.extend(Ext.form.CompositeField, { + + /** api:config[lowerBoundaryTip] + * ``String`` tooltip for the lower boundary textfield (i18n) + */ + lowerBoundaryTip: "lower boundary", + + /** api:config[upperBoundaryTip] + * ``String`` tooltip for the lower boundary textfield (i18n) + */ + upperBoundaryTip: "upper boundary", + + /** + * Property: filter + * {OpenLayers.Filter} Optional non-logical filter provided in the initial + * configuration. To retreive the filter, use instead + * of accessing this property directly. + */ + filter: null, + + /** + * Property: attributes + * {GeoExt.data.AttributeStore} A configured attributes store for use in + * the filter property combo. + */ + attributes: null, + + /** api:config[comparisonComboConfig] + * ``Object`` Config object for comparison combobox. + */ + + /** api:config[attributesComboConfig] + * ``Object`` Config object for attributes combobox. + */ + + /** + * Property: attributesComboConfig + * {Object} + */ + attributesComboConfig: null, + + initComponent: function() { + + if(!this.filter) { + this.filter = this.createDefaultFilter(); + } + // Maintain compatibility with QueryPanel, which relies on "remote" + // mode and the filterBy filter applied in it's attributeStore's load + // listener *after* the initial combo filtering. + //TODO Assume that the AttributeStore is already loaded and always + // create a new one without geometry fields. + var mode = "remote", attributes = new GeoExt.data.AttributeStore(); + if (this.attributes) { + if (this.attributes.getCount() != 0) { + mode = "local"; + this.attributes.each(function(r) { + var match = /gml:((Multi)?(Point|Line|Polygon|Curve|Surface|Geometry)).*/.exec(r.get("type")); + match || attributes.add([r]); + }); + } else { + attributes = this.attributes; + } + } + + var defAttributesComboConfig = { + xtype: "combo", + store: attributes, + editable: mode == "local", + typeAhead: true, + forceSelection: true, + mode: mode, + triggerAction: "all", + ref: "property", + allowBlank: this.allowBlank, + displayField: "name", + valueField: "name", + value: this.filter.property, + listeners: { + select: function(combo, record) { + this.items.get(1).enable(); + this.filter.property = record.get("name"); + this.fireEvent("change", this.filter, this); + }, + // workaround for select event not being fired when tab is hit + // after field was autocompleted with forceSelection + "blur": function(combo) { + var index = combo.store.findExact("name", combo.getValue()); + if (index != -1) { + combo.fireEvent("select", combo, combo.store.getAt(index)); + } else if (combo.startValue != null) { + combo.setValue(combo.startValue); + } + }, + scope: this + }, + width: 120 + }; + this.attributesComboConfig = this.attributesComboConfig || {}; + Ext.applyIf(this.attributesComboConfig, defAttributesComboConfig); + + this.items = this.createFilterItems(); + + this.addEvents( + /** + * Event: change + * Fires when the filter changes. + * + * Listener arguments: + * filter - {OpenLayers.Filter} This filter. + * this - {gxp.form.FilterField} (TODO change sequence of event parameters) + */ + "change" + ); + + gxp.form.FilterField.superclass.initComponent.call(this); + }, + + /** + * Method: validateValue + * Performs validation checks on the filter field. + * + * Returns: + * {Boolean} True if value is valid. + */ + validateValue: function(value, preventMark) { + if (this.filter.type === OpenLayers.Filter.Comparison.BETWEEN) { + return (this.filter.property !== null && this.filter.upperBoundary !== null && + this.filter.lowerBoundary !== null); + } else { + return (this.filter.property !== null && + this.filter.value !== null && this.filter.type !== null); + } + }, + + /** + * Method: createDefaultFilter + * May be overridden to change the default filter. + * + * Returns: + * {OpenLayers.Filter} By default, returns a comarison filter. + */ + createDefaultFilter: function() { + return new OpenLayers.Filter.Comparison(); + }, + + /** + * Method: createFilterItems + * Creates a panel config containing filter parts. + */ + createFilterItems: function() { + var isBetween = this.filter.type === OpenLayers.Filter.Comparison.BETWEEN; + return [ + this.attributesComboConfig, Ext.applyIf({ + xtype: "gxp_comparisoncombo", + ref: "type", + disabled: this.filter.property == null, + allowBlank: this.allowBlank, + value: this.filter.type, + listeners: { + select: function(combo, record) { + this.items.get(2).enable(); + this.items.get(3).enable(); + this.items.get(4).enable(); + this.setFilterType(record.get("value")); + this.fireEvent("change", this.filter, this); + }, + scope: this + } + }, this.comparisonComboConfig), { + xtype: "textfield", + disabled: this.filter.type == null, + hidden: isBetween, + ref: "value", + value: this.filter.value, + width: 50, + grow: true, + growMin: 50, + anchor: "100%", + allowBlank: this.allowBlank, + listeners: { + "change": function(field, value) { + this.filter.value = value; + this.fireEvent("change", this.filter, this); + }, + scope: this + } + }, { + xtype: "textfield", + disabled: this.filter.type == null, + hidden: !isBetween, + value: this.filter.lowerBoundary, + tooltip: this.lowerBoundaryTip, + grow: true, + growMin: 30, + ref: "lowerBoundary", + anchor: "100%", + allowBlank: this.allowBlank, + listeners: { + "change": function(field, value) { + this.filter.lowerBoundary = value; + this.fireEvent("change", this.filter, this); + }, + "render": function(c) { + Ext.QuickTips.register({ + target: c.getEl(), + text: this.lowerBoundaryTip + }); + }, + "autosize": function(field, width) { + field.setWidth(width); + field.ownerCt.doLayout(); + }, + scope: this + } + }, { + xtype: "textfield", + disabled: this.filter.type == null, + hidden: !isBetween, + grow: true, + growMin: 30, + ref: "upperBoundary", + value: this.filter.upperBoundary, + allowBlank: this.allowBlank, + listeners: { + "change": function(field, value) { + this.filter.upperBoundary = value; + this.fireEvent("change", this.filter, this); + }, + "render": function(c) { + Ext.QuickTips.register({ + target: c.getEl(), + text: this.upperBoundaryTip + }); + }, + scope: this + } + } + ]; + }, + + setFilterType: function(type) { + this.filter.type = type; + if (type === OpenLayers.Filter.Comparison.BETWEEN) { + this.items.get(2).hide(); + this.items.get(3).show(); + this.items.get(4).show(); + } else { + this.items.get(2).show(); + this.items.get(3).hide(); + this.items.get(4).hide(); + } + this.doLayout(); + }, + + /** api: method[setFilter] + * :arg filter: ``OpenLayers.Filter``` Change the filter object to be + * used. + */ + setFilter: function(filter) { + var previousType = this.filter.type; + this.filter = filter; + if (previousType !== filter.type) { + this.setFilterType(filter.type); + } + this['property'].setValue(filter.property); + this['type'].setValue(filter.type); + if (filter.type === OpenLayers.Filter.Comparison.BETWEEN) { + this['lowerBoundary'].setValue(filter.lowerBoundary); + this['upperBoundary'].setValue(filter.upperBoundary); + } else { + this['value'].setValue(filter.value); + } + this.fireEvent("change", this.filter, this); + } + +}); + +Ext.reg('gxp_filterfield', gxp.form.FilterField); diff --git a/src/geonode-client/app/static/externals/gxp/src/theme/img/silk/readme.txt b/src/geonode-client/app/static/externals/gxp/src/theme/img/silk/readme.txt index 400a64d..2cf67dc 100644 --- a/src/geonode-client/app/static/externals/gxp/src/theme/img/silk/readme.txt +++ b/src/geonode-client/app/static/externals/gxp/src/theme/img/silk/readme.txt @@ -1,22 +1,22 @@ -Silk icon set 1.3 - -_________________________________________ -Mark James -http://www.famfamfam.com/lab/icons/silk/ -_________________________________________ - -This work is licensed under a -Creative Commons Attribution 2.5 License. -[ http://creativecommons.org/licenses/by/2.5/ ] - -This means you may use it for any purpose, -and make any changes you like. -All I ask is that you include a link back -to this page in your credits. - -Are you using this icon set? Send me an email -(including a link or picture if available) to -mjames@gmail.com - -Any other questions about this icon set please +Silk icon set 1.3 + +_________________________________________ +Mark James +http://www.famfamfam.com/lab/icons/silk/ +_________________________________________ + +This work is licensed under a +Creative Commons Attribution 2.5 License. +[ http://creativecommons.org/licenses/by/2.5/ ] + +This means you may use it for any purpose, +and make any changes you like. +All I ask is that you include a link back +to this page in your credits. + +Are you using this icon set? Send me an email +(including a link or picture if available) to +mjames@gmail.com + +Any other questions about this icon set please contact mjames@gmail.com \ No newline at end of file diff --git a/src/geonode-client/app/static/externals/misc/jquery.simplemodal.1.4.4.min.js b/src/geonode-client/app/static/externals/misc/jquery.simplemodal.1.4.4.min.js index 382c736..de227a9 100644 --- a/src/geonode-client/app/static/externals/misc/jquery.simplemodal.1.4.4.min.js +++ b/src/geonode-client/app/static/externals/misc/jquery.simplemodal.1.4.4.min.js @@ -1,10 +1,10 @@ -/* - * SimpleModal 1.4.4 - jQuery Plugin - * http://simplemodal.com/ - * Copyright (c) 2013 Eric Martin - * Licensed under MIT and GPL - * Date: Sun, Jan 20 2013 15:58:56 -0800 - */ +/* + * SimpleModal 1.4.4 - jQuery Plugin + * http://simplemodal.com/ + * Copyright (c) 2013 Eric Martin + * Licensed under MIT and GPL + * Date: Sun, Jan 20 2013 15:58:56 -0800 + */ (function(b){"function"===typeof define&&define.amd?define(["jquery"],b):b(jQuery)})(function(b){var j=[],n=b(document),k=navigator.userAgent.toLowerCase(),l=b(window),g=[],o=null,p=/msie/.test(k)&&!/opera/.test(k),q=/opera/.test(k),m,r;m=p&&/msie 6./.test(k)&&"object"!==typeof window.XMLHttpRequest;r=p&&/msie 7.0/.test(k);b.modal=function(a,h){return b.modal.impl.init(a,h)};b.modal.close=function(){b.modal.impl.close()};b.modal.focus=function(a){b.modal.impl.focus(a)};b.modal.setContainerDimensions= function(){b.modal.impl.setContainerDimensions()};b.modal.setPosition=function(){b.modal.impl.setPosition()};b.modal.update=function(a,h){b.modal.impl.update(a,h)};b.fn.modal=function(a){return b.modal.impl.init(this,a)};b.modal.defaults={appendTo:"body",focus:!0,opacity:50,overlayId:"simplemodal-overlay",overlayCss:{},containerId:"simplemodal-container",containerCss:{},dataId:"simplemodal-data",dataCss:{},minHeight:null,minWidth:null,maxHeight:null,maxWidth:null,autoResize:!1,autoPosition:!0,zIndex:1E3, close:!0,closeHTML:'',closeClass:"simplemodal-close",escClose:!0,overlayClose:!1,fixed:!0,position:null,persist:!1,modal:!0,onOpen:null,onShow:null,onClose:null};b.modal.impl={d:{},init:function(a,h){if(this.d.data)return!1;o=p&&!b.support.boxModel;this.o=b.extend({},b.modal.defaults,h);this.zIndex=this.o.zIndex;this.occb=!1;if("object"===typeof a){if(a=a instanceof b?a:b(a),this.d.placeholder=!1,0").attr("id", diff --git a/src/geonode-client/app/static/externals/misc/nicEdit.js b/src/geonode-client/app/static/externals/misc/nicEdit.js index 68df988..a816611 100644 --- a/src/geonode-client/app/static/externals/misc/nicEdit.js +++ b/src/geonode-client/app/static/externals/misc/nicEdit.js @@ -4,8 +4,8 @@ * NicEdit is distributed under the terms of the MIT license * For more information visit http://nicedit.com/ * Do not remove this copyright message - */ -var bkExtend=function(){var A=arguments;if(A.length==1){A=[this,A[0]]}for(var B in A[1]){A[0][B]=A[1][B]}return A[0]};function bkClass(){}bkClass.prototype.construct=function(){};bkClass.extend=function(C){var A=function(){if(arguments[0]!==bkClass){return this.construct.apply(this,arguments)}};var B=new this(bkClass);bkExtend(B,C);A.prototype=B;A.extend=this.extend;return A};var bkElement=bkClass.extend({construct:function(B,A){if(typeof (B)=="string"){B=(A||document).createElement(B)}B=$BK(B);return B},appendTo:function(A){A.appendChild(this);return this},appendBefore:function(A){A.parentNode.insertBefore(this,A);return this},addEvent:function(B,A){bkLib.addEvent(this,B,A);return this},setContent:function(A){this.innerHTML=A;return this},pos:function(){var C=curtop=0;var B=obj=this;if(obj.offsetParent){do{C+=obj.offsetLeft;curtop+=obj.offsetTop}while(obj=obj.offsetParent)}var A=(!window.opera)?parseInt(this.getStyle("border-width")||this.style.border)||0:0;return[C+A,curtop+A+this.offsetHeight]},noSelect:function(){bkLib.noSelect(this);return this},parentTag:function(A){var B=this;do{if(B&&B.nodeName&&B.nodeName.toUpperCase()==A){return B}B=B.parentNode}while(B);return false},hasClass:function(A){return this.className.match(new RegExp("(\\s|^)nicEdit-"+A+"(\\s|$)"))},addClass:function(A){if(!this.hasClass(A)){this.className+=" nicEdit-"+A}return this},removeClass:function(A){if(this.hasClass(A)){this.className=this.className.replace(new RegExp("(\\s|^)nicEdit-"+A+"(\\s|$)")," ")}return this},setStyle:function(A){var B=this.style;for(var C in A){switch(C){case"float":B.cssFloat=B.styleFloat=A[C];break;case"opacity":B.opacity=A[C];B.filter="alpha(opacity="+Math.round(A[C]*100)+")";break;case"className":this.className=A[C];break;default:B[C]=A[C]}}return this},getStyle:function(A,C){var B=(!C)?document.defaultView:C;if(this.nodeType==1){return(B&&B.getComputedStyle)?B.getComputedStyle(this,null).getPropertyValue(A):this.currentStyle[bkLib.camelize(A)]}},remove:function(){this.parentNode.removeChild(this);return this},setAttributes:function(A){for(var B in A){this[B]=A[B]}return this}});var bkLib={isMSIE:(navigator.appVersion.indexOf("MSIE")!=-1),addEvent:function(C,B,A){(C.addEventListener)?C.addEventListener(B,A,false):C.attachEvent("on"+B,A)},toArray:function(C){var B=C.length,A=new Array(B);while(B--){A[B]=C[B]}return A},noSelect:function(B){if(B.setAttribute&&B.nodeName.toLowerCase()!="input"&&B.nodeName.toLowerCase()!="textarea"){B.setAttribute("unselectable","on")}for(var A=0;A.nicEdit-main p { margin: 0; } - - - - - -

Accelerometer

- -

- The goal of this script is to demonstrate the usage of accelerometer. -

-

- The orientation specification can be found here. -

- -
- browser, vendor, mobile, orientation -
- -

Device motion

- -
- -
-

Device orientation

- -
- -
-

MOZ orientation

- -
- -
- - + + + + + + + OpenLayers Accelerometer Usage + + + + + + + + +

Accelerometer

+ +

+ The goal of this script is to demonstrate the usage of accelerometer. +

+

+ The orientation specification can be found here. +

+ +
+ browser, vendor, mobile, orientation +
+ +

Device motion

+ +
+ +
+

Device orientation

+ +
+ +
+

MOZ orientation

+ +
+ +
+ + diff --git a/src/geonode-client/app/static/externals/openlayers/examples/browser.html b/src/geonode-client/app/static/externals/openlayers/examples/browser.html index 195f7d4..f5568ed 100644 --- a/src/geonode-client/app/static/externals/openlayers/examples/browser.html +++ b/src/geonode-client/app/static/externals/openlayers/examples/browser.html @@ -1,152 +1,152 @@ - - - - - - - OpenLayers Browser Detection - - - - - - - -

Browser detection

- -
- browser, vendor, mobile, events, HTML5, gesture, touch -
- -

- The goal of this script is to inform about the capacity of the browser used by the user. -

- -
-

- See the - browser.js source to see how this is done. -

-
- -

Your browser information

- -
-
- -

Click or touch the red square to get information about the selected events

- -
-
- click
- dblclick
- mousedown
- mouseup
- mouseover
- mousemove
- mouseout
- touchstart
- touchend
- touchmove
- touchcancel
- gesturestart
- gesturechange
- gestureend
-
- -
-
-
-
- -
-
- - - - + + + + + + + OpenLayers Browser Detection + + + + + + + +

Browser detection

+ +
+ browser, vendor, mobile, events, HTML5, gesture, touch +
+ +

+ The goal of this script is to inform about the capacity of the browser used by the user. +

+ +
+

+ See the + browser.js source to see how this is done. +

+
+ +

Your browser information

+ +
+
+ +

Click or touch the red square to get information about the selected events

+ +
+
+ click
+ dblclick
+ mousedown
+ mouseup
+ mouseover
+ mousemove
+ mouseout
+ touchstart
+ touchend
+ touchmove
+ touchcancel
+ gesturestart
+ gesturechange
+ gestureend
+
+ +
+
+
+
+ +
+
+ + + + diff --git a/src/geonode-client/app/static/externals/openlayers/examples/browser.js b/src/geonode-client/app/static/externals/openlayers/examples/browser.js index a593ca6..24e7ad4 100644 --- a/src/geonode-client/app/static/externals/openlayers/examples/browser.js +++ b/src/geonode-client/app/static/externals/openlayers/examples/browser.js @@ -1,241 +1,241 @@ -var isEventSupported = (function(undef) { - - var TAGNAMES = { - 'select':'input', - 'change':'input', - 'submit':'form', - 'reset':'form', - 'error':'img', - 'load':'img', - 'abort':'img' - }; - - function isEventSupported(eventName, element) { - element = element || document.createElement(TAGNAMES[eventName] || 'div'); - eventName = 'on' + eventName; - - var isSupported = (eventName in element); - - if (!isSupported) { - // if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element - if (!element.setAttribute) { - element = document.createElement('div'); - } - if (element.setAttribute && element.removeAttribute) { - element.setAttribute(eventName, ''); - isSupported = typeof element[eventName] == 'function'; - - // if property was created, "remove it" (by setting value to `undefined`) - if (typeof element[eventName] != 'undefined') { - element[eventName] = undef; - } - element.removeAttribute(eventName); - } - } - - element = null; - return isSupported; - } - - return isEventSupported; -})(); - -function divResult(category, name, element, div) { - div.innerHTML = div.innerHTML + category + " " + name + ": "; - div.innerHTML = div.innerHTML + ( - isEventSupported(name, element) - ? 'true' - : 'false' - ); - div.innerHTML = div.innerHTML + "
"; -} -var counter = 1; - -function log(title, detail) { - var logDiv = document.getElementById("log"); - idString = "'id" + counter + "'"; - var newlink = document.createElement('a'); - newlink.setAttribute('href', "javascript:toggle_visibility(" + idString + ")"); - newlink.innerHTML = counter + ". " + title; - var br1 = document.createElement('br'); - logDiv.appendChild(newlink); - logDiv.appendChild(br1); - - var childDiv = document.createElement('div'); - childDiv.setAttribute("id", idString.replace("'", "").replace("'", "")); - childDiv.setAttribute("style", 'display: none; margin-left : 5px;'); - childDiv.innerHTML = detail; - var br2 = document.createElement('br'); - logDiv.appendChild(childDiv); - - counter = counter + 1; -} - -function inspect(obj) { - if (typeof obj === "undefined") { - return "undefined"; - } - var _props = []; - - for (var i in obj) { - _props.push(i + " : " + obj[i]); - } - return " {" + _props.join(",
") + "} "; -} - -function click(e) { - if (document.getElementById("clickID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function dblclick(e) { - if (document.getElementById("dblclickID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function mousedown(e) { - if (document.getElementById("mousedownID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function mouseup(e) { - if (document.getElementById("mouseupID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function mouseover(e) { - if (document.getElementById("mouseoverID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function mousemove(e) { - if (document.getElementById("mousemoveID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function mouseout(e) { - if (document.getElementById("mouseoutID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function touchstart(e) { - if (document.getElementById("touchstartID").checked) { - var box = document.getElementById("box"); - var result = inspect(e); - for (var i = 0; i < e.touches.length; i++) { - result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); - } - log(e.type, result); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function touchend(e) { - if (document.getElementById("touchendID").checked) { - var box = document.getElementById("box"); - var result = inspect(e); - for (var i = 0; i < e.touches.length; i++) { - result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); - } - log(e.type, result); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function touchmove(e) { - if (document.getElementById("touchmoveID").checked) { - var targetEvent = e.touches.item(0); - var box = document.getElementById("box"); - box.style.left = targetEvent.clientX + "px"; - box.style.top = targetEvent.clientY + "px"; - var result = inspect(e); - for (var i = 0; i < e.touches.length; i++) { - result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); - } - log(e.type, result); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function touchcancel(e) { - if (document.getElementById("touchcancelID").checked) { - var box = document.getElementById("box"); - var result = inspect(e); - for (var i = 0; i < e.touches.length; i++) { - result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); - } - log(e.type, result); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function gesturestart(e) { - if (document.getElementById("gesturestartID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function gesturechange(e) { - if (document.getElementById("gesturechangeID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function gestureend(e) { - if (document.getElementById("gestureendID").checked) { - var box = document.getElementById("box"); - log(e.type, inspect(e)); - if (e.preventDefault) e.preventDefault(); - } - return false; -} - -function toggle_visibility(id) { - var e = document.getElementById(id); - if (e.style.display == 'block') { - e.style.display = 'none'; - } else { - e.style.display = 'block'; - } -} - - - +var isEventSupported = (function(undef) { + + var TAGNAMES = { + 'select':'input', + 'change':'input', + 'submit':'form', + 'reset':'form', + 'error':'img', + 'load':'img', + 'abort':'img' + }; + + function isEventSupported(eventName, element) { + element = element || document.createElement(TAGNAMES[eventName] || 'div'); + eventName = 'on' + eventName; + + var isSupported = (eventName in element); + + if (!isSupported) { + // if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element + if (!element.setAttribute) { + element = document.createElement('div'); + } + if (element.setAttribute && element.removeAttribute) { + element.setAttribute(eventName, ''); + isSupported = typeof element[eventName] == 'function'; + + // if property was created, "remove it" (by setting value to `undefined`) + if (typeof element[eventName] != 'undefined') { + element[eventName] = undef; + } + element.removeAttribute(eventName); + } + } + + element = null; + return isSupported; + } + + return isEventSupported; +})(); + +function divResult(category, name, element, div) { + div.innerHTML = div.innerHTML + category + " " + name + ": "; + div.innerHTML = div.innerHTML + ( + isEventSupported(name, element) + ? 'true' + : 'false' + ); + div.innerHTML = div.innerHTML + "
"; +} +var counter = 1; + +function log(title, detail) { + var logDiv = document.getElementById("log"); + idString = "'id" + counter + "'"; + var newlink = document.createElement('a'); + newlink.setAttribute('href', "javascript:toggle_visibility(" + idString + ")"); + newlink.innerHTML = counter + ". " + title; + var br1 = document.createElement('br'); + logDiv.appendChild(newlink); + logDiv.appendChild(br1); + + var childDiv = document.createElement('div'); + childDiv.setAttribute("id", idString.replace("'", "").replace("'", "")); + childDiv.setAttribute("style", 'display: none; margin-left : 5px;'); + childDiv.innerHTML = detail; + var br2 = document.createElement('br'); + logDiv.appendChild(childDiv); + + counter = counter + 1; +} + +function inspect(obj) { + if (typeof obj === "undefined") { + return "undefined"; + } + var _props = []; + + for (var i in obj) { + _props.push(i + " : " + obj[i]); + } + return " {" + _props.join(",
") + "} "; +} + +function click(e) { + if (document.getElementById("clickID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function dblclick(e) { + if (document.getElementById("dblclickID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function mousedown(e) { + if (document.getElementById("mousedownID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function mouseup(e) { + if (document.getElementById("mouseupID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function mouseover(e) { + if (document.getElementById("mouseoverID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function mousemove(e) { + if (document.getElementById("mousemoveID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function mouseout(e) { + if (document.getElementById("mouseoutID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function touchstart(e) { + if (document.getElementById("touchstartID").checked) { + var box = document.getElementById("box"); + var result = inspect(e); + for (var i = 0; i < e.touches.length; i++) { + result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); + } + log(e.type, result); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function touchend(e) { + if (document.getElementById("touchendID").checked) { + var box = document.getElementById("box"); + var result = inspect(e); + for (var i = 0; i < e.touches.length; i++) { + result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); + } + log(e.type, result); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function touchmove(e) { + if (document.getElementById("touchmoveID").checked) { + var targetEvent = e.touches.item(0); + var box = document.getElementById("box"); + box.style.left = targetEvent.clientX + "px"; + box.style.top = targetEvent.clientY + "px"; + var result = inspect(e); + for (var i = 0; i < e.touches.length; i++) { + result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); + } + log(e.type, result); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function touchcancel(e) { + if (document.getElementById("touchcancelID").checked) { + var box = document.getElementById("box"); + var result = inspect(e); + for (var i = 0; i < e.touches.length; i++) { + result = result + "
Touches nr." + i + "
" + inspect(e.touches[i]); + } + log(e.type, result); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function gesturestart(e) { + if (document.getElementById("gesturestartID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function gesturechange(e) { + if (document.getElementById("gesturechangeID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function gestureend(e) { + if (document.getElementById("gestureendID").checked) { + var box = document.getElementById("box"); + log(e.type, inspect(e)); + if (e.preventDefault) e.preventDefault(); + } + return false; +} + +function toggle_visibility(id) { + var e = document.getElementById(id); + if (e.style.display == 'block') { + e.style.display = 'none'; + } else { + e.style.display = 'block'; + } +} + + + diff --git a/src/geonode-client/app/static/externals/openlayers/examples/sos.html b/src/geonode-client/app/static/externals/openlayers/examples/sos.html index 096d19d..4f2ccd5 100644 --- a/src/geonode-client/app/static/externals/openlayers/examples/sos.html +++ b/src/geonode-client/app/static/externals/openlayers/examples/sos.html @@ -1,189 +1,189 @@ - - - - - - - SOS Client Example - - - - - - - -

SOS client example

- -
- sos, sensor, observation, popup, advanced -
-

- Shows how to connect OpenLayers to a Sensor Observation Service (SOS) -

-
-
-

This example uses a vector layer with a Protocol.SOS and a fixed Strategy. -

When clicking on a point feature (the weather stations offered by the SOS), the - latest values for all offerings are displayed in a popup.

-
- - + + + + + + + SOS Client Example + + + + + + + +

SOS client example

+ +
+ sos, sensor, observation, popup, advanced +
+

+ Shows how to connect OpenLayers to a Sensor Observation Service (SOS) +

+
+
+

This example uses a vector layer with a Protocol.SOS and a fixed Strategy. +

When clicking on a point feature (the weather stations offered by the SOS), the + latest values for all offerings are displayed in a popup.

+
+ + diff --git a/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js b/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js index 3e10064..ca6e7df 100644 --- a/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js +++ b/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js @@ -1,128 +1,128 @@ -/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for +/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the 2-clause BSD license. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - -/** - * @requires OpenLayers/Format/WMSCapabilities/v1.js - */ - -/** - * Class: OpenLayers.Format.WMSCapabilities/v1_3 - * Abstract base class for WMS Capabilities version 1.3.X. - * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, - * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd - * - * Inherits from: - * - - */ -OpenLayers.Format.WMSCapabilities.v1_3 = OpenLayers.Class( - OpenLayers.Format.WMSCapabilities.v1, { - - /** - * Property: readers - * Contains public functions, grouped by namespace prefix, that will - * be applied when a namespaced node is found matching the function - * name. The function will be applied in the scope of this parser - * with two arguments: the node being read and a context object passed - * from the parent. - */ - readers: { - "wms": OpenLayers.Util.applyDefaults({ - "WMS_Capabilities": function(node, obj) { - this.readChildNodes(node, obj); - }, - "LayerLimit": function(node, obj) { - obj.layerLimit = parseInt(this.getChildValue(node)); - }, - "MaxWidth": function(node, obj) { - obj.maxWidth = parseInt(this.getChildValue(node)); - }, - "MaxHeight": function(node, obj) { - obj.maxHeight = parseInt(this.getChildValue(node)); - }, - "BoundingBox": function(node, obj) { - var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]); - bbox.srs = node.getAttribute("CRS"); - obj.bbox[bbox.srs] = bbox; - }, - "CRS": function(node, obj) { - // CRS is the synonym of SRS - this.readers.wms.SRS.apply(this, [node, obj]); - }, - "EX_GeographicBoundingBox": function(node, obj) { - // replacement of LatLonBoundingBox - obj.llbbox = []; - this.readChildNodes(node, obj.llbbox); - - }, - "westBoundLongitude": function(node, obj) { - obj[0] = this.getChildValue(node); - }, - "eastBoundLongitude": function(node, obj) { - obj[2] = this.getChildValue(node); - }, - "southBoundLatitude": function(node, obj) { - obj[1] = this.getChildValue(node); - }, - "northBoundLatitude": function(node, obj) { - obj[3] = this.getChildValue(node); - }, - "MinScaleDenominator": function(node, obj) { - obj.maxScale = parseFloat(this.getChildValue(node)).toPrecision(16); - }, - "MaxScaleDenominator": function(node, obj) { - obj.minScale = parseFloat(this.getChildValue(node)).toPrecision(16); - }, - "Dimension": function(node, obj) { - // dimension has extra attributes: default, multipleValues, - // nearestValue, current which used to be part of Extent. It now - // also contains the values. - var name = node.getAttribute("name").toLowerCase(); - var dim = { - name: name, - units: node.getAttribute("units"), - unitsymbol: node.getAttribute("unitSymbol"), - nearestVal: node.getAttribute("nearestValue") === "1", - multipleVal: node.getAttribute("multipleValues") === "1", - "default": node.getAttribute("default") || "", - current: node.getAttribute("current") === "1", - values: this.getChildValue(node).split(",") - - }; - // Theoretically there can be more dimensions with the same - // name, but with a different unit. Until we meet such a case, - // let's just keep the same structure as the WMS 1.1 - // GetCapabilities parser uses. We will store the last - // one encountered. - obj.dimensions[dim.name] = dim; - }, - "Keyword": function(node, obj) { - // TODO: should we change the structure of keyword in v1.js? - // Make it an object with a value instead of a string? - var keyword = {value: this.getChildValue(node), - vocabulary: node.getAttribute("vocabulary")}; - if (obj.keywords) { - obj.keywords.push(keyword); - } - } - }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]), - "sld": { - "UserDefinedSymbolization": function(node, obj) { - this.readers.wms.UserDefinedSymbolization.apply(this, [node, obj]); - // add the two extra attributes - obj.userSymbols.inlineFeature = parseInt(node.getAttribute("InlineFeature")) == 1; - obj.userSymbols.remoteWCS = parseInt(node.getAttribute("RemoteWCS")) == 1; - }, - "DescribeLayer": function(node, obj) { - this.readers.wms.DescribeLayer.apply(this, [node, obj]); - }, - "GetLegendGraphic": function(node, obj) { - this.readers.wms.GetLegendGraphic.apply(this, [node, obj]); - } - } - }, - - CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3" - -}); + * See license.txt in the OpenLayers distribution or repository for the + * full text of the license. */ + +/** + * @requires OpenLayers/Format/WMSCapabilities/v1.js + */ + +/** + * Class: OpenLayers.Format.WMSCapabilities/v1_3 + * Abstract base class for WMS Capabilities version 1.3.X. + * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, + * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd + * + * Inherits from: + * - + */ +OpenLayers.Format.WMSCapabilities.v1_3 = OpenLayers.Class( + OpenLayers.Format.WMSCapabilities.v1, { + + /** + * Property: readers + * Contains public functions, grouped by namespace prefix, that will + * be applied when a namespaced node is found matching the function + * name. The function will be applied in the scope of this parser + * with two arguments: the node being read and a context object passed + * from the parent. + */ + readers: { + "wms": OpenLayers.Util.applyDefaults({ + "WMS_Capabilities": function(node, obj) { + this.readChildNodes(node, obj); + }, + "LayerLimit": function(node, obj) { + obj.layerLimit = parseInt(this.getChildValue(node)); + }, + "MaxWidth": function(node, obj) { + obj.maxWidth = parseInt(this.getChildValue(node)); + }, + "MaxHeight": function(node, obj) { + obj.maxHeight = parseInt(this.getChildValue(node)); + }, + "BoundingBox": function(node, obj) { + var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]); + bbox.srs = node.getAttribute("CRS"); + obj.bbox[bbox.srs] = bbox; + }, + "CRS": function(node, obj) { + // CRS is the synonym of SRS + this.readers.wms.SRS.apply(this, [node, obj]); + }, + "EX_GeographicBoundingBox": function(node, obj) { + // replacement of LatLonBoundingBox + obj.llbbox = []; + this.readChildNodes(node, obj.llbbox); + + }, + "westBoundLongitude": function(node, obj) { + obj[0] = this.getChildValue(node); + }, + "eastBoundLongitude": function(node, obj) { + obj[2] = this.getChildValue(node); + }, + "southBoundLatitude": function(node, obj) { + obj[1] = this.getChildValue(node); + }, + "northBoundLatitude": function(node, obj) { + obj[3] = this.getChildValue(node); + }, + "MinScaleDenominator": function(node, obj) { + obj.maxScale = parseFloat(this.getChildValue(node)).toPrecision(16); + }, + "MaxScaleDenominator": function(node, obj) { + obj.minScale = parseFloat(this.getChildValue(node)).toPrecision(16); + }, + "Dimension": function(node, obj) { + // dimension has extra attributes: default, multipleValues, + // nearestValue, current which used to be part of Extent. It now + // also contains the values. + var name = node.getAttribute("name").toLowerCase(); + var dim = { + name: name, + units: node.getAttribute("units"), + unitsymbol: node.getAttribute("unitSymbol"), + nearestVal: node.getAttribute("nearestValue") === "1", + multipleVal: node.getAttribute("multipleValues") === "1", + "default": node.getAttribute("default") || "", + current: node.getAttribute("current") === "1", + values: this.getChildValue(node).split(",") + + }; + // Theoretically there can be more dimensions with the same + // name, but with a different unit. Until we meet such a case, + // let's just keep the same structure as the WMS 1.1 + // GetCapabilities parser uses. We will store the last + // one encountered. + obj.dimensions[dim.name] = dim; + }, + "Keyword": function(node, obj) { + // TODO: should we change the structure of keyword in v1.js? + // Make it an object with a value instead of a string? + var keyword = {value: this.getChildValue(node), + vocabulary: node.getAttribute("vocabulary")}; + if (obj.keywords) { + obj.keywords.push(keyword); + } + } + }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]), + "sld": { + "UserDefinedSymbolization": function(node, obj) { + this.readers.wms.UserDefinedSymbolization.apply(this, [node, obj]); + // add the two extra attributes + obj.userSymbols.inlineFeature = parseInt(node.getAttribute("InlineFeature")) == 1; + obj.userSymbols.remoteWCS = parseInt(node.getAttribute("RemoteWCS")) == 1; + }, + "DescribeLayer": function(node, obj) { + this.readers.wms.DescribeLayer.apply(this, [node, obj]); + }, + "GetLegendGraphic": function(node, obj) { + this.readers.wms.GetLegendGraphic.apply(this, [node, obj]); + } + } + }, + + CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3" + +}); diff --git a/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js b/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js index 82da245..063a3d5 100644 --- a/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js +++ b/src/geonode-client/app/static/externals/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js @@ -1,30 +1,30 @@ -/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for +/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the 2-clause BSD license. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - -/** - * @requires OpenLayers/Format/WMSCapabilities/v1_3.js - */ - -/** - * Class: OpenLayers.Format.WMSCapabilities/v1_3_0 - * Read WMS Capabilities version 1.3.0. - * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, - * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd - * - * Inherits from: - * - - */ -OpenLayers.Format.WMSCapabilities.v1_3_0 = OpenLayers.Class( - OpenLayers.Format.WMSCapabilities.v1_3, { - - /** - * Property: version - * {String} The specific parser version. - */ - version: "1.3.0", - - CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3_0" - -}); + * See license.txt in the OpenLayers distribution or repository for the + * full text of the license. */ + +/** + * @requires OpenLayers/Format/WMSCapabilities/v1_3.js + */ + +/** + * Class: OpenLayers.Format.WMSCapabilities/v1_3_0 + * Read WMS Capabilities version 1.3.0. + * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, + * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd + * + * Inherits from: + * - + */ +OpenLayers.Format.WMSCapabilities.v1_3_0 = OpenLayers.Class( + OpenLayers.Format.WMSCapabilities.v1_3, { + + /** + * Property: version + * {String} The specific parser version. + */ + version: "1.3.0", + + CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3_0" + +}); diff --git a/src/geonode-client/app/static/script/app/GeoExplorer/GeoExplorer.js b/src/geonode-client/app/static/script/app/GeoExplorer/GeoExplorer.js index 1919d0c..6ead18c 100755 --- a/src/geonode-client/app/static/script/app/GeoExplorer/GeoExplorer.js +++ b/src/geonode-client/app/static/script/app/GeoExplorer/GeoExplorer.js @@ -198,6 +198,8 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { premiumSizeLabel: 'UT: Premium', printTipText: "UT:Print Map", printBtnText: "UT:Print", + infoActionText: "UT:About", + infoBtnText: "UT:About us", printWindowTitleText: "UT:Print Preview", propertiesText: "UT:Properties", publishActionText: 'UT:Link To Map', @@ -237,7 +239,8 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { worldmapDataText: 'Search', externalDataText: 'External Data', leavePageWarningText: 'If you leave this page, unsaved changes will be lost.', - + cgaharvardText: 'Center for Geographic Analysis', + bdandcampText: 'Bigdata and CAMAP Innovation Team', constructor: function(config) { this.config = config; this.popupCache = {}; @@ -265,6 +268,7 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { Ext.preg("gx_wmssource", gxp.plugins.WMSSource); Ext.preg("gx_olsource", gxp.plugins.OLSource); Ext.preg("gx_googlesource", gxp.plugins.GoogleSource); + Ext.preg("gx_tianditusource", gxp.plugins.TiandituSource); Ext.preg("gx_gnsource", gxp.plugins.GeoNodeSource); // global request proxy and error handling @@ -1091,7 +1095,7 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { var record = records[i]; // add an existing layers if ('uuid' in record.data){ - if (record.data['service_type'] == 'Hypermap:WorldMap'){ + if (record.data['service_type'] == 'Hypermap:WorldMap2'){ this.addLayerAjax(wmSource, this.worldMapSourceKey, record); } else { url = this.hypermapRegistryUrl + '/registry/hypermap/layer/' + record.data['uuid'] + '/map/wmts/' + record.data['name'] + '/default_grid/${z}/${x}/${y}.png'; @@ -1153,12 +1157,14 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { "source": key, "buffer": 0, "tiled": true, - "local": thisRecord.get('service_type') === 'Hypermap:WorldMap' + "local": thisRecord.get('service_type') === 'Hypermap:WorldMap2' }; - if (thisRecord.get('service_type') === 'Hypermap:WorldMap'){ layer_detail_url = 'http://worldmap.harvard.edu/data/' + thisRecord.get('name'); }; + if (thisRecord.get('service_type') === 'Hypermap:WorldMap2'){ + layer_detail_url = 'http://amap.zju.edu.cn:8000/data/' + thisRecord.get('name'); + }; if(layer.local){ // url is always the generic GeoServer endpoint for WM layers @@ -1404,7 +1410,11 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { */ createMapOverlay: function() { var cgaLink = new Ext.BoxComponent({ - html:'' + html:'' + }); + + var bdamapLink = new Ext.BoxComponent({ + html:'' }); var scaleLinePanel = new Ext.BoxComponent({ @@ -1491,6 +1501,7 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { items: [ scaleLinePanel, zoomSelectorWrapper, + bdamapLink, cgaLink ] }); @@ -1522,8 +1533,8 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { // create an info control to show introductory text window var infoButton = new Ext.Button({ id: 'infoButtonId', - tooltip: 'About', - text: 'About', + tooltip: this.infoActionText, + text: '' + this.infoBtnText + '', handler: this.showInfoWindow, scope:this }); @@ -1659,8 +1670,6 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { { xtype: "gx_linkembedmapdialog", linkUrl: this.rest + (this.about["urlsuffix"] ? this.about["urlsuffix"] : this.mapID) + '/' + encodedSnapshotId, - linkMessage: 'Paste link in email or IM:', - publishMessage: 'Paste HTML to embed in website:', url: this.rest + (this.about["urlsuffix"] ? this.about["urlsuffix"] : this.mapID) + '/' + encodedSnapshotId + "/embed" } ] @@ -1944,8 +1953,8 @@ var GeoExplorer = Ext.extend(gxp.Viewer, { closeAction: 'hide', items: this.infoTextPanel, modal: true, - width: 500, - height:400, + width: 512, + height:215, autoScroll: true }); }, diff --git a/src/geonode-client/app/static/script/app/GeoExplorer/ogp/HeatmapLayer.js b/src/geonode-client/app/static/script/app/GeoExplorer/ogp/HeatmapLayer.js index bc02aa2..b75b5df 100644 --- a/src/geonode-client/app/static/script/app/GeoExplorer/ogp/HeatmapLayer.js +++ b/src/geonode-client/app/static/script/app/GeoExplorer/ogp/HeatmapLayer.js @@ -1,301 +1,301 @@ -/* - * Copyright (c) 2010 Bjoern Hoehrmann . - * This module is licensed under the same terms as OpenLayers itself. - * - */ - -Heatmap = {}; - -/** - * Class: Heatmap.Source - */ -Heatmap.Source = OpenLayers.Class({ - - /** - * APIProperty: lonlat - * {OpenLayers.LonLat} location of the heat source - */ - lonlat: null, - - /** - * APIProperty: radius - * {Number} Heat source radius - */ - radius: null, - - /** - * APIProperty: intensity - * {Number} Heat source intensity - */ - intensity: null, - - /** - * Constructor: Heatmap.Source - * Create a heat source. - * - * Parameters: - * lonlat - {OpenLayers.LonLat} Coordinates of the heat source - * radius - {Number} Optional radius - * intensity - {Number} Optional intensity - */ - initialize: function(lonlat, radius, intensity) { - this.lonlat = lonlat; - this.radius = radius; - this.intensity = intensity; - }, - - CLASS_NAME: 'Heatmap.Source' -}); - -/** - * Class: Heatmap.Layer - * - * Inherits from: - * - - */ -Heatmap.Layer = OpenLayers.Class(OpenLayers.Layer, { - - /** - * APIProperty: isBaseLayer - * {Boolean} Heatmap layer is never a base layer. - */ - isBaseLayer: false, - - /** - * Property: points - * {Array()} internal coordinate list - */ - points: null, - - /** - * Property: cache - * {Object} Hashtable with CanvasGradient objects - */ - cache: null, - - /** - * Property: gradient - * {Array(Number)} RGBA gradient map used to colorize the intensity map. - */ - gradient: null, - - /** - * Property: canvas - * {DOMElement} Canvas element. - */ - canvas: null, - - /** - * APIProperty: defaultRadius - * {Number} Heat source default radius - */ - defaultRadius: null, - - /** - * APIProperty: defaultIntensity - * {Number} Heat source default intensity - */ - defaultIntensity: null, - - /** - * Constructor: Heatmap.Layer - * Create a heatmap layer. - * - * Parameters: - * name - {String} Name of the Layer - * options - {Object} Hashtable of extra options to tag onto the layer - */ - initialize: function(name, options) { - OpenLayers.Layer.prototype.initialize.apply(this, arguments); - this.points = []; - this.cache = {}; - this.canvas = document.createElement('canvas'); - this.canvas.style.position = 'absolute'; - this.defaultRadius = 20; - this.defaultIntensity = 0.2; - this.setGradientStops({ - 0.00: 0xffffff00, - 0.10: 0x99e9fdff, - 0.20: 0x00c9fcff, - 0.30: 0x00e9fdff, - 0.30: 0x00a5fcff, - 0.40: 0x0078f2ff, - 0.50: 0x0e53e9ff, - 0.60: 0x4a2cd9ff, - 0.70: 0x890bbfff, - 0.80: 0x99019aff, - 0.90: 0x990664ff, - 0.99: 0x660000ff, - 1.00: 0x000000ff - }); - - // For some reason OpenLayers.Layer.setOpacity assumes there is - // an additional div between the layer's div and its contents. - var sub = document.createElement('div'); - sub.appendChild(this.canvas); - this.div.appendChild(sub); - }, - - /** - * APIMethod: setGradientStops - * ... - * - * Parameters: - * stops - {Object} Hashtable with stop position as keys and colors - * as values. Stop positions are numbers between 0 - * and 1, color values numbers in 0xRRGGBBAA form. - */ - setGradientStops: function(stops) { - - // There is no need to perform the linear interpolation manually, - // it is sufficient to let the canvas implementation do that. - - var ctx = document.createElement('canvas').getContext('2d'); - var grd = ctx.createLinearGradient(0, 0, 256, 0); - - for (var i in stops) { - grd.addColorStop(i, 'rgba(' + - ((stops[i] >> 24) & 0xFF) + ',' + - ((stops[i] >> 16) & 0xFF) + ',' + - ((stops[i] >> 8) & 0xFF) + ',' + - ((stops[i] >> 0) & 0xFF) + ')'); - } - - ctx.fillStyle = grd; - ctx.fillRect(0, 0, 256, 1); - this.gradient = ctx.getImageData(0, 0, 256, 1).data; - }, - - /** - * APIMethod: addSource - * Adds a heat source to the layer. - * - * Parameters: - * source - {} - */ - addSource: function(source) { - this.points.push(source); - }, - - /** - * APIMethod: removeSource - * Removes a heat source from the layer. - * - * Parameters: - * source - {} - */ - removeSource: function(source) { - if (this.points && this.points.length) { - OpenLayers.Util.removeItem(this.points, source); - } - }, - - /** - * Method: moveTo - * - * Parameters: - * bounds - {} - * zoomChanged - {Boolean} - * dragging - {Boolean} - */ - moveTo: function(bounds, zoomChanged, dragging) { - - OpenLayers.Layer.prototype.moveTo.apply(this, arguments); - - // The code is too slow to update the rendering during dragging. - if (dragging) - return; - - // Pick some point on the map and use it to determine the offset - // between the map's 0,0 coordinate and the layer's 0,0 position. - var someLoc = new OpenLayers.LonLat(0,0); - var offsetX = this.map.getViewPortPxFromLonLat(someLoc).x - - this.map.getLayerPxFromLonLat(someLoc).x; - var offsetY = this.map.getViewPortPxFromLonLat(someLoc).y - - this.map.getLayerPxFromLonLat(someLoc).y; - - this.canvas.width = this.map.getSize().w; - this.canvas.height = this.map.getSize().h; - - var ctx = this.canvas.getContext('2d'); - - ctx.save(); // Workaround for a bug in Google Chrome - ctx.fillStyle = 'transparent'; - ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); - ctx.restore(); - - for (var i=0;i} - */ - getDataExtent: function () { - var maxExtent = null; - - if (this.points && (this.points.length > 0)) { - var maxExtent = new OpenLayers.Bounds(); - for(var i = 0, len = this.points.length; i < len; ++i) { - var point = this.points[i]; - maxExtent.extend(point.lonlat); - } - } - - return maxExtent; - }, - - CLASS_NAME: 'Heatmap.Layer' - -}); +/* + * Copyright (c) 2010 Bjoern Hoehrmann . + * This module is licensed under the same terms as OpenLayers itself. + * + */ + +Heatmap = {}; + +/** + * Class: Heatmap.Source + */ +Heatmap.Source = OpenLayers.Class({ + + /** + * APIProperty: lonlat + * {OpenLayers.LonLat} location of the heat source + */ + lonlat: null, + + /** + * APIProperty: radius + * {Number} Heat source radius + */ + radius: null, + + /** + * APIProperty: intensity + * {Number} Heat source intensity + */ + intensity: null, + + /** + * Constructor: Heatmap.Source + * Create a heat source. + * + * Parameters: + * lonlat - {OpenLayers.LonLat} Coordinates of the heat source + * radius - {Number} Optional radius + * intensity - {Number} Optional intensity + */ + initialize: function(lonlat, radius, intensity) { + this.lonlat = lonlat; + this.radius = radius; + this.intensity = intensity; + }, + + CLASS_NAME: 'Heatmap.Source' +}); + +/** + * Class: Heatmap.Layer + * + * Inherits from: + * - + */ +Heatmap.Layer = OpenLayers.Class(OpenLayers.Layer, { + + /** + * APIProperty: isBaseLayer + * {Boolean} Heatmap layer is never a base layer. + */ + isBaseLayer: false, + + /** + * Property: points + * {Array()} internal coordinate list + */ + points: null, + + /** + * Property: cache + * {Object} Hashtable with CanvasGradient objects + */ + cache: null, + + /** + * Property: gradient + * {Array(Number)} RGBA gradient map used to colorize the intensity map. + */ + gradient: null, + + /** + * Property: canvas + * {DOMElement} Canvas element. + */ + canvas: null, + + /** + * APIProperty: defaultRadius + * {Number} Heat source default radius + */ + defaultRadius: null, + + /** + * APIProperty: defaultIntensity + * {Number} Heat source default intensity + */ + defaultIntensity: null, + + /** + * Constructor: Heatmap.Layer + * Create a heatmap layer. + * + * Parameters: + * name - {String} Name of the Layer + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + OpenLayers.Layer.prototype.initialize.apply(this, arguments); + this.points = []; + this.cache = {}; + this.canvas = document.createElement('canvas'); + this.canvas.style.position = 'absolute'; + this.defaultRadius = 20; + this.defaultIntensity = 0.2; + this.setGradientStops({ + 0.00: 0xffffff00, + 0.10: 0x99e9fdff, + 0.20: 0x00c9fcff, + 0.30: 0x00e9fdff, + 0.30: 0x00a5fcff, + 0.40: 0x0078f2ff, + 0.50: 0x0e53e9ff, + 0.60: 0x4a2cd9ff, + 0.70: 0x890bbfff, + 0.80: 0x99019aff, + 0.90: 0x990664ff, + 0.99: 0x660000ff, + 1.00: 0x000000ff + }); + + // For some reason OpenLayers.Layer.setOpacity assumes there is + // an additional div between the layer's div and its contents. + var sub = document.createElement('div'); + sub.appendChild(this.canvas); + this.div.appendChild(sub); + }, + + /** + * APIMethod: setGradientStops + * ... + * + * Parameters: + * stops - {Object} Hashtable with stop position as keys and colors + * as values. Stop positions are numbers between 0 + * and 1, color values numbers in 0xRRGGBBAA form. + */ + setGradientStops: function(stops) { + + // There is no need to perform the linear interpolation manually, + // it is sufficient to let the canvas implementation do that. + + var ctx = document.createElement('canvas').getContext('2d'); + var grd = ctx.createLinearGradient(0, 0, 256, 0); + + for (var i in stops) { + grd.addColorStop(i, 'rgba(' + + ((stops[i] >> 24) & 0xFF) + ',' + + ((stops[i] >> 16) & 0xFF) + ',' + + ((stops[i] >> 8) & 0xFF) + ',' + + ((stops[i] >> 0) & 0xFF) + ')'); + } + + ctx.fillStyle = grd; + ctx.fillRect(0, 0, 256, 1); + this.gradient = ctx.getImageData(0, 0, 256, 1).data; + }, + + /** + * APIMethod: addSource + * Adds a heat source to the layer. + * + * Parameters: + * source - {} + */ + addSource: function(source) { + this.points.push(source); + }, + + /** + * APIMethod: removeSource + * Removes a heat source from the layer. + * + * Parameters: + * source - {} + */ + removeSource: function(source) { + if (this.points && this.points.length) { + OpenLayers.Util.removeItem(this.points, source); + } + }, + + /** + * Method: moveTo + * + * Parameters: + * bounds - {} + * zoomChanged - {Boolean} + * dragging - {Boolean} + */ + moveTo: function(bounds, zoomChanged, dragging) { + + OpenLayers.Layer.prototype.moveTo.apply(this, arguments); + + // The code is too slow to update the rendering during dragging. + if (dragging) + return; + + // Pick some point on the map and use it to determine the offset + // between the map's 0,0 coordinate and the layer's 0,0 position. + var someLoc = new OpenLayers.LonLat(0,0); + var offsetX = this.map.getViewPortPxFromLonLat(someLoc).x - + this.map.getLayerPxFromLonLat(someLoc).x; + var offsetY = this.map.getViewPortPxFromLonLat(someLoc).y - + this.map.getLayerPxFromLonLat(someLoc).y; + + this.canvas.width = this.map.getSize().w; + this.canvas.height = this.map.getSize().h; + + var ctx = this.canvas.getContext('2d'); + + ctx.save(); // Workaround for a bug in Google Chrome + ctx.fillStyle = 'transparent'; + ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + ctx.restore(); + + for (var i=0;i} + */ + getDataExtent: function () { + var maxExtent = null; + + if (this.points && (this.points.length > 0)) { + var maxExtent = new OpenLayers.Bounds(); + for(var i = 0, len = this.points.length; i < len; ++i) { + var point = this.points[i]; + maxExtent.extend(point.lonlat); + } + } + + return maxExtent; + }, + + CLASS_NAME: 'Heatmap.Layer' + +}); diff --git a/src/geonode-client/app/static/script/app/GeoNode/ogp/SearchTableSolr.js b/src/geonode-client/app/static/script/app/GeoNode/ogp/SearchTableSolr.js index 0592ca6..eae72c3 100755 --- a/src/geonode-client/app/static/script/app/GeoNode/ogp/SearchTableSolr.js +++ b/src/geonode-client/app/static/script/app/GeoNode/ogp/SearchTableSolr.js @@ -23,7 +23,10 @@ GeoNode.SearchTable = Ext.extend(Ext.util.Observable, { originatorSearchLabelText: 'Source', dataTypeSearchLableText: 'UT: Data Type', originatorText: 'Source', - + dateHeaderText: 'Date', + fromyearHeaderText: 'from year', + toyearHeaderText: 'to year', + resetButtonText: 'Reset', searchOnLoad: false, linkableTitle: true, @@ -244,9 +247,11 @@ GeoNode.SearchTable = Ext.extend(Ext.util.Observable, { if (this.queryInput.getValue() === ''){ GeoNode.queryTerms.q = '*'; } + else{ + GeoNode.queryTerms.q = '*' + this.queryInput.getValue() + '*'; + } GeoNode.queryTerms.start = 0; - // now trigger the heatmap update this.heatmap.fireEvent('fireSearch', false); @@ -356,7 +361,7 @@ GeoNode.SearchTable = Ext.extend(Ext.util.Observable, { sortable: true }, { - header: 'Date', + header: this.dateHeaderText, id: 'date', width: 50, sortable: true, @@ -414,6 +419,7 @@ GeoNode.SearchTable = Ext.extend(Ext.util.Observable, { layers_data = [ ['', 'All Layers'], + ['service_type:"Hypermap:WorldMap2"', 'AcadamicMap Layers'], ['service_type:"Hypermap:WorldMap"', 'WorldMap Layers'], ['service_type:"OGC:WMS"', 'WMS'], ['service_type:"ESRI:ArcGIS:ImageServer"', 'ESRI Image'], @@ -490,7 +496,7 @@ GeoNode.SearchTable = Ext.extend(Ext.util.Observable, { }); this.dateLabelPanel = new Ext.Panel({ - items: [new Ext.form.Label({text: 'from year'}), dateStartTextField, new Ext.form.Label({text: 'to year'}), dateEndTextField], + items: [new Ext.form.Label({text: this.fromyearHeaderText}), dateStartTextField, new Ext.form.Label({text: this.toyearHeaderText}), dateEndTextField], cls: 'search-bar date-form' }); @@ -518,7 +524,7 @@ GeoNode.SearchTable = Ext.extend(Ext.util.Observable, { searchButton.on('click', this.updateQuery, this); var clearSearchLink = new Ext.Button({ - text: "Reset", + text: this.resetButtonText, iconCls: 'not-prominent-btn', cls: 'search-bar clear-search-button', listeners: { @@ -546,8 +552,8 @@ GeoNode.SearchTable = Ext.extend(Ext.util.Observable, { this.queryInput, this.originatorInput, this.dataTypeInput, //dropdown - searchButton, - clearSearchLink + clearSearchLink, + searchButton ], colspan: 4 },{ diff --git a/src/geonode-client/app/static/script/app/GeoNode/ogp/ogpConfig.js b/src/geonode-client/app/static/script/app/GeoNode/ogp/ogpConfig.js index 4d54cc2..0300254 100644 --- a/src/geonode-client/app/static/script/app/GeoNode/ogp/ogpConfig.js +++ b/src/geonode-client/app/static/script/app/GeoNode/ogp/ogpConfig.js @@ -7,7 +7,7 @@ $(document).ready(function () { sort: "score desc", //qf: "LayerTitleSynonyms^0.2 ThemeKeywordsSynonymsIso^0.1 ThemeKeywordsSynonymsLcsh^0.1 PlaceKeywordsSynonyms^0.1 Publisher^0.1 layer_originator^0.1 Abstract^0.2", fl: "id, uuid, name, title, abstract, min_x, min_y, max_x, max_y, layer_originator, is_public, url, service_type, bbox, location, layer_datetype, srs", - qf: "title_txt^1 abstract_txt^0.2 originator_txt layer_username", + qf: "title^1 abstract^0.2 layer_originator^1 layer_datetype^0.2", wt: "json", defType: "edismax", q: "*", diff --git a/src/geonode-client/app/static/theme/app/geoexplorer.css b/src/geonode-client/app/static/theme/app/geoexplorer.css index ba2551d..cecb231 100755 --- a/src/geonode-client/app/static/theme/app/geoexplorer.css +++ b/src/geonode-client/app/static/theme/app/geoexplorer.css @@ -1,537 +1,537 @@ -/* do wrap lines on any tooltips */ -.x-tip { -} - -/* get images on buttons with text to line up with those with no text */ -.x-btn-text-icon .x-btn-center .x-btn-text { - background-position: 0 3px; -} - -/* apply some margin when using the row expander */ -.x-grid3-row-body p { - margin: 5px !important; -} - -/* workaround for semi-alpha pixels in IE7: background needs to be the same - * as the toolbar's background color */ -.ext-ie .x-item-disabled .x-btn-text { - background-color: #EAEAEA; -} - -.x-tree-node-leaf .gx-tree-layer-icon { - background-image: url(img/geosilk/vector.png); -} - -.x-tree-node-leaf .gx-tree-rasterlayer-icon { - background-image: url(img/geosilk/raster.png); -} - -.x-menu-group-item .x-menu-item-icon { - background: transparent url(../../externals/ext/resources/images/default/form/radio.gif) no-repeat 0 0; - height: 13px; - width: 13px; - margin: 2px; -} - -.x-menu-item-checked .x-menu-group-item .x-menu-item-icon { - background: transparent url(../../externals/ext/resources/images/default/form/radio.gif) no-repeat -13px -13px; - height: 13px; - width: 13px; - margin: 2px; -} - -.x-btn .icon-geoexplorer { - background-image: url(img/geoexplorer.png); -} - -.x-btn .icon-addlayers { - background-image: url(img/silk/add.png); -} - -.x-btn .icon-removelayers, .x-menu-item .icon-removelayers { - background-image: url(img/silk/delete.png); -} - -.x-btn .icon-layerproperties, .x-menu-item .icon-layerproperties { - background-image: url(img/silk/wrench.png); -} - -.x-btn .icon-layerstyles, .x-menu-item .icon-layerstyles { - background-image: url(img/silk/palette.png); -} - -.x-btn .icon-getfeatureinfo { - background-image: url(img/silk/information.png); -} - -.x-btn .icon-3D { - background-image: url(img/geosilk/google_earth.png); -} - -.x-btn .icon-save { - background-image: url(img/geosilk/map_save.png); -} - -/* Really for CAPRA, watch out! */ - -.x-menu-group-item .icon-point, -.x-btn .icon-point { - background: transparent url(img/geosilk/bullet_orange.png) no-repeat center center !important; - margin: 0px; - height: 16px; - width: 16px; -} - -.x-menu-group-item .icon-line, -.x-btn .icon-line { - background: transparent url(img/geosilk/line_orange.png) no-repeat center center !important; - margin: 0px; - height: 16px; - width: 16px; -} - -.x-menu-group-item .icon-polygon, -.x-btn .icon-polygon { - background: transparent url(img/geosilk/shape_square_orange.png) center center !important; - margin: 0px; - height: 16px; - width: 16px; -} - -.x-btn .icon-visibility { - background-image: url(img/silk/eye.png); -} - -.x-btn .icon-pdf { - background-image: url(img/silk/page_white_acrobat.png); -} - -div.report { - background-color: white; - height: 100%; -} - -div.report table, div.report td, div.report th { - padding: .4em; -} - -div.report th { - background-color: #CCC; -} - -div.report tr.odd { - background-color: #EEF; -} - -.report td.corner{ - background-color:white; -} - - -/* ------------ */ - -.x-btn .icon-export { - background-image: url(img/silk/map_go.png); -} -.x-btn .icon-measure { - background-image: url(img/geosilk/measure.png); -} - -.icon-measure-length { - background-image: url(img/geosilk/ruler.png) !important; -} - -.icon-measure-area { - background: url(img/geosilk/ruler_square.png) no-repeat 0 0 !important; - margin: 0 !important; - width: 16px !important; - height: 16px !important; -} - -.x-btn .icon-layer-switcher { - background-image: url(img/silk/layers.png); -} - -.x-btn .icon-zoom-in { - background-image: url(img/silk/magnifier_zoom_in.png); -} - -.x-btn .icon-zoom-out { - background-image: url(img/silk/magnifier_zoom_out.png); -} - -.x-btn .icon-zoom-previous { - background-image: url(img/silk/arrow_left.png); -} - -.x-btn .icon-zoom-next { - background-image: url(img/silk/arrow_right.png); -} - -.x-btn .icon-zoom-visible, .x-menu-item .icon-zoom-visible { - background-image: url(img/silk/arrow_out.png); -} - -.x-btn .icon-zoom-to, .x-menu-item .icon-zoom-to { - background-image: url(img/silk/magnifier.png); -} - -.x-btn .icon-pan { - background-image: url(img/geosilk/pan.png); -} - -.legend-item { - margin: 0.5em 10px; -} - -div.map-overlay { - z-index: 4000; - position: absolute; - right: 10px; - bottom: 10px; - background:transparent; -} - -div.map-overlay div.overlay-element { - display:inline; - float: left; - margin: 5px; - background:transparent; -} - -div.overlay-scaleline { - bottom: 0px; - left: 0px; - margin-top: 0px; - z-index: 10000; -} - -.olControlAttribution{ - color: gray; - bottom: .5em; - left: .4em; - right: 220px; - font-size: smaller; -} - -.olControlScaleLineTop, -.olControlScaleLineBottom { - font-size:10px; -} - -/* Pan- and Zoom- Panel Styles*/ - -.olControlPanPanel div { - background-image:url(../../externals/ext/resources/images/gray/panel/tool-sprites.gif); - height:15px; - width:15px; - /* workaround for button height in IE */ - font-size:0px; -} - -.olControlPanPanel .olControlPanNorthItemInactive { - background-position:15px -60px; - left:16px -} -.olControlPanPanel .olControlPanEastItemInactive { - background-position:15px -120px; - left: 30px; - top: 16px; -} -.olControlPanPanel .olControlPanSouthItemInactive { - background-position:15px -75px; - left: 16px; - top: 32px; -} -.olControlPanPanel .olControlPanWestItemInactive { - background-position:15px -105px; - left: 2px; - top: 16px; -} - -.olControlZoomPanel { - left:21px; -} - -.olControlZoomPanel div { - background-image:url(../../externals/ext/resources/images/gray/panel/tool-sprites.gif); - height:15px; - width:15px; - /* workaround for button height in IE */ - font-size:0px; -} - -.olControlZoomPanel .olControlZoomInItemInactive { - background-position:15px -240px; -} - -.olControlZoomPanel .olControlZoomToMaxExtentItemInactive { - display: none; -} - -.olControlZoomPanel .olControlZoomOutItemInactive { - background-position:15px -255px; - top: 123px; -} - -.olControlScaleLine { - line-height: 10px; - display: block; - position: relative; - font-family: tahoma,arial,helvetica,sans-serif; -} - -/* position the zoom slider within map panel */ -.gx-zoomslider { - top: 90px; - left: 17px -} - - -.gx-layer-menu { - background: #F0F0F0; -} - -.gx-field-label { - font-weight: bold; - margin: 4px; - vertical-align: baseline; -} - -.gx-snippet-area textarea { - color: black; - opacity: 1; -} - -.gx-info-panel { - margin: 1em; -} - -.gx-info-panel h2 { - margin-top: 1em; -} - -.gx-wizard-description p { - margin: 4px auto; - background: none; -} - -.gx-wizard-pane { - padding: 4px; -} - -.gx-grid-true { - background: red; -} - -.gx-grid-false { - background: blue; -} - -.gx-wizard-active button { - font-weight: bold; -} - -.gx-wizard-pane .x-panel-body { - background: none; -} - -.gx-wizard-pane .x-grid3-dirty-cell { - background-image: none; -} - -.gx-layer-visibility { - background-image: url(img/silk/eye.png); - width: 16px; - height: 16px; - display: block; -} - -.error-details { - font: 8pt courier,courier new,monospace; - padding: 5px; -} - -.user_item button { - width: 16px; - height: 16px; - margin: 4px; -} - -#more-info{ - float:right; -} - -/* gxp overrides for different folder structure */ -.olControlZoomPanel div { - background-image:url(../../externals/ext/resources/images/gray/panel/tool-sprites.gif); -} -.x-tree-node img.gxp-folder, .x-tree-node-collapsed img.gxp-folder{ - background: url(../../externals/ext/resources/images/default/tree/folder.gif); -} -.x-tree-node-expanded img.gxp-folder { - background: url(../../externals/ext/resources/images/default/tree/folder-open.gif); -} - -.olLayerGoogleV3.olLayerGoogleCopyright { - bottom: 1em !important; -} -.olLayerGoogleV3.olLayerGooglePoweredBy { - bottom: 2em !important; -} - -/* WorldMap additions/modifications */ - -.x-btn-text { - font-size: 8pt; - text-decoration: underline; - color: #18469C; - padding-right:5px; - border-right: 1px solid #99BBE8; -} - -.x-btn-text button { - font-size: 8pt; - text-decoration: underline; - color: #18469C; -} - -.x-btn-link-medium { - text-decoration:underline; - float:right; - text-align:right; -} - -.x-btn .icon-add, .x-menu-item .icon-add { - background-image: url(img/silk/add.png); -} - - -.x-span-font-eight { - font-size: 8pt; -} - -.x-form-field-inline { - display:inline; - padding:0 0 30px 0; - margin:0px; -} - -.transparent-panel { - background:transparent; -} - -cga-logo-overlay { - z-index: 10000; - position: absolute; - left: 100px; - bottom: 10px; - width:151px; - height:39px; - background: transparent; -} - -.more-overlay-element { - float: left; - z-index: 4000; - position: absolute; - right: 150px; - top: 10px; - height:25px; - width:50px; - background: #FFF; - text-decoration: none; - border: 1px solid #000; -} - -.more-overlay-element .x-btn-small td {background-image: none; text-decoration:none;} -.more-overlay-element .x-btn-small td button {text-decoration:none;} - -.language-overlay-element { - float: left; - z-index: 4000; - position: absolute; - right: 10px; - bottom: 70px; - height:25px; - text-decoration: none; -} - -div.cga-link { - margin:3px; - font-size:8pt; - clear: both; -} - -.featureDetailList { -} -.featureDetailList li { - margin:4px 5px; - min-height:16px; - position:relative; -} -* html .featureDetailList li { - height:16px; -} -.featureDetailList li label { - font-weight:bold; - left:0; - position:absolute; - top:0; - width:150px; -} -.featureDetailList li span { - margin-left:160px; -} - -.nicEdit-selected { - border: 2px solid #0000ff !important; -} - -.nicEdit-panel { - background-color: #fff !important; -} - -.nicEdit-button { - background-color: #fff !important; -} - -.wtf { - padding: 0px 10px 0px 10px; - border-right: 1px solid #000; -} - -div.cql-overlay { - z-index: 10000; - position: absolute; - margin: 0 15%; - background:#FFF; - opacity: 0.9 -} - -div.chart-overlay { - z-index: 10000; - position: absolute; - //left: 10px; - bottom: 10px; - margin: 0 15%; - background:#FFF; - opacity: 1.0 -} - -.icon-picasa { - background-image: url('img/picasa.png'); -} - -.icon-youtube { - background-image: url('img/youtube.png'); -} - - -.icon-harvard { - background-image: url('img/harvard.png'); -} - -.icon-flickr { - background-image: url('img/flickr.png'); +/* do wrap lines on any tooltips */ +.x-tip { +} + +/* get images on buttons with text to line up with those with no text */ +.x-btn-text-icon .x-btn-center .x-btn-text { + background-position: 0 3px; +} + +/* apply some margin when using the row expander */ +.x-grid3-row-body p { + margin: 5px !important; +} + +/* workaround for semi-alpha pixels in IE7: background needs to be the same + * as the toolbar's background color */ +.ext-ie .x-item-disabled .x-btn-text { + background-color: #EAEAEA; +} + +.x-tree-node-leaf .gx-tree-layer-icon { + background-image: url(img/geosilk/vector.png); +} + +.x-tree-node-leaf .gx-tree-rasterlayer-icon { + background-image: url(img/geosilk/raster.png); +} + +.x-menu-group-item .x-menu-item-icon { + background: transparent url(../../externals/ext/resources/images/default/form/radio.gif) no-repeat 0 0; + height: 13px; + width: 13px; + margin: 2px; +} + +.x-menu-item-checked .x-menu-group-item .x-menu-item-icon { + background: transparent url(../../externals/ext/resources/images/default/form/radio.gif) no-repeat -13px -13px; + height: 13px; + width: 13px; + margin: 2px; +} + +.x-btn .icon-geoexplorer { + background-image: url(img/geoexplorer.png); +} + +.x-btn .icon-addlayers { + background-image: url(img/silk/add.png); +} + +.x-btn .icon-removelayers, .x-menu-item .icon-removelayers { + background-image: url(img/silk/delete.png); +} + +.x-btn .icon-layerproperties, .x-menu-item .icon-layerproperties { + background-image: url(img/silk/wrench.png); +} + +.x-btn .icon-layerstyles, .x-menu-item .icon-layerstyles { + background-image: url(img/silk/palette.png); +} + +.x-btn .icon-getfeatureinfo { + background-image: url(img/silk/information.png); +} + +.x-btn .icon-3D { + background-image: url(img/geosilk/google_earth.png); +} + +.x-btn .icon-save { + background-image: url(img/geosilk/map_save.png); +} + +/* Really for CAPRA, watch out! */ + +.x-menu-group-item .icon-point, +.x-btn .icon-point { + background: transparent url(img/geosilk/bullet_orange.png) no-repeat center center !important; + margin: 0px; + height: 16px; + width: 16px; +} + +.x-menu-group-item .icon-line, +.x-btn .icon-line { + background: transparent url(img/geosilk/line_orange.png) no-repeat center center !important; + margin: 0px; + height: 16px; + width: 16px; +} + +.x-menu-group-item .icon-polygon, +.x-btn .icon-polygon { + background: transparent url(img/geosilk/shape_square_orange.png) center center !important; + margin: 0px; + height: 16px; + width: 16px; +} + +.x-btn .icon-visibility { + background-image: url(img/silk/eye.png); +} + +.x-btn .icon-pdf { + background-image: url(img/silk/page_white_acrobat.png); +} + +div.report { + background-color: white; + height: 100%; +} + +div.report table, div.report td, div.report th { + padding: .4em; +} + +div.report th { + background-color: #CCC; +} + +div.report tr.odd { + background-color: #EEF; +} + +.report td.corner{ + background-color:white; +} + + +/* ------------ */ + +.x-btn .icon-export { + background-image: url(img/silk/map_go.png); +} +.x-btn .icon-measure { + background-image: url(img/geosilk/measure.png); +} + +.icon-measure-length { + background-image: url(img/geosilk/ruler.png) !important; +} + +.icon-measure-area { + background: url(img/geosilk/ruler_square.png) no-repeat 0 0 !important; + margin: 0 !important; + width: 16px !important; + height: 16px !important; +} + +.x-btn .icon-layer-switcher { + background-image: url(img/silk/layers.png); +} + +.x-btn .icon-zoom-in { + background-image: url(img/silk/magnifier_zoom_in.png); +} + +.x-btn .icon-zoom-out { + background-image: url(img/silk/magnifier_zoom_out.png); +} + +.x-btn .icon-zoom-previous { + background-image: url(img/silk/arrow_left.png); +} + +.x-btn .icon-zoom-next { + background-image: url(img/silk/arrow_right.png); +} + +.x-btn .icon-zoom-visible, .x-menu-item .icon-zoom-visible { + background-image: url(img/silk/arrow_out.png); +} + +.x-btn .icon-zoom-to, .x-menu-item .icon-zoom-to { + background-image: url(img/silk/magnifier.png); +} + +.x-btn .icon-pan { + background-image: url(img/geosilk/pan.png); +} + +.legend-item { + margin: 0.5em 10px; +} + +div.map-overlay { + z-index: 4000; + position: absolute; + right: 10px; + bottom: 10px; + background:transparent; +} + +div.map-overlay div.overlay-element { + display:inline; + float: left; + margin: 5px; + background:transparent; +} + +div.overlay-scaleline { + bottom: 0px; + left: 0px; + margin-top: 0px; + z-index: 10000; +} + +.olControlAttribution{ + color: gray; + bottom: .5em; + left: .4em; + right: 220px; + font-size: smaller; +} + +.olControlScaleLineTop, +.olControlScaleLineBottom { + font-size:10px; +} + +/* Pan- and Zoom- Panel Styles*/ + +.olControlPanPanel div { + background-image:url(../../externals/ext/resources/images/gray/panel/tool-sprites.gif); + height:15px; + width:15px; + /* workaround for button height in IE */ + font-size:0px; +} + +.olControlPanPanel .olControlPanNorthItemInactive { + background-position:15px -60px; + left:16px +} +.olControlPanPanel .olControlPanEastItemInactive { + background-position:15px -120px; + left: 30px; + top: 16px; +} +.olControlPanPanel .olControlPanSouthItemInactive { + background-position:15px -75px; + left: 16px; + top: 32px; +} +.olControlPanPanel .olControlPanWestItemInactive { + background-position:15px -105px; + left: 2px; + top: 16px; +} + +.olControlZoomPanel { + left:21px; +} + +.olControlZoomPanel div { + background-image:url(../../externals/ext/resources/images/gray/panel/tool-sprites.gif); + height:15px; + width:15px; + /* workaround for button height in IE */ + font-size:0px; +} + +.olControlZoomPanel .olControlZoomInItemInactive { + background-position:15px -240px; +} + +.olControlZoomPanel .olControlZoomToMaxExtentItemInactive { + display: none; +} + +.olControlZoomPanel .olControlZoomOutItemInactive { + background-position:15px -255px; + top: 123px; +} + +.olControlScaleLine { + line-height: 10px; + display: block; + position: relative; + font-family: tahoma,arial,helvetica,sans-serif; +} + +/* position the zoom slider within map panel */ +.gx-zoomslider { + top: 90px; + left: 17px +} + + +.gx-layer-menu { + background: #F0F0F0; +} + +.gx-field-label { + font-weight: bold; + margin: 4px; + vertical-align: baseline; +} + +.gx-snippet-area textarea { + color: black; + opacity: 1; +} + +.gx-info-panel { + margin: 1em; +} + +.gx-info-panel h2 { + margin-top: 1em; +} + +.gx-wizard-description p { + margin: 4px auto; + background: none; +} + +.gx-wizard-pane { + padding: 4px; +} + +.gx-grid-true { + background: red; +} + +.gx-grid-false { + background: blue; +} + +.gx-wizard-active button { + font-weight: bold; +} + +.gx-wizard-pane .x-panel-body { + background: none; +} + +.gx-wizard-pane .x-grid3-dirty-cell { + background-image: none; +} + +.gx-layer-visibility { + background-image: url(img/silk/eye.png); + width: 16px; + height: 16px; + display: block; +} + +.error-details { + font: 8pt courier,courier new,monospace; + padding: 5px; +} + +.user_item button { + width: 16px; + height: 16px; + margin: 4px; +} + +#more-info{ + float:right; +} + +/* gxp overrides for different folder structure */ +.olControlZoomPanel div { + background-image:url(../../externals/ext/resources/images/gray/panel/tool-sprites.gif); +} +.x-tree-node img.gxp-folder, .x-tree-node-collapsed img.gxp-folder{ + background: url(../../externals/ext/resources/images/default/tree/folder.gif); +} +.x-tree-node-expanded img.gxp-folder { + background: url(../../externals/ext/resources/images/default/tree/folder-open.gif); +} + +.olLayerGoogleV3.olLayerGoogleCopyright { + bottom: 1em !important; +} +.olLayerGoogleV3.olLayerGooglePoweredBy { + bottom: 2em !important; +} + +/* WorldMap additions/modifications */ + +.x-btn-text { + font-size: 8pt; + text-decoration: underline; + color: #18469C; + padding-right:5px; + border-right: 1px solid #99BBE8; +} + +.x-btn-text button { + font-size: 8pt; + text-decoration: underline; + color: #18469C; +} + +.x-btn-link-medium { + text-decoration:underline; + float:right; + text-align:right; +} + +.x-btn .icon-add, .x-menu-item .icon-add { + background-image: url(img/silk/add.png); +} + + +.x-span-font-eight { + font-size: 8pt; +} + +.x-form-field-inline { + display:inline; + padding:0 0 30px 0; + margin:0px; +} + +.transparent-panel { + background:transparent; +} + +cga-logo-overlay { + z-index: 10000; + position: absolute; + left: 100px; + bottom: 10px; + width:151px; + height:39px; + background: transparent; +} + +.more-overlay-element { + float: left; + z-index: 4000; + position: absolute; + right: 150px; + top: 10px; + height:25px; + width:50px; + background: #FFF; + text-decoration: none; + border: 1px solid #000; +} + +.more-overlay-element .x-btn-small td {background-image: none; text-decoration:none;} +.more-overlay-element .x-btn-small td button {text-decoration:none;} + +.language-overlay-element { + float: left; + z-index: 4000; + position: absolute; + right: 10px; + bottom: 70px; + height:25px; + text-decoration: none; +} + +div.cga-link { + margin:3px; + font-size:8pt; + clear: both; +} + +.featureDetailList { +} +.featureDetailList li { + margin:4px 5px; + min-height:16px; + position:relative; +} +* html .featureDetailList li { + height:16px; +} +.featureDetailList li label { + font-weight:bold; + left:0; + position:absolute; + top:0; + width:150px; +} +.featureDetailList li span { + margin-left:160px; +} + +.nicEdit-selected { + border: 2px solid #0000ff !important; +} + +.nicEdit-panel { + background-color: #fff !important; +} + +.nicEdit-button { + background-color: #fff !important; +} + +.wtf { + padding: 0px 10px 0px 10px; + border-right: 1px solid #000; +} + +div.cql-overlay { + z-index: 10000; + position: absolute; + margin: 0 15%; + background:#FFF; + opacity: 0.9 +} + +div.chart-overlay { + z-index: 10000; + position: absolute; + //left: 10px; + bottom: 10px; + margin: 0 15%; + background:#FFF; + opacity: 1.0 +} + +.icon-picasa { + background-image: url('img/picasa.png'); +} + +.icon-youtube { + background-image: url('img/youtube.png'); +} + + +.icon-harvard { + background-image: url('img/harvard.png'); +} + +.icon-flickr { + background-image: url('img/flickr.png'); } \ No newline at end of file diff --git a/src/geonode-client/app/static/theme/app/geoexplorer_white.css b/src/geonode-client/app/static/theme/app/geoexplorer_white.css index 42f77d0..278e79c 100644 --- a/src/geonode-client/app/static/theme/app/geoexplorer_white.css +++ b/src/geonode-client/app/static/theme/app/geoexplorer_white.css @@ -1,997 +1,998 @@ - /* do wrap lines on any tooltips */ -.x-tip { -} - -/* get images on buttons with text to line up with those with no text */ -.x-btn-text-icon .x-btn-center .x-btn-text { - background-position: 0 3px; -} - -/* apply some margin when using the row expander */ -.x-grid3-row-body p { - margin: 5px !important; -} - -/* workaround for semi-alpha pixels in IE7: background needs to be the same - * as the toolbar's background color */ -.ext-ie .x-item-disabled .x-btn-text { - background-color: #EAEAEA; -} - -.x-tree-node-leaf .gx-tree-layer-icon { - background-image: url(img/geosilk/vector.png); -} - -.x-tree-node-leaf .gx-tree-rasterlayer-icon { - background-image: url(img/geosilk/raster.png); -} - -.x-menu-group-item .x-menu-item-icon { - background: transparent url(../../externals/ext/resources/images/white/form/radio.gif) no-repeat 0 0; - height: 13px; - width: 13px; - margin: 2px; -} - -.x-menu-item-checked .x-menu-group-item .x-menu-item-icon { - background: transparent url(../../externals/ext/resources/images/white/form/radio.gif) no-repeat -13px -13px; - height: 13px; - width: 13px; - margin: 2px; -} - -.x-btn .icon-geoexplorer { - background-image: url(img/geoexplorer.png); -} - -.x-btn .icon-addlayers { - background-image: url(img/silk/add.png); -} - -.x-btn .icon-removelayers, .x-menu-item .icon-removelayers { - background-image: url(img/silk/delete.png); -} - -.x-btn .icon-layerproperties, .x-menu-item .icon-layerproperties { - background-image: url(img/silk/wrench.png); -} - -.x-btn .icon-layerstyles, .x-menu-item .icon-layerstyles { - background-image: url(img/silk/palette.png); -} - -.x-btn .icon-getfeatureinfo { - background-image: url(img/silk/information.png); -} - -.x-btn .icon-3D { - background-image: url(img/geosilk/google_earth.png); -} - -.x-btn .icon-save { - background-image: url(img/geosilk/map_save.png); -} - -/* Really for CAPRA, watch out! */ - -.x-menu-group-item .icon-point, -.x-btn .icon-point { - background: transparent url(img/geosilk/bullet_orange.png) no-repeat center center !important; - margin: 0px; - height: 16px; - width: 16px; -} - -.x-menu-group-item .icon-line, -.x-btn .icon-line { - background: transparent url(img/geosilk/line_orange.png) no-repeat center center !important; - margin: 0px; - height: 16px; - width: 16px; -} - -.x-menu-group-item .icon-polygon, -.x-btn .icon-polygon { - background: transparent url(img/geosilk/shape_square_orange.png) center center !important; - margin: 0px; - height: 16px; - width: 16px; -} - -.x-btn .icon-visibility { - background-image: url(img/silk/eye.png); -} - -.x-btn .icon-pdf { - background-image: url(img/silk/page_white_acrobat.png); -} - -div.report { - background-color: white; - height: 100%; -} - -div.report table, div.report td, div.report th { - padding: .4em; -} - -div.report th { - background-color: #CCC; -} - -div.report tr.odd { - background-color: #EEF; -} - -.report td.corner{ - background-color:white; -} - - -/* ------------ */ - -.x-btn .icon-export { - background-image: url(img/silk/map_go.png); -} -.x-btn .icon-measure { - background-image: url(img/geosilk/measure.png); -} - -.icon-measure-length { - background-image: url(img/geosilk/ruler.png) !important; -} - -.icon-measure-area { - background: url(img/geosilk/ruler_square.png) no-repeat 0 0 !important; - margin: 0 !important; - width: 16px !important; - height: 16px !important; -} - -.x-btn .icon-layer-switcher { - background-image: url(img/silk/layers.png); -} - -.x-btn .icon-zoom-in { - background-image: url(img/silk/magnifier_zoom_in.png); -} - -.x-btn .icon-zoom-out { - background-image: url(img/silk/magnifier_zoom_out.png); -} - -.x-btn .icon-zoom-previous { - background-image: url(img/silk/arrow_left.png); -} - -.x-btn .icon-zoom-next { - background-image: url(img/silk/arrow_right.png); -} - -.x-btn .icon-zoom-visible, .x-menu-item .icon-zoom-visible { - background-image: url(img/silk/arrow_out.png); -} - -.x-btn .icon-zoom-to, .x-menu-item .icon-zoom-to { - background-image: url(img/silk/magnifier.png); -} - -.x-btn .icon-pan { - background-image: url(img/geosilk/pan.png); -} - -.legend-item { - margin: 0.5em 10px; -} - -div.map-overlay { - z-index: 4000; - position: absolute; - right: 10px; - bottom: 10px; - background:transparent; -} - -div.map-overlay div.overlay-element { - display:inline; - float: left; - margin: 5px; - background:transparent; -} - -div.overlay-scaleline { - bottom: 0px; - left: 0px; - margin-top: 0px; - z-index: 10000; -} - -.olControlAttribution{ - color: gray; - bottom: .5em; - left: .4em; - right: 220px; - font-size: smaller; -} - -.olControlScaleLineTop, -.olControlScaleLineBottom { - font-size:10px; -} - -/* Pan- and Zoom- Panel Styles*/ - -.olControlPanPanel div { - background-image:url(../../externals/ext/resources/images/white/panel/tool-sprites.gif); - height:15px; - width:15px; - /* workaround for button height in IE */ - font-size:0px; -} - -.olControlPanPanel .olControlPanNorthItemInactive { - background-position:15px -60px; - left:16px -} -.olControlPanPanel .olControlPanEastItemInactive { - background-position:15px -120px; - left: 30px; - top: 16px; -} -.olControlPanPanel .olControlPanSouthItemInactive { - background-position:15px -75px; - left: 16px; - top: 32px; -} -.olControlPanPanel .olControlPanWestItemInactive { - background-position:15px -105px; - left: 2px; - top: 16px; -} - -.olControlZoomPanel { - left:21px; -} - -.olControlZoomPanel div { - background-image:url(../../externals/ext/resources/images/white/panel/tool-sprites.gif); - height:15px; - width:15px; - /* workaround for button height in IE */ - font-size:0px; -} - -.olControlZoomPanel .olControlZoomInItemInactive { - background-position:15px -240px; -} - -.olControlZoomPanel .olControlZoomToMaxExtentItemInactive { - display: none; -} - -.olControlZoomPanel .olControlZoomOutItemInactive { - background-position:15px -255px; - top: 123px; -} - -.olControlScaleLine { - line-height: 10px; - display: block; - position: relative; - font-family: tahoma,arial,helvetica,sans-serif; -} - -/* position the zoom slider within map panel */ -.gx-zoomslider { - top: 90px; - left: 17px -} - - -.gx-layer-menu { - background: #F0F0F0; -} - -.gx-field-label { - font-weight: bold; - margin: 4px; - vertical-align: baseline; -} - -.gx-snippet-area textarea { - color: black; - opacity: 1; -} - -.gx-info-panel { - margin: 1em; -} - -.gx-info-panel h2 { - margin-top: 1em; -} - -.gx-wizard-description p { - margin: 4px auto; - background: none; -} - -.gx-wizard-pane { - padding: 4px; -} - -.gx-grid-true { - background: red; -} - -.gx-grid-false { - background: blue; -} - -.gx-wizard-active button { - font-weight: bold; -} - -.gx-wizard-pane .x-panel-body { - background: none; -} - -.gx-wizard-pane .x-grid3-dirty-cell { - background-image: none; -} - -.gx-layer-visibility { - background-image: url(img/silk/eye.png); - width: 16px; - height: 16px; - display: block; -} - -.error-details { - font: 8pt courier,courier new,monospace; - padding: 5px; -} - -.user_item button { - width: 16px; - height: 16px; - margin: 4px; -} - -#more-info{ - float:right; -} - -/* gxp overrides for different folder structure */ -.olControlZoomPanel div { - background-image:url(../../externals/ext/resources/images/white/panel/tool-sprites.gif); -} -.x-tree-node img.gxp-folder, .x-tree-node-collapsed img.gxp-folder{ - background: url(../../externals/ext/resources/images/white/tree/folder.gif); -} -.x-tree-node-expanded img.gxp-folder { - background: url(../../externals/ext/resources/images/white/tree/folder-open.gif); -} - -.olLayerGoogleV3.olLayerGoogleCopyright { - bottom: 1em !important; -} -.olLayerGoogleV3.olLayerGooglePoweredBy { - bottom: 2em !important; -} - -/* WorldMap additions/modifications */ - -.x-btn-noicon .x-btn-small .x-btn-text { - height: 21px; -} - -.ext-gecko .x-btn button, .ext-webkit .x-btn button { - color: #0d0d0d; - border: 1px solid #bbb; - border-radius: 5px; -} - -.ext-gecko .x-btn button:hover { - color:#fff; - background-color: #2657A8; - border: 1px solid #2657A8; -} - -.x-btn .user_item .icon-removeuser .remove-button { - border: 1px solid #fff; -} - -.x-btn-text { - font-size: 8pt; - /*color: #18469C;*/ - padding:0px; - border-radius: 5px; - /*border: 1px solid #000;*/ - border:none; - text-transform: capitalize; -} - -.x-btn-text button { - font-size: 8pt; - text-decoration: none; -} - -.x-btn-link-medium { - text-decoration:underline; - float:right; - text-align:right; -} - - -.x-btn .icon-add, .x-menu-item .icon-add { - background-image: url(../../externals/ext/resources/images/white/silk/add.png); -} - - -.x-span-font-eight { - font-size: 8pt; -} - -.x-form-field-inline { - display:inline; - padding:0 0 30px 0; - margin:0px; -} - -.transparent-panel { - background:transparent; -} - -cga-logo-overlay { - z-index: 10000; - position: absolute; - left: 100px; - bottom: 10px; - width:151px; - height:39px; - background: transparent; -} - -.more-overlay-element { - float: left; - z-index: 4000; - position: absolute; - right: 150px; - top: 10px; - height:25px; - width:50px; - background: #FFF; - text-decoration: none; - /*border: 1px solid #000;*/ -} - -.more-overlay-element .x-btn-small td {background-image: none; text-decoration:none;} -.more-overlay-element .x-btn-small td button {text-decoration:none;} - -.language-overlay-element { - float: left; - z-index: 4000; - position: absolute; - right: 10px; - bottom: 70px; - height:25px; - text-decoration: none; -} - -div.cga-link { - margin:3px; - font-size:8pt; - clear: both; -} - -.featureDetailList { -} -.featureDetailList li { - margin:4px 5px; - min-height:16px; - position:relative; -} -* html .featureDetailList li { - height:16px; -} -.featureDetailList li label { - font-weight:bold; - left:0; - position:absolute; - top:0; - width:150px; -} -.featureDetailList li span { - margin-left:160px; -} - -.nicEdit-selected { - border: 2px solid #0000ff !important; -} - -.nicEdit-panel { - background-color: #fff !important; -} - -.nicEdit-button { - background-color: #fff !important; -} - -.wtf { - padding: 0px 10px 0px 10px; - border-right: 1px solid #000; -} - -div.cql-overlay { - z-index: 10000; - position: absolute; - margin: 0 15%; - background:#FFF; - opacity: 0.9 -} - -div.chart-overlay { - z-index: 10000; - position: absolute; - //left: 10px; - bottom: 10px; - margin: 0 15%; - background:#FFF; - opacity: 1.0 -} - -.icon-picasa { - background-image: url('img/picasa.png'); -} - -.icon-youtube { - background-image: url('img/youtube.png'); -} - - -.icon-harvard { - background-image: url('img/harvard.png'); -} - -.icon-flickr { - background-image: url('img/flickr.png'); -} - - -/** WHITE **/ - - -.x-toolbar{ - background-color: #fff; - background-image: none; -} -.x-tab-panel-header{ - background-color: #fff; - background-image: none; - } -ul.x-tab-strip-top { - background-color: #fff; - background-image: none; -} - -.x-panel{ - border-color: #fff; -} - -.x-panel-tbar{ - border-color: #fff; - -} -.x-toolbar{ - border-color: #fff; - -} -.x-small-editor{ - border-color: #fff; - -} -.x-toolbar-layout-ct{ - border-color: #fff; -} - - -.x-tab-panel-header, .x-tab-panel-footer { - border-color: #fff; - -} - -.x-panel-noborder .x-panel-tbar-noborder .x-toolbar { - border-color: #fff; -} - -.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar { - border-color: #fff; -} - -.x-border-layout-ct { - border-top: 0px solid #dbdbdb; -} - - -.x-panel-tbar { - border-top: 0px solid; - border-bottom: 1px solid; - border-color: #dbdbdb; -} - -.x-panel-tbar-noborder { - border-top: 0px solid; - border-bottom: 0px solid; - border-color: #dbdbdb; -} - -.x-panel-body-noheader { - border-top: 0px solid; - border-bottom: 0px solid; - border-color: #fff; - /*border-color: #dbdbdb;*/ -} - - - -.x-tab-panel-body { - border-color: #fff; -} - -.x-layout-collapsed { - background-color: #fff; - border-color: #fff; -} - -.x-window-tc { - background-image: none; - background-color: #fff; -} - -.x-window-ml { - background-image: none; - background-color: #fff; -} - -.x-window-mr { - background-image: none; - background-color: #fff; -} - -.x-window-bc { - background-image: none; - background-color: #fff; -} - -.x-window-bl { - background-image: none; - background-color: #fff; -} - -.x-window-br { - background-image: none; - background-color: #fff; -} - -.x-window-tl { - background-image: none; - background-color: #fff; -} - -.x-window-tr { - background-image: none; - background-color: #fff; -} - -.x-layout-split { - height: 5px; - line-height: 1px; - font-size: 1px; - z-index: 3; - background-color: #fff; - width: 5px; - position: absolute; -} - -.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc { - background-image: none; - background-color: #fff; -} -.x-btn-focus, .x-btn-pressed{ - background-image: none; - background-color: #fff; -} - -.x-btn-tl:hover, .x-btn-tr:hover, .x-btn-tc:hover, .x-btn-ml:hover, .x-btn-mr:hover, .x-btn-mc:hover, .x-btn-bl:hover, .x-btn-br:hover, .x-btn-bc:hover { - background-image: none; - background-color: #fff; -} - -.x-toolbar .x-btn-click .x-btn-bc, .x-toolbar .x-btn-menu-active .x-btn-bc, .x-toolbar .x-btn-pressed .x-btn-bc, .x-toolbar .x-btn-over .x-btn-bc { - background-image: none; - height: 1px; -/* background-color: #287AB0;*/ -} - -.x-btn .gxp-icon-note { - background-image: url("../../externals/ext/resources/images/white/tree/note.png"); - background-size: 17%; -} - -.x-btn-text-icon .x-btn-icon-small-left .x-btn-text { - background-position: 0px center; - background-repeat: no-repeat; - padding-left: 19px; - height: 21px; -} - -.x-btn-icon .x-btn-small .x-btn-text { - border: 1px solid #fff; - /* height: 25px;*/ -} - -.x-tree-node .x-tree-selected { - background-color: #d3d3d3; -} - -.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr { - background-image: none; - background-color: #fff; -} - -.x-menu-item-active { - background-image: none; - background-color: #fff; - border-color: #fff; -} - -.x-menu-list { - background-color: #fff; -} - -.x-menu-item-active a.x-menu-item { - border-color: #fff; -} - -.x-menu-floating { - border-color: #fff; -} - -.x-toolbar .x-btn-mc em.x-btn-split { - background-image: url("../../externals/ext/resources/images/white/button/s-arrow-noline.gif"); -} - -.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split { - background-image: url("../../externals/ext/resources/images/white/button/s-arrow-noline.gif"); -} - -.x-slider-vert .x-slider-inner { - background-image: none; - background-color: rgba(100, 100, 100, .5); - border-radius: 5px; - width: 10px; - margin-left: 6px; -} - -.x-slider-vert .x-slider-thumb { - background-image: none; - background-color: #737373; - border-bottom: 0px solid #737373; - border-top: 0px solid #737373; - border-radius: 10px; - height: 10px; - width: 10px; - margin-left: -3px; -} - -.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner { - background-image: none; -} - -.x-form-field-wrap .x-form-trigger { - background-image: url("../../externals/ext/resources/images/white/form/trigger.gif"); - border: 1px solid #fff; - padding-top: 0px; -} - -.x-form-field-wrap .x-form-trigger img { - padding-top: 4px; -} - -.x-small-editor .x-form-field-wrap .x-form-trigger { - height: 19px; -} - -.ext-gecko .x-btn button, .ext-webkit .x-btn button { - padding-left: 5px; - padding-right: 5px; -} - -.x-tab-strip-active span.x-tab-strip-text { - color: #1a1a1a; - font-weight: bold; - text-transform: uppercase; - margin-left: 9px; -} - -.x-toolbar .xtb-sep { - background-image:none; -} - -.x-grid3-header { - background-color: #FFF; - background-image: none; -} - -.td.sort-asc .x-grid3-hd-inner { - background-color: #FFF; - background-image: none; -} - -.gxp-crumb span.x-tab-strip-text { - margin: 4px 4px 4px 9px; - color: #1a1a1a; - font-weight: bold; - text-transform: uppercase; -} - -.gxp-crumb .x-tab-strip-text a { - cursor: pointer; - color: #1a1a1a; - text-transform: uppercase; -} - -td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner { - background-color: #fff; - background-image: none; -} - -a.x-grid3-hd-btn { - background-image: url("../../externals/ext/resources/images/white/grid/grid3-hd-btn.gif"); - background-color: #FFF; -} - -.x-form-text, textarea.x-form-field { - color: #1a1a1a; - background-color: #FFF; - background-image: none; - border-color: #d3d3d3; - margin-bottom: 5px; - margin-right: 5px; - margin-left: 5px; - border-radius: 3px; -} - -.x-grid3-scroller { - border-radius: 1px; - border: 1px solid #d3d3d3; -} - -.x-form-field-wrap .x-form-field-trigger-wrap { - border: 1px solid #1a1a1a; -} - -.x-combo-list { - border-color: #dbdbdb; - background-color: #FFF; - font: 12px tahoma,arial,helvetica,sans-serif; -} - -.x-combo-list .x-combo-selected { - border-color: #737373 !important; - background-color: #dbdbdb; -} - -.x-grid3-hd-row td { - border-left-color: #FFF; - border-right-color: #FFF; -} - -.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander { - background-image: none; - background-color: #fff; -} - -.x-grid3-row-selected { - background-color: #18469c !important; - background-image: none; - border-color: #18469c; -} - -.x-grid3-row-selected .x-grid3-cell-inner{ - color: #fff; - -} - -.x-grid3-col .x-grid3-cell .x-grid3-td-expander .x-grid3-cell-first { - background-image:none; - background-color: #dbdbdb; -} - - .x-grid3-row-first .x-grid3-row-last { - background-color: #fff; -} - -.x-grid3-row-over { - border-color:#18469c ; - background-color: #18469c; - background-image:none; -} - -.x-grid3-row-over .x-grid3-cell-inner{ - color: #fff; - -} - -.x-grid3-row .x-grid3-row-collapsed .x-grid3-row-over { - background-color: #fff !important; - background-image: none; - border-color: #1a1a1a; -} - -.x-grid3-body .x-grid3-td-expander { - background-image: none; -} - -td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner { - background: transparent none repeat-x scroll left bottom; -} - -.olImageLoadError { - opacity: 0 !important; - filter: alpha(opacity=0) !important; -} - -.x-btn .prominent-btn, .prominent-btn, .prominent-button button, ext-gecko .x-btn .prominent-button button { - background-color: #18469c !important; - border-color: #18469c !important; - border-radius: 5px !important; - color: #fff !important; - font-size: 14px !important; - font-weight: bold; - height: 25px !important; - padding-left: 10px !important; - padding-right: 10px !important; - margin-top: -2px; -} - -.x-btn .not-prominent-btn, .not-prominent-btn, .not-prominent-button button, ext-gecko .x-btn .not-prominent-button button { - border-radius: 5px !important; - font-size: 14px !important; - height: 25px !important; - padding-left: 10px !important; - padding-right: 10px !important; - margin-top: -2px; -} - -.search-bar{ - float: left; -} - -.data-type{ - /*float:left;*/ - /*width: 140px;*/ - height: 25px; -} - -.x-form-field-wrap, .x-form-field-trigger-wrap, .x-trigger-wrap-focus { - margin-left: 0px; - float: left; -} - -.x-panel-body .x-panel-body-noheader .x-panel-body-noborder { - max-width: 100%; - max-height: 100%; - /*max-width: 884px; - max-height: 520px;*/ -} - -#search_controls{ - margin-left: 20px; + /* do wrap lines on any tooltips */ +.x-tip { +} + +/* get images on buttons with text to line up with those with no text */ +.x-btn-text-icon .x-btn-center .x-btn-text { + background-position: 0 3px; +} + +/* apply some margin when using the row expander */ +.x-grid3-row-body p { + margin: 5px !important; +} + +/* workaround for semi-alpha pixels in IE7: background needs to be the same + * as the toolbar's background color */ +.ext-ie .x-item-disabled .x-btn-text { + background-color: #EAEAEA; +} + +.x-tree-node-leaf .gx-tree-layer-icon { + background-image: url(img/geosilk/vector.png); +} + +.x-tree-node-leaf .gx-tree-rasterlayer-icon { + background-image: url(img/geosilk/raster.png); +} + +.x-menu-group-item .x-menu-item-icon { + background: transparent url(../../externals/ext/resources/images/white/form/radio.gif) no-repeat 0 0; + height: 13px; + width: 13px; + margin: 2px; +} + +.x-menu-item-checked .x-menu-group-item .x-menu-item-icon { + background: transparent url(../../externals/ext/resources/images/white/form/radio.gif) no-repeat -13px -13px; + height: 13px; + width: 13px; + margin: 2px; +} + +.x-btn .icon-geoexplorer { + background-image: url(img/geoexplorer.png); +} + +.x-btn .icon-addlayers { + background-image: url(img/silk/add.png); +} + +.x-btn .icon-removelayers, .x-menu-item .icon-removelayers { + background-image: url(img/silk/delete.png); +} + +.x-btn .icon-layerproperties, .x-menu-item .icon-layerproperties { + background-image: url(img/silk/wrench.png); +} + +.x-btn .icon-layerstyles, .x-menu-item .icon-layerstyles { + background-image: url(img/silk/palette.png); +} + +.x-btn .icon-getfeatureinfo { + background-image: url(img/silk/information.png); +} + +.x-btn .icon-3D { + background-image: url(img/geosilk/google_earth.png); +} + +.x-btn .icon-save { + background-image: url(img/geosilk/map_save.png); +} + +/* Really for CAPRA, watch out! */ + +.x-menu-group-item .icon-point, +.x-btn .icon-point { + background: transparent url(img/geosilk/bullet_orange.png) no-repeat center center !important; + margin: 0px; + height: 16px; + width: 16px; +} + +.x-menu-group-item .icon-line, +.x-btn .icon-line { + background: transparent url(img/geosilk/line_orange.png) no-repeat center center !important; + margin: 0px; + height: 16px; + width: 16px; +} + +.x-menu-group-item .icon-polygon, +.x-btn .icon-polygon { + background: transparent url(img/geosilk/shape_square_orange.png) center center !important; + margin: 0px; + height: 16px; + width: 16px; +} + +.x-btn .icon-visibility { + background-image: url(img/silk/eye.png); +} + +.x-btn .icon-pdf { + background-image: url(img/silk/page_white_acrobat.png); +} + +div.report { + background-color: white; + height: 100%; +} + +div.report table, div.report td, div.report th { + padding: .4em; +} + +div.report th { + background-color: #CCC; +} + +div.report tr.odd { + background-color: #EEF; +} + +.report td.corner{ + background-color:white; +} + + +/* ------------ */ + +.x-btn .icon-export { + background-image: url(img/silk/map_go.png); +} +.x-btn .icon-measure { + background-image: url(img/geosilk/measure.png); +} + +.icon-measure-length { + background-image: url(img/geosilk/ruler.png) !important; +} + +.icon-measure-area { + background: url(img/geosilk/ruler_square.png) no-repeat 0 0 !important; + margin: 0 !important; + width: 16px !important; + height: 16px !important; +} + +.x-btn .icon-layer-switcher { + background-image: url(img/silk/layers.png); +} + +.x-btn .icon-zoom-in { + background-image: url(img/silk/magnifier_zoom_in.png); +} + +.x-btn .icon-zoom-out { + background-image: url(img/silk/magnifier_zoom_out.png); +} + +.x-btn .icon-zoom-previous { + background-image: url(img/silk/arrow_left.png); +} + +.x-btn .icon-zoom-next { + background-image: url(img/silk/arrow_right.png); +} + +.x-btn .icon-zoom-visible, .x-menu-item .icon-zoom-visible { + background-image: url(img/silk/arrow_out.png); +} + +.x-btn .icon-zoom-to, .x-menu-item .icon-zoom-to { + background-image: url(img/silk/magnifier.png); +} + +.x-btn .icon-pan { + background-image: url(img/geosilk/pan.png); +} + +.legend-item { + margin: 0.5em 10px; +} + +div.map-overlay { + z-index: 4000; + position: absolute; + right: 10px; + bottom: 10px; + background:transparent; +} + +div.map-overlay div.overlay-element { + display:inline; + float: left; + margin: 5px; + background:transparent; +} + +div.overlay-scaleline { + bottom: 0px; + left: 0px; + margin-top: 0px; + z-index: 10000; +} + +.olControlAttribution{ + color: gray; + bottom: .5em; + left: .4em; + right: 220px; + font-size: smaller; +} + +.olControlScaleLineTop, +.olControlScaleLineBottom { + font-size:10px; +} + +/* Pan- and Zoom- Panel Styles*/ + +.olControlPanPanel div { + background-image:url(../../externals/ext/resources/images/white/panel/tool-sprites.gif); + height:15px; + width:15px; + /* workaround for button height in IE */ + font-size:0px; +} + +.olControlPanPanel .olControlPanNorthItemInactive { + background-position:15px -60px; + left:16px +} +.olControlPanPanel .olControlPanEastItemInactive { + background-position:15px -120px; + left: 30px; + top: 16px; +} +.olControlPanPanel .olControlPanSouthItemInactive { + background-position:15px -75px; + left: 16px; + top: 32px; +} +.olControlPanPanel .olControlPanWestItemInactive { + background-position:15px -105px; + left: 2px; + top: 16px; +} + +.olControlZoomPanel { + left:21px; +} + +.olControlZoomPanel div { + background-image:url(../../externals/ext/resources/images/white/panel/tool-sprites.gif); + height:15px; + width:15px; + /* workaround for button height in IE */ + font-size:0px; +} + +.olControlZoomPanel .olControlZoomInItemInactive { + background-position:15px -240px; +} + +.olControlZoomPanel .olControlZoomToMaxExtentItemInactive { + display: none; +} + +.olControlZoomPanel .olControlZoomOutItemInactive { + background-position:15px -255px; + top: 123px; +} + +.olControlScaleLine { + line-height: 10px; + display: block; + position: relative; + font-family: tahoma,arial,helvetica,sans-serif; +} + +/* position the zoom slider within map panel */ +.gx-zoomslider { + top: 90px; + left: 17px +} + + +.gx-layer-menu { + background: #F0F0F0; +} + +.gx-field-label { + font-weight: bold; + margin: 4px; + vertical-align: baseline; +} + +.gx-snippet-area textarea { + color: black; + opacity: 1; +} + +.gx-info-panel { + margin: 1em; +} + +.gx-info-panel h2 { + margin-top: 1em; +} + +.gx-wizard-description p { + margin: 4px auto; + background: none; +} + +.gx-wizard-pane { + padding: 4px; +} + +.gx-grid-true { + background: red; +} + +.gx-grid-false { + background: blue; +} + +.gx-wizard-active button { + font-weight: bold; +} + +.gx-wizard-pane .x-panel-body { + background: none; +} + +.gx-wizard-pane .x-grid3-dirty-cell { + background-image: none; +} + +.gx-layer-visibility { + background-image: url(img/silk/eye.png); + width: 16px; + height: 16px; + display: block; +} + +.error-details { + font: 8pt courier,courier new,monospace; + padding: 5px; +} + +.user_item button { + width: 16px; + height: 16px; + margin: 4px; +} + +#more-info{ + float:right; +} + +/* gxp overrides for different folder structure */ +.olControlZoomPanel div { + background-image:url(../../externals/ext/resources/images/white/panel/tool-sprites.gif); +} +.x-tree-node img.gxp-folder, .x-tree-node-collapsed img.gxp-folder{ + background: url(../../externals/ext/resources/images/white/tree/folder.gif); +} +.x-tree-node-expanded img.gxp-folder { + background: url(../../externals/ext/resources/images/white/tree/folder-open.gif); +} + +.olLayerGoogleV3.olLayerGoogleCopyright { + bottom: 1em !important; +} +.olLayerGoogleV3.olLayerGooglePoweredBy { + bottom: 2em !important; +} + +/* WorldMap additions/modifications */ + +.x-btn-noicon .x-btn-small .x-btn-text { + height: 21px; +} + +.ext-gecko .x-btn button, .ext-webkit .x-btn button { + color: #0d0d0d; + border: 1px solid #bbb; + border-radius: 5px; +} + +.ext-gecko .x-btn button:hover { + color:#fff; + background-color: #2657A8; + border: 1px solid #2657A8; +} + +.x-btn .user_item .icon-removeuser .remove-button { + border: 1px solid #fff; +} + +.x-btn-text { + font-size: 8pt; + /*color: #18469C;*/ + padding:0px; + border-radius: 5px; + /*border: 1px solid #000;*/ + border:none; + text-transform: capitalize; +} + +.x-btn-text button { + font-size: 8pt; + text-decoration: none; +} + +.x-btn-link-medium { + text-decoration:underline; + float:right; + text-align:right; +} + + +.x-btn .icon-add, .x-menu-item .icon-add { + background-image: url(../../externals/ext/resources/images/white/silk/add.png); +} + + +.x-span-font-eight { + font-size: 8pt; +} + +.x-form-field-inline { + display:inline; + padding:0 0 30px 0; + margin:0px; +} + +.transparent-panel { + background:transparent; +} + +cga-logo-overlay { + z-index: 10000; + position: absolute; + left: 100px; + bottom: 10px; + width:151px; + height:39px; + background: transparent; +} + +.more-overlay-element { + float: left; + z-index: 4000; + position: absolute; + right: 150px; + top: 10px; + height:25px; + width:50px; + background: #FFF; + text-decoration: none; + /*border: 1px solid #000;*/ +} + +.more-overlay-element .x-btn-small td {background-image: none; text-decoration:none;} +.more-overlay-element .x-btn-small td button {text-decoration:none;} + +.language-overlay-element { + float: left; + z-index: 4000; + position: absolute; + right: 10px; + bottom: 70px; + height:25px; + text-decoration: none; +} + +div.cga-link { + margin:3px; + font-size:8pt; + clear: both; +} + +.featureDetailList { +} +.featureDetailList li { + margin:4px 5px; + min-height:16px; + position:relative; +} +* html .featureDetailList li { + height:16px; +} +.featureDetailList li label { + font-weight:bold; + left:0; + position:absolute; + top:0; + width:150px; +} +.featureDetailList li span { + margin-left:160px; +} + +.nicEdit-selected { + border: 2px solid #0000ff !important; +} + +.nicEdit-panel { + background-color: #fff !important; +} + +.nicEdit-button { + background-color: #fff !important; +} + +.wtf { + padding: 0px 10px 0px 10px; + border-right: 1px solid #000; +} + +div.cql-overlay { + z-index: 10000; + position: absolute; + margin: 0 15%; + background:#FFF; + opacity: 0.9 +} + +div.chart-overlay { + z-index: 10000; + position: absolute; + //left: 10px; + bottom: 10px; + margin: 0 15%; + background:#FFF; + opacity: 1.0 +} + +.icon-picasa { + background-image: url('img/picasa.png'); +} + +.icon-youtube { + background-image: url('img/youtube.png'); +} + + +.icon-harvard { + background-image: url('img/harvard.png'); +} + +.icon-flickr { + background-image: url('img/flickr.png'); +} + + +/** WHITE **/ + + +.x-toolbar{ + background-color: #fff; + background-image: none; +} +.x-tab-panel-header{ + background-color: #fff; + background-image: none; + } +ul.x-tab-strip-top { + background-color: #fff; + background-image: none; +} + +.x-panel{ + border-color: #fff; +} + +.x-panel-tbar{ + border-color: #fff; + +} +.x-toolbar{ + border-color: #fff; + +} +.x-small-editor{ + border-color: #fff; + +} +.x-toolbar-layout-ct{ + border-color: #fff; +} + + +.x-tab-panel-header, .x-tab-panel-footer { + border-color: #fff; + +} + +.x-panel-noborder .x-panel-tbar-noborder .x-toolbar { + border-color: #fff; +} + +.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar { + border-color: #fff; +} + +.x-border-layout-ct { + border-top: 0px solid #dbdbdb; +} + + +.x-panel-tbar { + border-top: 0px solid; + border-bottom: 1px solid; + border-color: #dbdbdb; +} + +.x-panel-tbar-noborder { + border-top: 0px solid; + border-bottom: 0px solid; + border-color: #dbdbdb; +} + +.x-panel-body-noheader { + border-top: 0px solid; + border-bottom: 0px solid; + border-color: #fff; + /*border-color: #dbdbdb;*/ +} + + + +.x-tab-panel-body { + border-color: #fff; +} + +.x-layout-collapsed { + background-color: #fff; + border-color: #fff; +} + +.x-window-tc { + background-image: none; + background-color: #fff; +} + +.x-window-ml { + background-image: none; + background-color: #fff; +} + +.x-window-mr { + background-image: none; + background-color: #fff; +} + +.x-window-bc { + background-image: none; + background-color: #fff; +} + +.x-window-bl { + background-image: none; + background-color: #fff; +} + +.x-window-br { + background-image: none; + background-color: #fff; +} + +.x-window-tl { + background-image: none; + background-color: #fff; +} + +.x-window-tr { + background-image: none; + background-color: #fff; +} + +.x-layout-split { + height: 5px; + line-height: 1px; + font-size: 1px; + z-index: 3; + background-color: #fff; + width: 5px; + position: absolute; +} + +.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc { + background-image: none; + background-color: #fff; +} +.x-btn-focus, .x-btn-pressed{ + background-image: none; + background-color: #fff; +} + +.x-btn-tl:hover, .x-btn-tr:hover, .x-btn-tc:hover, .x-btn-ml:hover, .x-btn-mr:hover, .x-btn-mc:hover, .x-btn-bl:hover, .x-btn-br:hover, .x-btn-bc:hover { + background-image: none; + background-color: #fff; +} + +.x-toolbar .x-btn-click .x-btn-bc, .x-toolbar .x-btn-menu-active .x-btn-bc, .x-toolbar .x-btn-pressed .x-btn-bc, .x-toolbar .x-btn-over .x-btn-bc { + background-image: none; + height: 1px; +/* background-color: #287AB0;*/ +} + +.x-btn .gxp-icon-note { + background-image: url("../../externals/ext/resources/images/white/tree/note.png"); + background-size: 17%; +} + +.x-btn-text-icon .x-btn-icon-small-left .x-btn-text { + background-position: 0px center; + background-repeat: no-repeat; + padding-left: 19px; + height: 21px; +} + +.x-btn-icon .x-btn-small .x-btn-text { + border: 1px solid #fff; + /* height: 25px;*/ +} + +.x-tree-node .x-tree-selected { + background-color: #d3d3d3; +} + +.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr { + background-image: none; + background-color: #fff; +} + +.x-menu-item-active { + background-image: none; + background-color: #fff; + border-color: #fff; +} + +.x-menu-list { + background-color: #fff; +} + +.x-menu-item-active a.x-menu-item { + border-color: #fff; +} + +.x-menu-floating { + border-color: #fff; +} + +.x-toolbar .x-btn-mc em.x-btn-split { + background-image: url("../../externals/ext/resources/images/white/button/s-arrow-noline.gif"); +} + +.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split { + background-image: url("../../externals/ext/resources/images/white/button/s-arrow-noline.gif"); +} + +.x-slider-vert .x-slider-inner { + background-image: none; + background-color: rgba(100, 100, 100, .5); + border-radius: 5px; + width: 10px; + margin-left: 6px; +} + +.x-slider-vert .x-slider-thumb { + background-image: none; + background-color: #737373; + border-bottom: 0px solid #737373; + border-top: 0px solid #737373; + border-radius: 10px; + height: 10px; + width: 10px; + margin-left: -3px; +} + +.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner { + background-image: none; +} + +.x-form-field-wrap .x-form-trigger { + background-image: url("../../externals/ext/resources/images/white/form/trigger.gif"); + border: 1px solid #fff; + padding-top: 0px; +} + +.x-form-field-wrap .x-form-trigger img { + padding-top: 4px; +} + +.x-small-editor .x-form-field-wrap .x-form-trigger { + height: 19px; +} + +.ext-gecko .x-btn button, .ext-webkit .x-btn button { + padding-left: 5px; + padding-right: 5px; +} + +.x-tab-strip-active span.x-tab-strip-text { + color: #1a1a1a; + font-weight: bold; + text-transform: uppercase; + margin-left: 9px; +} + +.x-toolbar .xtb-sep { + background-image:none; +} + +.x-grid3-header { + background-color: #FFF; + background-image: none; +} + +.td.sort-asc .x-grid3-hd-inner { + background-color: #FFF; + background-image: none; +} + +.gxp-crumb span.x-tab-strip-text { + margin: 4px 4px 4px 9px; + color: #1a1a1a; + font-weight: bold; + text-transform: uppercase; +} + +.gxp-crumb .x-tab-strip-text a { + cursor: pointer; + color: #1a1a1a; + text-transform: uppercase; +} + +td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner { + background-color: #fff; + background-image: none; +} + +a.x-grid3-hd-btn { + background-image: url("../../externals/ext/resources/images/white/grid/grid3-hd-btn.gif"); + background-color: #FFF; +} + +.x-form-text, textarea.x-form-field { + color: #1a1a1a; + background-color: #FFF; + background-image: none; + border-color: #d3d3d3; + margin-bottom: 5px; + margin-right: 5px; + margin-left: 5px; + border-radius: 3px; +} + +.x-grid3-scroller { + border-radius: 1px; + border: 1px solid #d3d3d3; +} + +.x-form-field-wrap .x-form-field-trigger-wrap { + border: 1px solid #1a1a1a; +} + +.x-combo-list { + border-color: #dbdbdb; + background-color: #FFF; + font: 12px tahoma,arial,helvetica,sans-serif; +} + +.x-combo-list .x-combo-selected { + border-color: #737373 !important; + background-color: #dbdbdb; +} + +.x-grid3-hd-row td { + border-left-color: #FFF; + border-right-color: #FFF; +} + +.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander { + background-image: none; + background-color: #fff; +} + +.x-grid3-row-selected { + background-color: #18469c !important; + background-image: none; + border-color: #18469c; +} + +.x-grid3-row-selected .x-grid3-cell-inner{ + color: #fff; + +} + +.x-grid3-col .x-grid3-cell .x-grid3-td-expander .x-grid3-cell-first { + background-image:none; + background-color: #dbdbdb; +} + + .x-grid3-row-first .x-grid3-row-last { + background-color: #fff; +} + +.x-grid3-row-over { + border-color:#18469c ; + background-color: #18469c; + background-image:none; +} + +.x-grid3-row-over .x-grid3-cell-inner{ + color: #fff; + +} + +.x-grid3-row .x-grid3-row-collapsed .x-grid3-row-over { + background-color: #fff !important; + background-image: none; + border-color: #1a1a1a; +} + +.x-grid3-body .x-grid3-td-expander { + background-image: none; +} + +td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner { + background: transparent none repeat-x scroll left bottom; +} + +.olImageLoadError { + opacity: 0 !important; + filter: alpha(opacity=0) !important; +} + +.x-btn .prominent-btn, .prominent-btn, .prominent-button button, ext-gecko .x-btn .prominent-button button { + background-color: #18469c !important; + border-color: #18469c !important; + border-radius: 5px !important; + color: #fff !important; + font-size: 14px !important; + font-weight: bold; + height: 25px !important; + padding-left: 10px !important; + padding-right: 10px !important; + margin-top: -2px; +} + +.x-btn .not-prominent-btn, .not-prominent-btn, .not-prominent-button button, ext-gecko .x-btn .not-prominent-button button { + border-radius: 5px !important; + font-size: 14px !important; + height: 25px !important; + padding-left: 10px !important; + padding-right: 10px !important; + margin-top: -2px; +} + +.search-bar{ + float: left; +} + +.data-type{ + /*float:left;*/ + /*width: 140px;*/ + height: 25px; +} + +.x-form-field-wrap, .x-form-field-trigger-wrap, .x-trigger-wrap-focus { + margin-left: 0px; + float: left; +} + +.x-panel-body .x-panel-body-noheader .x-panel-body-noborder { + max-width: 100%; + max-height: 100%; + /*max-width: 884px; + max-height: 520px;*/ +} + +#search_controls{ + margin-left: 20px; } .search-button { + float:right; margin-top:-29px; margin-left: 336px; } diff --git a/src/geonode-client/buildjs.cfg b/src/geonode-client/buildjs.cfg index f4047b3..e516aa8 100755 --- a/src/geonode-client/buildjs.cfg +++ b/src/geonode-client/buildjs.cfg @@ -162,6 +162,7 @@ include = plugins/WMSCSource.js plugins/BingSource.js plugins/GoogleSource.js + plugins/TiandituSource.js plugins/MapBoxSource.js plugins/MapQuestSource.js plugins/OLSource.js @@ -201,8 +202,17 @@ include = widgets/CatalogueSearchPanel.js widgets/ScaleOverlay.js menu/LayerMenu.js + locale/ca.js + locale/de.js + locale/el.js + locale/en.js locale/es.js locale/fr.js + locale/id.js + locale/nl.js + locale/pl.js + locale/zh.js + locale/zh-cn.js plugins/AddCategory.js plugins/RenameCategory.js plugins/RemoveCategory.js diff --git a/wm_extra/accounts/forms.py b/wm_extra/accounts/forms.py index 362c721..51fa0ef 100644 --- a/wm_extra/accounts/forms.py +++ b/wm_extra/accounts/forms.py @@ -56,10 +56,13 @@ class SignupForm(forms.Form): is_org_member = forms.TypedChoiceField(coerce=lambda x: bool(int(x)), choices=((1, _(u'Yes')), (0, _(u'No'))), widget=forms.RadioSelect, - initial=0, label=settings.CUSTOM_ORG_AUTH_TEXT + #initial=0, label=_("Are you affiliated with Zhejiang University?") + initial=0, + label=_("Are you affiliated with Zhejiang University?") ) agree_tos = forms.BooleanField( - label=mark_safe("I agree to the Terms and Conditions") + #label=mark_safe(_("I agree to the Terms and Conditions")) + label=_("I agree to the Terms and Conditions") ) def clean_username(self): diff --git a/wm_extra/api/resources.py b/wm_extra/api/resources.py index f55286a..c776f89 100644 --- a/wm_extra/api/resources.py +++ b/wm_extra/api/resources.py @@ -3,8 +3,9 @@ from taggit.models import Tag from geonode.maps.models import Layer -from geonode.base.models import TopicCategory +from geonode.base.models import TopicCategory, ResourceBase +from actstream.models import Action class TopicCategoryResource(ModelResource): """ @@ -67,3 +68,15 @@ class Meta: 'name', 'owner_username', 'srs', 'temporal_extent_end', 'temporal_extent_start', 'title', 'topic_category', 'typename', 'uuid', ] + + +class ActionLayerDeleteResource(ModelResource): + + class Meta: + queryidarr = Action.objects.filter(data__contains={'raw_action': 'created'}, action_object_content_type_id=53).order_by('-timestamp').values_list('action_object_object_id', flat=True) + queryidarrint = [] + for queryid in queryidarr: + queryidarrint.append(int(queryid)) + queryset = ResourceBase.objects.filter(id__in=queryidarrint) + allowed_methods = ['get', ] + fields = ['uuid',] \ No newline at end of file diff --git a/wm_extra/views.py b/wm_extra/views.py index adf9684..56822b2 100644 --- a/wm_extra/views.py +++ b/wm_extra/views.py @@ -15,7 +15,7 @@ from django.template import RequestContext from django.views.decorators.csrf import csrf_exempt -from geonode.base.models import TopicCategory +from geonode.base.models import TopicCategory, ResourceBase from geonode.geoserver.helpers import ogc_server_settings from geonode.layers.models import Layer from geonode.maps.models import Map, MapLayer @@ -27,7 +27,7 @@ from geonode.utils import DEFAULT_TITLE from geonode.utils import DEFAULT_ABSTRACT -from .models import LayerStats +from .models import LayerStats, MapStats from .forms import EndpointForm @@ -550,3 +550,90 @@ def official_site(request, site): """ map_obj = get_object_or_404(Map,urlsuffix=site) return map_view_wm(request, str(map_obj.id)) + + + +# TODO get the category list +def get_categorys(request): + """ + return the category + :param request: language + :return: + """ + if request.POST.has_key('language'): + language = request.POST['language'] + key = 'gn_description' + categorys = TopicCategory.objects.all().values('id',key) + category_dict ={} + for category in categorys: + category_dict[category['id']] = [category[key]] + categoryjson = json.dumps(category_dict) + # from django.utils import simplejson + # return HttpResponse(simplejson.dumps(category, ensure_ascii=False)) + return HttpResponse(categoryjson) + + +# TODO get the major maps created by admin, or get the hotest and latest layer/map +def get_most_maps(request): + """ + return the six admin's/hottest/latest maps + :param request: category[0:all the category 1-20: appointed category], type['hottest','latest'] + :return: json of resourcebase + """ + resourcebase_dict = {} + count = 0 + if request.POST.has_key('type'): + type = request.POST['type'] + # if type==admin key='owner_id' elseif type==hottest key=popular_count else type==latest key =date + # order_by('-key'): the same with order by(key) asce + if type == 'admin': + key = 'owner_id' + else: + key = '-popular_count' if type == 'hottest' else '-date' + if request.POST['category'] != '0': + categoryid = int(request.POST['category']) + resourcebase_queryset = ResourceBase.objects.instance_of(Map).filter(category_id=categoryid).order_by(key)[0:5] + else: + resourcebase_queryset = ResourceBase.objects.instance_of(Map).all().order_by(key,'-date')[0:5] + count = 0 + for resourcebase in resourcebase_queryset: + resourcebase_dict[count] = [resourcebase.title, resourcebase.thumbnail_url, resourcebase.detail_url] + count = count + 1 + resourcebase_json = json.dumps(resourcebase_dict) + return HttpResponse(resourcebase_json) + +# def get_hottest_maps(request): +# """ +# return the six hottest maps of the appointed cateory +# :param request: +# :return: +# """ +# hottestmapstats = MapStats.objects.order_by('-visits').values('map_id') +# resourcebase_dict = {} +# count = 0 +# if request.POST.has_key('category'): +# categoryid = int(request.POST['category']) +# for mapstats in hottestmapstats: +# if(count > 5): +# break +# try: +# resourcebase = ResourceBase.objects.get(id=mapstats['map_id'], category_id=categoryid) +# except: +# count =count +# else: +# resourcebase_dict[count] = [resourcebase.title, resourcebase.thumbnail_url, resourcebase.detail_url] +# count = count +1 +# else: +# for mapstats in hottestmapstats: +# if(count > 5): +# break +# try: +# resourcebase = ResourceBase.objects.get(id=mapstats['map_id']) +# except: +# count = count +# else: +# resourcebase_dict[count] = [resourcebase.title, resourcebase.thumbnail_url, resourcebase.detail_url] +# count = count + 1 +# # return HttpResponse(simplejson.dumps(hottestresourcebase, ensure_ascii=False)) +# resourcebasejson = json.dumps(resourcebase_dict) +# return HttpResponse(resourcebasejson) \ No newline at end of file diff --git a/worldmap-migration/README.md b/worldmap-migration/README.md index fe81c41..eb84d39 100644 --- a/worldmap-migration/README.md +++ b/worldmap-migration/README.md @@ -4,87 +4,25 @@ Worldmap Database migrations....written in pure shell Usage ===== -The code is made in bash for the migration of an old version of worldmap to the current version. In order for the migration process to be done correctly, please follow the instructions below. -1. Make sure to load the sql dump from old worldmap database. It is necessary to make a copy, wr don't recommend to use the original db because we dont want to lose information To clarify, `$OLD_DB` corresponds to the name that we will assign to the database that is the copy of the old worldmap database. And `$SQL_DUMP_PATH` is the path from dump file of old worldmap database which we should generate before to do this process. - - sudo -u $DB_USER psql -c "CREATE DATABASE $OLD_DB" +1. Make sure to load the sql dump. - sudo -u $DB_USER psql -d $OLD_DB < $SQL_DUMP_PATH + sudo -u $DB_USER psql -c "CREATE DATABASE $OLD_DB" -2. Getting styles for Geoserver. + sudo -u $DB_USER psql -d $OLD_DB < $SQL_DUMP_PATH - 2.1. Copy styles_migration.sh to GEOSERVER DATA DIRECTORY - - cp styles_migration.sh /path/to/data/dir/geoserver - -     2.2. Edit GEOSERVER_URL and STYLES_FOLDER. Make sure `GEOSERVER_URL` corresponds to public location and `STYLES_FOLDER` is the directory where geoserver saves the styles. - - vim styles_migration.sh -     2.3. Generate `styles.csv`. - - ./styles_migration.sh -3. Configurate some env variables. Please edit config.sh file. +2. Run migration scripts -   -``` -   - export USER=postgres - export OLD_DB=Name_for_backup_database_of_old_worldmap - export DB_USER=worldmap #DATABASE OWNER - export DB_PW=password #OWNER USER PASSWORD - export PGPASSWORD=$DB_PW - export DB_HOST=localhost #database host location - export NEW_DB=new_one_database_name - export GEONODE_PATH=/home/paolo/worldmap #Worldmap location, if you will do the migration locally - export GEOSERVER_URL=http://128.31.22.83:8080/geoserver/ #GEOSERVER LOCATION - export ENV_PATH=/path/to/env - export DATABASE_URL=postgis://$DB_USER:$DB_PW@$DB_HOST:5432/$NEW_DB - export STYLES_PATH=/path/to/styles/csv/file #you can find this file inside geoserver directory - -``` + chmod +x main.sh + source main.sh -d $OLD_DB -4. Run migration scripts +If you wanna migrate geoserver styles + source main.sh --database $OLD_DB --styles - chmod +x main.sh - chmod -R +x scripts/ -   4.1 If you want to run django migration using the django server. Dont forget to edit `/home/ubuntu/wm.sh` file in your djando server and add new `DATABASE_URL`. - - source main.sh --database $OLD_DB - For example: - source main.sh --database worldmaplegacy -   4.2 If you wan to run django migration locally. Remind to set correctly `GEONODE_PATH` and `ENV_PATH`. - - source main.sh --database worldmaplegacy --local - - 4.3 Migration with geoserver styles: - - - Remote mode - source main.sh --database $OLD_DB --styles - - -Locally mode - source main.sh --database $OLD_DB --styles --local **Notes** - Make sure you have loaded your database dump. - Make sure you have the geoserver styles tables within files. - - -Other things to do during migration -=================================== - -* install GDAL GeoServer plugin -* run django find_geoserver_broken_layers to check if some layers was not imported -* truncate styles and links table -* run django fix_migrated_layers (regenerate styles, links and thumbnails) -* run django sync_geofence command - -GeoServer data Directory -======================== - -* security directory must be removed, and we need to use the one which comes with geoserver-2.12.x.war -* add geofence directory (included in geoserver-2.12.x.war) -* configure security (input oauth parameters) diff --git a/worldmap-migration/main.sh b/worldmap-migration/main.sh index 663c9ac..ff255d6 100755 --- a/worldmap-migration/main.sh +++ b/worldmap-migration/main.sh @@ -65,16 +65,7 @@ sudo -u $USER PGPASSWORD=$DB_PW psql -c "CREATE DATABASE $NEW_DB;" sudo -u $USER PGPASSWORD=$DB_PW \ psql -v ON_ERROR_STOP=1 -U $DB_USER -h $DB_HOST -d $NEW_DB -c \ "CREATE EXTENSION postgis;" -do_hr -echo "CREATE EXTENSION FOR UUID" -sudo -u $USER PGPASSWORD=$DB_PW \ -psql -v ON_ERROR_STOP=1 -U $DB_USER -h $DB_HOST -d $OLD_DB -c \ - 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";' -sudo -u $USER PGPASSWORD=$DB_PW \ -psql -v ON_ERROR_STOP=1 -U $DB_USER -h $DB_HOST -d $NEW_DB -c \ - 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";' -do_hr ############################################################################# if [ $LOCAL ]; then @@ -83,7 +74,6 @@ echo "Generating tables locally" do_hr source $ENV_PATH/bin/activate -#python $GEONODE_PATH/manage.py makemigrations --noinput python $GEONODE_PATH/manage.py migrate # python $GEONODE_PATH/manage.py loaddata $GEONODE_PATH/fixtures/default_oauth_apps.json else diff --git a/worldmap-migration/scripts/maps.sh b/worldmap-migration/scripts/maps.sh index 904d06d..f8a400f 100755 --- a/worldmap-migration/scripts/maps.sh +++ b/worldmap-migration/scripts/maps.sh @@ -31,7 +31,7 @@ MAP_CT_ID=$(sudo -u $USER psql $NEW_DB -c \ echo "\nCopying elements into resourcebase table"; do_dash sudo -u $USER PGPASSWORD=$DB_PW \ psql -v ON_ERROR_STOP=1 -U $DB_USER -h $DB_HOST $OLD_DB -c \ - "copy (select base_id, $MAP_CT_ID, uuid_generate_v5(uuid_ns_url(), 'base_id'), owner_id, title, last_modified, 'date_type', abstract, 'eng', 'supplemental_information', 'EPSG:4326', 'csw_typename', 'csw_schema', 'csw_mdsource', 'csw_type', 'csw_wkt_geometry', false, 0, 0, false, false, false, CONCAT('/maps/', base_id), false from augmented_maps_map) to stdout with csv" | \ + "copy (select base_id, $MAP_CT_ID, 'uuid', owner_id, title, last_modified, 'date_type', abstract, 'eng', 'supplemental_information', 'EPSG:4326', 'csw_typename', 'csw_schema', 'csw_mdsource', 'csw_type', 'csw_wkt_geometry', false, 0, 0, false, false, false, CONCAT('/maps/', base_id), false from augmented_maps_map) to stdout with csv" | \ sudo -u $USER \ psql $NEW_DB -c 'copy base_resourcebase (id, polymorphic_ctype_id, uuid, owner_id, title, date, date_type, abstract, language, supplemental_information, srid, csw_typename, csw_schema, csw_mdsource, csw_type, csw_wkt_geometry, metadata_uploaded, popular_count, share_count, featured, is_published, metadata_uploaded_preserve, detail_url, is_approved) from stdin csv' diff --git a/worldmap/context_processors.py b/worldmap/context_processors.py index efbc120..2980a45 100644 --- a/worldmap/context_processors.py +++ b/worldmap/context_processors.py @@ -11,7 +11,5 @@ def worldmap(request): 'HYPERMAP_REGISTRY_URL': settings.HYPERMAP_REGISTRY_URL, 'MAPPROXY_URL': settings.MAPPROXY_URL, 'SOLR_URL': settings.SOLR_URL, - 'USE_GAZETTEER': settings.USE_GAZETTEER, - 'GOOGLE_API_KEY': settings.GOOGLE_API_KEY, - 'GOOGLE_MAPS_API_KEY': settings.GOOGLE_MAPS_API_KEY + 'USE_GAZETTEER': settings.USE_GAZETTEER } diff --git a/worldmap/locale/zh/LC_MESSAGES/django.po b/worldmap/locale/zh/LC_MESSAGES/django.po index 73e60a3..ea7b23b 100644 --- a/worldmap/locale/zh/LC_MESSAGES/django.po +++ b/worldmap/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-11-06 09:01-0600\n" +"POT-Creation-Date: 2017-11-14 05:10-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -20,83 +20,91 @@ msgstr "" #: wm_extra/accounts/forms.py:32 worldmap/templates/base.html:155 #: worldmap/templates/base.html.py:156 msgid "Username" -msgstr "" +msgstr "用户名" #: wm_extra/accounts/forms.py:38 worldmap/templates/base.html:159 #: worldmap/templates/base.html.py:160 msgid "Password" -msgstr "" +msgstr "密码" #: wm_extra/accounts/forms.py:42 msgid "Password (again)" -msgstr "" +msgstr "确认密码" #: wm_extra/accounts/forms.py:46 #: worldmap/templates/people/profile_detail.html:73 msgid "Email" -msgstr "" +msgstr "Email" #: wm_extra/accounts/forms.py:57 msgid "Yes" -msgstr "" +msgstr "是的" #: wm_extra/accounts/forms.py:57 msgid "No" -msgstr "" +msgstr "不是" + +#: wm_extra/accounts/forms.py:61 +msgid "Are you affiliated with Zhejiang University?" +msgstr "是否从属于浙江大学?" + +#: wm_extra/accounts/forms.py:64 +msgid "I agree to the Terms and Conditions" +msgstr "我已阅读并同意相关条款" #: wm_extra/accounts/forms.py:67 msgid "Usernames can only contain letters, numbers, dots and underscores." -msgstr "" +msgstr "用户名只能包含字母、数字、标点和下划线。" #: wm_extra/accounts/forms.py:75 msgid "This username is already taken. Please choose another." -msgstr "" +msgstr "该用户名已存在,请使用其他用户名。" #: wm_extra/accounts/forms.py:82 msgid "A user is registered with this email address." -msgstr "" +msgstr "该邮件地址已被其他用户注册。" #: wm_extra/accounts/forms.py:87 msgid "You must type the same password each time." -msgstr "" +msgstr "密码和确认密码不一致。" #: wm_extra/accounts/views.py:42 #, python-brace-format msgid "Confirmation email sent to {email}." -msgstr "" +msgstr "确认邮件已经发送至{email}。" #: wm_extra/accounts/views.py:46 #, python-brace-format msgid "The code {code} is invalid." -msgstr "" +msgstr "该验证码{code}是无效的。" #: wm_extra/models.py:11 wm_extra/models.py:21 msgid "Visits" -msgstr "" +msgstr "访问量" #: wm_extra/models.py:12 wm_extra/models.py:22 msgid "Unique Visitors" -msgstr "" +msgstr "访客量" #: wm_extra/models.py:23 msgid "Downloads" -msgstr "" +msgstr "下载" #: wm_extra/models.py:34 msgid "Describe Map Service" -msgstr "" +msgstr "描述地图服务" #: wm_extra/models.py:35 msgid "Map service URL" -msgstr "" +msgstr "地图服务地址" #: wm_extra/templates/wm_extra/endpoint_add.html:6 msgid "Suggests an Endpoint" -msgstr "" +msgstr "建议一个端点" #: wm_extra/templates/wm_extra/endpoint_add.html:13 msgid "Submit Map Service URL" -msgstr "" +msgstr "提交地图服务地址" #: wm_extra/templates/wm_extra/endpoint_add.html:16 msgid "" @@ -105,12 +113,16 @@ msgid "" "organization hosting the map service, the source of the data, and the year " "or year range the data represents." msgstr "" +"请描述地图服务的制图类型(比如道路、河流要素、历史地图、卫星影像等等),管理地图服务的机构," +"数据的来源,数据代表的年份或者年份范围。" + #: wm_extra/templates/wm_extra/endpoint_add.html:17 msgid "" "Service harvesting and loading to WorldMap is currently a manual process so " "it may take some time for your map service layers to appear in search." -msgstr "" +msgstr "服务获取并加载至世界地图,目前还是一个手动操作的过程。" +"所以地图服务图层搜索结果的呈现可能会花费一段时间" #: wm_extra/templates/wm_extra/endpoint_add.html:18 msgid "" @@ -118,264 +130,274 @@ msgid "" "service endpoint types. If you are not sure what you have, feel free to " "submit it and we will attempt to load it." msgstr "" - +"该系统现在支持OGC、WMS、CSW和Esri Image和 Map " +"service endpoint types。如果不确定你的系统是什么,你" +"可以提交它,随后我们将会尝试加载它。" #: wm_extra/templates/wm_extra/endpoint_add.html:19 msgid "" "Write us at worldmap@harvard.edu if you have any questions. Thank you for " "your contribution." msgstr "" +"如果你有任何问题,请写邮件给我们worldmap@harvard.edu。非常感谢你的贡献。" #: wm_extra/templates/wm_extra/endpoint_add.html:23 msgid "Submit map service URL" -msgstr "" +msgstr "提交地图服务地址" #: wm_extra/templates/wm_extra/endpoint_added.html:6 #: wm_extra/templates/wm_extra/endpoint_added.html:13 msgid "Endpoint Suggested" -msgstr "" +msgstr "端点建议" #: wm_extra/templates/wm_extra/endpoint_added.html:16 msgid "Thanks" -msgstr "" +msgstr "谢谢" #: wm_extra/templates/wm_extra/endpoint_added.html:16 msgid "for suggesting the endpoint" -msgstr "" +msgstr "对于建议端点" #: worldmap/certification/templates/certification/certification_add.html:13 msgid "Are you sure you want to certify" -msgstr "" +msgstr "你确定你想要认证" #: worldmap/certification/templates/certification/certification_add.html:16 msgid "Yes, certify" -msgstr "" +msgstr "是的,认证" #: worldmap/certification/templates/certification/certification_add.html:19 #: worldmap/certification/templates/certification/certification_remove.html:22 msgid "No, cancel" -msgstr "" +msgstr "不了,取消" #: worldmap/certification/templates/certification/certification_add.html:30 msgid "Certify" -msgstr "" +msgstr "认证" #: worldmap/certification/templates/certification/certification_remove.html:16 msgid "Are you sure you want to uncertify" -msgstr "" +msgstr "你确定你不想要认证" #: worldmap/certification/templates/certification/certification_remove.html:19 msgid "Yes, uncertify" -msgstr "" +msgstr "是的,不认证" #: worldmap/certification/templates/certification/certification_remove.html:33 msgid "Uncertify" -msgstr "" +msgstr "不认证" #: worldmap/templates/base.html:53 worldmap/templates/site_index.html:54 msgid "Create Map" -msgstr "" +msgstr "创建地图" #: worldmap/templates/base.html:54 worldmap/templates/maps/map_detail.html:163 #: worldmap/templates/site_index.html:55 msgid "View Map" -msgstr "" +msgstr "查看地图" #: worldmap/templates/base.html:58 msgid "Profile" -msgstr "" +msgstr "个人简介" #: worldmap/templates/base.html:59 msgid "Recent Activity" -msgstr "" +msgstr "最近活动" #: worldmap/templates/base.html:60 msgid "Inbox" -msgstr "" +msgstr "收件箱" #: worldmap/templates/base.html:65 msgid "Help" -msgstr "" +msgstr "帮助" #: worldmap/templates/base.html:71 worldmap/templates/base.html.py:146 #: worldmap/templates/base.html:167 msgid "Sign in" -msgstr "" +msgstr "登录" #: worldmap/templates/base.html:111 msgid "Need Help?" -msgstr "" +msgstr "需要帮助?" #: worldmap/templates/base.html:112 msgid "Contact Us" -msgstr "" +msgstr "联系我们" #: worldmap/templates/base.html:113 msgid "Source Code" -msgstr "" +msgstr "源代码" #: worldmap/templates/base.html:114 msgid "Report Copyright Infringement" -msgstr "" +msgstr "报告侵权" #: worldmap/templates/base.html:115 msgid "Copyright 2017 © The President and Fellows of Harvard College" -msgstr "" +msgstr "版权 2017 © 哈佛大学的主席和他的同事" #: worldmap/templates/base.html:118 msgid "Language" -msgstr "" +msgstr "语言" #: worldmap/templates/base.html:151 msgid "Register" -msgstr "" +msgstr "注册" #: worldmap/templates/base.html:163 msgid "Remember Me" -msgstr "" +msgstr "记住我" #: worldmap/templates/base.html:204 msgid "Type your search here ..." -msgstr "" +msgstr "在这输入关键词......" +#: worldmap/templates/base.html:140 +msgid "Worldmap Help" +msgstr "Worldmap帮助文档" + +#: worldmap/templates/base.html:142 +msgid "GeoNode Help" +msgstr "GeoNode简介" #: worldmap/templates/base/_resourcebase_snippet.html:44 #: worldmap/templates/layers/layer_detail.html:453 msgid "Create a Map" -msgstr "" +msgstr "创建地图" #: worldmap/templates/createlayer/layer_create.html:7 #: worldmap/templates/site_index.html:58 msgid "Create Layer" -msgstr "" +msgstr "创建图层" #: worldmap/templates/createlayer/layer_create.html:20 msgid "Create an empty layer" -msgstr "" +msgstr "创建空的图层" #: worldmap/templates/createlayer/layer_create.html:38 msgid "Add Attribute" -msgstr "" +msgstr "添加属性" #: worldmap/templates/createlayer/layer_create.html:45 msgid "Create" -msgstr "" +msgstr "创建" #: worldmap/templates/createlayer/layer_create.html:54 #: worldmap/templates/layers/layer_detail.html:511 #: worldmap/templates/maps/map_detail.html:202 #: worldmap/templates/upload/layer_upload.html:118 msgid "Permissions" -msgstr "" +msgstr "许可" #: worldmap/templates/fullscreen.html:5 msgid "WorldMap" -msgstr "" +msgstr "世界地图" #: worldmap/templates/layers/layer_detail.html:67 msgid "Filter Granules" -msgstr "" +msgstr "过滤颗粒" #: worldmap/templates/layers/layer_detail.html:70 msgid "Active Filter:" -msgstr "" +msgstr "激活过滤器" #: worldmap/templates/layers/layer_detail.html:76 msgid "Granule ID" -msgstr "" +msgstr "颗粒ID" #: worldmap/templates/layers/layer_detail.html:77 msgid "Bounding Box" -msgstr "" +msgstr "包围盒" #: worldmap/templates/layers/layer_detail.html:78 msgid "Time" -msgstr "" +msgstr "时间" #: worldmap/templates/layers/layer_detail.html:79 msgid "Elevation" -msgstr "" +msgstr "高程" #: worldmap/templates/layers/layer_detail.html:80 msgid "Actions" -msgstr "" +msgstr "操作" #: worldmap/templates/layers/layer_detail.html:142 msgid "Dimension" -msgstr "" +msgstr "维度" #: worldmap/templates/layers/layer_detail.html:143 msgid "Enabled" -msgstr "" +msgstr "可用的" #: worldmap/templates/layers/layer_detail.html:144 msgid "Regex" -msgstr "" +msgstr "正则表达式" #: worldmap/templates/layers/layer_detail.html:149 msgid "TIME" -msgstr "" +msgstr "时间" #: worldmap/templates/layers/layer_detail.html:150 #: worldmap/templates/layers/layer_detail.html:155 msgid "True" -msgstr "" +msgstr "正确" #: worldmap/templates/layers/layer_detail.html:150 #: worldmap/templates/layers/layer_detail.html:155 msgid "False" -msgstr "" +msgstr "错误" #: worldmap/templates/layers/layer_detail.html:154 msgid "ELEVATION" -msgstr "" +msgstr "高程" #: worldmap/templates/layers/layer_detail.html:165 msgid "Attribute Name" -msgstr "" +msgstr "属性名" #: worldmap/templates/layers/layer_detail.html:166 #: worldmap/templates/layers/layer_metadata_advanced.html:105 msgid "Label" -msgstr "" +msgstr "标签" #: worldmap/templates/layers/layer_detail.html:167 #: worldmap/templates/layers/layer_metadata_advanced.html:106 #: worldmap/templates/people/profile_detail.html:107 msgid "Description" -msgstr "" +msgstr "描述" #: worldmap/templates/layers/layer_detail.html:169 msgid "Range" -msgstr "" +msgstr "范围" #: worldmap/templates/layers/layer_detail.html:170 msgid "Average" -msgstr "" +msgstr "平均值" #: worldmap/templates/layers/layer_detail.html:171 msgid "Median" -msgstr "" +msgstr "中位数" #: worldmap/templates/layers/layer_detail.html:172 msgid "Standard Deviation" -msgstr "" +msgstr "标准偏差" #: worldmap/templates/layers/layer_detail.html:233 msgid "Rate this layer" -msgstr "" +msgstr "给该图层评分" #: worldmap/templates/layers/layer_detail.html:237 #: worldmap/templates/maps/map_detail.html:74 msgid "Average Rating" -msgstr "" +msgstr "平均分" #: worldmap/templates/layers/layer_detail.html:254 #: worldmap/templates/layers/layer_detail.html:267 msgid "Download Layer" -msgstr "" +msgstr "下载图层" #: worldmap/templates/layers/layer_detail.html:257 msgid "Request Download" -msgstr "" +msgstr "请求下载" #: worldmap/templates/layers/layer_detail.html:306 #: worldmap/templates/layers/layer_detail.html:370 @@ -383,177 +405,181 @@ msgstr "" #: worldmap/templates/maps/map_detail.html:112 #: worldmap/templates/maps/map_detail.html:156 msgid "Close" -msgstr "" +msgstr "关闭" #: worldmap/templates/layers/layer_detail.html:318 #: worldmap/templates/maps/map_detail.html:94 msgid "Metadata Detail" -msgstr "" +msgstr "元数据详细信息" #: worldmap/templates/layers/layer_detail.html:324 #: worldmap/templates/layers/layer_detail.html:331 msgid "Edit Layer" -msgstr "" +msgstr "编辑图层" #: worldmap/templates/layers/layer_detail.html:338 #: worldmap/templates/maps/map_detail.html:133 msgid "Metadata" -msgstr "" +msgstr "元数据" #: worldmap/templates/layers/layer_detail.html:339 #: worldmap/templates/maps/map_detail.html:134 msgid "Wizard" -msgstr "" +msgstr "向导" #: worldmap/templates/layers/layer_detail.html:340 #: worldmap/templates/maps/map_detail.html:135 msgid "Advanced Edit" -msgstr "" +msgstr "高级编辑" #: worldmap/templates/layers/layer_detail.html:341 msgid "Upload Metadata" -msgstr "" +msgstr "上传元数据" #: worldmap/templates/layers/layer_detail.html:348 #: worldmap/templates/maps/map_detail.html:141 msgid "Thumbnail" -msgstr "" +msgstr "缩略图" #: worldmap/templates/layers/layer_detail.html:349 #: worldmap/templates/maps/map_detail.html:142 msgid "Set" -msgstr "" +msgstr "设置" #: worldmap/templates/layers/layer_detail.html:355 msgid "Layer" -msgstr "" +msgstr "图层" #: worldmap/templates/layers/layer_detail.html:357 msgid "Replace" -msgstr "" +msgstr "替换" #: worldmap/templates/layers/layer_detail.html:360 msgid "Edit data" -msgstr "" +msgstr "编辑数据" #: worldmap/templates/layers/layer_detail.html:363 #: worldmap/templates/maps/map_detail.html:150 msgid "Remove" -msgstr "" +msgstr "移除" #: worldmap/templates/layers/layer_detail.html:378 #: worldmap/templates/layers/layer_detail.html:386 msgid "Download Metadata" -msgstr "" +msgstr "下载元数据" #: worldmap/templates/layers/layer_detail.html:424 msgid "Legend" -msgstr "" +msgstr "比例尺" #: worldmap/templates/layers/layer_detail.html:438 msgid "Maps using this layer" -msgstr "" +msgstr "使用该图层的地图" #: worldmap/templates/layers/layer_detail.html:440 msgid "List of maps using this layer:" -msgstr "" +msgstr "使用该图层的地图列表:" #: worldmap/templates/layers/layer_detail.html:446 msgid "This layer is not currently used in any maps." -msgstr "" +msgstr "该图层现在未被任何地图使用。" #: worldmap/templates/layers/layer_detail.html:451 msgid "Create a map using this layer" -msgstr "" +msgstr "创建使用该图层的地图" #: worldmap/templates/layers/layer_detail.html:452 msgid "Click the button below to generate a new map based on this layer." -msgstr "" +msgstr "点击下方按钮生成一个基于该图层的新地图。" #: worldmap/templates/layers/layer_detail.html:457 msgid "Add the layer to an existing map" -msgstr "" +msgstr "给已存在的地图添加图层" #: worldmap/templates/layers/layer_detail.html:465 msgid "Click the button below to add the layer to the selected map." -msgstr "" +msgstr "点击下方按钮添加图层到选中地图。" #: worldmap/templates/layers/layer_detail.html:467 msgid "Add to Map" -msgstr "" +msgstr "添加到地图" #: worldmap/templates/layers/layer_detail.html:474 msgid "Documents related to this layer" -msgstr "" +msgstr "关于该图层的文档" #: worldmap/templates/layers/layer_detail.html:475 msgid "List of documents related to this layer:" -msgstr "" +msgstr "关于该图层的文档列表:" #: worldmap/templates/layers/layer_detail.html:488 msgid "Styles" -msgstr "" +msgstr "样式" #: worldmap/templates/layers/layer_detail.html:489 msgid "" "The following styles are associated with this layer. Choose a style to view " "it in the preview map." msgstr "" - +"下列样式与该图层有关。选择一种样式在预览地图中浏览。" #: worldmap/templates/layers/layer_detail.html:502 msgid "No styles associated with this layer" -msgstr "" +msgstr "没有该图层相关的样式" + +#: worldmap/templates/layers/layer_detail.html:505 +msgid "(default style)" +msgstr "(默认样式)" #: worldmap/templates/layers/layer_detail.html:512 msgid "Click the button below to change the permissions of this layer." -msgstr "" +msgstr "点击下方按钮改变该图层的许可" #: worldmap/templates/layers/layer_detail.html:513 msgid "Change Layer Permissions" -msgstr "" +msgstr "改变图层许可" #: worldmap/templates/layers/layer_detail.html:522 #: worldmap/templates/maps/map_detail.html:232 msgid "Certifications" -msgstr "" +msgstr "认证" #: worldmap/templates/layers/layer_detail.html:529 msgid "This layer has not been certified by any users." -msgstr "" +msgstr "该图层还未被任何用户认证" #: worldmap/templates/layers/layer_detail.html:537 msgid "Uncertify this layer." -msgstr "" +msgstr "该图层未认证" #: worldmap/templates/layers/layer_detail.html:541 msgid "Certify this layer." -msgstr "" +msgstr "认证该图层" #: worldmap/templates/layers/layer_detail.html:551 msgid "External service layer" -msgstr "" +msgstr "该图层的外部服务" #: worldmap/templates/layers/layer_detail.html:552 msgid "Source" -msgstr "" +msgstr "来源" #: worldmap/templates/layers/layer_detail.html:553 msgid "Type" -msgstr "" +msgstr "类型" #: worldmap/templates/layers/layer_list.html:6 #: worldmap/templates/layers/layer_list.html:13 msgid "Explore Layers" -msgstr "" +msgstr "浏览图层" #: worldmap/templates/layers/layer_list.html:12 #: worldmap/templates/upload/layer_upload.html:17 msgid "Upload Layers" -msgstr "" +msgstr "上传图层" #: worldmap/templates/layers/layer_metadata_advanced.html:16 msgid "Edit Metadata" -msgstr "" +msgstr "编辑元数据" #: worldmap/templates/layers/layer_metadata_advanced.html:21 #, python-format @@ -562,6 +588,9 @@ msgid "" " Editing details for %(layer_title)s\n" " " msgstr "" +"\n" +" 为%(layer_title)s编辑详细信息\n" +" " #: worldmap/templates/layers/layer_metadata_advanced.html:27 msgid "" @@ -569,6 +598,8 @@ msgid "" "a metadata XML file.\n" " This metadata cannot be edited." msgstr "" +"注意:该图层的原始元数据通过导入一个元数据XML文件来保存的。\n" +" 该元数据不可被编辑。" #: worldmap/templates/layers/layer_metadata_advanced.html:30 msgid "" @@ -578,165 +609,168 @@ msgid "" "Dublin Core metadata elements.\n" " Some of your original metadata may have been lost." msgstr "" +"注:此图的原单的元数据被填充通过导入元数据的XML文件。" +" GeoNode的元数据导入支持ISO,FGDC和都柏林核心元数据元素的一个子集。" +" 一些你原来的元数据可能已经丢失。" #: worldmap/templates/layers/layer_metadata_advanced.html:36 msgid "Error updating metadata. Please check the following fields: " -msgstr "" +msgstr "更新元数据时发生错误。请检查下列区域:" #: worldmap/templates/layers/layer_metadata_advanced.html:39 msgid "Metadata Author" -msgstr "" +msgstr "元数据作者" #: worldmap/templates/layers/layer_metadata_advanced.html:43 #: worldmap/templates/layers/layer_metadata_advanced.html:122 msgid "Point of Contact" -msgstr "" +msgstr "联系点" #: worldmap/templates/layers/layer_metadata_advanced.html:52 #: worldmap/templates/layers/layer_metadata_advanced.html:100 msgid "Attributes" -msgstr "" +msgstr "属性" #: worldmap/templates/layers/layer_metadata_advanced.html:67 #: worldmap/templates/layers/layer_metadata_advanced.html:134 msgid "Update" -msgstr "" +msgstr "更新" #: worldmap/templates/layers/layer_metadata_advanced.html:77 msgid "Category" -msgstr "" +msgstr "分类" #: worldmap/templates/layers/layer_metadata_advanced.html:104 msgid "Attribute" -msgstr "" +msgstr "属性" #: worldmap/templates/layers/layer_metadata_advanced.html:107 msgid "Display Order" -msgstr "" +msgstr "显示顺序" #: worldmap/templates/layers/layer_metadata_advanced.html:127 msgid "Metadata Provider" -msgstr "" +msgstr "元数据提供者" #: worldmap/templates/maps/map_detail.html:70 msgid "Rate this Map" -msgstr "" +msgstr "给该地图评分" #: worldmap/templates/maps/map_detail.html:88 #: worldmap/templates/maps/map_detail.html:103 msgid "Download Map" -msgstr "" +msgstr "下载地图" #: worldmap/templates/maps/map_detail.html:107 msgid "Download Data Layers" -msgstr "" +msgstr "下载数据图层" #: worldmap/templates/maps/map_detail.html:108 msgid "Download Web Map Context" -msgstr "" +msgstr "下载网络地图环境" #: worldmap/templates/maps/map_detail.html:119 #: worldmap/templates/maps/map_detail.html:126 msgid "Edit Map" -msgstr "" +msgstr "编辑地图" #: worldmap/templates/maps/map_detail.html:148 #: worldmap/templates/maps/map_view.html:6 msgid "Map" -msgstr "" +msgstr "地图" #: worldmap/templates/maps/map_detail.html:149 msgid "Edit" -msgstr "" +msgstr "编辑" #: worldmap/templates/maps/map_detail.html:173 msgid "Map Layers" -msgstr "" +msgstr "地图图层" #: worldmap/templates/maps/map_detail.html:174 msgid "This map uses the following layers:" -msgstr "" +msgstr "该地图使用了下列图层:" #: worldmap/templates/maps/map_detail.html:190 msgid "Documents related to this map" -msgstr "" +msgstr "该地图有关的文档" #: worldmap/templates/maps/map_detail.html:191 msgid "List of documents related to this map:" -msgstr "" +msgstr "该地图有关的文档表" #: worldmap/templates/maps/map_detail.html:203 msgid "Specify which users can view or modify this map" -msgstr "" +msgstr "指定哪个用户可以查看或者修改该地图" #: worldmap/templates/maps/map_detail.html:204 msgid "Change Permissions of this Map" -msgstr "" +msgstr "更改该地图的许可" #: worldmap/templates/maps/map_detail.html:210 msgid "Copy this map" -msgstr "" +msgstr "复制该地图" #: worldmap/templates/maps/map_detail.html:211 msgid "Duplicate this map and modify it for your own purposes" -msgstr "" +msgstr "复制该地图,按照你的意愿修改它" #: worldmap/templates/maps/map_detail.html:212 #: worldmap/templates/maps/map_list.html:16 msgid "Create a New Map" -msgstr "" +msgstr "创建新地图" #: worldmap/templates/maps/map_detail.html:217 msgid "Map WMS" -msgstr "" +msgstr "地图WMS" #: worldmap/templates/maps/map_detail.html:219 msgid "WMS layer group for local map layers" -msgstr "" +msgstr "给本地地图图层的WMS图层组" #: worldmap/templates/maps/map_detail.html:220 msgid "on" -msgstr "" +msgstr "在" #: worldmap/templates/maps/map_detail.html:220 msgid "local OWS" -msgstr "" +msgstr "本地OWS" #: worldmap/templates/maps/map_detail.html:223 msgid "Publish local map layers as WMS layer group" -msgstr "" +msgstr "以WMS图层组形式发布本地地图图层" #: worldmap/templates/maps/map_detail.html:224 msgid "Publish Map WMS" -msgstr "" +msgstr "发布地图WMS" #: worldmap/templates/maps/map_detail.html:239 msgid "This map has not been certified by any users" -msgstr "" +msgstr "该地图还未被任何用户认证" #: worldmap/templates/maps/map_detail.html:247 msgid "Uncertify this map" -msgstr "" +msgstr "该地图未认证" #: worldmap/templates/maps/map_detail.html:251 msgid "Certify this map" -msgstr "" +msgstr "认证该地图" #: worldmap/templates/maps/map_list.html:13 msgid "Search for maps" -msgstr "" +msgstr "搜索地图" #: worldmap/templates/maps/map_list.html:22 msgid "Search by text" -msgstr "" +msgstr "通过文本搜索" #: worldmap/templates/maps/map_new.html:6 msgid "New Map" -msgstr "" +msgstr "新地图" #: worldmap/templates/people/profile_detail.html:12 msgid "Profile of " -msgstr "" +msgstr "简介-" #: worldmap/templates/people/profile_detail.html:77 #: worldmap/templates/people/profile_detail.html:83 @@ -745,266 +779,414 @@ msgstr "" #: worldmap/templates/people/profile_detail.html:104 #: worldmap/templates/people/profile_detail.html:108 msgid "Not provided." -msgstr "" +msgstr "未提供。" #: worldmap/templates/people/profile_detail.html:82 msgid "Position" -msgstr "" +msgstr "职位" #: worldmap/templates/people/profile_detail.html:86 msgid "Organization" -msgstr "" +msgstr "组织" #: worldmap/templates/people/profile_detail.html:91 msgid "Location" -msgstr "" +msgstr "位置" #: worldmap/templates/people/profile_detail.html:95 msgid "Voice" -msgstr "" +msgstr "声音" #: worldmap/templates/people/profile_detail.html:103 msgid "Fax" -msgstr "" +msgstr "传真" #: worldmap/templates/people/profile_detail.html:112 msgid "Keywords" -msgstr "" +msgstr "关键词" #: worldmap/templates/people/profile_detail.html:119 msgid "Not provided" -msgstr "" +msgstr "未提供" #: worldmap/templates/people/profile_detail.html:129 msgid "Message User" -msgstr "" +msgstr "消息用户" #: worldmap/templates/people/profile_detail.html:133 #: worldmap/templates/people/profile_detail.html:167 msgid "Edit profile" -msgstr "" +msgstr "编辑简介" #: worldmap/templates/people/profile_detail.html:134 msgid "Change password" -msgstr "" +msgstr "更改密码" #: worldmap/templates/people/profile_detail.html:137 msgid "Upload new layers" -msgstr "" +msgstr "上传新图层" #: worldmap/templates/people/profile_detail.html:139 msgid "Create a new layer" -msgstr "" +msgstr "创建新图层" #: worldmap/templates/people/profile_detail.html:141 msgid "Create a new map" -msgstr "" +msgstr "创建新地图" #: worldmap/templates/people/profile_detail.html:142 msgid "My Activities" -msgstr "" +msgstr "我的活动" #: worldmap/templates/people/profile_detail.html:146 msgid "Notifications" -msgstr "" +msgstr "通知" #: worldmap/templates/people/profile_detail.html:149 msgid "Announcements" -msgstr "" +msgstr "公告" #: worldmap/templates/people/profile_detail.html:154 msgid "Remote Services" -msgstr "" +msgstr "遥感服务" #: worldmap/templates/people/profile_detail.html:155 msgid "GeoServer" -msgstr "" +msgstr "GeoServer" +#: worldmap/templates/base.html:73 #: worldmap/templates/people/profile_detail.html:158 msgid "Admin" -msgstr "" +msgstr "管理员" #: worldmap/templates/people/profile_detail.html:171 msgid "User Activities" -msgstr "" +msgstr "用户活动" #: worldmap/templates/people/profile_detail.html:184 msgid "Resources" -msgstr "" +msgstr "资源" #: worldmap/templates/people/profile_detail.html:200 msgid "Certified Resources" -msgstr "" +msgstr "认证资源" #: worldmap/templates/site_index.html:56 msgid "My Layers" -msgstr "" +msgstr "我的图层" #: worldmap/templates/site_index.html:57 #: worldmap/templates/upload/layer_upload.html:5 msgid "Upload Layer" -msgstr "" +msgstr "上传图层" #: worldmap/templates/site_index.html:59 msgid "About" -msgstr "" +msgstr "关于" #: worldmap/templates/site_index.html:68 msgid "" "Build your own mapping portal and publish it to the world or to just a few " "collaborators. WorldMap is open source software." msgstr "" +"搭建你自己的制图门户网站,发布给世界或者一些合作者。WorldMap是一个开源软件。" #: worldmap/templates/site_index.html:70 msgid "WorldMap is being developed by the " -msgstr "" +msgstr "开发WorldMap的是" #: worldmap/templates/site_index.html:70 -msgid "Center for Geographic Analysis" -msgstr "" +msgid "Center for Geographic Analysis at Zhejiang University" +msgstr "哈佛大学地理分析中心" + +#: worldmap/templates/site_index.html:70 +msgid "Bigdata and Chinese AMAP Innovation Team of Zhejiang University" +msgstr "浙江大学大数据与中国学术地图创新团队" #: worldmap/templates/site_index.html:70 msgid "at" -msgstr "" +msgstr "在" #: worldmap/templates/upload/layer_upload.html:39 msgid "Incomplete Uploads" -msgstr "" +msgstr "不完整的上传" #: worldmap/templates/upload/layer_upload.html:40 msgid "You have the following incomplete uploads" -msgstr "" +msgstr "你有下列不完整的上传文件" #: worldmap/templates/upload/layer_upload.html:43 msgid "last updated on" -msgstr "" +msgstr "上一次更新在" #: worldmap/templates/upload/layer_upload.html:45 msgid "Resume" -msgstr "" +msgstr "重新开始" #: worldmap/templates/upload/layer_upload.html:46 #: worldmap/templates/upload/layer_upload.html:53 msgid "Delete" -msgstr "" +msgstr "删除" #: worldmap/templates/upload/layer_upload.html:52 msgid "Are you sure you want to delete this upload?" -msgstr "" +msgstr "你确定你想要删除这次上传?" #: worldmap/templates/upload/layer_upload.html:54 msgid "Cancel" -msgstr "" +msgstr "取消" #: worldmap/templates/upload/layer_upload.html:55 msgid "Delete, and don't ask me again." -msgstr "" +msgstr "删除,并不再提醒。" #: worldmap/templates/upload/layer_upload.html:72 msgid "Drop files here" -msgstr "" +msgstr "把文件拖至此处" #: worldmap/templates/upload/layer_upload.html:75 msgid " or select them one by one:" -msgstr "" +msgstr "或者逐一选中它们:" + +#: worldmap/templates/upload/layer_upload.html:80 +msgid "Choose Files" +msgstr "选择文件" #: worldmap/templates/upload/layer_upload.html:85 msgid "Files to be uploaded" -msgstr "" +msgstr "将被上传的文件" #: worldmap/templates/upload/layer_upload.html:93 msgid "Select the charset or leave default" -msgstr "" +msgstr "选中字符集或者保持默认" #: worldmap/templates/upload/layer_upload.html:111 msgid "Clear" -msgstr "" +msgstr "清空" #: worldmap/templates/upload/layer_upload.html:112 msgid "Upload files" -msgstr "" +msgstr "上传文件" #: worldmap/templates/worldmap_client/worldmap.html:53 msgid "Identify" -msgstr "" +msgstr "识别" #: worldmap/templates/worldmap_client/worldmap.html:62 msgid "Map Coordinates - longitude, latitude" -msgstr "" +msgstr "地图坐标-经度,纬度" #: worldmap/templates/worldmap_client/worldmap.html:69 msgid "Print" -msgstr "" +msgstr "打印" #: worldmap/templates/worldmap_client/worldmap.html:81 msgid "Google Earth" -msgstr "" +msgstr "谷歌地球" #: worldmap/templates/worldmap_client/worldmap.html:93 msgid "Measure" -msgstr "" +msgstr "测量" #: worldmap/templates/worldmap_client/worldmap.html:100 msgid "Share Map" -msgstr "" +msgstr "分享地图" #: worldmap/templates/worldmap_client/worldmap.html:107 msgid "Find Place" -msgstr "" +msgstr "找到地点" #: worldmap/templates/worldmap_client/worldmap.html:134 msgid "Create Feature" -msgstr "" +msgstr "创建要素" #: worldmap/templates/worldmap_client/worldmap.html:135 msgid "Edit Feature" -msgstr "" +msgstr "编辑要素" #: worldmap/templates/worldmap_client/worldmap.html:220 msgid "Upload a Layer" -msgstr "" +msgstr "上传图层" #: worldmap/templates/worldmap_client/worldmap.html:222 msgid "Click here to upload a layer." -msgstr "" +msgstr "点击这里上传图层" #: worldmap/templates/worldmap_client/worldmap.html:223 #: worldmap/templates/worldmap_client/worldmap.html:235 msgid "Remember to save the map before." -msgstr "" +msgstr "记得先进行地图保存" #: worldmap/templates/worldmap_client/worldmap.html:232 msgid "Create a new Layer" -msgstr "" +msgstr "创建新图层" #: worldmap/templates/worldmap_client/worldmap.html:234 msgid "Click here to create a new layer." -msgstr "" +msgstr "点击这里创建新图层。" #: worldmap/templates/worldmap_client/worldmap.html:247 msgid "Rectify Images" -msgstr "" +msgstr "校正影像" #: worldmap/templates/worldmap_client/worldmap.html:248 msgid "" "Use WorldMap " "WARP to upload and rectify scanned maps for use in WorldMap." msgstr "" +"使用 WorldMap " +"WARP 上传并校正扫描地图,以便于在WorldMap中使用。" #: worldmap/templates/worldmap_client/worldmap.html:248 msgid "" -"Maps rectified using this tool can be brought into WorldMap by following the " -"instructions under Section 4.5 in WorldMap Help." +"Maps rectified using this tool can be brought into WorldMap by following the instructions under Section 4.7 in WorldMap Help." msgstr "" +"使用该工具进行校正的地图可以导入WorldMap中,具体流程请查看 WorldMap帮助文档中的4.7章节。" #: worldmap/templates/worldmap_client/worldmap.html:261 #: worldmap/templates/worldmap_client/worldmap.html:277 msgid "Submit a Map Service URL" -msgstr "" +msgstr "提交地图服务地址" #: worldmap/templates/worldmap_client/worldmap.html:264 #: worldmap/templates/worldmap_client/worldmap.html:280 msgid "" "Submit a Map Service URL" msgstr "" +"提交地图服务地址" + +#: worldmap/templates/site_index.html:hottest +msgid "Hottest Maps" +msgstr "最热地图" + +#: worldmap/templates/site_index.html:latest +msgid "Latest Maps" +msgstr "最新地图" + +#: worldmap/templates/site_index.html:categories +msgid "All the categories" +msgstr "所有学科" +msgid "Geoscientific Information" +msgstr "地学信息" +msgid "Farming" +msgstr "农学" +#msgid "Elevation" +#msgstr "高程" +msgid "Utilities Communication" +msgstr "公用通信" +msgid "Oceans" +msgstr "海洋" +msgid "Boundaries" +msgstr "边界" +msgid "Inland Waters" +msgstr "内陆水域" +msgid "Intelligence Military" +msgstr "军事情报" +msgid "Environment" +msgstr "环境" +#msgid "Location" +#msgstr "位置" +msgid "Economy" +msgstr "经济" +msgid "Planning Cadastre" +msgstr "规划地籍" +msgid "Biota" +msgstr "生物群" +msgid "Health" +msgstr "健康" +msgid "Imagery Base Maps Earth Cover" +msgstr "植被影像基础地图" +msgid "Transportation" +msgstr "交通" +msgid "Society" +msgstr "社会科学" +msgid "Structure" +msgstr "建筑物" +msgid "Climatology Meteorology Atmosphere" +msgstr "气候气象" +msgid "Humanity History" +msgstr "人文历史" + +#: worldmap/templates/base.html:155 +msgid "Don't have an account yet?" +msgstr "未创建账户?" +#: worldmap/templates/base.html:61 +msgid "Academic Map Publishing Platform" +msgstr "学术地图发布平台" + +#: worldmap/templates/base.html:133 +msgid "Zhejiang University" +msgstr "浙江大学" +msgid "CGA Harvard" +msgstr "哈佛大学CGA" +msgid "Copyright Notice" +msgstr "版权声明" +msgid "All rights reserved" +msgstr "版权所有" +msgid "Choose Language" +msgstr "语言选择" + +#: worldmap/templates/site_index.html:88 +msgid "About Us" +msgstr "关于我们" +msgid "About GeoNode" +msgstr "关于GeoNode" + +#: worldmap/templates/aboutus.html:23 +msgid "Disclaimer" +msgstr "免责声明" + +#: worldmap/templates/aboutus.html:23 +msgid "A large amount of geographical information which is closely related to human activities exists in the brilliant human civilization, numerous documents since ancient times, as well as the vast land and ocean. For example, the geographical distribution of individuals, the traces and the social relations for a single person, the migration of a group, as well as the existence, distribution and change of a region and trajectory for non-living things; as for a place, it also contains the people, events, things and other geographical information in previous time." +msgstr "灿烂辉煌的人类文明、浩如烟海的古今文献以及广袤无垠的陆地海洋,存在着海量的与人类活动息息相关的地理信息。就单个人物来说,包括人物的籍贯、行迹、社会关系的地理分布;就群体来说,包括一个群体的地理分布和迁徙轨迹;就非生命的物体来说,也有其存在、分布和变化的地理区域;就一个地方来说,则又包含了既往时间里人、事、物等地理信息的总汇。" + + #: worldmap/templates/aboutus.html:23 +msgid "The Academic Map Publishing Platform, established by Zhejiang University and Harvard University together, is not only an integrated database providing multi-functional query services, but also a display platform ready for users to present their research productions about geographic information and visualize analysis and select. The big data formed by the platform, will greatly contribute to future scientific research, government decision-making and social services." +msgstr "由浙江大学与哈佛大学共建的学术地图发布平台愿为广大用户提供地理信息研究成果的发布、可视化分析及多功能查询服务,平台所形成的大数据,可以为未来科学研究、政府决策及社会服务提供重要的参考。 " + +#: worldmap/templates/aboutus.html:23 +msgid "The big data and Chinese academic map innovation team of Zhejiang University" +msgstr "浙江大学大数据与中国学术地图创新团队" + +#: worldmap/templates/aboutus.html:23 +msgid "The Center for Geographic Analysis of Harvard University" +msgstr "哈佛大学地理分析中心" + +#: worldmap/templates/aboutus.html:23 +msgid "Dec 18, 2017" +msgstr "2017年12月18日" + +#: worldmap/templates/aboutus.html:23 +msgid "The copyright of the Academic Map Publishing Platform belongs to both the big data and Chinese academic map innovation team of Zhejiang University and the Center for Geographic Analysis of Harvard University. All copyrights of data and maps uploaded by users are held by their respective owners and the Platform." +msgstr "“学术地图发布平台”的版权归“浙江大学大数据与中国学术地图创新团队”和“哈佛大学地理分析中心”共同所有。学者上传的地理信息数据与呈现的地图,版权归发布者和平台方共同所有。" + +#: worldmap/templates/aboutus.html:23 +msgid "The data and information (including texts, pictures, audio and video files) must comply with national laws, regulations and academic norms. The legal liability caused by the content should be undertaken by the author, and this site has no joint liability." +msgstr "发布者发布的数据和信息(包括文字、图片、影音文件),必须符合国家的法律法规和学术规范,若因发布的内容而引起的法律责任,由发布者自负。" + +#: worldmap/templates/aboutus.html:23 +msgid "The authors have to back up files by themselves. This site does not assume responsibility for data loss due to hacker attacks, viruses or any other reasons. " +msgstr "发布者发布的数据和信息,务必自己备份,本网站不承担因黑客攻击或病毒侵入造成的发布者数据损失的责任。" + +#: worldmap/templates/aboutus.html:23 +msgid "This site and its employees are not required to take responsibility for any errors, inaccuracies or faults during information transmission or delivery in any way. " +msgstr "本网站及其雇员一概毋须以任何方式就任何信息传递或传送的失误、不准确或错误对用户或任何其他人士负任何直接或间接的责任。" + +#: worldmap/templates/aboutus.html:23 +msgid "If the information provided on this site that is used by any person or distributed to any person in any jurisdiction violates the laws or regulations of that jurisdiction, or makes this website or its third-party agents subject to any regulatory requirement in that jurisdiction, such information should not be used or distributed to any person in such jurisdiction. Users have to make sure that their materials will not be subject to any local restrictions that restrict or prohibit users from using or distributing such kind of information provided on this site." +msgstr "本网站所提供的信息,若在任何司法管辖地区供任何人士使用或分发给任何人士时会违反该司法管辖地区的法律或条例的规定或会导致本网站或其第三方代理人受限于该司法管辖地区内的任何监管规定时,则该等信息不宜在该司法管辖地区供该等任何人士使用或分发给该等任何人士。用户须自行保证不会受限于任何限制或禁止用户使用或分发本网站所提供信息的当地的规定。" + +#: worldmap/templates/aboutus.html:23 +msgid "Because this site is open to any registered user to upload pictures or text, and the site cannot identify the copyright of the uploaded pictures or text. Please inform us immediately once you find any possible infringement of yours, and we will delete it promptly." +msgstr "本网站图片,文字之类版权申明,因为网站可以由注册用户自行上传图片或文字,本网站无法鉴别所上传图片或文字的知识版权,如果侵犯,请及时通知我们,本网站将在第一时间及时删除。" + +#: worldmap/templates/aboutus.html:23 +msgid "We accept no liability for any loss or damage arising by force majeure that influences the normal operation of this website, such as hacker attacks, computer virus invasion or attack, the temporary closure caused by government regulation and so on. If other websites linked to this site cause the disclosure of personal information and relevant legal disputes or consequences, this site needn't undertake responsibility for this situation." +msgstr "任何由于黑客攻击、计算机病毒侵入或发作、因政府管制而造成的暂时性关闭等影响网络正常经营的不可抗力而造成的损失,本网站均得免责(不可抗力因素不需要网站负责)。因和本网站链接的其它网站所造成的个人资料泄露及由此而导致的任何法律争议和后果,本网站均得免责。" + +#: worldmap/templates/aboutus.html:23 +msgid "We regard that those who get access to this site or use the data of this site in any way have accepted the constraints of this disclaimer voluntarily." +msgstr "凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。" + + + diff --git a/worldmap/settings.py b/worldmap/settings.py index 2d451d0..75cc438 100644 --- a/worldmap/settings.py +++ b/worldmap/settings.py @@ -79,7 +79,7 @@ def str2bool(v): # This is needed for integration tests, they require # geonode to be listening for GeoServer auth requests. -os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = 'localhost:8000' +os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = 'amap.zju.edu.cn:8000' ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost').split(',') @@ -129,14 +129,14 @@ def str2bool(v): MANAGERS = ADMINS = os.getenv('ADMINS', []) USE_CUSTOM_ORG_AUTHORIZATION = True -CUSTOM_ORG_AUTH_TEXT = 'Are you affiliated with Harvard University?' +#CUSTOM_ORG_AUTH_TEXT = 'Are you affiliated with Harvard University?' # Local time zone for this installation. Choices can be found here: # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # although not all choices may be available on all operating systems. # If running in a Windows environment this must be set to the same as your # system time zone. -TIME_ZONE = os.getenv('TIME_ZONE', "America/Chicago") +TIME_ZONE = os.getenv('TIME_ZONE', "Asia/Shanghai") SITE_ID = int(os.getenv('SITE_ID', '1')) @@ -145,7 +145,7 @@ def str2bool(v): # Language code for this installation. All choices can be found here: # http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = os.getenv('LANGUAGE_CODE', "en-us") +LANGUAGE_CODE = os.getenv('LANGUAGE_CODE', "zh-cn") # Underscore at the beginning added to represent a private variable. # should not be used in the application. _DEFAULT_LANGUAGES = ( @@ -212,9 +212,9 @@ def str2bool(v): AUTH_USER_MODEL = os.getenv('AUTH_USER_MODEL', 'people.Profile') -MODELTRANSLATION_LANGUAGES = ['en', ] -MODELTRANSLATION_DEFAULT_LANGUAGE = 'en' -MODELTRANSLATION_FALLBACK_LANGUAGES = ('en',) +MODELTRANSLATION_LANGUAGES = ['zh-cn',] +MODELTRANSLATION_DEFAULT_LANGUAGE = 'zh-cn' +MODELTRANSLATION_FALLBACK_LANGUAGES = ('zh-cn',) # Absolute path to the directory that holds media. @@ -285,7 +285,6 @@ def str2bool(v): WORLDMAP_APPS = ( # WorldMap applications - 'worldmap', 'wm_extra', 'worldmap.certification', ) @@ -575,16 +574,16 @@ def str2bool(v): ACTSTREAM_SETTINGS = os.getenv('ACTSTREAM_SETTINGS',_DEFAULT_ACTSTREAM_SETTINGS) # Email settings -EMAIL_ENABLE = False +EMAIL_ENABLE = True if EMAIL_ENABLE: EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' - EMAIL_HOST = 'localhost' + DEFAULT_FROM_EMAIL = 'camp2018@zju.edu.cn' + EMAIL_USE_TLS = True + EMAIL_HOST = 'smtp.zju.edu.cn' + EMAIL_HOST_USER = DEFAULT_FROM_EMAIL + EMAIL_HOST_PASSWORD = 'zjuworldmap120!' EMAIL_PORT = 25 - EMAIL_HOST_USER = '' - EMAIL_HOST_PASSWORD = '' - EMAIL_USE_TLS = False - DEFAULT_FROM_EMAIL = 'GeoNode ' # Settings for Social Apps REGISTRATION_OPEN = str2bool(os.getenv('REGISTRATION_OPEN', 'False')) @@ -628,13 +627,6 @@ def str2bool(v): ] NOSE_ARGS = os.getenv('NOSE_ARGS',_DEFAULT_NOSE_ARGS) -# this is for the gazetteer -GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY',"gme-harvarduniversity1") -# this is for the basemaps -GOOGLE_MAPS_API_KEY = os.getenv('GOOGLE_MAPS_API_KEY', None) - -# GOOGLE_SECRET_KEY = None - GEONAMES_USER = '' # # GeoNode specific settings @@ -700,7 +692,7 @@ def str2bool(v): 'BACKEND_WRITE_ENABLED': True, 'WPS_ENABLED': False, 'LOG_FILE': '%s/geoserver/data/logs/geoserver.log' - % os.path.abspath(os.path.join(PROJECT_ROOT, os.pardir)), + % os.path.abspath(os.path.join(GEONODE_ROOT, os.pardir)), # Set to name of database in DATABASES dictionary to enable 'DATASTORE': 'datastore', 'PG_GEOGIG': False, @@ -733,7 +725,7 @@ def str2bool(v): # 'ENGINE': 'geonode.catalogue.backends.generic', # The FULLY QUALIFIED base url to the CSW instance for this GeoNode - 'URL': '%scatalogue/csw' % SITEURL, + 'URL': '%s/catalogue/csw' % SITEURL, # 'URL': 'http://localhost:8080/geonetwork/srv/en/csw', # 'URL': 'http://localhost:8080/deegree-csw-demo-3.0.4/services', @@ -801,9 +793,10 @@ def str2bool(v): DEFAULT_MAP_CRS = os.getenv('DEFAULT_MAP_CRS',"EPSG:900913") #GeoNode Client -GEONODE_CLIENT_LOCATION = os.getenv('GEONODE_CLIENT_LOCATION', - '/static/worldmap_client/') -#GEONODE_CLIENT_LOCATION = "http://localhost:9090/" +#GEONODE_CLIENT_LOCATION = os.getenv('GEONODE_CLIENT_LOCATION', +# '/static/worldmap_client/') +GEONODE_CLIENT_LOCATION = "http://amap.zju.edu.cn:9090/" + # Where should newly created maps be focused? DEFAULT_MAP_CENTER = (0, 0) @@ -927,38 +920,37 @@ def str2bool(v): }, { "source": { - "ptype": "gxp_googlesource" + "ptype": "gxp_tianditusource" }, "group": "background", - "name": "SATELLITE", - "visibility": False, + "name": "TIANDITUROAD", + "visibility": True, "fixed": True, }, { "source": { - "ptype": "gxp_googlesource", + "ptype": "gxp_tianditusource", }, "group": "background", - "name": "TERRAIN", - "visibility": True, + "name": "TIANDITUIMAGE", + "visibility": False, "fixed": True, }, { "source": { - "ptype": "gxp_googlesource" + "ptype": "gxp_tianditusource" }, "group": "background", - "name": "HYBRID", + "name": "TIANDITUTERRAIN", "visibility": False, "fixed": True, }, { "source": { - "ptype": "gxp_googlesource" + "ptype": "gxp_tianditusource" }, "group": "background", - "name": "ROADMAP", - "visibility": False, + "name": "TIANDITUANNOTATION", + "visibility": True, "fixed": True, - "group": "background" } ] @@ -1064,7 +1056,7 @@ def str2bool(v): ] DOWNLOAD_FORMATS_VECTOR = [ 'JPEG', 'PDF', 'PNG', 'Zipped Shapefile', 'GML 2.0', 'GML 3.1.1', 'CSV', - 'Excel', 'GeoJSON', 'KML', 'View in Google Earth', 'Tiles', + 'Excel', 'GeoJSON', 'KML', 'Tiles', ] DOWNLOAD_FORMATS_RASTER = [ 'JPEG', @@ -1075,7 +1067,6 @@ def str2bool(v): 'Gtopo30', 'ImageMosaic', 'KML', - 'View in Google Earth', 'Tiles', 'GML', 'GZIP' diff --git a/worldmap/static/css/autocomplete.css b/worldmap/static/css/autocomplete.css new file mode 100644 index 0000000..09ed6b9 --- /dev/null +++ b/worldmap/static/css/autocomplete.css @@ -0,0 +1,13 @@ +@CHARSET "UTF-8"; +.auto_hidden{ + display:none +} +.auto_onmouseover{ + background-color:#e7e2fc +} +.auto_onmouseout{ + background-color:#d7cde4 +} +.auto_show{ + display:inline +} \ No newline at end of file diff --git a/worldmap/static/css/blackstyle.css b/worldmap/static/css/blackstyle.css new file mode 100644 index 0000000..3fc056c --- /dev/null +++ b/worldmap/static/css/blackstyle.css @@ -0,0 +1,18 @@ +html, body{background-color: #000000} +footer{ + background-color: #000000; + text-align: center; + color: #EEEEEE; +} +.navbar{ + background-color: rgba(0, 0, 0, 0.7); +} +.navbar-inverse .navbar-nav>li>a { + color: #EEEEEE; +} +.navbar-inverse .navbar-nav>li>ul>li>a { + color: #000000; +} +#usermenu{ + background-color: rgba(255,255, 255, 0.7); +} \ No newline at end of file diff --git a/worldmap/static/css/footer.css b/worldmap/static/css/footer.css new file mode 100644 index 0000000..86ffece --- /dev/null +++ b/worldmap/static/css/footer.css @@ -0,0 +1,9 @@ +.footerDiv{ + width: 800px; + margin-top: 50px; + margin-bottom: 100px; +} + +.footerContent{ + text-align: left; +} diff --git a/worldmap/static/css/index.css b/worldmap/static/css/index.css new file mode 100644 index 0000000..e1e5f7c --- /dev/null +++ b/worldmap/static/css/index.css @@ -0,0 +1,130 @@ +body { + width: 100%; + height: 100%; + margin: 0px; + padding: 0 +} + +ul, ol { + padding: 0; +} + +#headInterval { + height: 50px; + background-color: rgba(0, 0, 0, 0); +} + +footer { + text-align: center; +} + +#indexTop { + width: 100%; + padding-top: 2%; + padding-bottom: 2%; +} + +#topleft { + width: 36%; + margin-right: 2%; + margin-left: 2%; + padding: 0px; + display: inline-block; +} + +#topRight { + width: 54%; + margin-right: 2%; + margin-left: 2%; + border-radius: 20px; + /* background:#ffffff; */ + display: inline-block; +} + +.carousel-inner { + border-radius: 20px; +} + +.topRightDiv { + width: 31%; + margin-left: 1%; + margin-right: 1%; + margin-top: 1%; + margin-bottom: 0.5%; + float: left; + position: relative; +} + +.thematicMapList { + width: 100%; + padding-left: 2%; + padding-right: 4%; + padding-bottom: 2%; + font-size: 16px; +} + +.thematicDiv { + width: 22%; + display: inline-block; + margin: 1%; + position: relative; +} + +.subMapList { + width: 100%; + padding: 1%; + overflow: auto; + white-space: nowrap; +} + +.MapListTitle { + font-size: 300%; +} + +.subMapListTitle { + font-size: 200%; +} + +.picItem { + width: 100%; + border-radius: 5px; +} + +.imgTitle { + position: absolute; + text-align: center; + width: 100%; + z-index: 1; + bottom: 0px; + color: #ffffff; + opacity: 0.8; + font-size: 180%; + background: linear-gradient(to top, rgba(0, 0, 0, 1.0), rgba(0, 0, 0, 0)); + border-radius: 5px; + margin: 0 0 0 0px; +} + +/* + * Author: zbn + */ +body { + background: url(../img/body.png); + background-repeat: repeat; +} + +.headBackgroud { + background: url(../img/background.jpg); + height: 200px; + width: 100%; + text-align: center; +} + +.headTitle { + height: 100px; + width: 794px; + margin-top: 15px; +} + +.topRightDiv .picItem { + cursor: pointer; +} \ No newline at end of file diff --git a/worldmap/static/css/main.css b/worldmap/static/css/main.css new file mode 100644 index 0000000..5366d28 --- /dev/null +++ b/worldmap/static/css/main.css @@ -0,0 +1,127 @@ +.maplayerTree { + background: rgba(220, 220, 220, 0.8); + max-height: 40%; + overflow: auto; +} + +.headerCls { + +} + +.bodyCls { + background: rgba(255, 255, 255, 0.9); +} + +#toolPanel { + position: absolute; + left: 50px; + top: 60px; + background: rgba(255, 255, 255, 0.5); + -moz-user-select: none; + -khtml-user-select: none; + user-select: none; +} + +#sharePanel { + position: absolute; + display: none; + padding: 5px; + opacity: 0.9; + background: #EEEEEE; + top: 90px; + left: 140px; + border-radius: 5px +} + +#mapPanel { + position: absolute; + display: none; + padding: 5px; + opacity: 0.9; + background: #EEEEEE; + top: 90px; + left: 80px; + border-radius: 5px +} + +#searchBox { + position: absolute; + display: none; + padding: 5px; + opacity: 0.9; + background: #EEEEEE; + top: 90px; + left: 230px; + border-radius: 5px +} + +#mylegend { + position: absolute; + display: none; + padding: 5px; + background: rgba(220, 220, 220, 0.7); + bottom: 60px; + right: 10px; + border-radius: 5px; + cursor: move; + max-height: 80%; + overflow: auto; + -moz-user-select: none; + -khtml-user-select: none; + user-select: none; +} + +#mytooltip { + position: absolute; + display: none; + padding: 5px; + background: rgba(220, 220, 220, 0.7); + top: 50%; + left: 50%; + border-radius: 5px; +} + +#MarkBoard { + display: none; + height: 170px; +} + +/* .changeMapWrapper { + position: absolute; + right: 5px; + top: 100px; +} + +.hoverType { + width: 56px; + height: 58px; + background-color: rgba(255, 255, 255, 0.5); + float: left; + margin: 5px; + text-align: center; + cursor: pointer; +} */ + +#myMapMap { + background-color: rgba(181, 218, 255, 0.5); +} + +#map { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} +#resultPanel { + max-height:500px; + overflow:auto; +} +#QueryBoard { + max-height:500px; + overflow:auto; +} +#DeatailInfoPanel{ + max-height:500px; + overflow:auto; +} \ No newline at end of file diff --git a/worldmap/static/css/navbar.css b/worldmap/static/css/navbar.css new file mode 100644 index 0000000..29166c4 --- /dev/null +++ b/worldmap/static/css/navbar.css @@ -0,0 +1,12 @@ +.navbar{ + background-color: rgba(0, 0, 0, 0.7); +} +.navbar-inverse .navbar-nav>li>a { + color: #EEEEEE; +} +.navbar-inverse .navbar-nav>li>ul>li>a { + color: #EEEEEE; +} +#usermenu{ + background-color: rgba(0,0, 0, 0.7); +} diff --git a/worldmap/static/css/privacy.css b/worldmap/static/css/privacy.css new file mode 100644 index 0000000..ebbd3d1 --- /dev/null +++ b/worldmap/static/css/privacy.css @@ -0,0 +1,69 @@ +*{margin:0;padding:0} +body{font:12px "","Arial Narrow",HELVETICA;background:#fff;-webkit-text-size-adjust:100%} +.layout{width:1000px;margin:0 auto;border-bottom:1px solid #d1d1d1;padding-bottom:20px;} +.layout h1{font-size:20px;line-height:80px;text-indent:62px;font-family:"΢ź";color:#0c0c0c;} +.layout h2{font-size:18px;font-family:"΢ź";height:38px;line-height:38px;margin:38px 0 10px;border-left:3px solid #187ac7;background:#eaf1fa;text-indent:16px;color:#187ac7;} +.layout h3{font-size:14px;line-height:18px;margin:20px 0 10px;color:#355a77;font-weight:bold;} +.layout p{font-size:14px;line-height:32px;margin:20px 0 10px} +.layout ul{margin:10px 10px 10px 30px} +.layout li{padding-left:17px;font-size:14px;line-height:32px;background:url(http://mat1.gtimg.com/www/images/qq2012/privacyIcon.png) no-repeat left 12px;} +.layout .inner{margin:10px 10px 10px 0;} +.layout .inner li{background:url(http://mat1.gtimg.com/www/images/qq2012/privacyIcon.png) no-repeat left -482px;} +.layout strong{color:#355a77;} +.clear{clear:both;} +.layout .ysNav{width:1000px;height:266px;background:#f8f8f8;} +.layout .ysNav ul{width:500px;float:left;margin:13px 0 0;padding:0;} +.layout .ysNav li{width:500px;font-size:14px;line-height:30px;float:left;margin:0;padding:0;color:#187ac7;text-indent:66px;background:none;} +.layout .ysNav li a{color:#187ac7;} +.layout .ysNav li a:hover{color:#105a94;} +#tcopyright{color:#333!important;padding-top:15px;} +#tcopyright a{color:#333!important;} + +.footer{display:none;padding:10px 45px 12px 0;overflow:hidden;position:relative;background: #404a54;} +.footer .foot_user{display: none;} +.footer .links{height:25px;line-height:25px;color:#565e61;font-size:13px;text-align:left} +.footer .links a{color:#95a0ac;margin:0 0 0 8px;display:inline;float:left} +.footer .links a:before{content:'';background:#565e61;width:1px;height:12px;display:inline-block;vertical-align:-1px;font-size:1em;color:#565e61;margin-right:8px} +.footer .links a:first-child:before{display:none} +.footer .copyright{font-size:13px;color:#707982;text-align:left;text-indent:8px;white-space:nowrap} + +@media screen and (max-width: 750px){ + body{width: 100%; position: relative;font-family: Helvetica,STHeiti,Droid Sans Fallback!important; } + .layout, .logo{width: 100%;} + .logoLayout, .logo{height: 62px;} + .logo{background-size: 50%;} + .nav{display: none;} + .layout{position: relative;overflow: hidden;} + .layout h1{text-indent: 18px;} + .layout .ysNav{height: auto; width: 100%;} + .layout .ysNav ul, .layout .ysNav li{float: none;} + .layout .ysNav ul{margin: 0;} + .layout .ysNav li{width: auto; text-indent: 18px;} + .tcopyright{display: none;} + .layout h2, .layout h3, .layout h4, .layout p{padding: 0 10px;} + .footer{display: block;} +} + +.tcopyright {width:960px;margin:0 auto;padding:8px 0;font-size:12px;line-height:28px;color:#333; text-align:center; overflow:hidden;clear:both;} +.tcopyright .en{font-family:Arial;} +.tcopyright a{color:#333;text-decoration: none;} +.tcopyright a:hover{color:#bd0a01;text-decoration: underline;} + +a:visited { + color: #000; + text-decoration: none; +} + +a:link { + outline: none; + color: #000; + text-decoration: none; +} + +ul, ol { + list-style: none; +} + +h1, h2, h3, h4, h5, h6 { + font-weight: normal; +} \ No newline at end of file diff --git a/worldmap/static/css/public.css b/worldmap/static/css/public.css new file mode 100644 index 0000000..203fd78 --- /dev/null +++ b/worldmap/static/css/public.css @@ -0,0 +1,11 @@ +html,body {width:100%;height:100%;margin: 0px;padding:0} +ul, ol { padding: 0;} + +#headInterval{ + height: 50px; + background-color: rgba(0,0,0,0); +} + +footer{ + text-align:center; +} \ No newline at end of file diff --git a/worldmap/static/css/publicstyle.css b/worldmap/static/css/publicstyle.css new file mode 100644 index 0000000..203fd78 --- /dev/null +++ b/worldmap/static/css/publicstyle.css @@ -0,0 +1,11 @@ +html,body {width:100%;height:100%;margin: 0px;padding:0} +ul, ol { padding: 0;} + +#headInterval{ + height: 50px; + background-color: rgba(0,0,0,0); +} + +footer{ + text-align:center; +} \ No newline at end of file diff --git a/worldmap/static/css/scroll.css b/worldmap/static/css/scroll.css new file mode 100644 index 0000000..cbda5fd --- /dev/null +++ b/worldmap/static/css/scroll.css @@ -0,0 +1,45 @@ +/*chromeʽ*/ +.custom-scrollbar::-webkit-scrollbar { + /*岿֣еwidth,height,background,borderͺһ鼶Ԫһȡ*/ + width: 10px; + height: 10px; +} +.custom-scrollbar::-webkit-scrollbar-button { + /*˵İťdisplay:none䲻ʾҲӱͼƬɫıʾЧ*/ + display: none; +} +.custom-scrollbar::-webkit-scrollbar-track { + /*display:none䲻ʾҲӱͼƬɫıʾЧ*/ + display: none; +} +.custom-scrollbar::-webkit-scrollbar-track-piece { + /*ڲм䲿֣ȥ*/ + background: #ccc; +} +.custom-scrollbar::-webkit-scrollbar-track-piece:increment { + /*ڲм䲿֣ȥ*/ +} +.custom-scrollbar::-webkit-scrollbar-track-piece:decrement { + /*ڲм䲿֣ȥ*/ +} +.custom-scrollbar::-webkit-scrollbar-track-piece:start { + /*ڲм䲿֣ȥ*/ +} +.custom-scrollbar::-webkit-scrollbar-track-piece:end { + /*ڲм䲿֣ȥ*/ +} +.custom-scrollbar::-webkit-scrollbar-thumb { + /*϶Dz*/ + background: #dcedef; + border: 1px solid #ddd; + border-radius: 4px; +} +.custom-scrollbar::-webkit-scrollbar-thumb:hover { + /*϶Dz*/ +} +.custom-scrollbar::-webkit-scrollbar-corner { + /*߽*/ +} +.custom-scrollbar::-webkit-scrollbar-resizer { + /*½϶ʽ*/ +} \ No newline at end of file diff --git a/worldmap/static/css/site_base.css b/worldmap/static/css/site_base.css index 17243cc..21a223c 100644 --- a/worldmap/static/css/site_base.css +++ b/worldmap/static/css/site_base.css @@ -115,15 +115,17 @@ footer { text-align: center; - background-color: #2c689c; + background-color: #f5f5f5; + font-family: Helvetica, Microsoft YaHei, Tohoma, Arial; } footer a { - color: #bfbfbf; + color: #2c689c; + font-size: 17px; } footer a:hover { - color: #fff; + color: #000FE8; } #permissions-body .panel .radio{ diff --git a/worldmap/static/css/whitestyle.css b/worldmap/static/css/whitestyle.css new file mode 100644 index 0000000..1a80163 --- /dev/null +++ b/worldmap/static/css/whitestyle.css @@ -0,0 +1,12 @@ +html, body{background-color: #FFFFFF} +footer{ + background-color: #FFFFFF; + text-align: center; + color: #000000; +} +.navbar{ + background-color: rgba(1.0, 1.0, 1.0, 0.7); +} +#usermenu{ + background-color: rgba(1.0, 1.0, 1.0, 0.7); +} diff --git a/worldmap/static/docs/WorldMap_Help_zh.pdf b/worldmap/static/docs/WorldMap_Help_zh.pdf new file mode 100644 index 0000000..42d7e47 Binary files /dev/null and b/worldmap/static/docs/WorldMap_Help_zh.pdf differ diff --git a/worldmap/static/img/01.jpg b/worldmap/static/img/01.jpg new file mode 100644 index 0000000..adbb6df Binary files /dev/null and b/worldmap/static/img/01.jpg differ diff --git a/worldmap/static/img/05.jpg b/worldmap/static/img/05.jpg new file mode 100644 index 0000000..4a3979e Binary files /dev/null and b/worldmap/static/img/05.jpg differ diff --git a/worldmap/static/img/1.jpg b/worldmap/static/img/1.jpg new file mode 100644 index 0000000..ad3d2c6 Binary files /dev/null and b/worldmap/static/img/1.jpg differ diff --git a/worldmap/static/img/11.jpg b/worldmap/static/img/11.jpg new file mode 100644 index 0000000..2e18191 Binary files /dev/null and b/worldmap/static/img/11.jpg differ diff --git a/worldmap/static/img/12.jpg b/worldmap/static/img/12.jpg new file mode 100644 index 0000000..14ba66b Binary files /dev/null and b/worldmap/static/img/12.jpg differ diff --git a/worldmap/static/img/13.jpg b/worldmap/static/img/13.jpg new file mode 100644 index 0000000..db7941f Binary files /dev/null and b/worldmap/static/img/13.jpg differ diff --git a/worldmap/static/img/14.jpg b/worldmap/static/img/14.jpg new file mode 100644 index 0000000..da668ce Binary files /dev/null and b/worldmap/static/img/14.jpg differ diff --git a/worldmap/static/img/22.jpg b/worldmap/static/img/22.jpg new file mode 100644 index 0000000..29d39bd Binary files /dev/null and b/worldmap/static/img/22.jpg differ diff --git a/worldmap/static/img/3_blue_blue.png b/worldmap/static/img/3_blue_blue.png new file mode 100644 index 0000000..112a400 Binary files /dev/null and b/worldmap/static/img/3_blue_blue.png differ diff --git a/worldmap/static/img/3_blue_gray.png b/worldmap/static/img/3_blue_gray.png new file mode 100644 index 0000000..41bb435 Binary files /dev/null and b/worldmap/static/img/3_blue_gray.png differ diff --git a/worldmap/static/img/3_gray_gray.png b/worldmap/static/img/3_gray_gray.png new file mode 100644 index 0000000..0d523ee Binary files /dev/null and b/worldmap/static/img/3_gray_gray.png differ diff --git a/worldmap/static/img/3_ok.png b/worldmap/static/img/3_ok.png new file mode 100644 index 0000000..5b0f6a6 Binary files /dev/null and b/worldmap/static/img/3_ok.png differ diff --git a/worldmap/static/img/background.jpg b/worldmap/static/img/background.jpg new file mode 100644 index 0000000..963346e Binary files /dev/null and b/worldmap/static/img/background.jpg differ diff --git a/worldmap/static/img/blue_gray.png b/worldmap/static/img/blue_gray.png new file mode 100644 index 0000000..41bb435 Binary files /dev/null and b/worldmap/static/img/blue_gray.png differ diff --git a/worldmap/static/img/body.png b/worldmap/static/img/body.png new file mode 100644 index 0000000..c8126e8 Binary files /dev/null and b/worldmap/static/img/body.png differ diff --git a/worldmap/static/img/body2.png b/worldmap/static/img/body2.png new file mode 100644 index 0000000..7d92025 Binary files /dev/null and b/worldmap/static/img/body2.png differ diff --git a/worldmap/static/img/body3.png b/worldmap/static/img/body3.png new file mode 100644 index 0000000..cbcf0ae Binary files /dev/null and b/worldmap/static/img/body3.png differ diff --git a/worldmap/static/img/book.png b/worldmap/static/img/book.png new file mode 100644 index 0000000..cf1dd2f Binary files /dev/null and b/worldmap/static/img/book.png differ diff --git a/worldmap/static/img/dufu.gif b/worldmap/static/img/dufu.gif new file mode 100644 index 0000000..4b533b4 Binary files /dev/null and b/worldmap/static/img/dufu.gif differ diff --git a/worldmap/static/img/gis.png b/worldmap/static/img/gis.png new file mode 100644 index 0000000..3185352 Binary files /dev/null and b/worldmap/static/img/gis.png differ diff --git a/worldmap/static/img/gray_gray.png b/worldmap/static/img/gray_gray.png new file mode 100644 index 0000000..0d523ee Binary files /dev/null and b/worldmap/static/img/gray_gray.png differ diff --git a/worldmap/static/img/icon.ico b/worldmap/static/img/icon.ico new file mode 100644 index 0000000..41467a9 Binary files /dev/null and b/worldmap/static/img/icon.ico differ diff --git a/worldmap/static/img/icon1.png b/worldmap/static/img/icon1.png new file mode 100644 index 0000000..57f8137 Binary files /dev/null and b/worldmap/static/img/icon1.png differ diff --git a/worldmap/static/img/image.jpg b/worldmap/static/img/image.jpg new file mode 100644 index 0000000..29162ab Binary files /dev/null and b/worldmap/static/img/image.jpg differ diff --git a/worldmap/static/img/layerIcon.jpg b/worldmap/static/img/layerIcon.jpg new file mode 100644 index 0000000..8ae2ef8 Binary files /dev/null and b/worldmap/static/img/layerIcon.jpg differ diff --git a/worldmap/static/img/libai.gif b/worldmap/static/img/libai.gif new file mode 100644 index 0000000..04d8bf3 Binary files /dev/null and b/worldmap/static/img/libai.gif differ diff --git a/worldmap/static/img/logo.jpg b/worldmap/static/img/logo.jpg new file mode 100644 index 0000000..01fc224 Binary files /dev/null and b/worldmap/static/img/logo.jpg differ diff --git a/worldmap/static/img/logo.png b/worldmap/static/img/logo.png new file mode 100644 index 0000000..9f83878 Binary files /dev/null and b/worldmap/static/img/logo.png differ diff --git a/worldmap/static/img/map/100.jpg b/worldmap/static/img/map/100.jpg new file mode 100644 index 0000000..6c3c9a4 Binary files /dev/null and b/worldmap/static/img/map/100.jpg differ diff --git a/worldmap/static/img/map/101.jpg b/worldmap/static/img/map/101.jpg new file mode 100644 index 0000000..3f0b377 Binary files /dev/null and b/worldmap/static/img/map/101.jpg differ diff --git a/worldmap/static/img/map/14.jpg b/worldmap/static/img/map/14.jpg new file mode 100644 index 0000000..f3b965d Binary files /dev/null and b/worldmap/static/img/map/14.jpg differ diff --git a/worldmap/static/img/map/noData.jpg b/worldmap/static/img/map/noData.jpg new file mode 100644 index 0000000..176531a Binary files /dev/null and b/worldmap/static/img/map/noData.jpg differ diff --git a/worldmap/static/img/map/noData1.jpg b/worldmap/static/img/map/noData1.jpg new file mode 100644 index 0000000..f325678 Binary files /dev/null and b/worldmap/static/img/map/noData1.jpg differ diff --git a/worldmap/static/img/map_image.jpg b/worldmap/static/img/map_image.jpg new file mode 100644 index 0000000..6f8cb0d Binary files /dev/null and b/worldmap/static/img/map_image.jpg differ diff --git a/worldmap/static/img/map_logo.jpg b/worldmap/static/img/map_logo.jpg new file mode 100644 index 0000000..282b37d Binary files /dev/null and b/worldmap/static/img/map_logo.jpg differ diff --git a/worldmap/static/img/map_map.jpg b/worldmap/static/img/map_map.jpg new file mode 100644 index 0000000..63a68a0 Binary files /dev/null and b/worldmap/static/img/map_map.jpg differ diff --git a/worldmap/static/img/mapicon.jpg b/worldmap/static/img/mapicon.jpg new file mode 100644 index 0000000..14247dc Binary files /dev/null and b/worldmap/static/img/mapicon.jpg differ diff --git a/worldmap/static/img/qingdaifunv.gif b/worldmap/static/img/qingdaifunv.gif new file mode 100644 index 0000000..60dd101 Binary files /dev/null and b/worldmap/static/img/qingdaifunv.gif differ diff --git a/worldmap/static/img/quansongwen.gif b/worldmap/static/img/quansongwen.gif new file mode 100644 index 0000000..86bbad7 Binary files /dev/null and b/worldmap/static/img/quansongwen.gif differ diff --git a/worldmap/static/img/right.png b/worldmap/static/img/right.png new file mode 100644 index 0000000..e8ec274 Binary files /dev/null and b/worldmap/static/img/right.png differ diff --git a/worldmap/static/img/safe.png b/worldmap/static/img/safe.png new file mode 100644 index 0000000..66c79d7 Binary files /dev/null and b/worldmap/static/img/safe.png differ diff --git a/worldmap/static/img/slide-africa.jpg b/worldmap/static/img/slide-africa.jpg index b29b7c1..f55d80b 100644 Binary files a/worldmap/static/img/slide-africa.jpg and b/worldmap/static/img/slide-africa.jpg differ diff --git a/worldmap/static/img/slide-boston.jpg b/worldmap/static/img/slide-boston.jpg index af97727..571765f 100644 Binary files a/worldmap/static/img/slide-boston.jpg and b/worldmap/static/img/slide-boston.jpg differ diff --git a/worldmap/static/img/slide-china.jpg b/worldmap/static/img/slide-china.jpg index 330a6d6..382e27c 100644 Binary files a/worldmap/static/img/slide-china.jpg and b/worldmap/static/img/slide-china.jpg differ diff --git a/worldmap/static/img/slide-dufu.gif b/worldmap/static/img/slide-dufu.gif new file mode 100644 index 0000000..2f343ea Binary files /dev/null and b/worldmap/static/img/slide-dufu.gif differ diff --git a/worldmap/static/img/slide-giza.jpg b/worldmap/static/img/slide-giza.jpg index 0eb2010..9c5e9df 100644 Binary files a/worldmap/static/img/slide-giza.jpg and b/worldmap/static/img/slide-giza.jpg differ diff --git a/worldmap/static/img/slide-japan.jpg b/worldmap/static/img/slide-japan.jpg index 237328c..0b4f839 100644 Binary files a/worldmap/static/img/slide-japan.jpg and b/worldmap/static/img/slide-japan.jpg differ diff --git a/worldmap/static/img/slide-libai.gif b/worldmap/static/img/slide-libai.gif new file mode 100644 index 0000000..1d40249 Binary files /dev/null and b/worldmap/static/img/slide-libai.gif differ diff --git a/worldmap/static/img/slide-qingdaifunv.gif b/worldmap/static/img/slide-qingdaifunv.gif new file mode 100644 index 0000000..ba0c3b7 Binary files /dev/null and b/worldmap/static/img/slide-qingdaifunv.gif differ diff --git a/worldmap/static/img/slide-quansongwen.gif b/worldmap/static/img/slide-quansongwen.gif new file mode 100644 index 0000000..83c59ca Binary files /dev/null and b/worldmap/static/img/slide-quansongwen.gif differ diff --git a/worldmap/static/img/slide-tangxianzu.gif b/worldmap/static/img/slide-tangxianzu.gif new file mode 100644 index 0000000..d08a3ce Binary files /dev/null and b/worldmap/static/img/slide-tangxianzu.gif differ diff --git a/worldmap/static/img/slide2/slide-dufu.jpg b/worldmap/static/img/slide2/slide-dufu.jpg new file mode 100644 index 0000000..b91fcd9 Binary files /dev/null and b/worldmap/static/img/slide2/slide-dufu.jpg differ diff --git a/worldmap/static/img/slide2/slide-libai.jpg b/worldmap/static/img/slide2/slide-libai.jpg new file mode 100644 index 0000000..a1be792 Binary files /dev/null and b/worldmap/static/img/slide2/slide-libai.jpg differ diff --git a/worldmap/static/img/slide2/slide-qingdaifunv.jpg b/worldmap/static/img/slide2/slide-qingdaifunv.jpg new file mode 100644 index 0000000..bd0b629 Binary files /dev/null and b/worldmap/static/img/slide2/slide-qingdaifunv.jpg differ diff --git a/worldmap/static/img/slide2/slide-quansongwen.jpg b/worldmap/static/img/slide2/slide-quansongwen.jpg new file mode 100644 index 0000000..945dc2b Binary files /dev/null and b/worldmap/static/img/slide2/slide-quansongwen.jpg differ diff --git a/worldmap/static/img/slide2/slide-tangxianzu.jpg b/worldmap/static/img/slide2/slide-tangxianzu.jpg new file mode 100644 index 0000000..38b0828 Binary files /dev/null and b/worldmap/static/img/slide2/slide-tangxianzu.jpg differ diff --git a/worldmap/static/img/tangxianzu.gif b/worldmap/static/img/tangxianzu.gif new file mode 100644 index 0000000..ce45e35 Binary files /dev/null and b/worldmap/static/img/tangxianzu.gif differ diff --git a/worldmap/static/img/template_bubble_china.png b/worldmap/static/img/template_bubble_china.png new file mode 100644 index 0000000..19cf755 Binary files /dev/null and b/worldmap/static/img/template_bubble_china.png differ diff --git a/worldmap/static/img/template_point.jpg b/worldmap/static/img/template_point.jpg new file mode 100644 index 0000000..71d0064 Binary files /dev/null and b/worldmap/static/img/template_point.jpg differ diff --git a/worldmap/static/img/template_polyline.jpg b/worldmap/static/img/template_polyline.jpg new file mode 100644 index 0000000..8f72470 Binary files /dev/null and b/worldmap/static/img/template_polyline.jpg differ diff --git a/worldmap/static/img/template_range_china.png b/worldmap/static/img/template_range_china.png new file mode 100644 index 0000000..d20ff65 Binary files /dev/null and b/worldmap/static/img/template_range_china.png differ diff --git a/worldmap/static/img/title.png b/worldmap/static/img/title.png new file mode 100644 index 0000000..291c096 Binary files /dev/null and b/worldmap/static/img/title.png differ diff --git a/worldmap/static/img/title2.png b/worldmap/static/img/title2.png new file mode 100644 index 0000000..2f74b2b Binary files /dev/null and b/worldmap/static/img/title2.png differ diff --git a/worldmap/static/img/title_small.png b/worldmap/static/img/title_small.png new file mode 100644 index 0000000..61d47a1 Binary files /dev/null and b/worldmap/static/img/title_small.png differ diff --git a/worldmap/static/img/title_small2.png b/worldmap/static/img/title_small2.png new file mode 100644 index 0000000..0fd66e2 Binary files /dev/null and b/worldmap/static/img/title_small2.png differ diff --git a/worldmap/static/img/title_small3.png b/worldmap/static/img/title_small3.png new file mode 100644 index 0000000..e0a560b Binary files /dev/null and b/worldmap/static/img/title_small3.png differ diff --git a/worldmap/static/img/warning.png b/worldmap/static/img/warning.png new file mode 100644 index 0000000..c5db7fc Binary files /dev/null and b/worldmap/static/img/warning.png differ diff --git a/worldmap/static/js/AdminPanel.js b/worldmap/static/js/AdminPanel.js new file mode 100644 index 0000000..8303db2 --- /dev/null +++ b/worldmap/static/js/AdminPanel.js @@ -0,0 +1,251 @@ +$(function () { + + //1.初始化Table + var oTable = new TableInit(); + oTable.Init(); + + //2.初始化Button的点击事件 + var oButtonInit = new ButtonInit(); + oButtonInit.Init(); +}); + + + +var TableInit = function () { + var oTableInit = new Object(); + //初始化Table + oTableInit.Init = function () { + $('#tb_users').bootstrapTable({ + url: './getUserList.action', //请求后台的URL(*) + method: 'get', //请求方式(*) + //toolbar: '#toolbar', //工具按钮用哪个容器 + striped: true, //是否显示行间隔色 + cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*) + pagination: true, //是否显示分页(*) + sortable: false, //是否启用排序 + sortOrder: "asc", //排序方式 + queryParams: oTableInit.userQueryParams,//传递参数(*) + sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*) + pageNumber:1, //初始化加载第一页,默认第一页 + pageSize: 10, //每页的记录行数(*) + pageList: [10, 25, 50, 100], //可供选择的每页的行数(*) + search: false, //是否显示表格搜索,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大 + strictSearch: true, + showColumns: true, //是否显示所有的列 + showRefresh: true, //是否显示刷新按钮 + minimumCountColumns: 2, //最少允许的列数 + clickToSelect: false, //是否启用点击选中行 + height: 500, //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度 + uniqueId: "ID", //每一行的唯一标识,一般为主键列 + showToggle:true, //是否显示详细视图和列表视图的切换按钮 + cardView: false, //是否显示详细视图 + detailView: false, //是否显示父子表 + columns: [{ + checkbox: true + }, { + field: 'id', + title: 'ID' + }, { + field: 'username', + title: '用户名' + }, { + field: 'email', + title: '邮箱' + }, { + field: 'realname', + title: '姓名' + }, { + field: 'comp', + title: '单位' + }, { + field: 'cretificate', + title: '证件号码' + }, { + field: 'cretifitype', + title: '证件类型' + }, + { + field: 'authority', + title: '权限' + }] + }); + + $('#tb_maps').bootstrapTable({ + url: './getMapList2.action', //请求后台的URL(*) + method: 'get', //请求方式(*) + //toolbar: '#toolbar', //工具按钮用哪个容器 + striped: true, //是否显示行间隔色 + cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*) + pagination: true, //是否显示分页(*) + sortable: false, //是否启用排序 + sortOrder: "asc", //排序方式 + queryParams: oTableInit.mapQueryParams,//传递参数(*) + sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*) + pageNumber:1, //初始化加载第一页,默认第一页 + pageSize: 10, //每页的记录行数(*) + pageList: [10, 25, 50, 100], //可供选择的每页的行数(*) + search: false, //是否显示表格搜索,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大 + strictSearch: true, + showColumns: true, //是否显示所有的列 + showRefresh: true, //是否显示刷新按钮 + minimumCountColumns: 2, //最少允许的列数 + clickToSelect: false, //是否启用点击选中行 + height: 500, //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度 + uniqueId: "ID", //每一行的唯一标识,一般为主键列 + showToggle:true, //是否显示详细视图和列表视图的切换按钮 + cardView: false, //是否显示详细视图 + detailView: false, //是否显示父子表 + columns: [{ + checkbox: true + }, { + field: 'id', + title: 'ID' + }, { + field: 'mapname', + title: '地图名' + }, { + field: 'userid', + title: '建立地图用户id' + }, { + field: 'accessibility', + title: '地图公开性' + }, { + field: 'addable', + title: '审核状态' + }], + onClickRow: function (item, $element) { + window.open("./main.action?mapid="+item.id); + return false; + } + }); + }; + + //得到查询的参数 + oTableInit.userQueryParams = function (params) { + var temp = { + limit: params.limit, //页面大小 + offset: params.offset, //页码 + username: $("#user_txt_username").val().trim() + }; + return temp; + }; + + oTableInit.mapQueryParams = function (params) { + var temp = { + limit: params.limit, //页面大小 + offset: params.offset, //页码 + mapname: $("#map_txt_mapname").val().trim() + }; + return temp; + }; + + return oTableInit; +}; + +var ButtonInit = function () { + var oInit = new Object(); + var postdata = {}; + + oInit.Init = function () { + $('#user_btn_query').click( + function(){ + $('#tb_users').bootstrapTable('refresh'); + }); + $('#map_btn_query').click( + function(){ + $('#tb_maps').bootstrapTable('refresh'); + }); + $('#map_btn_pass').click( + function(){ + var mapList = getSelectMapIdList(); + $.ajax({ + url: "./passMap.action", + async: true, + type: "POST", + dataType: "text", + data: { + mapList: JSON.stringify(mapList) + }, + success: function (result) { + $('#tb_maps').bootstrapTable('refresh'); + } + }) + + }); + $('#map_btn_ban').click( + function(){ + var mapList = getSelectMapIdList(); + $.ajax({ + url: "./banMap.action", + async: true, + type: "POST", + dataType: "text", + data: { + mapList: JSON.stringify(mapList) + }, + success: function (result) { + $('#tb_maps').bootstrapTable('refresh'); + } + }) + + }); + $('#user_btn_pass').click( + function(){ + var userList = getSelectUserIdList(); + $.ajax({ + url: "./passUser.action", + async: true, + type: "POST", + dataType: "text", + data: { + userList: JSON.stringify(userList) + }, + success: function (result) { + $('#tb_users').bootstrapTable('refresh'); + } + }) + + }); + $('#user_btn_ban').click( + function(){ + var userList = getSelectUserIdList(); + $.ajax({ + url: "./banUser.action", + async: true, + type: "POST", + dataType: "text", + data: { + userList: JSON.stringify(userList) + }, + success: function (result) { + $('#tb_users').bootstrapTable('refresh'); + } + }) + + }); + }; + + return oInit; +}; + +function getSelectMapIdList() +{ + var selections = $('#tb_maps').bootstrapTable('getSelections'); + var mapList = new Array(); + for (var i=0;i20) length=20; + //光标键"↓" + if (event.keyCode == 40) { + ++this.index; + if (this.index > length) { + this.index = 0; + } else if (this.index == length) { + this.obj.value = this.search_value; + } + this.changeClassname(length); + } + //光标键"↑" + else if (event.keyCode == 38) { + this.index--; + if (this.index < -1) { + this.index = length - 1; + } else if (this.index == -1) { + this.obj.value = this.search_value; + } + this.changeClassname(length); + } + //回车键 + else if (event.keyCode == 13) { + this.autoObj.children[this.index].onclick(); + this.autoObj.className = "auto_hidden"; + + this.index = -1; + } else { + this.index = -1; + } + }, + //程序入口 + start: function (event) { + if (event.keyCode != 13 && event.keyCode != 38 && event.keyCode != 40) { + this.init(); + this.deleteDIV(); + this.select = null; + this.count = 0; + this.search_value = this.obj.value; + var valueArr = this.value_arr; + valueArr.sort( + function (a, b) { + if (a.name > b.name) return 1; + else if (a.name < b.name) return -1; + else return 0; + } + ); + if (this.obj.value.replace(/(^\s*)|(\s*$)/g, '') == "") { return; }//值为空,退出 + try { var reg1 = new RegExp("^" + this.obj.value, "i"); } + catch (e) { return; } + try { var reg2 = new RegExp("(" + this.obj.value + ")", "i"); } + catch (e) { return; } + var div_index = 0;//记录创建的DIV的索引 + var tempArr = new Array(); + var deleteIndex = new Array(); + var terminateFlag = true; + //这段需要函数化重构 + for (var i = 0; i < valueArr.length; i++) { + if (reg1.test(valueArr[i].name)) { + if (tempArr.has(valueArr[i], resultEqual)) { + deleteIndex.push(i); + continue; + } + tempArr.push(valueArr[i]); + var div = document.createElement("div"); + div.className = "auto_onmouseout"; + div.seq = valueArr[i].name; + var tempobj = valueArr[i]; + div.onclick = this.setValue(this, tempobj); + div.onmouseover = this.autoOnmouseover(this, div_index); + div.innerHTML = valueArr[i].name.replace(reg2, "$1") + ' ' + valueArr[i].type + '';//搜索到的字符粗体显示 + this.autoObj.appendChild(div); + this.autoObj.className = "auto_show"; + div_index++; + this.count++; + if (this.count > 19) { terminateFlag = false; break; } + } + } + for (var i = 0; i < deleteIndex.length; i++) { + valueArr.splice(i, 1); + } + for (var i = 0; i < valueArr.length; i++) { + if (terminateFlag && !reg2.test(valueArr[i].name) && reg2.test(valueArr[i].name)) { + tempArr.push(valueArr[i]); + var div = document.createElement("div"); + div.className = "auto_onmouseout"; + div.seq = valueArr[i].name; + div.onclick = this.setValue(this, i); + div.onmouseover = this.autoOnmouseover(this, div_index); + div.innerHTML = valueArr[i].name.replace(reg2, "$1") + ' ' + valueArr[i].type + '';//搜索到的字符粗体显示 + this.autoObj.appendChild(div); + this.autoObj.className = "auto_show"; + div_index++; + this.count++; + if (this.count > 19) { terminateFlag = false; break; } + } + } + if(!terminateFlag){ + var div = document.createElement("div"); + div.className = "auto_onmouseout"; + div.seq = ""; + div.onclick = null; + div.onmouseover = null; + div.innerHTML = "仅显示前20条记录..." + this.autoObj.appendChild(div); + this.autoObj.className = "auto_show"; + div_index++; + } + + } + this.pressKey(event); + } +} \ No newline at end of file diff --git a/worldmap/static/js/AttrSearch2.js b/worldmap/static/js/AttrSearch2.js new file mode 100644 index 0000000..5e31b7c --- /dev/null +++ b/worldmap/static/js/AttrSearch2.js @@ -0,0 +1,412 @@ +function bgsearch() { + autoComplete.deleteDIV(); + if(has(autoComplete.select)) + match(autoComplete.select); + else + match({name:autoComplete.obj.value,type:'all'}); +} +function match(info) {//查询所需要的信息匹配 并且返回结果选框 + var infoType = info.type; + var infoKey = info.name; + var resultSet = new Array(); + try { var reg = new RegExp("(" + infoKey + ")", "i"); } + catch (e) { return; } + //————————————————————switchBegin + switch (infoType) { + case "图层": + { + var index = info.index; + var type = myMapMana.maplayerlist[index].type; + switch (type) { + case 0: + var data = myMapMana.maplayerlist[index].style.dataSet._data; + for (var i = 0; i < data.length; i++) { + var temp = { + layername: infoKey, + name: data[i].name, + count: data[i].count, + type: '面', + index: { layer: index, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + break; + case 1: + var data = myMapMana.maplayerlist[index].style.series.data; + case 2: + if (type == 2) { + var data = myMapMana.maplayerlist[index].style.series.data; + } + for (var i = 0; i < data.length; i++) { + var temp = { + layername: infoKey, + name: data[i].name, + count: data[i].value[2], + type: '点', + index: { layer: index, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + break; + case 3: + var data = myMapMana.maplayerlist[index].style.data; + for (var i = 0; i < data.length; i++) { + var temp = { + layername: infoKey, + name: data.ID, + count: data.coords, + type: '面', + index: { layer: index, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + break; + } + break; + } + case "all": + case "地名": + { + for (var j = 0; j < myMapMana.maplayerlist.length; j++) { + var type = myMapMana.maplayerlist[j].type; + var layername = myMapMana.maplayerlist[j].layername; + switch (type) { + case 0: + var data = myMapMana.maplayerlist[j].style.dataSet._data; + for (var i = 0; i < data.length; i++) { + if (reg.test(data[i].name)) { + var temp = { + layername: layername, + name: data[i].name, + count: data[i].count, + type: '面', + index: { layer: j, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + } + break; + case 1: + var data = myMapMana.maplayerlist[j].style.series.data; + case 2: + if (type == 2) { + var data = myMapMana.maplayerlist[j].style.series.data; + } + for (var i = 0; i < data.length; i++) { + if (reg.test(data[i].name)) { + var temp = { + layername: layername, + name: data[i].name, + count: data[i].value[2], + type: '点', + index: { layer: j, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + } + break; + case 3: + var data = myMapMana.maplayerlist[j].style.data; + for (var i = 0; i < data.length; i++) { + if (reg.test(data[i].ID)) { + var temp = { + layername: layername, + name: data[i].ID, + count: data[i].coords, + type: '线', + index: { layer: j, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + } + break; + } + } + if(!infoType=="all") break; + } + case "数据": + { + + for (var j = 0; j < myMapMana.maplayerlist.length; j++) { + var type = myMapMana.maplayerlist[j].type; + var layername = myMapMana.maplayerlist[j].layername; + switch (type) { + case 2: + var data = myMapMana.maplayerlist[j].style.series.data; + for (var i = 0; i < data.length; i++) { + if (reg.test(data[i].value[2])) { + var temp = { + layername: layername, + name: data[i].name, + count: data[i].value[2], + type: '点', + index: { layer: j, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + } + break; + case 3: + if(infoType=="all") break; + var data = myMapMana.maplayerlist[j].style.data; + for (var i = 0; i < data.length; i++) { + if (reg.test(data[i].ID)) { + var temp = { + layername: layername, + name: data[i].ID, + count: data[i].coords, + type: '线', + index: { layer: j, feature: i }//遇事不决存索引 这里还在纠结平移缩放怎么弄 + } + resultSet.push(temp); + } + } + break; + } + } + break; + } + } + //————————————————————switchEnd + showResultPanel(resultSet); +} + +var autoComplete; +function getLayerStringDataArr() { + var resultArr = new Array(); + for (var i = 0; i < myMapMana.maplayerlist.length; i++) {//获取地图的所有文字信息 + var layer = myMapMana.maplayerlist[i]; + if (!layer.state) continue; + resultArr.push({ name: layer.layername, type: "图层", index: i }); + switch (layer.type) { + case 0: + { + var data = layer.style.dataSet._data; + for (var j = 0; j < data.length; j++) { + resultArr.push({ name: data[j].name, type: "地名" }); + } + break; + } + case 1: + { + var data = layer.style.series.data; + for (var j = 0; j < data.length; j++) { + resultArr.push({ name: data[j].name, type: "地名" }); + } + break; + } + case 2: + { + var data = layer.style.series.data; + for (var j = 0; j < data.length; j++) { + resultArr.push({ name: data[j].name, type: "地名" }); + resultArr.push({ name: data[j].value[2], type: "数据" }); + } + break; + } + case 3: + { + var data = layer.style.data; + for (var j = 0; j < data.length; j++) { + resultArr.push({ name: data[j].ID, type: "路径名" }); + } + break; + } + } + } + return resultArr; +} +Array.prototype.has = function (obj, equalFunc) { + var myEqual = function (a, b) { if (a == b) return true; else return false; } + if (has(equalFunc)) myEqual = equalFunc; + for (var i = 0; i < this.length; i++) { + if (myEqual(this[i], obj)) return true; + } + return false; +} +function resultEqual(a, b) { + if (a.name == b.name && a.type == b.type) return true; + else return false; +} +function createAutoComplete() { + var inputValue = getLayerStringDataArr(); + if (!autoComplete) { + autoComplete = new AutoComplete('p_apiName', 'auto', inputValue);//第一个参数是输入框id,第二个是下拉显示的id,第三个是获取的全部数据。 + } +} +function AutoComplete(obj, autoObj, arr) { + this.obj = document.getElementById(obj); //输入框 + this.autoObj = document.getElementById(autoObj);//DIV的根节点 + this.value_arr = arr; //不要包含重复值 + this.index = -1; //当前选中的DIV的索引 + this.search_value = ""; //保存当前搜索的字符 + this.select = null; + this.count = 0; +} +AutoComplete.prototype = { + setArr: function (newArr) { + this.value_arr = newArr; + }, + init: function () { + this.autoObj.style.left = this.obj.offsetLeft + "px"; + this.autoObj.style.top = this.obj.offsetTop + this.obj.offsetHeight + "px"; + this.autoObj.style.width = this.obj.offsetWidth - 2 + "px";//减去边框的长度2px + }, + //删除自动完成需要的所有DIV + deleteDIV: function () { + while (this.autoObj.hasChildNodes()) { + this.autoObj.removeChild(this.autoObj.firstChild); + } + this.autoObj.className = "auto_hidden"; + }, + //设置值 + setValue: function (_this, result) { + return function () { + _this.select = result; + _this.obj.value = this.seq; + _this.autoObj.className = "auto_hidden"; + } + }, + //模拟鼠标移动至DIV时,DIV高亮 + autoOnmouseover: function (_this, _div_index) { + return function () { + _this.index = _div_index; + var length = _this.autoObj.children.length; + for (var j = 0; j < length; j++) { + if (j != _this.index) { + _this.autoObj.childNodes[j].className = 'auto_onmouseout'; + } else { + _this.autoObj.childNodes[j].className = 'auto_onmouseover'; + _this.obj.value=this.seq; + } + } + } + }, + //更改classname + changeClassname: function (length) { + for (var i = 0; i < length; i++) { + if (i != this.index) { + this.autoObj.childNodes[i].className = 'auto_onmouseout'; + } else { + this.autoObj.childNodes[i].className = 'auto_onmouseover'; + this.obj.value = this.autoObj.childNodes[i].seq; + } + } + } + , + //响应键盘 + pressKey: function (event) { + var length = this.autoObj.children.length; + if(length>20) length=20; + //光标键"↓" + if (event.keyCode == 40) { + ++this.index; + if (this.index > length) { + this.index = 0; + } else if (this.index == length) { + this.obj.value = this.search_value; + } + this.changeClassname(length); + } + //光标键"↑" + else if (event.keyCode == 38) { + this.index--; + if (this.index < -1) { + this.index = length - 1; + } else if (this.index == -1) { + this.obj.value = this.search_value; + } + this.changeClassname(length); + } + //回车键 + else if (event.keyCode == 13) { + this.autoObj.children[this.index].onclick(); + this.autoObj.className = "auto_hidden"; + + this.index = -1; + } else { + this.index = -1; + } + }, + //程序入口 + start: function (event) { + if (event.keyCode != 13 && event.keyCode != 38 && event.keyCode != 40) { + this.init(); + this.deleteDIV(); + this.select = null; + this.count = 0; + this.search_value = this.obj.value; + var valueArr = this.value_arr; + valueArr.sort( + function (a, b) { + if (a.name > b.name) return 1; + else if (a.name < b.name) return -1; + else return 0; + } + ); + if (this.obj.value.replace(/(^\s*)|(\s*$)/g, '') == "") { return; }//值为空,退出 + try { var reg1 = new RegExp("^" + this.obj.value, "i"); } + catch (e) { return; } + try { var reg2 = new RegExp("(" + this.obj.value + ")", "i"); } + catch (e) { return; } + var div_index = 0;//记录创建的DIV的索引 + var tempArr = new Array(); + var deleteIndex = new Array(); + var terminateFlag = true; + //这段需要函数化重构 + for (var i = 0; i < valueArr.length; i++) { + if (reg1.test(valueArr[i].name)) { + if (tempArr.has(valueArr[i], resultEqual)) { + deleteIndex.push(i); + continue; + } + tempArr.push(valueArr[i]); + var div = document.createElement("div"); + div.className = "auto_onmouseout"; + div.seq = valueArr[i].name; + var tempobj = valueArr[i]; + div.onclick = this.setValue(this, tempobj); + div.onmouseover = this.autoOnmouseover(this, div_index); + div.innerHTML = valueArr[i].name.replace(reg2, "$1") + ' ' + valueArr[i].type + '';//搜索到的字符粗体显示 + this.autoObj.appendChild(div); + this.autoObj.className = "auto_show"; + div_index++; + this.count++; + if (this.count > 19) { terminateFlag = false; break; } + } + } + for (var i = 0; i < deleteIndex.length; i++) { + valueArr.splice(i, 1); + } + for (var i = 0; i < valueArr.length; i++) { + if (terminateFlag && !reg2.test(valueArr[i].name) && reg2.test(valueArr[i].name)) { + tempArr.push(valueArr[i]); + var div = document.createElement("div"); + div.className = "auto_onmouseout"; + div.seq = valueArr[i].name; + div.onclick = this.setValue(this, i); + div.onmouseover = this.autoOnmouseover(this, div_index); + div.innerHTML = valueArr[i].name.replace(reg2, "$1") + ' ' + valueArr[i].type + '';//搜索到的字符粗体显示 + this.autoObj.appendChild(div); + this.autoObj.className = "auto_show"; + div_index++; + this.count++; + if (this.count > 19) { terminateFlag = false; break; } + } + } + if(!terminateFlag){ + var div = document.createElement("div"); + div.className = "auto_onmouseout"; + div.seq = ""; + div.onclick = null; + div.onmouseover = null; + div.innerHTML = "仅显示前20条记录..." + this.autoObj.appendChild(div); + this.autoObj.className = "auto_show"; + div_index++; + } + + } + this.pressKey(event); + } +} \ No newline at end of file diff --git a/worldmap/static/js/DistanceTool.js b/worldmap/static/js/DistanceTool.js new file mode 100644 index 0000000..8ce770c --- /dev/null +++ b/worldmap/static/js/DistanceTool.js @@ -0,0 +1,1791 @@ +/** + * @fileoverview 百度地图的测距工具类,对外开放。 + * 允许用户在地图上点击完成距离的测量。 + * 使用者可以自定义测距线段的相关样式,例如线宽、颜色、测距结果所用的单位制等等。 + * 主入口类是DistanceTool, + * 基于Baidu Map API 1.2。 + * + * @author Baidu Map Api Group + * @version 1.2 + */ + +/** + * @namespace BMap的所有library类均放在BMapLib命名空间下 + */ +var BMapLib = window.BMapLib = BMapLib || {}; + +(function() { + /** + * 声明baidu包 + */ + var baidu = baidu || {guid : "$BAIDU$"}; + (function() { + // 一些页面级别唯一的属性,需要挂载在window[baidu.guid]上 + window[baidu.guid] = {}; + + /** + * 将源对象的所有属性拷贝到目标对象中 + * @name baidu.extend + * @function + * @grammar baidu.extend(target, source) + * @param {Object} target 目标对象 + * @param {Object} source 源对象 + * @returns {Object} 目标对象 + */ + baidu.extend = function (target, source) { + for (var p in source) { + if (source.hasOwnProperty(p)) { + target[p] = source[p]; + } + } + return target; + }; + + /** + * @ignore + * @namespace + * @baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。 + * @property guid 对象的唯一标识 + */ + baidu.lang = baidu.lang || {}; + + /** + * 返回一个当前页面的唯一标识字符串。 + * @function + * @grammar baidu.lang.guid() + * @returns {String} 当前页面的唯一标识字符串 + */ + baidu.lang.guid = function() { + return "TANGRAM__" + (window[baidu.guid]._counter ++).toString(36); + }; + + window[baidu.guid]._counter = window[baidu.guid]._counter || 1; + + /** + * 所有类的实例的容器 + * key为每个实例的guid + */ + window[baidu.guid]._instances = window[baidu.guid]._instances || {}; + + /** + * Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。 + * @function + * @name baidu.lang.Class + * @grammar baidu.lang.Class(guid) + * @param {string} guid 对象的唯一标识 + * @meta standard + * @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。 + * guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。
+ * baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。 + */ + baidu.lang.Class = function(guid) { + this.guid = guid || baidu.lang.guid(); + window[baidu.guid]._instances[this.guid] = this; + }; + + window[baidu.guid]._instances = window[baidu.guid]._instances || {}; + + /** + * 判断目标参数是否string类型或String对象 + * @name baidu.lang.isString + * @function + * @grammar baidu.lang.isString(source) + * @param {Any} source 目标参数 + * @shortcut isString + * @meta standard + * + * @returns {boolean} 类型判断结果 + */ + baidu.lang.isString = function (source) { + return '[object String]' == Object.prototype.toString.call(source); + }; + + /** + * 判断目标参数是否为function或Function实例 + * @name baidu.lang.isFunction + * @function + * @grammar baidu.lang.isFunction(source) + * @param {Any} source 目标参数 + * @returns {boolean} 类型判断结果 + */ + baidu.lang.isFunction = function (source) { + return '[object Function]' == Object.prototype.toString.call(source); + }; + + /** + * 重载了默认的toString方法,使得返回信息更加准确一些。 + * @return {string} 对象的String表示形式 + */ + baidu.lang.Class.prototype.toString = function(){ + return "[object " + (this._className || "Object" ) + "]"; + }; + + /** + * 释放对象所持有的资源,主要是自定义事件。 + * @name dispose + * @grammar obj.dispose() + */ + baidu.lang.Class.prototype.dispose = function(){ + delete window[baidu.guid]._instances[this.guid]; + for(var property in this){ + if (!baidu.lang.isFunction(this[property])) { + delete this[property]; + } + } + this.disposed = true; + }; + + /** + * 自定义的事件对象。 + * @function + * @name baidu.lang.Event + * @grammar baidu.lang.Event(type[, target]) + * @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。 + * @param {Object} [target]触发事件的对象 + * @meta standard + * @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。 + * @see baidu.lang.Class + */ + baidu.lang.Event = function (type, target) { + this.type = type; + this.returnValue = true; + this.target = target || null; + this.currentTarget = null; + }; + + /** + * 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 + * @grammar obj.addEventListener(type, handler[, key]) + * @param {string} type 自定义事件的名称 + * @param {Function} handler 自定义事件被触发时应该调用的回调函数 + * @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。 + * @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。 + */ + baidu.lang.Class.prototype.addEventListener = function (type, handler, key) { + if (!baidu.lang.isFunction(handler)) { + return; + } + !this.__listeners && (this.__listeners = {}); + var t = this.__listeners, id; + if (typeof key == "string" && key) { + if (/[^\w\-]/.test(key)) { + throw("nonstandard key:" + key); + } else { + handler.hashCode = key; + id = key; + } + } + type.indexOf("on") != 0 && (type = "on" + type); + typeof t[type] != "object" && (t[type] = {}); + id = id || baidu.lang.guid(); + handler.hashCode = id; + t[type][id] = handler; + }; + + /** + * 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 + * @grammar obj.removeEventListener(type, handler) + * @param {string} type 事件类型 + * @param {Function|string} handler 要移除的事件监听函数或者监听函数的key + * @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。 + */ + baidu.lang.Class.prototype.removeEventListener = function (type, handler) { + if (baidu.lang.isFunction(handler)) { + handler = handler.hashCode; + } else if (!baidu.lang.isString(handler)) { + return; + } + !this.__listeners && (this.__listeners = {}); + type.indexOf("on") != 0 && (type = "on" + type); + var t = this.__listeners; + if (!t[type]) { + return; + } + t[type][handler] && delete t[type][handler]; + }; + + /** + * 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 + * @grammar obj.dispatchEvent(event, options) + * @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持) + * @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持) + * @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。 + * 例如:
+ * myobj.onMyEvent = function(){}
+ * myobj.addEventListener("onMyEvent", function(){}); + */ + baidu.lang.Class.prototype.dispatchEvent = function (event, options) { + if (baidu.lang.isString(event)) { + event = new baidu.lang.Event(event); + } + !this.__listeners && (this.__listeners = {}); + options = options || {}; + for (var i in options) { + event[i] = options[i]; + } + var i, t = this.__listeners, p = event.type; + event.target = event.target || this; + event.currentTarget = this; + p.indexOf("on") != 0 && (p = "on" + p); + baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments); + if (typeof t[p] == "object") { + for (i in t[p]) { + t[p][i].apply(this, arguments); + } + } + return event.returnValue; + }; + + /** + * 为类型构造器建立继承关系 + * @name baidu.lang.inherits + * @function + * @grammar baidu.lang.inherits(subClass, superClass[, className]) + * @param {Function} subClass 子类构造器 + * @param {Function} superClass 父类构造器 + * @param {string} className 类名标识 + * @remark 使subClass继承superClass的prototype, + * 因此subClass的实例能够使用superClass的prototype中定义的所有属性和方法。
+ * 这个函数实际上是建立了subClass和superClass的原型链集成,并对subClass进行了constructor修正。
+ * 注意:如果要继承构造函数,需要在subClass里面call一下,具体见下面的demo例子 + * @shortcut inherits + * @meta standard + * @see baidu.lang.Class + */ + baidu.lang.inherits = function (subClass, superClass, className) { + var key, proto, + selfProps = subClass.prototype, + clazz = new Function(); + clazz.prototype = superClass.prototype; + proto = subClass.prototype = new clazz(); + for (key in selfProps) { + proto[key] = selfProps[key]; + } + subClass.prototype.constructor = subClass; + subClass.superClass = superClass.prototype; + + if ("string" == typeof className) { + proto._className = className; + } + }; + + /** + * @ignore + * @namespace baidu.dom 操作dom的方法。 + */ + baidu.dom = baidu.dom || {}; + + /** + * 从文档中获取指定的DOM元素 + * + * @param {string|HTMLElement} id 元素的id或DOM元素 + * @meta standard + * @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数 + */ + baidu._g = baidu.dom._g = function (id) { + if (baidu.lang.isString(id)) { + return document.getElementById(id); + } + return id; + }; + + /** + * 从文档中获取指定的DOM元素 + * @name baidu.dom.g + * @function + * @grammar baidu.dom.g(id) + * @param {string|HTMLElement} id 元素的id或DOM元素 + * @meta standard + * + * @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数 + */ + baidu.g = baidu.dom.g = function (id) { + if ('string' == typeof id || id instanceof String) { + return document.getElementById(id); + } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) { + return id; + } + return null; + }; + + /** + * 在目标元素的指定位置插入HTML代码 + * @name baidu.dom.insertHTML + * @function + * @grammar baidu.dom.insertHTML(element, position, html) + * @param {HTMLElement|string} element 目标元素或目标元素的id + * @param {string} position 插入html的位置信息,取值为beforeBegin,afterBegin,beforeEnd,afterEnd + * @param {string} html 要插入的html + * @remark + * + * 对于position参数,大小写不敏感
+ * 参数的意思:beforeBegin<span>afterBegin this is span! beforeEnd</span> afterEnd
+ * 此外,如果使用本函数插入带有script标签的HTML字符串,script标签对应的脚本将不会被执行。 + * + * @shortcut insertHTML + * @meta standard + * + * @returns {HTMLElement} 目标元素 + */ + baidu.insertHTML = baidu.dom.insertHTML = function (element, position, html) { + element = baidu.dom.g(element); + var range,begin; + + if (element.insertAdjacentHTML) { + element.insertAdjacentHTML(position, html); + } else { + // 这里不做"undefined" != typeof(HTMLElement) && !window.opera判断,其它浏览器将出错?! + // 但是其实做了判断,其它浏览器下等于这个函数就不能执行了 + range = element.ownerDocument.createRange(); + // FF下range的位置设置错误可能导致创建出来的fragment在插入dom树之后html结构乱掉 + // 改用range.insertNode来插入html, by wenyuxiang @ 2010-12-14. + position = position.toUpperCase(); + if (position == 'AFTERBEGIN' || position == 'BEFOREEND') { + range.selectNodeContents(element); + range.collapse(position == 'AFTERBEGIN'); + } else { + begin = position == 'BEFOREBEGIN'; + range[begin ? 'setStartBefore' : 'setEndAfter'](element); + range.collapse(begin); + } + range.insertNode(range.createContextualFragment(html)); + } + return element; + }; + + /** + * 为目标元素添加className + * @name baidu.dom.addClass + * @function + * @grammar baidu.dom.addClass(element, className) + * @param {HTMLElement|string} element 目标元素或目标元素的id + * @param {string} className 要添加的className,允许同时添加多个class,中间使用空白符分隔 + * @remark + * 使用者应保证提供的className合法性,不应包含不合法字符,className合法字符参考:http://www.w3.org/TR/CSS2/syndata.html。 + * @shortcut addClass + * @meta standard + * + * @returns {HTMLElement} 目标元素 + */ + baidu.ac = baidu.dom.addClass = function (element, className) { + element = baidu.dom.g(element); + var classArray = className.split(/\s+/), + result = element.className, + classMatch = " " + result + " ", + i = 0, + l = classArray.length; + + for (; i < l; i++){ + if ( classMatch.indexOf( " " + classArray[i] + " " ) < 0 ) { + result += (result ? ' ' : '') + classArray[i]; + } + } + + element.className = result; + return element; + }; + + /** + * @ignore + * @namespace baidu.event 屏蔽浏览器差异性的事件封装。 + * @property target 事件的触发元素 + * @property pageX 鼠标事件的鼠标x坐标 + * @property pageY 鼠标事件的鼠标y坐标 + * @property keyCode 键盘事件的键值 + */ + baidu.event = baidu.event || {}; + + /** + * 事件监听器的存储表 + * @private + * @meta standard + */ + baidu.event._listeners = baidu.event._listeners || []; + + /** + * 为目标元素添加事件监听器 + * @name baidu.event.on + * @function + * @grammar baidu.event.on(element, type, listener) + * @param {HTMLElement|string|window} element 目标元素或目标元素id + * @param {string} type 事件类型 + * @param {Function} listener 需要添加的监听器 + * @remark + * 1. 不支持跨浏览器的鼠标滚轮事件监听器添加
+ * 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败 + * @shortcut on + * @meta standard + * @see baidu.event.un + * + * @returns {HTMLElement|window} 目标元素 + */ + baidu.on = baidu.event.on = function (element, type, listener) { + type = type.replace(/^on/i, ''); + element = baidu._g(element); + var realListener = function (ev) { + // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载 + // 2. element是为了修正this + listener.call(element, ev); + }, + lis = baidu.event._listeners, + filter = baidu.event._eventFilter, + afterFilter, + realType = type; + type = type.toLowerCase(); + // filter过滤 + if(filter && filter[type]){ + afterFilter = filter[type](element, type, realListener); + realType = afterFilter.type; + realListener = afterFilter.listener; + } + // 事件监听器挂载 + if (element.addEventListener) { + element.addEventListener(realType, realListener, false); + } else if (element.attachEvent) { + element.attachEvent('on' + realType, realListener); + } + + // 将监听器存储到数组中 + lis[lis.length] = [element, type, listener, realListener, realType]; + return element; + }; + + /** + * 为目标元素移除事件监听器 + * @name baidu.event.un + * @function + * @grammar baidu.event.un(element, type, listener) + * @param {HTMLElement|string|window} element 目标元素或目标元素id + * @param {string} type 事件类型 + * @param {Function} listener 需要移除的监听器 + * @shortcut un + * @meta standard + * + * @returns {HTMLElement|window} 目标元素 + */ + baidu.un = baidu.event.un = function (element, type, listener) { + element = baidu._g(element); + type = type.replace(/^on/i, '').toLowerCase(); + + var lis = baidu.event._listeners, + len = lis.length, + isRemoveAll = !listener, + item, + realType, realListener; + + //如果将listener的结构改成json + //可以节省掉这个循环,优化性能 + //但是由于un的使用频率并不高,同时在listener不多的时候 + //遍历数组的性能消耗不会对代码产生影响 + //暂不考虑此优化 + while (len--) { + item = lis[len]; + + // listener存在时,移除element的所有以listener监听的type类型事件 + // listener不存在时,移除element的所有type类型事件 + if (item[1] === type + && item[0] === element + && (isRemoveAll || item[2] === listener)) { + realType = item[4]; + realListener = item[3]; + if (element.removeEventListener) { + element.removeEventListener(realType, realListener, false); + } else if (element.detachEvent) { + element.detachEvent('on' + realType, realListener); + } + lis.splice(len, 1); + } + } + return element; + }; + + /** + * 阻止事件的默认行为 + * @name baidu.event.preventDefault + * @function + * @grammar baidu.event.preventDefault(event) + * @param {Event} event 事件对象 + * @meta standard + */ + baidu.preventDefault = baidu.event.preventDefault = function (event) { + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; + } + }; + })(); + + /** + * @exports DistanceTool as BMapLib.DistanceTool + */ + var DistanceTool = + /** + * DistanceTool类的构造函数 + * @class 距离测算类,实现测距效果的入口。 + * 实例化该类后,即可调用该类提供的open + * 方法开启测距状态。 + * + * @constructor + * @param {Map} map Baidu map的实例对象 + * @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:
+ * {"followText" : {String} 测距过程中,提示框文字, + *
"unit" : {String} 测距结果所用的单位制,可接受的属性为"metric"表示米制和"us"表示美国传统单位, + *
"lineColor" : {String} 折线颜色, + *
"lineStroke" : {Number} 折线宽度, + *
"opacity" : {Number} 透明度, + *
"lineStyle" : {String} 折线的样式,只可设置solid和dashed, + *
"secIcon" : {BMap.Icon} 转折点的Icon, + *
"closeIcon" : {BMap.Icon} 关闭按钮的Icon, + *
"cursor" : {String} 跟随的鼠标样式} + * + * @example 参考示例:
+ * var map = new BMap.Map("container");
map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);
var myDistanceToolObject = new BMapLib.DistanceTool(map, {lineStroke : 2}); + */ + BMapLib.DistanceTool = function(map, opts){ + if (!map) { + return; + } + + /** + * map对象 + * @private + * @type {Map} + */ + this._map = map; + + opts = opts || {}; + /** + * _opts是默认参数赋值。 + * 下面通过用户输入的opts,对默认参数赋值 + * @private + * @type {Json} + */ + this._opts = baidu.extend( + baidu.extend(this._opts || {}, { + + /** + * 测距提示 + * @private + * @type {String} + */ + tips : "测距", + + /** + * 测距过程中,提示框文字 + * @private + * @type {String} + */ + followText : "单击确定地点,双击结束", + + /** + * 测距结果所用的单位制,可接受的属性为"metric"表示米制和"us"表示美国传统单位 + * @private + * @type {String} + */ + unit : "metric", + + /** + * 折线颜色 + * @private + * @type {String} + */ + lineColor : "#ff6319", + + /** + * 折线线宽 + * @private + * @type {Number} + */ + lineStroke : 2, + + /** + * 折线透明度 + * @private + * @type {Number} + */ + opacity : 0.8, + + /** + * 折线样式 + * @private + * @type {String} + */ + lineStyle : "solid", + + /** + * 跟随鼠标样式 + * @private + * @type {String} + */ + cursor : "http://api.map.baidu.com/images/ruler.cur", + + /** + * 转折点的ICON样式 + * @private + * @type {BMap.Icon} + */ + secIcon : null, + + /** + * 转折点的ICON样式 + * @private + * @type {BMap.Icon} + */ + closeIcon : null + }) + , opts); + + /** + * 跟随的title覆盖物 + * @private + * @type {BMap.Label} + */ + this._followTitle = null; + + /** + * 折线包含所有点的数组 + * @private + * @type {Array} + */ + this._points = []; + + /** + * 折线所包含的所有path数组 + * @private + * @type {Array} + */ + this._paths = []; + + /** + * 折线结点图片数组 + * @private + * @type {Array} + */ + this._dots = []; + + /** + * 折线测距包含所有线段的距离 + * @private + * @type {Array} + */ + this._segDistance = []; + + /** + * 覆盖物的数组 + * @private + * @type {Array} + */ + this._overlays = []; + + /** + * 是否在调用map.clearOverlays清除画线需要建立的相关overlay元素 + * @private + * @type {Boolean} + */ + this._enableMassClear = true, + + /** + * 单位制,存储语言包中定义的单位名称 + * @private + * @type {Json} + */ + this._units = { + // metric 表示米制 + metric : { + /** + * 米制的名称 + * @type {String} + */ + name : "metric", + + /** + * 和米制的换算关系 + * @type {Number} + */ + conv : 1, + + /** + * 米制单位下两个单位制之间的换算关系 + * @type {Number} + */ + incon : 1000, + + /** + * 米制单位下较小单位 + * @type {String} + */ + u1 : "米", + + /** + * 米制单位下较大单位 + * @type {String} + */ + u2 : "公里" + }, + // us 表示美国传统单位,各参数意义同上metric + us : { + name : "us", + conv : 3.2808, + incon : 5279.856, + u1 : "英尺", + u2 : "英里" + } + }; + + /** + * 是否已经开启了测距状态 + * @private + * @type {Boolean} + */ + this._isOpen = false; + + /** + * 未点击任何一点时,鼠标移动时的跟随提示文字 + * @private + * @type {String} + */ + this._startFollowText = "单击确定起点"; + + /** + * 地图移动的计时器 + * @private + * @type {Object} + */ + this._movingTimerId = null; + + /** + * 测距需要添加的CSS样式 + * @private + * @type {Json} + */ + this._styles = { + "BMapLib_diso" : "height:17px;width:5px;position:absolute;background:url(http://api.map.baidu.com/images/dis_box_01.gif) no-repeat left top" + ,"BMapLib_disi" : "color:#7a7a7a;position:absolute;left:5px;padding:0 4px 1px 0;line-height:17px;background:url(http://api.map.baidu.com/images/dis_box_01.gif) no-repeat right top" + ,"BMapLib_disBoxDis" : "color:#ff6319;font-weight:bold;" + }; + + if (this._opts.lineStroke <= 0) { + this._opts.lineStroke = 2; + } + if (this._opts.opacity > 1) { + this._opts.opacity = 1; + } else if (this._opts.opacity < 0) { + this._opts.opacity = 0; + } + if (this._opts.lineStyle != "solid" && + this._opts.lineStyle != "dashed") { + this._opts.lineStyle = "solid"; + } + if (!this._units[this._opts.unit]) { + this._opts.unit = "metric"; + } + + this.text = "测距"; + } + + // 通过baidu.lang下的inherits方法,让DistanceTool继承baidu.lang.Class + baidu.lang.inherits(DistanceTool, baidu.lang.Class, "DistanceTool"); + + /** + * 地图区域的移动事件绑定 + * @return 无返回值 + */ + DistanceTool.prototype._bind = function(){ + // 设置鼠标样式 + this._setCursor(this._opts.cursor); + var me = this; + // 在装载地图的页面元素上,绑定鼠标移动事件 + baidu.on(this._map.getContainer(), "mousemove", function(e){ + if (!me._isOpen) { + return; + } + if (!me._followTitle) { + return; + } + e = window.event || e; + var t = e.target || e.srcElement; + // 如果触发该事件的页面元素不是遮盖效果层,则返回,无操作 + if (t != OperationMask.getDom(me._map)) { + me._followTitle.hide(); + return; + } + if (!me._mapMoving) { + me._followTitle.show(); + } + // 设置鼠标移动过程中,跟随的文字提示框的位置 + var pt = OperationMask.getDrawPoint(e, true); + me._followTitle.setPosition(pt); + }); + // 创建鼠标跟随的文字提示框 + if (this._startFollowText) { + var t = this._followTitle = new BMap.Label(this._startFollowText, {offset : new BMap.Size(14, 16)}); + this._followTitle.setStyles({color : "#333", borderColor : "#ff0103"}); + } + }; + + /** + * 开启地图的测距状态 + * @return {Boolean},开启测距状态成功,返回true;否则返回false。 + * + * @example 参考示例:
+ * myDistanceToolObject.open(); + */ + DistanceTool.prototype.open = function(){ + // 判断测距状态是否已经开启 + if (this._isOpen == true){ + return true; + } + // 已有其他地图上的鼠标操作工具开启 + if (!!BMapLib._toolInUse) { + return; + } + this._isOpen = true; + BMapLib._toolInUse = true; + + // 判断是否是否在移动过程中 + if (this._mapMoving){ + delete this._mapMoving; + } + + var me = this; + // 增加鼠标在地图区域移动的事件 + // 通过binded参数,避免多次绑定 + if (!this._binded) { + this._binded = true; + // 绑定控件项事件 + this._bind(); + // 地图的移动过程中,需要隐藏相关的提示框 + this._map.addEventListener("moving", function(){ + me._hideCurrent(); + }); + } + + // 将文字提示框作为BMap.Label元素,提交给Map Api进行管理 + if (this._followTitle) { + this._map.addOverlay(this._followTitle); + this._followTitle.hide(); + } + + /** + * 测距过程中,点击地图时,触发的操作 + * @ignore + * @param {Object} e event对象 + */ + var distClick = function(e) { + var map = me._map; + if (!me._isOpen) { + return; + } + // 通过event对象,计算得出点击位置的物理坐标,poi为一个BMap.Point对象 + e = window.event || e; + var poi = OperationMask.getDrawPoint(e, true); + // 验证计算得出的该点的位置合理性 + if (!me._isPointValid(poi)) { + return; + } + // 记录当前点的屏幕位置 + me._bind.initX = e.pageX || e.clientX || 0; + me._bind.initY = e.pageY || e.clientY || 0; + + // 这个if循环内的计算是,判断当前这个点,与存储内的最后一个点的距离, + // 如果距离过小,比如小于5,可以认为是用户的误点,可以忽略掉 + if (me._points.length > 0){ + var lstPx = map.pointToPixel(me._points[me._points.length - 1]); + var thisPx = map.pointToPixel(poi); + var dis = Math.sqrt(Math.pow(lstPx.x - thisPx.x, 2) + Math.pow(lstPx.y - thisPx.y, 2)); + if (dis < 5) { + return; + } + } + + me._bind.x = e.layerX || e.offsetX || 0; + me._bind.y = e.layerY || e.offsetY || 0; + me._points.push(poi); + // 添加测距结点 + me._addSecPoint(poi); + + // 调整跟踪鼠标的标签 + if (me._paths.length == 0) { + me._formatTitle(1, me._opts.followText, me._getTotalDistance()); + } + + // 修改确定线的颜色 + if (me._paths.length > 0) { + me._paths[me._paths.length - 1].show(); + me._paths[me._paths.length - 1].setStrokeOpacity(me._opts.opacity); + } + + var path = new BMap.Polyline([poi, poi], {enableMassClear : me._enableMassClear}); + me._map.addOverlay(path); + me._paths.push(path); + me._overlays.push(path); + + // 测距模式下线样式固定 + path.setStrokeWeight(me._opts.lineStroke); + path.setStrokeColor(me._opts.lineColor); + path.setStrokeOpacity(me._opts.opacity / 2); + path.setStrokeStyle(me._opts.lineStyle); + + // 如果地图正在移动则隐藏掉 + if (me._mapMoving){ + path.hide(); + } + + if (me._points.length > 1) { + var siblingPath = me._paths[me._points.length - 2]; + siblingPath.setPositionAt(1, poi); + } + + // 生成节点旁边的距离显示框 + var disText = ""; + if (me._points.length > 1) { + // 非起点的节点,显示当前的距离 + var segDis = me._setSegDistance(me._points[me._points.length - 2], me._points[me._points.length - 1]); + var meters = me._getTotalDistance(); + disText = me._formatDisStr(meters); + } else { + disText = "起点"; + } + var disLabel = new BMap.Label(disText, {offset : new BMap.Size(10, -5), enableMassClear : me._enableMassClear}); + disLabel.setStyles({color : "#333", borderColor : "#ff0103"}); + me._map.addOverlay(disLabel); + me._formatSegLabel(disLabel, disText); + me._overlays.push(disLabel); + poi.disLabel = disLabel; + disLabel.setPosition(poi); + + /** + * 测距过程中,每次点击底图添加节点时,派发事件的接口 + * @name DistanceTool#onaddpoint + * @event + * @param {Event Object} e 回调函数会返回event参数,包括以下返回值: + *
{"point : {BMap.Point} 最新添加上的节点BMap.Point对象, + *
"pixel:{BMap.pixel} 最新添加上的节点BMap.Pixel对象, + *
"index:{Number} 最新添加的节点的索引, + *
"distance:{Number} 截止最新添加的节点的总距离} + * + * @example 参考示例:
+ * myDistanceToolObject.addEventListener("addpoint", function(e) { alert(e.distance); }); + */ + + // 生成名为onaddpoint的baidu.lang.Event对象 + // 并给该event对象添加上point、pixel、index和distance等属性字段 + // 然后在此刻,将绑定在onaddpoint上事件,全部赋予event参数,然后派发出去 + var event = new baidu.lang.Event("onaddpoint"); + event.point = poi; + event.pixel = me._map.pointToPixel(poi); + event.index = me._points.length - 1; + event.distance = me._getTotalDistance().toFixed(0); + me.dispatchEvent(event); + }; + + /** + * 测距过程中,鼠标在地图上移动时,触发的操作 + * @ignore + * @param {Object} e event对象 + */ + var distMove = function(e) { + if (!me._isOpen){ + return; + } + // 通过判断数组me._paths的长度,判断当前是否已经有测量节点 + // 也就是,如果没有节点,则还没有开始测量 + if (me._paths.length > 0) { + // 通过event参数,计算当前点的位置 + e = window.event || e; + var curX = e.pageX || e.clientX || 0; + var curY = e.pageY || e.clientY || 0; + if (typeof me._bind.initX == "undefined") { + me._bind.x = e.layerX || e.offsetX || 0; + me._bind.y = e.layerY || e.offsetY || 0; + me._bind.initX = curX; + me._bind.initY = curY; + } + var x = me._bind.x + curX - me._bind.initX; + var y = me._bind.y + curY - me._bind.initY; + + // 修改最后一条折线的终点位置,使之随着鼠标移动画线 + var path = me._paths[me._paths.length - 1]; + var poi = me._map.pixelToPoint(new BMap.Pixel(x, y)); + path.setPositionAt(1, poi); + + if (!me._mapMoving) { + path.show(); + } + var dx = 0; + var dy = 0; + // 计算当前鼠标位置,是否靠近边界、或者已经出了边界 + // 如果在边界位置,则需要向对应的方向移动地图,来进行测量 + // 每次移动的距离,设定为8 + if (x < 10) { + dx = 8; + } else if (x > me._map.getSize().width - 10){ + dx = -8; + } + if (y < 10) { + dy = 8; + } else if (y > me._map.getSize().height - 10){ + dy = -8; + } + // 如果dx和dy都等于0,表明不需要移动地图 + if (dx != 0 || dy != 0){ + // 此时需要向一个方向,平移地图 + if (!distMove._movingTimerId){ + me._mapMoving = true; + me._map.panBy(dx, dy, {noAnimation : true}); + me._movingTimerId = distMove._movingTimerId = setInterval(function(){ + me._map.panBy(dx, dy, {noAnimation : true}); + }, 30); + // 地图移动过程中,隐藏线段和标签 + path.hide(); + me._followTitle && me._followTitle.hide(); + } + } else { + if (distMove._movingTimerId) { + // 此时用户不在需要移动地图来测量,可以清除计时器 + clearInterval(distMove._movingTimerId); + delete distMove._movingTimerId; + delete me._movingTimerId; + + // 显示跟随提示框,并修改线路位置 + var lstP = me._paths[me._paths.length - 1]; + var poiN = me._map.pixelToPoint(new BMap.Pixel(x, y)); + if (!lstP) { + return; + } + lstP.setPositionAt(1, poiN); + lstP.show(); + if (me._followTitle) { + me._followTitle.setPosition(poiN); + me._followTitle.show(); + } + me._bind.i = 0; + me._bind.j = 0; + delete me._mapMoving; + } + } + // 实时更新文字提示框中的距离 + if (me._followTitle) { + var td = me._getTotalDistance(); + var dis = me._map.getDistance(me._points[me._points.length - 1], poi); + me._updateInstDis(me._followTitle, td + dis); + } + } else { + // 此时用户还没有开始测量,只是鼠标随便在地图上移动 + if (me._followTitle) { + me._followTitle.show(); + e = window.event || e; + var t = e.target || e.srcElement; + if (t != OperationMask.getDom()) { + me._followTitle.hide(); + } + } + } + }; + + /** + * 测距要结束时,双击地图,触发的操作 + * @ignore + * @param {Object} e event对象 + */ + var distDblclick = function(e) { + if (!me._isOpen) { + return; + } + // 结束时,删除绑定的事件 + baidu.un(OperationMask.getDom(me._map), "click", distClick); + baidu.un(document, "mousemove", distMove); + baidu.un(OperationMask.getDom(me._map), "dblclick", distDblclick); + baidu.un(document, "keydown", distKeyDown); + baidu.un(OperationMask.getDom(me._map), "mouseup", distMouseUp); + + // 调用close()关闭测距状态 + setTimeout(function(){ + me.close(); + }, 50); + }; + + /** + * 测距时的键盘操作 + * @ignore + * @param {Object} e event对象 + */ + var distKeyDown = function(e){ + e = window.event || e; + if (e.keyCode == 27){ + // [ESC]退出本次测距 + me._clearCurData(); + setTimeout(function(){ + me.close(); + }, 50); + } + }; + + /** + * 测距过程中,鼠标弹起时,触发的操作 + * @ignore + * @param {Object} e event对象 + */ + var distMouseUp = function(e) { + e = window.event || e; + var ieVersion = 0; + if (/msie (\d+\.\d)/i.test(navigator.userAgent)) { + ieVersion = document.documentMode || + RegExp['\x241']; + } + if (ieVersion && + e.button != 1 || + e.button == 2){ + me.close(); + } + }; + + // 初始化存储数据 + me._initData(); + + // 调整title的内容 + this._formatTitle(); + + // 创建透明覆盖层,并设置鼠标样式 + OperationMask.show(this._map); + this._setCursor(this._opts.cursor); + + // 绑定全部事件 + baidu.on(OperationMask.getDom(this._map), "click", distClick); + baidu.on(document, "mousemove", distMove); + baidu.on(OperationMask.getDom(this._map), "dblclick", distDblclick); + baidu.on(document, "keydown", distKeyDown); + baidu.on(OperationMask.getDom(this._map), "mouseup", distMouseUp); + + // 将绑定的事件、和对应的绑定对象,记录在数组中 + this.bindFunc = [ + {elem : OperationMask.getDom(this._map), type : "click", func : distClick}, + {elem : OperationMask.getDom(this._map), type : "dblclick", func : distDblclick}, + {elem : document, type : "mousemove", func : distMove}, + {elem : document, type : "keydown", func : distKeyDown}, + {elem : OperationMask.getDom(this._map), type : "mouseup", func : distMouseUp}]; + return true; + }; + + /** + * 画线结束时,派发drawend事件 + * @return 无返回值 + */ + DistanceTool.prototype._dispatchLastEvent = function() { + /** + * 测距时,每次双击底图结束当前测距折线时,派发事件的接口 + * @name DistanceTool#ondrawend + * @event + * @param {Event Object} e 回调函数会返回event参数,包括以下返回值: + *
{"points : {BMap.Point} 所有测量时,打下的节点BMap.Point对象, + *
"overlays:{Array} 所有测量时,生成的线段BMap.Overlay对象, + *
"distance:{Number} 测量解释时的最终距离} + * + * @example 参考示例:
+ * myDistanceToolObject.addEventListener("drawend", function(e) { alert(e.distance); }); + */ + + // 生成名为ondrawend的baidu.lang.Event对象 + // 并给该event对象添加上points、overlays和distance等属性字段 + // 然后在此刻,将绑定在ondrawend上事件,全部赋予event参数,然后派发出去 + var event = new baidu.lang.Event("ondrawend"); + event.points = + this._points ? + this._points.slice(0) : + []; + event.overlays = + this._paths ? + this._paths.slice(0, this._paths.length - 1) : + []; + event.distance = this._getTotalDistance().toFixed(0); + this.dispatchEvent(event); + }; + + /** + * 关闭测距状态 + * @return 无返回值 + * + * @example 参考示例:
+ * myDistanceToolObject.close(); + */ + DistanceTool.prototype.close = function(){ + if (this._isOpen == false){ + return; + } + this._isOpen = false; + BMapLib._toolInUse = false; + + if (this._mapMoving){ + delete this._mapMoving; + } + var me = this; + me._dispatchLastEvent(); + if (me._points.length < 2){ + // 不是有效绘制,清除所有内容 + me._clearCurData(); + } else { + me._paths[me._paths.length - 1].remove(); + me._paths[me._paths.length - 1] = null; + me._paths.length = me._paths.length - 1; + // 移除最近一次标记 + var pt = me._points[me._points.length - 1]; + if (pt.disLabel){ + pt.disLabel.remove(); + } + me._processLastOp(); + } + OperationMask.hide(); + + // 删除绑定的事件 + for (var i = 0, l = this.bindFunc.length; i < l; i ++){ + baidu.un(this.bindFunc[i].elem, this.bindFunc[i].type, this.bindFunc[i].func); + } + + // 停止地图移动 + if (me._movingTimerId){ + clearInterval(me._movingTimerId); + me._movingTimerId = null; + } + + if (this._followTitle){ + this._followTitle.hide(); + } + }; + + /** + * 清除本次测距的暂存数据 + * @return 无返回值 + */ + DistanceTool.prototype._clearCurData = function(){ + for (var i = 0, l = this._points.length; i < l; i ++){ + if (this._points[i].disLabel){ + this._points[i].disLabel.remove(); + } + } + for (var i = 0, l = this._paths.length; i < l; i ++){ + this._paths[i].remove(); + } + for (var i = 0, l = this._dots.length; i < l; i ++){ + this._dots[i].remove(); + } + this._initData(); + }; + + /** + * 初始化存储数组 + * @return 无返回值 + */ + DistanceTool.prototype._initData = function(){ + // 初始化point数组 + this._points.length = 0; + // 初始化path数组 + this._paths.length = 0; + // 初始化分段距离数组 + this._segDistance.length = 0; + // 初始化结点图像数组 + this._dots.length = 0; + }; + + /** + * 计算两点之间距离并存放在分段距离数组中 + * @param {Point} + * @param {Point} + * @return {Number} 两个地理点之间的距离 + */ + DistanceTool.prototype._setSegDistance = function(pt0, pt1){ + if (!pt0 || !pt1){ + return; + } + var dis = this._map.getDistance(pt0, pt1); + this._segDistance.push(dis); + return dis; + }; + + /** + * 获得总距离 + * @return {Number} 总距离 + */ + DistanceTool.prototype._getTotalDistance = function(){ + var totalDis = 0; + for (var i = 0, l = this._segDistance.length; i < l; i ++){ + totalDis += this._segDistance[i]; + } + return totalDis; + }; + + /** + * 将米制单位的数值换算成为目标单位下的数值 + * @type {Number} 需要转换的数值 + * @type {String} 字符串描述的目标单位, + * "metric" 表示米制单位, + * "us" 表示美国传统单位制 + * @return {Number} 转换后的数值 + */ + DistanceTool.prototype._convertUnit = function(num, unit){ + unit = unit || "metric"; + if (this._units[unit]){ + return num * this._units[unit].conv; + } + return num; + }; + + /** + * 添加测距结点 + * @param {BMap.Point} 节点 + * @return 无返回值 + */ + DistanceTool.prototype._addSecPoint = function(pt){ + var ico = + this._opts.secIcon ? + this._opts.secIcon : + new BMap.Icon("http://api.map.baidu.com/images/mapctrls.png", new BMap.Size(11, 11), {imageOffset: new BMap.Size(-26, -313)}); + var secPt = new BMap.Marker(pt, { + icon : ico, + clickable : false, + baseZIndex : 3500000, + zIndexFixed : true, + enableMassClear : this._enableMassClear + }); + this._map.addOverlay(secPt); + this._dots.push(secPt); + }; + + /** + * 格式化距离字符串 + * @param {Number} 距离 + * @return {String} 格式化的字符串 + */ + DistanceTool.prototype._formatDisStr = function(distance){ + var u = this._opts.unit; + var unit = this._units[u].u1; + var dis = this._convertUnit(distance, u); + + if (dis > this._units[u].incon){ + dis = dis / this._units[u].incon; + unit = this._units[u].u2; + dis = dis.toFixed(1); + } else { + dis = dis.toFixed(0); + } + return dis + unit; + }; + + /** + * 设置鼠标样式 + * @param {String} cursor 鼠标样式 + * @return 没有返回值 + */ + DistanceTool.prototype._setCursor = function(cursor){ + // 由于webkit内核浏览器下,cursor设置后默认不会居中,所以需要对偏移值进行设置 + var csr = + /webkit/.test(navigator.userAgent.toLowerCase()) ? + "url(" + this._opts.cursor + ") 3 6, crosshair" : + "url(" + this._opts.cursor + "), crosshair" + OperationMask._setCursor(csr); + }; + + /** + * 获取鼠标样式 + * @return {String} 跟随的鼠标样式 + */ + DistanceTool.prototype._getCursor = function(){ + return this._opts.cursor; + }; + + /** + * 调整分段距离样式 + * @param {BMap.Label} label 提示框的Label + * @param {String} 需要填入的文字 + * @return 没有返回值 + */ + DistanceTool.prototype._formatSegLabel = function(label, text){ + label.setStyle({"border" : "none", "padding" : "0"}); + label.setContent("" + text + ""); + }; + + /** + * 处理最后一次操作,当用户双击或测距被强行退出时调用 + * @return 没有返回值 + */ + DistanceTool.prototype._processLastOp = function() { + var me = this; + // 删除上次移动临时数据 + delete me._bind.x; + delete me._bind.y; + delete me._bind.initX; + delete me._bind.initY; + // 验证路径 + if (me._paths.length > me._points.length - 1){ + var l = me._paths.length - 1; + me._paths[l].remove(); + me._paths[l] = null; + me._paths.length = l; + } + // 保存本次测距对象 + var disObj = {}; + disObj.points = me._points.slice(0); + disObj.paths = me._paths.slice(0); + disObj.dots = me._dots.slice(0); + disObj.segDis = me._segDistance.slice(0); + // 判断总距离和按钮位置 + var lstPx = me._map.pointToPixel(disObj.points[disObj.points.length - 1]); + var prePx = me._map.pointToPixel(disObj.points[disObj.points.length - 2]); + var btnOffset = [0, 0]; + var disOffset = [0, 0]; + if (lstPx.y - prePx.y >= 0){ + // 距离位于下端 + disOffset = [-5, 11]; + } else { + // 距离位于上端 + disOffset = [-5, -35]; + } + if (lstPx.x - prePx.x >= 0){ + // 按钮位于右侧 + btnOffset = [14, 0]; + } else { + // 按钮位于左侧 + btnOffset = [-14, 0]; + } + // 显示总距离 + var pt = disObj.points[disObj.points.length - 1]; + pt.disLabel = new BMap.Label("", {offset: new BMap.Size(-15, -40), enableMassClear: me._enableMassClear}); + pt.disLabel.setStyles({color: "#333", borderColor: "#ff0103"}); + me._map.addOverlay(pt.disLabel); + pt.disLabel.setOffset(new BMap.Size(disOffset[0], disOffset[1])); + pt.disLabel.setPosition(pt); + me._formatTitle(2, "", "", pt.disLabel); + // 添加关闭按钮 + var bico = + this._opts.closeIcon ? + this._opts.closeIcon : + new BMap.Icon("http://api.map.baidu.com/images/mapctrls.gif", new BMap.Size(12, 12), {imageOffset: new BMap.Size(0, -14)}); + disObj.closeBtn = new BMap.Marker(disObj.points[disObj.points.length - 1], + {icon : bico, + offset : new BMap.Size(btnOffset[0], btnOffset[1]), + baseZIndex : 3600000, + enableMassClear : me._enableMassClear} + ); + me._map.addOverlay(disObj.closeBtn); + disObj.closeBtn.setTitle("清除本次测距"); + // 点击关闭按钮,绑定关闭按钮事件 + disObj.closeBtn.addEventListener("click", function(e){ + // 关闭本次测距,清除相关存储和变量 + for (var i = 0, l = disObj.points.length; i < l; i ++){ + disObj.points[i].disLabel.remove(); + disObj.points[i].disLabel = null; + } + for (var i = 0, l = disObj.paths.length; i < l; i ++){ + disObj.paths[i].remove(); + disObj.paths[i] = null; + } + for (var i = 0, l = disObj.dots.length; i < l; i ++){ + disObj.dots[i].remove(); + disObj.dots[i] = null; + } + disObj.closeBtn.remove(); + disObj.closeBtn = null; + stopBubble(e); + + /** + * @ignore + * 测距结束后,点击线段上最后一个节点旁的关闭按钮时,派发事件的接口 + * @name DistanceTool#onremovepolyline + * @event + * @param {Event Object} e 回调函数会返回event参数 + * + * @example 参考示例:
+ * myDistanceToolObject.addEventListener("removepolyline", function(e) { alert(e.type); }); + */ + + // 生成名为onremovepolyline的baidu.lang.Event对象 + // 然后在此刻,将绑定在onremovepolyline上事件,全部赋予event参数,然后派发出去 + var event = new baidu.lang.Event("onremovepolyline"); + me.dispatchEvent(event); + }); + me._initData(); + }; + + /** + * 生成测距过程中的文字提示框 + * @param {String} type + * @param {String} text + * @param {String} distance + * @param {Label} label + * @return 无返回值 + */ + DistanceTool.prototype._formatTitle = function(type, text, distance, label){ + var title = label || this._followTitle; + if (!title){ + return; + } + title.setStyle({"lineHeight" : "16px", "zIndex" : "85", "padding" : "0px 0px","border": "none","backgroud-color":"rgba(0,0,0,0.0)"}); + var t = this._startFollowText || ""; + var htmls = []; + if (type == 1){ + // 测距过程中的提示 + title.setOffset(0, 25); + var u = this._opts.unit; + var unit = this._units[u].u1; + var dis = this._convertUnit(distance, u); + if (dis > this._units[u].incon){ + dis = dis / this._units[u].incon; + unit = this._units[u].u2; + dis = dis.toFixed(1); + } else { + dis = dis.toFixed(0); + } + htmls.push("总长:" + dis + "" + unit + "
"); + htmls.push("" + text + ""); + } else if (type == 2) { + // 结束时的总距离展示 + var u = this._opts.unit; + var unit = this._units[u].u1; + var dis = this._convertUnit(this._getTotalDistance(), u); + if (dis > this._units[u].incon){ + dis = dis / this._units[u].incon; + unit = this._units[u].u2; + dis = dis.toFixed(1); + } else{ + dis = dis.toFixed(0); + } + htmls.push("总长:" + dis + "" + unit); + } else { + title.setOffset(0, 25); + htmls.push(t); + } + title.setContent(htmls.join("")); + }; + + /** + * 更新label的距离 + * @param HTMLElement label的DOM元素 + * @param Number 距离 + */ + DistanceTool.prototype._updateInstDis = function(label, dis){ + // 换算距离 + var u = this._opts.unit; + var unit = this._units[u].u1; + if (dis > this._units[u].incon){ + dis = dis / this._units[u].incon; + unit = this._units[u].u2; + dis = dis.toFixed(1); + } else { + dis = dis.toFixed(0); + } + // 修改Label的内容 + if (label) { + var htmls = []; + htmls.push("总长:" + dis + "" + unit + "
"); + htmls.push("" + this._opts.followText + ""); + label.setContent(htmls.join("")); + } + }; + + /** + * 隐藏相关的线段和提示框文字 + * @return 无返回值 + */ + DistanceTool.prototype._hideCurrent = function(){ + if (!this._isOpen){ + return; + } + if (this._paths.length > 0){ + var p = this._paths[this._paths.length - 1]; + p.hide(); + } + this._followTitle && this._followTitle.hide(); + }; + + /** + * 验证传入点的位置合理性 + * @param {BMap.Point} pt 需要被验证的point点 + * @return 无返回值 + */ + DistanceTool.prototype._isPointValid = function(pt){ + if (!pt){ + return false; + } + var mapBounds = this._map.getBounds(); + var sw = mapBounds.getSouthWest(), + ne = mapBounds.getNorthEast(); + if (pt.lng < sw.lng || + pt.lng > ne.lng || + pt.lat < sw.lat || + pt.lat > ne.lat) { + return false; + } + return true; + }; + + + /** + * OperationMask,透明覆盖层,在地图上进行鼠标绘制操作时使用, + * 闭包,对外不暴露 + */ + var OperationMask = { + /** + * map对象 + * @type {Map} + */ + _map : null, + + /** + * HTML字符串 + * @type {String} + */ + _html : "
", + + /** + * html元素 + * @type {HTMLElement} + */ + _maskElement : null, + + /** + * 鼠标指针 + * @type {String} + */ + _cursor: 'default', + + /** + * 操作层是否在使用中 + * @type {Boolean} + */ + _inUse: false, + + /** + * 透明覆盖层的显示 + * + * @param {Map} map map对象 + * @return 无返回值 + */ + show : function(map) { + if (!this._map) { + this._map = map; + } + this._inUse = true; + if (!this._maskElement) { + this._createMask(map); + } + this._maskElement.style.display = 'block'; + }, + + /** + * 创建覆盖层 + * + * @param {Map} map map对象 + * @return 无返回值 + */ + _createMask : function(map) { + this._map = map; + if (!this._map) { + return; + } + baidu.insertHTML(this._map.getContainer(), "beforeEnd", this._html); + var elem = this._maskElement = this._map.getContainer().lastChild; + + var stopAndPrevent = function(e) { + stopBubble(e); + return baidu.preventDefault(e); + } + baidu.on(elem, 'mouseup', function(e) { + if (e.button == 2) { + stopAndPrevent(e); + } + }); + baidu.on(elem, 'contextmenu', stopAndPrevent); + elem.style.display = 'none'; + }, + + /** + * 获取当前绘制点的地理坐标 + * + * @param {Event} e e对象 + * @param {Boolean} n 是否向上查到相对于地图container元素的坐标位置 + * @return Point对象的位置信息 + */ + getDrawPoint : function(e, n) { + e = window.event || e; + var x = e.layerX || e.offsetX || 0; + var y = e.layerY || e.offsetY || 0; + var t = e.target || e.srcElement; + if (t != OperationMask.getDom(this._map) && n == true) { + while (t && t != this._map.getContainer()) { + if (!(t.clientWidth == 0 && + t.clientHeight == 0 && + t.offsetParent && + t.offsetParent.nodeName.toLowerCase() == 'td')) { + x += t.offsetLeft; + y += t.offsetTop; + } + t = t.offsetParent; + } + } + + if (t != OperationMask.getDom(this._map) && + t != this._map.getContainer()) { + return; + } + if (typeof x === 'undefined' || + typeof y === 'undefined') { + return; + } + if (isNaN(x) || isNaN(y)) { + return; + } + return this._map.pixelToPoint(new BMap.Pixel(x, y)); + }, + + /** + * 透明覆盖层的隐藏 + * + * @return 无返回值 + */ + hide : function() { + if (!this._map) { + return; + } + this._inUse = false; + if (this._maskElement) { + this._maskElement.style.display = 'none'; + } + }, + + /** + * 获取HTML容器 + * + * @param {Map} map map对象 + * @return HTML容器元素 + */ + getDom : function(map) { + if (!this._maskElement) { + this._createMask(map); + } + return this._maskElement; + }, + + /** + * 设置鼠标样式 + * + * @type {String} cursor 鼠标样式 + * @return 无返回值 + */ + _setCursor : function(cursor) { + this._cursor = cursor || 'default'; + if (this._maskElement) { + this._maskElement.style.cursor = this._cursor; + } + } + }; + + /** + * 停止事件冒泡传播, + * 闭包,对外不暴露 + * + * @type {Event} e e对象 + */ + function stopBubble(e){ + var e = window.event || e; + e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; + }; +})(); \ No newline at end of file diff --git a/worldmap/static/js/Register.js b/worldmap/static/js/Register.js new file mode 100644 index 0000000..2232069 --- /dev/null +++ b/worldmap/static/js/Register.js @@ -0,0 +1,276 @@ +$(document).ready(function () { + //背景动画 + //glInitialize(); + //用户名验证 + var state1 = false; + $("#username").textbox('textbox').blur(function () { + if ($(this).val() == '') { + $("#uinfo").text("用户名不能为空"); + state1 = false;     + } else { + $.ajax({ + url: "./userExists.action", + async: true, + type: "POST", + dataType: "text", + data: { + username: $('#username').val().trim() + }, + success: function (flag) { + if (flag == "true") { + $("#uinfo").text("该用户名已存在,请重新填写"); + state1 = false; + } else if (flag == "false") { + $("#uinfo").text(''); + $("#uinfo").append(""); + state1 = true; + } + } + }) + } + }); + + //密码验证 + var state2 = false; + $("#password").textbox('textbox').blur(function () { + if ($(this).val() == '') { + $("#pinfo").text("密码不能为空"); + state2 = false;     + } else { + if ($(this).val().length < 6) { + $("#pinfo").text("密码必须大于等于6位,请重新填写"); + state2 = false;         + } else if ($(this).val().length > 20) { + $("#pinfo").text("密码必须小于等于20位,请重新填写"); + state2 = false;         + } else { +             $("#pinfo").text(''); +             $("#pinfo").append(""); +             state2 = true; + } + } + }); + //确认密码 + var state3 = false; + $("#passwordagain").textbox('textbox').blur(function () { + if ($(this).val() == '') { + $("#painfo").text("密码不能为空");      + state3 = false; + } else { + if ($("#passwordagain").textbox('getValue') != $("#password").val()) { + $("#painfo").text("两次输入的密码不一致,请重新填写");      + state3 = false; + } else { +             $("#painfo").text(''); +             $("#painfo").append(""); +             state3 = true;          + } + } + }); + //邮箱验证 + var state4 = false; + $("#email").textbox('textbox').blur(function () { + if ($(this).val() == '') { + $("#einfo").text("邮箱不能为空");      + state4 = false; + } else { + if (/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test($(this).val()) == false) { + $("#einfo").text("邮箱格式不正确,请重新填写"); + state4 = false;         + } else { + $.ajax({ + url: "./emailExists.action", + async: true, + type: "POST", + dataType: "text", + data: { + email: $('#email').val().trim() + }, + success: function (flag) { + if (flag == "true") { + $("#einfo").text("该邮箱已被占用,请重新填写"); + state4 = false; + } else if (flag == "false") { + $("#einfo").text(''); + $("#einfo").append(""); + state4 = true; + } + } + }) +         + } + } + }); + + var state5 = false; + $("#realname").textbox('textbox').blur(function () { + if ($(this).val() == '') { + $("#rninfo").text("姓名不能为空");      + state5 = false; + } + else{ + $("#rninfo").text(''); + $("#rninfo").append(""); + state5 = true; + } + });         + + + var state6 = false; + $("#comp").textbox('textbox').blur(function () { + if ($(this).val() == '') { + $("#cpinfo").text("所在单位不能为空"); + state6 = false;      + } + else{ + $("#cpinfo").text(''); + $("#cpinfo").append(""); + state6 = true; + } + }); + + var state7 = false; + $("#cretificate").textbox('textbox').blur(function () { + if ($(this).val() == '') { + $("#creinfo").text("证件号码不能为空");      + state7 = false; + } + else{ + $("#creinfo").text(''); + $("#creinfo").append(""); + state7 = true; + } + }); + + var state8 = false; + //初始化没有阅读相关政策时的状态——不能注册 + $("#mustagree").css("display","block"); + $("#registerbtn").addClass("disabled"); + $("#registerbtn").css("background","#aaaaaa"); + $("#registerbtn").hover(function(){ + $("#registerbt").css("background","#aaaaaa"); + }) + + $("#agree").click(function(){ + if($("#agree").is(':checked')){ + $("#mustagree").css("display","none"); + $("#registerbtn").removeClass("disabled"); + $("#registerbtn").css("background","#2573f0"); + $("#registerbtn").hover( + function(){ + $("#registerbtn").css("backgroun","#0000ff"); + $("#registerbtn").css("cursor","pointer"); + },function(){ + $("#registerbtn").css("background","#2573f0"); + }) + state8 = true; + }else{ + $("#mustagree").css("display","block"); + $("#registerbtn").addClass("disabled"); + $("#registerbtn").css("background","#aaaaaa"); + $("#registerbtn").hover(function(){ + $("#registerbt").css("background","#aaaaaa"); + }) + } + }); + + $("#cretifitype").combobox( + { + valueField:'id', + textField:'text', + data:[ + { + id:0, + text:"身份证" + }, + { + id:1, + text:"护照" + }, + { + id:2, + text:"学生证" + } + ] + + } + ); + $("#cretifitype").combobox('select',0); + //发邮件 + $("#sendcode2email").click(function () { + if(state4){ + $.ajax({ + url: "./sendcode2email.action", + async: true, + type: "POST", + dataType: "text", + data: { + email: $('#email').val().trim() + }, + //contentType:"application/json", + success: function (data) { + alert(data); + }, + error: function () { + alert("未知错误"); + } + }); + }else{ + alert("邮箱信息错误!") + } + }); + + //注册 + $("#registerbtn").click(function () { + if(!state8){} + if (state1 && state2 && state3 && state4 + && state5 && state6 && state7) { + $.ajax({ + url: "./register.action", + type: "POST", + dataType: "text", + data: { + username: $('#username').val().trim(), + password: hex_md5($('#password').val().trim()), + email: $('#email').val().trim(), + checkcode: $('#email_code').val().trim(), + cretificate:$('#cretificate').val().trim(), + realname:$('#realname').val().trim(), + comp:$('#comp').val().trim(), + cretifitype:$('#cretifitype').combobox('getValue').trim(), + }, + success: function (row) { + if (row == 1) { + //alert("注册成功"); + $.messager.show({ + title: '恭喜您', + msg: '注册成功!', + showType: 'show', + timeout: 1000, + style: { + right: '', + bottom: '', + } + }); + setTimeout(function () { + window.location.href = "./index.action" + }, 1000); + } else { + alert(row); + } + }, + error: function () { + alert("未知错误!"); + } + }) + } else { + $.messager.alert('注册失败', '注册信息不正确!'); + } + + }); + + $("#cancelbtn").click(function (){ + location.href = "http://localhost:8080/AncientMap/index.action"; + }); + +}) diff --git a/worldmap/static/js/base.js b/worldmap/static/js/base.js new file mode 100644 index 0000000..2ac0e74 --- /dev/null +++ b/worldmap/static/js/base.js @@ -0,0 +1,300 @@ +window.onload=function(){ + setImgHeight();//set the height according to the width, the rate is 4:3[noData.jpg] +} +//be activated when browser's size is changed +window.onresize=function(){ + setImgHeight();//set the height according to the width, the rate is 4:3[noData.jpg] +} +//set the selectchange event of category selectpicker +function selectOnChange1(obj){ + var value = obj.options[obj.selectedIndex].value; + showMaps("tmi1","hottest",value); +} +function selectOnChange2(obj){ + var value = obj.options[obj.selectedIndex].value; + showMaps("tmi2","latest", value); +} +function showCategorys(language){ + var url = "/getCategory/"; + var data = null; + var csrftoken = getCookie('csrftoken'); + $.ajax({ + url: url, + async: false, + cache: false, + type: "POST", + data: { + language: language + }, + success: function (res) { + data = $.parseJSON(res); + }, + beforeSend: function(xhr, settings) { + xhr.setRequestHeader("X-CSRFToken", csrftoken); + } + }); + var selectHTML = ""; + for(category in data){ + var categoryid = parseInt(category); + var categorydescription = data[category][0]; + selectHTML += "" + } + $("#category1").append(selectHTML); + $("#category2").append(selectHTML); + $("#category1").selectpicker('refresh'); + $("#category2").selectpicker('refresh'); +} +function showMaps(divIdPrefix, type, category){ + var result = null; + var url = "/getMostMaps/"; + var csrftoken = getCookie('csrftoken'); + $.ajax({ + url: url, + async: false, + type: "POST", + data: { + category: category, + type: type + }, + success: function (res) { + result = $.parseJSON(res); + }, + beforeSend: function(xhr, settings) { + xhr.setRequestHeader("X-CSRFToken", csrftoken); + } + }); + for(var i = 0; i< 6; i++) + { + var mapname, curdiv, imgurl, mapurl, img; + if(result[i] != null) + { + mapname = result[i][0]; + curdiv = divIdPrefix + (i+1); + imgurl = result[i][1]; + mapurl = result[i][2]; + img = $("#"+curdiv).find("img"); + $("#"+curdiv).attr("onclick","location='"+mapurl+"'"); + $("#"+curdiv).children("p").text(mapname); + + if(type=="admin"){ + if (mapname=="李白行迹图") { + imgurl =window.location.href+"uploaded/admingif/libai.gif" + }else if (mapname=="杜甫行迹图") { + imgurl =window.location.href+"uploaded/admingif/dufu.gif" + }else if (mapname=="汤显祖行迹图") { + imgurl =window.location.href+"uploaded/admingif/tangxianzu.gif" + }else if (mapname=="全宋文专题") { + imgurl =window.location.href+"uploaded/admingif/quansongwen.gif" + }else if (mapname=="清代妇女作家专题图") { + imgurl =window.location.href+"uploaded/admingif/qingdaifunv.gif" + } + } + + img.attr("src",imgurl); + } + else + { + curdiv = divIdPrefix + (i+1); + img = $("#"+curdiv).find("img"); + if(typeof($("#"+curdiv).attr("onclick"))!="undefined") + { + $("#"+curdiv).removeAttr("onclick"); + $("#"+curdiv).children("p").text(""); + img.attr("src","{{ STATIC_URL }}img/map/noData.jpg"); + } + } + } +} +// get cookie value from cookies +function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie !== '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) === (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} +function setImgHeight() { + var imgs = $(".picItem"); + imgs.each(function (i) { + var img = $(this); + var width = img.width(); + var height = width* 0.75; + img.height(height); + }); + var imgs = $(".item"); + imgs.each(function (i) { + var img = $(this); + var width = img.width(); + var height = width* 0.75; + img.height(height); + }); +} + // + // + // + // + // + // + // + // + // + // + // \ No newline at end of file diff --git a/worldmap/static/js/bmap.js b/worldmap/static/js/bmap.js new file mode 100644 index 0000000..e19bb47 --- /dev/null +++ b/worldmap/static/js/bmap.js @@ -0,0 +1,424 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("echarts")); + else if(typeof define === 'function' && define.amd) + define(["echarts"], factory); + else if(typeof exports === 'object') + exports["bmap"] = factory(require("echarts")); + else + root["echarts"] = root["echarts"] || {}, root["echarts"]["bmap"] = factory(root["echarts"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/** + * BMap component extension + */ + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + __webpack_require__(1).registerCoordinateSystem( + 'bmap', __webpack_require__(2) + ); + __webpack_require__(3); + __webpack_require__(4); + + // Action + __webpack_require__(1).registerAction({ + type: 'bmapRoam', + event: 'bmapRoam', + update: 'updateLayout' + }, function (payload, ecModel) { + ecModel.eachComponent('bmap', function (bMapModel) { + var bmap = bMapModel.getBMap(); + var center = bmap.getCenter(); + bMapModel.setCenterAndZoom([center.lng, center.lat], bmap.getZoom()); + }); + }); + + return { + version: '1.0.0' + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 1 */ +/***/ function(module, exports) { + + module.exports = __WEBPACK_EXTERNAL_MODULE_1__; + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + var echarts = __webpack_require__(1); + var zrUtil = echarts.util; + + function BMapCoordSys(bmap, api) { + this._bmap = bmap; + this.dimensions = ['lng', 'lat']; + this._mapOffset = [0, 0]; + + this._api = api; + + this._projection = new BMap.MercatorProjection(); + } + + BMapCoordSys.prototype.dimensions = ['lng', 'lat']; + + BMapCoordSys.prototype.setZoom = function (zoom) { + this._zoom = zoom; + }; + + BMapCoordSys.prototype.setCenter = function (center) { + this._center = this._projection.lngLatToPoint(new BMap.Point(center[0], center[1])); + }; + + BMapCoordSys.prototype.setMapOffset = function (mapOffset) { + this._mapOffset = mapOffset; + }; + + BMapCoordSys.prototype.getBMap = function () { + return this._bmap; + }; + + BMapCoordSys.prototype.dataToPoint = function (data) { + var point = new BMap.Point(data[0], data[1]); + // TODO mercator projection is toooooooo slow + // var mercatorPoint = this._projection.lngLatToPoint(point); + + // var width = this._api.getZr().getWidth(); + // var height = this._api.getZr().getHeight(); + // var divider = Math.pow(2, 18 - 10); + // return [ + // Math.round((mercatorPoint.x - this._center.x) / divider + width / 2), + // Math.round((this._center.y - mercatorPoint.y) / divider + height / 2) + // ]; + var px = this._bmap.pointToOverlayPixel(point); + var mapOffset = this._mapOffset; + return [px.x - mapOffset[0], px.y - mapOffset[1]]; + }; + + BMapCoordSys.prototype.pointToData = function (pt) { + var mapOffset = this._mapOffset; + var pt = this._bmap.overlayPixelToPoint({ + x: pt[0] + mapOffset[0], + y: pt[1] + mapOffset[1] + }); + return [pt.lng, pt.lat]; + }; + + BMapCoordSys.prototype.getViewRect = function () { + var api = this._api; + return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()); + }; + + BMapCoordSys.prototype.getRoamTransform = function () { + return echarts.matrix.create(); + }; + + BMapCoordSys.prototype.prepareCustoms = function (data) { + var rect = this.getViewRect(); + return { + coordSys: { + // The name exposed to user is always 'cartesian2d' but not 'grid'. + type: 'bmap', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: zrUtil.bind(this.dataToPoint, this), + size: zrUtil.bind(dataToCoordSize, this) + } + }; + }; + + function dataToCoordSize(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return zrUtil.map([0, 1], function (dimIdx) { + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var p1 = []; + var p2 = []; + p1[dimIdx] = val - halfSize; + p2[dimIdx] = val + halfSize; + p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; + return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); + }, this); + } + + var Overlay; + + // For deciding which dimensions to use when creating list data + BMapCoordSys.dimensions = BMapCoordSys.prototype.dimensions; + + function createOverlayCtor() { + function Overlay(root) { + this._root = root; + } + + Overlay.prototype = new BMap.Overlay(); + /** + * 鍒濆鍖� + * + * @param {BMap.Map} map + * @override + */ + Overlay.prototype.initialize = function (map) { + map.getPanes().labelPane.appendChild(this._root); + return this._root; + }; + /** + * @override + */ + Overlay.prototype.draw = function () {}; + + return Overlay; + } + + BMapCoordSys.create = function (ecModel, api) { + var bmapCoordSys; + var root = api.getDom(); + + // TODO Dispose + ecModel.eachComponent('bmap', function (bmapModel) { + var viewportRoot = api.getZr().painter.getViewportRoot(); + if (typeof BMap === 'undefined') { + throw new Error('BMap api is not loaded'); + } + Overlay = Overlay || createOverlayCtor(); + if (bmapCoordSys) { + throw new Error('Only one bmap component can exist'); + } + if (!bmapModel.__bmap) { + // Not support IE8 + var bmapRoot = root.querySelector('.ec-extension-bmap'); + if (bmapRoot) { + // Reset viewport left and top, which will be changed + // in moving handler in BMapView + viewportRoot.style.left = '0px'; + viewportRoot.style.top = '0px'; + root.removeChild(bmapRoot); + } + bmapRoot = document.createElement('div'); + bmapRoot.style.cssText = 'width:100%;height:100%'; + // Not support IE8 + bmapRoot.classList.add('ec-extension-bmap'); + root.appendChild(bmapRoot); + var bmap = bmapModel.__bmap = new BMap.Map(bmapRoot); + + var overlay = new Overlay(viewportRoot); + bmap.addOverlay(overlay); + } + var bmap = bmapModel.__bmap; + + // Set bmap options + // centerAndZoom before layout and render + var center = bmapModel.get('center'); + var zoom = bmapModel.get('zoom'); + if (center && zoom) { + var pt = new BMap.Point(center[0], center[1]); + bmap.centerAndZoom(pt, zoom); + } + + bmapCoordSys = new BMapCoordSys(bmap, api); + bmapCoordSys.setMapOffset(bmapModel.__mapOffset || [0, 0]); + bmapCoordSys.setZoom(zoom); + bmapCoordSys.setCenter(center); + + bmapModel.coordinateSystem = bmapCoordSys; + }); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'bmap') { + seriesModel.coordinateSystem = bmapCoordSys; + } + }); + }; + + return BMapCoordSys; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + function v2Equal(a, b) { + return a && b && a[0] === b[0] && a[1] === b[1]; + } + + return __webpack_require__(1).extendComponentModel({ + type: 'bmap', + + getBMap: function () { + // __bmap is injected when creating BMapCoordSys + return this.__bmap; + }, + + setCenterAndZoom: function (center, zoom) { + this.option.center = center; + this.option.zoom = zoom; + }, + + centerOrZoomChanged: function (center, zoom) { + var option = this.option; + return !(v2Equal(center, option.center) && zoom === option.zoom); + }, + + defaultOption: { + + center: [104.114129, 37.550339], + + zoom: 5, + + mapStyle: {}, + + roam: false + } + }); + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + return __webpack_require__(1).extendComponentView({ + type: 'bmap', + + render: function (bMapModel, ecModel, api) { + var rendering = true; + + var bmap = bMapModel.getBMap(); + var viewportRoot = api.getZr().painter.getViewportRoot(); + var coordSys = bMapModel.coordinateSystem; + var moveHandler = function (type, target) { + if (rendering) { + return; + } + var offsetEl = viewportRoot.parentNode.parentNode.parentNode; + var mapOffset = [ + -parseInt(offsetEl.style.left, 10) || 0, + -parseInt(offsetEl.style.top, 10) || 0 + ]; + viewportRoot.style.left = mapOffset[0] + 'px'; + viewportRoot.style.top = mapOffset[1] + 'px'; + + coordSys.setMapOffset(mapOffset); + bMapModel.__mapOffset = mapOffset; + + api.dispatchAction({ + type: 'bmapRoam' + }); + }; + + function zoomEndHandler() { + if (rendering) { + return; + } + api.dispatchAction({ + type: 'bmapRoam' + }); + } + + bmap.removeEventListener('moving', this._oldMoveHandler); + // FIXME + // Moveend may be triggered by centerAndZoom method when creating coordSys next time + // bmap.removeEventListener('moveend', this._oldMoveHandler); + bmap.removeEventListener('zoomend', this._oldZoomEndHandler); + bmap.addEventListener('moving', moveHandler); + // bmap.addEventListener('moveend', moveHandler); + bmap.addEventListener('zoomend', zoomEndHandler); + + this._oldMoveHandler = moveHandler; + this._oldZoomEndHandler = zoomEndHandler; + + var roam = bMapModel.get('roam'); + if (roam && roam !== 'scale') { + bmap.enableDragging(); + } + else { + bmap.disableDragging(); + } + if (roam && roam !== 'move') { + bmap.enableScrollWheelZoom(); + bmap.enableDoubleClickZoom(); + bmap.enablePinchToZoom(); + } + else { + bmap.disableScrollWheelZoom(); + bmap.disableDoubleClickZoom(); + bmap.disablePinchToZoom(); + } + + var originalStyle = bMapModel.__mapStyle; + + var newMapStyle = bMapModel.get('mapStyle') || {}; + // FIXME, Not use JSON methods + var mapStyleStr = JSON.stringify(newMapStyle); + if (JSON.stringify(originalStyle) !== mapStyleStr) { + // FIXME May have blank tile when dragging if setMapStyle + if (Object.keys(newMapStyle).length) { + bmap.setMapStyle(newMapStyle); + } + bMapModel.__mapStyle = JSON.parse(mapStyleStr); + } + + rendering = false; + } + }); + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/worldmap/static/js/dragging.js b/worldmap/static/js/dragging.js new file mode 100644 index 0000000..1c11e75 --- /dev/null +++ b/worldmap/static/js/dragging.js @@ -0,0 +1,71 @@ +//参数为验证点击区域是否为可移动区域,如果是返回欲移动元素,负责返回null +var Dragging=function(validateHandler){ + var draggingObj=null; //dragging Dialog + var diffX=0; + var diffY=0; + var windowH; + var windowW; + function mouseHandler(e){ + var windowH =$(window).height(); + var windowW =$(window).width(); + + switch(e.type){ + case 'mousedown': + draggingObj=validateHandler(e);//验证是否为可点击移动区域 + if(draggingObj!=null){ + diffX=e.clientX-draggingObj.offsetLeft; + diffY=e.clientY-draggingObj.offsetTop; + } + break; + + case 'mousemove': + if(draggingObj){ + if(draggingObj.className.indexOf('dragablerb')>=0){ + draggingObj.style.right=windowW-draggingObj.offsetWidth-(e.clientX-diffX)+'px'; + draggingObj.style.bottom=windowH-draggingObj.offsetHeight-(e.clientY-diffY)+'px'; + } + else{ + draggingObj.style.left=(e.clientX-diffX)+'px'; + draggingObj.style.top=(e.clientY-diffY)+'px'; + + } + } + break; + + case 'mouseup': + draggingObj =null; + diffX=0; + diffY=0; + break; + } + }; + + return { + enable:function(){ + document.addEventListener('mousedown',mouseHandler); + document.addEventListener('mousemove',mouseHandler); + document.addEventListener('mouseup',mouseHandler); + }, + disable:function(){ + document.removeEventListener('mousedown',mouseHandler); + document.removeEventListener('mousemove',mouseHandler); + document.removeEventListener('mouseup',mouseHandler); + } + } + } + + function getDraggingDialog(e){ + var target=e.target; + + while(target && target.className.indexOf('dragable')==-1){ + target=target.offsetParent; + } + + if(target!=null && target.className.indexOf('dragable')>=0) + return target; + else{ + return null; + } + } + + \ No newline at end of file diff --git a/worldmap/static/js/echarts.js b/worldmap/static/js/echarts.js new file mode 100644 index 0000000..ee759b2 --- /dev/null +++ b/worldmap/static/js/echarts.js @@ -0,0 +1,75145 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["echarts"] = factory(); + else + root["echarts"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Export echarts as CommonJS module + */ + module.exports = __webpack_require__(1); + + // Import all charts and components + __webpack_require__(113); + __webpack_require__(139); + __webpack_require__(146); + __webpack_require__(155); + __webpack_require__(159); + + __webpack_require__(169); + __webpack_require__(193); + __webpack_require__(205); + __webpack_require__(226); + __webpack_require__(230); + __webpack_require__(234); + __webpack_require__(251); + __webpack_require__(257); + __webpack_require__(264); + __webpack_require__(270); + __webpack_require__(274); + __webpack_require__(283); + __webpack_require__(287); + __webpack_require__(290); + __webpack_require__(313); + + __webpack_require__(319); + __webpack_require__(320); + __webpack_require__(321); + __webpack_require__(327); + __webpack_require__(298); + __webpack_require__(331); + __webpack_require__(344); + __webpack_require__(235); + __webpack_require__(291); + __webpack_require__(347); + __webpack_require__(358); + + __webpack_require__(362); + + __webpack_require__(363); + __webpack_require__(376); + + __webpack_require__(391); + __webpack_require__(397); + __webpack_require__(400); + + __webpack_require__(403); + __webpack_require__(412); + + __webpack_require__(424); + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + // Enable DEV mode when using source code without build. which has no __DEV__ variable + // In build process 'typeof __DEV__' will be replace with 'boolean' + // So this code will be removed or disabled anyway after built. + if (false) { + // In browser + if (typeof window !== 'undefined') { + window.__DEV__ = true; + } + // In node + else if (typeof global !== 'undefined') { + global.__DEV__ = true; + } + } + + /*! + * ECharts, a javascript interactive chart library. + * + * Copyright (c) 2015, Baidu Inc. + * All rights reserved. + * + * LICENSE + * https://github.com/ecomfe/echarts/blob/master/LICENSE.txt + */ + + /** + * @module echarts + */ + + + var env = __webpack_require__(2); + + var GlobalModel = __webpack_require__(3); + var ExtensionAPI = __webpack_require__(75); + var CoordinateSystemManager = __webpack_require__(76); + var OptionManager = __webpack_require__(77); + + var ComponentModel = __webpack_require__(69); + var SeriesModel = __webpack_require__(78); + + var ComponentView = __webpack_require__(79); + var ChartView = __webpack_require__(80); + var graphic = __webpack_require__(18); + var modelUtil = __webpack_require__(5); + var throttle = __webpack_require__(81); + + var zrender = __webpack_require__(82); + var zrUtil = __webpack_require__(4); + var colorTool = __webpack_require__(31); + var Eventful = __webpack_require__(25); + var timsort = __webpack_require__(86); + + var each = zrUtil.each; + var parseClassType = ComponentModel.parseClassType; + + var PRIORITY_PROCESSOR_FILTER = 1000; + var PRIORITY_PROCESSOR_STATISTIC = 5000; + + + var PRIORITY_VISUAL_LAYOUT = 1000; + var PRIORITY_VISUAL_GLOBAL = 2000; + var PRIORITY_VISUAL_CHART = 3000; + var PRIORITY_VISUAL_COMPONENT = 4000; + // FIXME + // necessary? + var PRIORITY_VISUAL_BRUSH = 5000; + + // Main process have three entries: `setOption`, `dispatchAction` and `resize`, + // where they must not be invoked nestedly, except the only case: invoke + // dispatchAction with updateMethod "none" in main process. + // This flag is used to carry out this rule. + // All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]). + var IN_MAIN_PROCESS = '__flagInMainProcess'; + var HAS_GRADIENT_OR_PATTERN_BG = '__hasGradientOrPatternBg'; + var OPTION_UPDATED = '__optionUpdated'; + var ACTION_REG = /^[a-zA-Z0-9_]+$/; + + function createRegisterEventWithLowercaseName(method) { + return function (eventName, handler, context) { + // Event name is all lowercase + eventName = eventName && eventName.toLowerCase(); + Eventful.prototype[method].call(this, eventName, handler, context); + }; + } + + /** + * @module echarts~MessageCenter + */ + function MessageCenter() { + Eventful.call(this); + } + MessageCenter.prototype.on = createRegisterEventWithLowercaseName('on'); + MessageCenter.prototype.off = createRegisterEventWithLowercaseName('off'); + MessageCenter.prototype.one = createRegisterEventWithLowercaseName('one'); + zrUtil.mixin(MessageCenter, Eventful); + + /** + * @module echarts~ECharts + */ + function ECharts(dom, theme, opts) { + opts = opts || {}; + + // Get theme by name + if (typeof theme === 'string') { + theme = themeStorage[theme]; + } + + /** + * @type {string} + */ + this.id; + /** + * Group id + * @type {string} + */ + this.group; + /** + * @type {HTMLDomElement} + * @private + */ + this._dom = dom; + /** + * @type {module:zrender/ZRender} + * @private + */ + var zr = this._zr = zrender.init(dom, { + renderer: opts.renderer || 'canvas', + devicePixelRatio: opts.devicePixelRatio, + width: opts.width, + height: opts.height + }); + + /** + * Expect 60 pfs. + * @type {Function} + * @private + */ + this._throttledZrFlush = throttle.throttle(zrUtil.bind(zr.flush, zr), 17); + + /** + * @type {Object} + * @private + */ + this._theme = zrUtil.clone(theme); + + /** + * @type {Array.} + * @private + */ + this._chartsViews = []; + + /** + * @type {Object.} + * @private + */ + this._chartsMap = {}; + + /** + * @type {Array.} + * @private + */ + this._componentsViews = []; + + /** + * @type {Object.} + * @private + */ + this._componentsMap = {}; + + /** + * @type {module:echarts/CoordinateSystem} + * @private + */ + this._coordSysMgr = new CoordinateSystemManager(); + + /** + * @type {module:echarts/ExtensionAPI} + * @private + */ + this._api = createExtensionAPI(this); + + Eventful.call(this); + + /** + * @type {module:echarts~MessageCenter} + * @private + */ + this._messageCenter = new MessageCenter(); + + // Init mouse events + this._initEvents(); + + // In case some people write `window.onresize = chart.resize` + this.resize = zrUtil.bind(this.resize, this); + + // Can't dispatch action during rendering procedure + this._pendingActions = []; + // Sort on demand + function prioritySortFunc(a, b) { + return a.prio - b.prio; + } + timsort(visualFuncs, prioritySortFunc); + timsort(dataProcessorFuncs, prioritySortFunc); + + zr.animation.on('frame', this._onframe, this); + + // ECharts instance can be used as value. + zrUtil.setAsPrimitive(this); + } + + var echartsProto = ECharts.prototype; + + echartsProto._onframe = function () { + // Lazy update + if (this[OPTION_UPDATED]) { + var silent = this[OPTION_UPDATED].silent; + + this[IN_MAIN_PROCESS] = true; + + updateMethods.prepareAndUpdate.call(this); + + this[IN_MAIN_PROCESS] = false; + + this[OPTION_UPDATED] = false; + + flushPendingActions.call(this, silent); + + triggerUpdatedEvent.call(this, silent); + } + }; + /** + * @return {HTMLDomElement} + */ + echartsProto.getDom = function () { + return this._dom; + }; + + /** + * @return {module:zrender~ZRender} + */ + echartsProto.getZr = function () { + return this._zr; + }; + + /** + * Usage: + * chart.setOption(option, notMerge, lazyUpdate); + * chart.setOption(option, { + * notMerge: ..., + * lazyUpdate: ..., + * silent: ... + * }); + * + * @param {Object} option + * @param {Object|boolean} [opts] opts or notMerge. + * @param {boolean} [opts.notMerge=false] + * @param {boolean} [opts.lazyUpdate=false] Useful when setOption frequently. + */ + echartsProto.setOption = function (option, notMerge, lazyUpdate) { + if (true) { + zrUtil.assert(!this[IN_MAIN_PROCESS], '`setOption` should not be called during main process.'); + } + + var silent; + if (zrUtil.isObject(notMerge)) { + lazyUpdate = notMerge.lazyUpdate; + silent = notMerge.silent; + notMerge = notMerge.notMerge; + } + + this[IN_MAIN_PROCESS] = true; + + if (!this._model || notMerge) { + var optionManager = new OptionManager(this._api); + var theme = this._theme; + var ecModel = this._model = new GlobalModel(null, null, theme, optionManager); + ecModel.init(null, null, theme, optionManager); + } + + this._model.setOption(option, optionPreprocessorFuncs); + + if (lazyUpdate) { + this[OPTION_UPDATED] = {silent: silent}; + this[IN_MAIN_PROCESS] = false; + } + else { + updateMethods.prepareAndUpdate.call(this); + // Ensure zr refresh sychronously, and then pixel in canvas can be + // fetched after `setOption`. + this._zr.flush(); + + this[OPTION_UPDATED] = false; + this[IN_MAIN_PROCESS] = false; + + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + } + }; + + /** + * @DEPRECATED + */ + echartsProto.setTheme = function () { + console.log('ECharts#setTheme() is DEPRECATED in ECharts 3.0'); + }; + + /** + * @return {module:echarts/model/Global} + */ + echartsProto.getModel = function () { + return this._model; + }; + + /** + * @return {Object} + */ + echartsProto.getOption = function () { + return this._model && this._model.getOption(); + }; + + /** + * @return {number} + */ + echartsProto.getWidth = function () { + return this._zr.getWidth(); + }; + + /** + * @return {number} + */ + echartsProto.getHeight = function () { + return this._zr.getHeight(); + }; + + /** + * @return {number} + */ + echartsProto.getDevicePixelRatio = function () { + return this._zr.painter.dpr || window.devicePixelRatio || 1; + }; + + /** + * Get canvas which has all thing rendered + * @param {Object} opts + * @param {string} [opts.backgroundColor] + */ + echartsProto.getRenderedCanvas = function (opts) { + if (!env.canvasSupported) { + return; + } + opts = opts || {}; + opts.pixelRatio = opts.pixelRatio || 1; + opts.backgroundColor = opts.backgroundColor + || this._model.get('backgroundColor'); + var zr = this._zr; + var list = zr.storage.getDisplayList(); + // Stop animations + zrUtil.each(list, function (el) { + el.stopAnimation(true); + }); + return zr.painter.getRenderedCanvas(opts); + }; + /** + * @return {string} + * @param {Object} opts + * @param {string} [opts.type='png'] + * @param {string} [opts.pixelRatio=1] + * @param {string} [opts.backgroundColor] + * @param {string} [opts.excludeComponents] + */ + echartsProto.getDataURL = function (opts) { + opts = opts || {}; + var excludeComponents = opts.excludeComponents; + var ecModel = this._model; + var excludesComponentViews = []; + var self = this; + + each(excludeComponents, function (componentType) { + ecModel.eachComponent({ + mainType: componentType + }, function (component) { + var view = self._componentsMap[component.__viewId]; + if (!view.group.ignore) { + excludesComponentViews.push(view); + view.group.ignore = true; + } + }); + }); + + var url = this.getRenderedCanvas(opts).toDataURL( + 'image/' + (opts && opts.type || 'png') + ); + + each(excludesComponentViews, function (view) { + view.group.ignore = false; + }); + return url; + }; + + + /** + * @return {string} + * @param {Object} opts + * @param {string} [opts.type='png'] + * @param {string} [opts.pixelRatio=1] + * @param {string} [opts.backgroundColor] + */ + echartsProto.getConnectedDataURL = function (opts) { + if (!env.canvasSupported) { + return; + } + var groupId = this.group; + var mathMin = Math.min; + var mathMax = Math.max; + var MAX_NUMBER = Infinity; + if (connectedGroups[groupId]) { + var left = MAX_NUMBER; + var top = MAX_NUMBER; + var right = -MAX_NUMBER; + var bottom = -MAX_NUMBER; + var canvasList = []; + var dpr = (opts && opts.pixelRatio) || 1; + + zrUtil.each(instances, function (chart, id) { + if (chart.group === groupId) { + var canvas = chart.getRenderedCanvas( + zrUtil.clone(opts) + ); + var boundingRect = chart.getDom().getBoundingClientRect(); + left = mathMin(boundingRect.left, left); + top = mathMin(boundingRect.top, top); + right = mathMax(boundingRect.right, right); + bottom = mathMax(boundingRect.bottom, bottom); + canvasList.push({ + dom: canvas, + left: boundingRect.left, + top: boundingRect.top + }); + } + }); + + left *= dpr; + top *= dpr; + right *= dpr; + bottom *= dpr; + var width = right - left; + var height = bottom - top; + var targetCanvas = zrUtil.createCanvas(); + targetCanvas.width = width; + targetCanvas.height = height; + var zr = zrender.init(targetCanvas); + + each(canvasList, function (item) { + var img = new graphic.Image({ + style: { + x: item.left * dpr - left, + y: item.top * dpr - top, + image: item.dom + } + }); + zr.add(img); + }); + zr.refreshImmediately(); + + return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png')); + } + else { + return this.getDataURL(opts); + } + }; + + /** + * Convert from logical coordinate system to pixel coordinate system. + * See CoordinateSystem#convertToPixel. + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * geoIndex / geoId, geoName, + * bmapIndex / bmapId / bmapName, + * xAxisIndex / xAxisId / xAxisName, + * yAxisIndex / yAxisId / yAxisName, + * gridIndex / gridId / gridName, + * ... (can be extended) + * } + * @param {Array|number} value + * @return {Array|number} result + */ + echartsProto.convertToPixel = zrUtil.curry(doConvertPixel, 'convertToPixel'); + + /** + * Convert from pixel coordinate system to logical coordinate system. + * See CoordinateSystem#convertFromPixel. + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * geoIndex / geoId / geoName, + * bmapIndex / bmapId / bmapName, + * xAxisIndex / xAxisId / xAxisName, + * yAxisIndex / yAxisId / yAxisName + * gridIndex / gridId / gridName, + * ... (can be extended) + * } + * @param {Array|number} value + * @return {Array|number} result + */ + echartsProto.convertFromPixel = zrUtil.curry(doConvertPixel, 'convertFromPixel'); + + function doConvertPixel(methodName, finder, value) { + var ecModel = this._model; + var coordSysList = this._coordSysMgr.getCoordinateSystems(); + var result; + + finder = modelUtil.parseFinder(ecModel, finder); + + for (var i = 0; i < coordSysList.length; i++) { + var coordSys = coordSysList[i]; + if (coordSys[methodName] + && (result = coordSys[methodName](ecModel, finder, value)) != null + ) { + return result; + } + } + + if (true) { + console.warn( + 'No coordinate system that supports ' + methodName + ' found by the given finder.' + ); + } + } + + /** + * Is the specified coordinate systems or components contain the given pixel point. + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * geoIndex / geoId / geoName, + * bmapIndex / bmapId / bmapName, + * xAxisIndex / xAxisId / xAxisName, + * yAxisIndex / yAxisId / yAxisName, + * gridIndex / gridId / gridName, + * ... (can be extended) + * } + * @param {Array|number} value + * @return {boolean} result + */ + echartsProto.containPixel = function (finder, value) { + var ecModel = this._model; + var result; + + finder = modelUtil.parseFinder(ecModel, finder); + + zrUtil.each(finder, function (models, key) { + key.indexOf('Models') >= 0 && zrUtil.each(models, function (model) { + var coordSys = model.coordinateSystem; + if (coordSys && coordSys.containPoint) { + result |= !!coordSys.containPoint(value); + } + else if (key === 'seriesModels') { + var view = this._chartsMap[model.__viewId]; + if (view && view.containPoint) { + result |= view.containPoint(value, model); + } + else { + if (true) { + console.warn(key + ': ' + (view + ? 'The found component do not support containPoint.' + : 'No view mapping to the found component.' + )); + } + } + } + else { + if (true) { + console.warn(key + ': containPoint is not supported'); + } + } + }, this); + }, this); + + return !!result; + }; + + /** + * Get visual from series or data. + * @param {string|Object} finder + * If string, e.g., 'series', means {seriesIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * dataIndex / dataIndexInside + * } + * If dataIndex is not specified, series visual will be fetched, + * but not data item visual. + * If all of seriesIndex, seriesId, seriesName are not specified, + * visual will be fetched from first series. + * @param {string} visualType 'color', 'symbol', 'symbolSize' + */ + echartsProto.getVisual = function (finder, visualType) { + var ecModel = this._model; + + finder = modelUtil.parseFinder(ecModel, finder, {defaultMainType: 'series'}); + + var seriesModel = finder.seriesModel; + + if (true) { + if (!seriesModel) { + console.warn('There is no specified seires model'); + } + } + + var data = seriesModel.getData(); + + var dataIndexInside = finder.hasOwnProperty('dataIndexInside') + ? finder.dataIndexInside + : finder.hasOwnProperty('dataIndex') + ? data.indexOfRawIndex(finder.dataIndex) + : null; + + return dataIndexInside != null + ? data.getItemVisual(dataIndexInside, visualType) + : data.getVisual(visualType); + }; + + /** + * Get view of corresponding component model + * @param {module:echarts/model/Component} componentModel + * @return {module:echarts/view/Component} + */ + echartsProto.getViewOfComponentModel = function (componentModel) { + return this._componentsMap[componentModel.__viewId]; + }; + + /** + * Get view of corresponding series model + * @param {module:echarts/model/Series} seriesModel + * @return {module:echarts/view/Chart} + */ + echartsProto.getViewOfSeriesModel = function (seriesModel) { + return this._chartsMap[seriesModel.__viewId]; + }; + + + var updateMethods = { + + /** + * @param {Object} payload + * @private + */ + update: function (payload) { + // console.profile && console.profile('update'); + + var ecModel = this._model; + var api = this._api; + var coordSysMgr = this._coordSysMgr; + var zr = this._zr; + // update before setOption + if (!ecModel) { + return; + } + + // Fixme First time update ? + 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. + + // Create new coordinate system each update + // In LineView may save the old coordinate system and use it to get the orignal point + coordSysMgr.create(this._model, this._api); + + processData.call(this, ecModel, api); + + stackSeriesData.call(this, ecModel); + + coordSysMgr.update(ecModel, api); + + doVisualEncoding.call(this, ecModel, payload); + + doRender.call(this, ecModel, payload); + + // Set background + var backgroundColor = ecModel.get('backgroundColor') || 'transparent'; + + var painter = zr.painter; + // TODO all use clearColor ? + if (painter.isSingleCanvas && painter.isSingleCanvas()) { + zr.configLayer(0, { + clearColor: backgroundColor + }); + } + else { + // In IE8 + if (!env.canvasSupported) { + var colorArr = colorTool.parse(backgroundColor); + backgroundColor = colorTool.stringify(colorArr, 'rgb'); + if (colorArr[3] === 0) { + backgroundColor = 'transparent'; + } + } + if (backgroundColor.colorStops || backgroundColor.image) { + // Gradient background + // FIXME Fixed layer? + zr.configLayer(0, { + clearColor: backgroundColor + }); + this[HAS_GRADIENT_OR_PATTERN_BG] = true; + + this._dom.style.background = 'transparent'; + } + else { + if (this[HAS_GRADIENT_OR_PATTERN_BG]) { + zr.configLayer(0, { + clearColor: null + }); + } + this[HAS_GRADIENT_OR_PATTERN_BG] = false; + + this._dom.style.background = backgroundColor; + } + } + + each(postUpdateFuncs, function (func) { + func(ecModel, api); + }); + + // console.profile && console.profileEnd('update'); + }, + + /** + * @param {Object} payload + * @private + */ + updateView: function (payload) { + var ecModel = this._model; + + // update before setOption + if (!ecModel) { + return; + } + + ecModel.eachSeries(function (seriesModel) { + seriesModel.getData().clearAllVisual(); + }); + + doVisualEncoding.call(this, ecModel, payload); + + invokeUpdateMethod.call(this, 'updateView', ecModel, payload); + }, + + /** + * @param {Object} payload + * @private + */ + updateVisual: function (payload) { + var ecModel = this._model; + + // update before setOption + if (!ecModel) { + return; + } + + ecModel.eachSeries(function (seriesModel) { + seriesModel.getData().clearAllVisual(); + }); + + doVisualEncoding.call(this, ecModel, payload, true); + + invokeUpdateMethod.call(this, 'updateVisual', ecModel, payload); + }, + + /** + * @param {Object} payload + * @private + */ + updateLayout: function (payload) { + var ecModel = this._model; + + // update before setOption + if (!ecModel) { + return; + } + + doLayout.call(this, ecModel, payload); + + invokeUpdateMethod.call(this, 'updateLayout', ecModel, payload); + }, + + /** + * @param {Object} payload + * @private + */ + prepareAndUpdate: function (payload) { + var ecModel = this._model; + + prepareView.call(this, 'component', ecModel); + + prepareView.call(this, 'chart', ecModel); + + updateMethods.update.call(this, payload); + } + }; + + /** + * @private + */ + function updateDirectly(ecIns, method, payload, mainType, subType) { + var ecModel = ecIns._model; + + // broadcast + if (!mainType) { + each(ecIns._componentsViews.concat(ecIns._chartsViews), callView); + return; + } + + var query = {}; + query[mainType + 'Id'] = payload[mainType + 'Id']; + query[mainType + 'Index'] = payload[mainType + 'Index']; + query[mainType + 'Name'] = payload[mainType + 'Name']; + + var condition = {mainType: mainType, query: query}; + subType && (condition.subType = subType); // subType may be '' by parseClassType; + + // If dispatchAction before setOption, do nothing. + ecModel && ecModel.eachComponent(condition, function (model, index) { + callView(ecIns[ + mainType === 'series' ? '_chartsMap' : '_componentsMap' + ][model.__viewId]); + }, ecIns); + + function callView(view) { + view && view.__alive && view[method] && view[method]( + view.__model, ecModel, ecIns._api, payload + ); + } + } + + /** + * Resize the chart + * @param {Object} opts + * @param {number} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number} [opts.height] Can be 'auto' (the same as null/undefined) + * @param {boolean} [opts.silent=false] + */ + echartsProto.resize = function (opts) { + if (true) { + zrUtil.assert(!this[IN_MAIN_PROCESS], '`resize` should not be called during main process.'); + } + + this[IN_MAIN_PROCESS] = true; + + this._zr.resize(opts); + + var optionChanged = this._model && this._model.resetOption('media'); + var updateMethod = optionChanged ? 'prepareAndUpdate' : 'update'; + + updateMethods[updateMethod].call(this); + + // Resize loading effect + this._loadingFX && this._loadingFX.resize(); + + this[IN_MAIN_PROCESS] = false; + + var silent = opts && opts.silent; + + flushPendingActions.call(this, silent); + + triggerUpdatedEvent.call(this, silent); + }; + + /** + * Show loading effect + * @param {string} [name='default'] + * @param {Object} [cfg] + */ + echartsProto.showLoading = function (name, cfg) { + if (zrUtil.isObject(name)) { + cfg = name; + name = ''; + } + name = name || 'default'; + + this.hideLoading(); + if (!loadingEffects[name]) { + if (true) { + console.warn('Loading effects ' + name + ' not exists.'); + } + return; + } + var el = loadingEffects[name](this._api, cfg); + var zr = this._zr; + this._loadingFX = el; + + zr.add(el); + }; + + /** + * Hide loading effect + */ + echartsProto.hideLoading = function () { + this._loadingFX && this._zr.remove(this._loadingFX); + this._loadingFX = null; + }; + + /** + * @param {Object} eventObj + * @return {Object} + */ + echartsProto.makeActionFromEvent = function (eventObj) { + var payload = zrUtil.extend({}, eventObj); + payload.type = eventActionMap[eventObj.type]; + return payload; + }; + + /** + * @pubilc + * @param {Object} payload + * @param {string} [payload.type] Action type + * @param {Object|boolean} [opt] If pass boolean, means opt.silent + * @param {boolean} [opt.silent=false] Whether trigger events. + * @param {boolean} [opt.flush=undefined] + * true: Flush immediately, and then pixel in canvas can be fetched + * immediately. Caution: it might affect performance. + * false: Not not flush. + * undefined: Auto decide whether perform flush. + */ + echartsProto.dispatchAction = function (payload, opt) { + if (!zrUtil.isObject(opt)) { + opt = {silent: !!opt}; + } + + if (!actions[payload.type]) { + return; + } + + // May dispatchAction in rendering procedure + if (this[IN_MAIN_PROCESS]) { + this._pendingActions.push(payload); + return; + } + + doDispatchAction.call(this, payload, opt.silent); + + if (opt.flush) { + this._zr.flush(true); + } + else if (opt.flush !== false && env.browser.weChat) { + // In WeChat embeded browser, `requestAnimationFrame` and `setInterval` + // hang when sliding page (on touch event), which cause that zr does not + // refresh util user interaction finished, which is not expected. + // But `dispatchAction` may be called too frequently when pan on touch + // screen, which impacts performance if do not throttle them. + this._throttledZrFlush(); + } + + flushPendingActions.call(this, opt.silent); + + triggerUpdatedEvent.call(this, opt.silent); + }; + + function doDispatchAction(payload, silent) { + var payloadType = payload.type; + var escapeConnect = payload.escapeConnect; + var actionWrap = actions[payloadType]; + var actionInfo = actionWrap.actionInfo; + + var cptType = (actionInfo.update || 'update').split(':'); + var updateMethod = cptType.pop(); + cptType = cptType[0] != null && parseClassType(cptType[0]); + + this[IN_MAIN_PROCESS] = true; + + var payloads = [payload]; + var batched = false; + // Batch action + if (payload.batch) { + batched = true; + payloads = zrUtil.map(payload.batch, function (item) { + item = zrUtil.defaults(zrUtil.extend({}, item), payload); + item.batch = null; + return item; + }); + } + + var eventObjBatch = []; + var eventObj; + var isHighDown = payloadType === 'highlight' || payloadType === 'downplay'; + + each(payloads, function (batchItem) { + // Action can specify the event by return it. + eventObj = actionWrap.action(batchItem, this._model, this._api); + // Emit event outside + eventObj = eventObj || zrUtil.extend({}, batchItem); + // Convert type to eventType + eventObj.type = actionInfo.event || eventObj.type; + eventObjBatch.push(eventObj); + + // light update does not perform data process, layout and visual. + if (isHighDown) { + // method, payload, mainType, subType + updateDirectly(this, updateMethod, batchItem, 'series'); + } + else if (cptType) { + updateDirectly(this, updateMethod, batchItem, cptType.main, cptType.sub); + } + }, this); + + if (updateMethod !== 'none' && !isHighDown && !cptType) { + // Still dirty + if (this[OPTION_UPDATED]) { + // FIXME Pass payload ? + updateMethods.prepareAndUpdate.call(this, payload); + this[OPTION_UPDATED] = false; + } + else { + updateMethods[updateMethod].call(this, payload); + } + } + + // Follow the rule of action batch + if (batched) { + eventObj = { + type: actionInfo.event || payloadType, + escapeConnect: escapeConnect, + batch: eventObjBatch + }; + } + else { + eventObj = eventObjBatch[0]; + } + + this[IN_MAIN_PROCESS] = false; + + !silent && this._messageCenter.trigger(eventObj.type, eventObj); + } + + function flushPendingActions(silent) { + var pendingActions = this._pendingActions; + while (pendingActions.length) { + var payload = pendingActions.shift(); + doDispatchAction.call(this, payload, silent); + } + } + + function triggerUpdatedEvent(silent) { + !silent && this.trigger('updated'); + } + + /** + * Register event + * @method + */ + echartsProto.on = createRegisterEventWithLowercaseName('on'); + echartsProto.off = createRegisterEventWithLowercaseName('off'); + echartsProto.one = createRegisterEventWithLowercaseName('one'); + + /** + * @param {string} methodName + * @private + */ + function invokeUpdateMethod(methodName, ecModel, payload) { + var api = this._api; + + // Update all components + each(this._componentsViews, function (component) { + var componentModel = component.__model; + component[methodName](componentModel, ecModel, api, payload); + + updateZ(componentModel, component); + }, this); + + // Upate all charts + ecModel.eachSeries(function (seriesModel, idx) { + var chart = this._chartsMap[seriesModel.__viewId]; + chart[methodName](seriesModel, ecModel, api, payload); + + updateZ(seriesModel, chart); + + updateProgressiveAndBlend(seriesModel, chart); + }, this); + + // If use hover layer + updateHoverLayerStatus(this._zr, ecModel); + + // Post render + each(postUpdateFuncs, function (func) { + func(ecModel, api); + }); + } + + /** + * Prepare view instances of charts and components + * @param {module:echarts/model/Global} ecModel + * @private + */ + function prepareView(type, ecModel) { + var isComponent = type === 'component'; + var viewList = isComponent ? this._componentsViews : this._chartsViews; + var viewMap = isComponent ? this._componentsMap : this._chartsMap; + var zr = this._zr; + + for (var i = 0; i < viewList.length; i++) { + viewList[i].__alive = false; + } + + ecModel[isComponent ? 'eachComponent' : 'eachSeries'](function (componentType, model) { + if (isComponent) { + if (componentType === 'series') { + return; + } + } + else { + model = componentType; + } + + // Consider: id same and type changed. + var viewId = '_ec_' + model.id + '_' + model.type; + var view = viewMap[viewId]; + if (!view) { + var classType = parseClassType(model.type); + var Clazz = isComponent + ? ComponentView.getClass(classType.main, classType.sub) + : ChartView.getClass(classType.sub); + if (Clazz) { + view = new Clazz(); + view.init(ecModel, this._api); + viewMap[viewId] = view; + viewList.push(view); + zr.add(view.group); + } + else { + // Error + return; + } + } + + model.__viewId = view.__id = viewId; + view.__alive = true; + view.__model = model; + view.group.__ecComponentInfo = { + mainType: model.mainType, + index: model.componentIndex + }; + }, this); + + for (var i = 0; i < viewList.length;) { + var view = viewList[i]; + if (!view.__alive) { + zr.remove(view.group); + view.dispose(ecModel, this._api); + viewList.splice(i, 1); + delete viewMap[view.__id]; + view.__id = view.group.__ecComponentInfo = null; + } + else { + i++; + } + } + } + + /** + * Processor data in each series + * + * @param {module:echarts/model/Global} ecModel + * @private + */ + function processData(ecModel, api) { + each(dataProcessorFuncs, function (process) { + process.func(ecModel, api); + }); + } + + /** + * @private + */ + function stackSeriesData(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]; + // Avoid conflict with Object.prototype + if (stackedDataMap.hasOwnProperty(stack) && previousStack) { + data.stackedOn = previousStack; + } + stackedDataMap[stack] = data; + } + }); + } + + /** + * Layout before each chart render there series, special visual encoding stage + * + * @param {module:echarts/model/Global} ecModel + * @private + */ + function doLayout(ecModel, payload) { + var api = this._api; + each(visualFuncs, function (visual) { + if (visual.isLayout) { + visual.func(ecModel, api, payload); + } + }); + } + + /** + * Encode visual infomation from data after data processing + * + * @param {module:echarts/model/Global} ecModel + * @param {object} layout + * @param {boolean} [excludesLayout] + * @private + */ + function doVisualEncoding(ecModel, payload, excludesLayout) { + var api = this._api; + ecModel.clearColorPalette(); + ecModel.eachSeries(function (seriesModel) { + seriesModel.clearColorPalette(); + }); + each(visualFuncs, function (visual) { + (!excludesLayout || !visual.isLayout) + && visual.func(ecModel, api, payload); + }); + } + + /** + * Render each chart and component + * @private + */ + function doRender(ecModel, payload) { + var api = this._api; + // Render all components + each(this._componentsViews, function (componentView) { + var componentModel = componentView.__model; + componentView.render(componentModel, ecModel, api, payload); + + updateZ(componentModel, componentView); + }, this); + + each(this._chartsViews, function (chart) { + chart.__alive = false; + }, this); + + // Render all charts + ecModel.eachSeries(function (seriesModel, idx) { + var chartView = this._chartsMap[seriesModel.__viewId]; + chartView.__alive = true; + chartView.render(seriesModel, ecModel, api, payload); + + chartView.group.silent = !!seriesModel.get('silent'); + + updateZ(seriesModel, chartView); + + updateProgressiveAndBlend(seriesModel, chartView); + + }, this); + + // If use hover layer + updateHoverLayerStatus(this._zr, ecModel); + + // Remove groups of unrendered charts + each(this._chartsViews, function (chart) { + if (!chart.__alive) { + chart.remove(ecModel, api); + } + }, this); + } + + var MOUSE_EVENT_NAMES = [ + 'click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', + 'mousedown', 'mouseup', 'globalout', 'contextmenu' + ]; + /** + * @private + */ + echartsProto._initEvents = function () { + each(MOUSE_EVENT_NAMES, function (eveName) { + this._zr.on(eveName, function (e) { + var ecModel = this.getModel(); + var el = e.target; + var params; + + // no e.target when 'globalout'. + if (eveName === 'globalout') { + params = {}; + } + else if (el && el.dataIndex != null) { + + //**yukichange begin here made a params array as a result + if(el.selected&&eveName=="click"){ + params = new Array(); + for(var selectIndex=0;selectIndex ecModel.get('hoverLayerThreshold') && !env.node) { + storage.traverse(function (el) { + if (!el.isGroup) { + el.useHoverLayer = true; + } + }); + } + } + + /** + * Update chart progressive and blend. + * @param {module:echarts/model/Series|module:echarts/model/Component} model + * @param {module:echarts/view/Component|module:echarts/view/Chart} view + */ + function updateProgressiveAndBlend(seriesModel, chartView) { + // Progressive configuration + var elCount = 0; + chartView.group.traverse(function (el) { + if (el.type !== 'group' && !el.ignore) { + elCount++; + } + }); + var frameDrawNum = +seriesModel.get('progressive'); + var needProgressive = elCount > seriesModel.get('progressiveThreshold') && frameDrawNum && !env.node; + if (needProgressive) { + chartView.group.traverse(function (el) { + // FIXME marker and other components + if (!el.isGroup) { + el.progressive = needProgressive ? + Math.floor(elCount++ / frameDrawNum) : -1; + if (needProgressive) { + el.stopAnimation(true); + } + } + }); + } + + // Blend configration + var blendMode = seriesModel.get('blendMode') || null; + if (true) { + if (!env.canvasSupported && blendMode && blendMode !== 'source-over') { + console.warn('Only canvas support blendMode'); + } + } + chartView.group.traverse(function (el) { + // FIXME marker and other components + if (!el.isGroup) { + el.setStyle('blend', blendMode); + } + }); + } + + /** + * @param {module:echarts/model/Series|module:echarts/model/Component} model + * @param {module:echarts/view/Component|module:echarts/view/Chart} view + */ + function updateZ(model, view) { + var z = model.get('z'); + var zlevel = model.get('zlevel'); + // Set z and zlevel + view.group.traverse(function (el) { + if (el.type !== 'group') { + z != null && (el.z = z); + zlevel != null && (el.zlevel = zlevel); + } + }); + } + + function createExtensionAPI(ecInstance) { + var coordSysMgr = ecInstance._coordSysMgr; + return zrUtil.extend(new ExtensionAPI(ecInstance), { + // Inject methods + getCoordinateSystems: zrUtil.bind( + coordSysMgr.getCoordinateSystems, coordSysMgr + ), + getComponentByElement: function (el) { + while (el) { + var modelInfo = el.__ecComponentInfo; + if (modelInfo != null) { + return ecInstance._model.getComponent(modelInfo.mainType, modelInfo.index); + } + el = el.parent; + } + } + }); + } + + /** + * @type {Object} key: actionType. + * @inner + */ + var actions = {}; + + /** + * Map eventType to actionType + * @type {Object} + */ + var eventActionMap = {}; + + /** + * Data processor functions of each stage + * @type {Array.>} + * @inner + */ + var dataProcessorFuncs = []; + + /** + * @type {Array.} + * @inner + */ + var optionPreprocessorFuncs = []; + + /** + * @type {Array.} + * @inner + */ + var postUpdateFuncs = []; + + /** + * Visual encoding functions of each stage + * @type {Array.>} + * @inner + */ + var visualFuncs = []; + /** + * Theme storage + * @type {Object.} + */ + var themeStorage = {}; + /** + * Loading effects + */ + var loadingEffects = {}; + + + var instances = {}; + var connectedGroups = {}; + + var idBase = new Date() - 0; + var groupIdBase = new Date() - 0; + var DOM_ATTRIBUTE_KEY = '_echarts_instance_'; + + /** + * @alias module:echarts + */ + var echarts = { + /** + * @type {number} + */ + version: '3.6.2', + dependencies: { + zrender: '3.5.2' + } + }; + + function enableConnect(chart) { + var STATUS_PENDING = 0; + var STATUS_UPDATING = 1; + var STATUS_UPDATED = 2; + var STATUS_KEY = '__connectUpdateStatus'; + + function updateConnectedChartsStatus(charts, status) { + for (var i = 0; i < charts.length; i++) { + var otherChart = charts[i]; + otherChart[STATUS_KEY] = status; + } + } + + zrUtil.each(eventActionMap, function (actionType, eventType) { + chart._messageCenter.on(eventType, function (event) { + if (connectedGroups[chart.group] && chart[STATUS_KEY] !== STATUS_PENDING) { + if (event && event.escapeConnect) { + return; + } + + var action = chart.makeActionFromEvent(event); + var otherCharts = []; + + zrUtil.each(instances, function (otherChart) { + if (otherChart !== chart && otherChart.group === chart.group) { + otherCharts.push(otherChart); + } + }); + + updateConnectedChartsStatus(otherCharts, STATUS_PENDING); + each(otherCharts, function (otherChart) { + if (otherChart[STATUS_KEY] !== STATUS_UPDATING) { + otherChart.dispatchAction(action); + } + }); + updateConnectedChartsStatus(otherCharts, STATUS_UPDATED); + } + }); + }); + } + + /** + * @param {HTMLDomElement} dom + * @param {Object} [theme] + * @param {Object} opts + * @param {number} [opts.devicePixelRatio] Use window.devicePixelRatio by default + * @param {string} [opts.renderer] Currently only 'canvas' is supported. + * @param {number} [opts.width] Use clientWidth of the input `dom` by default. + * Can be 'auto' (the same as null/undefined) + * @param {number} [opts.height] Use clientHeight of the input `dom` by default. + * Can be 'auto' (the same as null/undefined) + */ + echarts.init = function (dom, theme, opts) { + if (true) { + // Check version + if ((zrender.version.replace('.', '') - 0) < (echarts.dependencies.zrender.replace('.', '') - 0)) { + throw new Error( + 'ZRender ' + zrender.version + + ' is too old for ECharts ' + echarts.version + + '. Current version need ZRender ' + + echarts.dependencies.zrender + '+' + ); + } + + if (!dom) { + throw new Error('Initialize failed: invalid dom.'); + } + } + + var existInstance = echarts.getInstanceByDom(dom); + if (existInstance) { + if (true) { + console.warn('There is a chart instance already initialized on the dom.'); + } + return existInstance; + } + + if (true) { + if (zrUtil.isDom(dom) + && dom.nodeName.toUpperCase() !== 'CANVAS' + && ( + (!dom.clientWidth && (!opts || opts.width == null)) + || (!dom.clientHeight && (!opts || opts.height == null)) + ) + ) { + console.warn('Can\'t get dom width or height'); + } + } + + var chart = new ECharts(dom, theme, opts); + chart.id = 'ec_' + idBase++; + instances[chart.id] = chart; + + if (dom.setAttribute) { + dom.setAttribute(DOM_ATTRIBUTE_KEY, chart.id); + } + else { + dom[DOM_ATTRIBUTE_KEY] = chart.id; + } + + enableConnect(chart); + + return chart; + }; + + /** + * @return {string|Array.} 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 || ('g_' + groupIdBase++); + zrUtil.each(charts, function (chart) { + chart.group = groupId; + }); + } + connectedGroups[groupId] = true; + return groupId; + }; + + /** + * @DEPRECATED + * @return {string} groupId + */ + echarts.disConnect = function (groupId) { + connectedGroups[groupId] = false; + }; + + /** + * @return {string} groupId + */ + echarts.disconnect = echarts.disConnect; + + /** + * Dispose a chart instance + * @param {module:echarts~ECharts|HTMLDomElement|string} chart + */ + echarts.dispose = function (chart) { + if (typeof chart === 'string') { + chart = instances[chart]; + } + else if (!(chart instanceof ECharts)){ + // Try to treat as dom + chart = echarts.getInstanceByDom(chart); + } + if ((chart instanceof ECharts) && !chart.isDisposed()) { + chart.dispose(); + } + }; + + /** + * @param {HTMLDomElement} dom + * @return {echarts~ECharts} + */ + echarts.getInstanceByDom = function (dom) { + var key; + if (dom.getAttribute) { + key = dom.getAttribute(DOM_ATTRIBUTE_KEY); + } + else { + key = dom[DOM_ATTRIBUTE_KEY]; + } + return instances[key]; + }; + + /** + * @param {string} key + * @return {echarts~ECharts} + */ + echarts.getInstanceById = function (key) { + return instances[key]; + }; + + /** + * Register theme + */ + echarts.registerTheme = function (name, theme) { + themeStorage[name] = theme; + }; + + /** + * Register option preprocessor + * @param {Function} preprocessorFunc + */ + echarts.registerPreprocessor = function (preprocessorFunc) { + optionPreprocessorFuncs.push(preprocessorFunc); + }; + + /** + * @param {number} [priority=1000] + * @param {Function} processorFunc + */ + echarts.registerProcessor = function (priority, processorFunc) { + if (typeof priority === 'function') { + processorFunc = priority; + priority = PRIORITY_PROCESSOR_FILTER; + } + if (true) { + if (isNaN(priority)) { + throw new Error('Unkown processor priority'); + } + } + dataProcessorFuncs.push({ + prio: priority, + func: processorFunc + }); + }; + + /** + * Register postUpdater + * @param {Function} postUpdateFunc + */ + echarts.registerPostUpdate = function (postUpdateFunc) { + postUpdateFuncs.push(postUpdateFunc); + }; + + /** + * Usage: + * registerAction('someAction', 'someEvent', function () { ... }); + * registerAction('someAction', function () { ... }); + * registerAction( + * {type: 'someAction', event: 'someEvent', update: 'updateView'}, + * function () { ... } + * ); + * + * @param {(string|Object)} actionInfo + * @param {string} actionInfo.type + * @param {string} [actionInfo.event] + * @param {string} [actionInfo.update] + * @param {string} [eventName] + * @param {Function} action + */ + echarts.registerAction = function (actionInfo, eventName, action) { + if (typeof eventName === 'function') { + action = eventName; + eventName = ''; + } + var actionType = zrUtil.isObject(actionInfo) + ? actionInfo.type + : ([actionInfo, actionInfo = { + event: eventName + }][0]); + + // Event name is all lowercase + actionInfo.event = (actionInfo.event || actionType).toLowerCase(); + eventName = actionInfo.event; + + // Validate action type and event name. + zrUtil.assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName)); + + if (!actions[actionType]) { + actions[actionType] = {action: action, actionInfo: actionInfo}; + } + eventActionMap[eventName] = actionType; + }; + + /** + * @param {string} type + * @param {*} CoordinateSystem + */ + echarts.registerCoordinateSystem = function (type, CoordinateSystem) { + CoordinateSystemManager.register(type, CoordinateSystem); + }; + + /** + * Get dimensions of specified coordinate system. + * @param {string} type + * @return {Array.} + */ + echarts.getCoordinateSystemDimensions = function (type) { + var coordSysCreator = CoordinateSystemManager.get(type); + if (coordSysCreator) { + return coordSysCreator.getDimensionsInfo + ? coordSysCreator.getDimensionsInfo() + : coordSysCreator.dimensions.slice(); + } + }; + + /** + * Layout is a special stage of visual encoding + * Most visual encoding like color are common for different chart + * But each chart has it's own layout algorithm + * + * @param {number} [priority=1000] + * @param {Function} layoutFunc + */ + echarts.registerLayout = function (priority, layoutFunc) { + if (typeof priority === 'function') { + layoutFunc = priority; + priority = PRIORITY_VISUAL_LAYOUT; + } + if (true) { + if (isNaN(priority)) { + throw new Error('Unkown layout priority'); + } + } + visualFuncs.push({ + prio: priority, + func: layoutFunc, + isLayout: true + }); + }; + + /** + * @param {number} [priority=3000] + * @param {Function} visualFunc + */ + echarts.registerVisual = function (priority, visualFunc) { + if (typeof priority === 'function') { + visualFunc = priority; + priority = PRIORITY_VISUAL_CHART; + } + if (true) { + if (isNaN(priority)) { + throw new Error('Unkown visual priority'); + } + } + visualFuncs.push({ + prio: priority, + func: visualFunc + }); + }; + + /** + * @param {string} name + */ + echarts.registerLoading = function (name, loadingFx) { + loadingEffects[name] = loadingFx; + }; + + /** + * @param {Object} opts + * @param {string} [superClass] + */ + echarts.extendComponentModel = function (opts/*, superClass*/) { + // var Clazz = ComponentModel; + // if (superClass) { + // var classType = parseClassType(superClass); + // Clazz = ComponentModel.getClass(classType.main, classType.sub, true); + // } + return ComponentModel.extend(opts); + }; + + /** + * @param {Object} opts + * @param {string} [superClass] + */ + echarts.extendComponentView = function (opts/*, superClass*/) { + // var Clazz = ComponentView; + // if (superClass) { + // var classType = parseClassType(superClass); + // Clazz = ComponentView.getClass(classType.main, classType.sub, true); + // } + return ComponentView.extend(opts); + }; + + /** + * @param {Object} opts + * @param {string} [superClass] + */ + echarts.extendSeriesModel = function (opts/*, superClass*/) { + // var Clazz = SeriesModel; + // if (superClass) { + // superClass = 'series.' + superClass.replace('series.', ''); + // var classType = parseClassType(superClass); + // Clazz = ComponentModel.getClass(classType.main, classType.sub, true); + // } + return SeriesModel.extend(opts); + }; + + /** + * @param {Object} opts + * @param {string} [superClass] + */ + echarts.extendChartView = function (opts/*, superClass*/) { + // var Clazz = ChartView; + // if (superClass) { + // superClass = superClass.replace('series.', ''); + // var classType = parseClassType(superClass); + // Clazz = ChartView.getClass(classType.main, true); + // } + return ChartView.extend(opts); + }; + + /** + * ZRender need a canvas context to do measureText. + * But in node environment canvas may be created by node-canvas. + * So we need to specify how to create a canvas instead of using document.createElement('canvas') + * + * Be careful of using it in the browser. + * + * @param {Function} creator + * @example + * var Canvas = require('canvas'); + * var echarts = require('echarts'); + * echarts.setCanvasCreator(function () { + * // Small size is enough. + * return new Canvas(32, 32); + * }); + */ + echarts.setCanvasCreator = function (creator) { + zrUtil.createCanvas = creator; + }; + + echarts.registerVisual(PRIORITY_VISUAL_GLOBAL, __webpack_require__(94)); + echarts.registerPreprocessor(__webpack_require__(95)); + echarts.registerLoading('default', __webpack_require__(97)); + + // Default action + echarts.registerAction({ + type: 'highlight', + event: 'highlight', + update: 'highlight' + }, zrUtil.noop); + echarts.registerAction({ + type: 'downplay', + event: 'downplay', + update: 'downplay' + }, zrUtil.noop); + + + // -------- + // Exports + // -------- + echarts.zrender = zrender; + + echarts.List = __webpack_require__(98); + echarts.Model = __webpack_require__(12); + + echarts.Axis = __webpack_require__(100); + + echarts.graphic = __webpack_require__(18); + echarts.number = __webpack_require__(7); + echarts.format = __webpack_require__(6); + echarts.throttle = throttle.throttle; + echarts.matrix = __webpack_require__(11); + echarts.vector = __webpack_require__(10); + echarts.color = __webpack_require__(31); + + echarts.util = {}; + each([ + 'map', 'each', 'filter', 'indexOf', 'inherits', 'reduce', 'filter', + 'bind', 'curry', 'isArray', 'isString', 'isObject', 'isFunction', + 'extend', 'defaults', 'clone', 'merge' + ], + function (name) { + echarts.util[name] = zrUtil[name]; + } + ); + + echarts.helper = __webpack_require__(108); + + + // PRIORITY + echarts.PRIORITY = { + PROCESSOR: { + FILTER: PRIORITY_PROCESSOR_FILTER, + STATISTIC: PRIORITY_PROCESSOR_STATISTIC + }, + VISUAL: { + LAYOUT: PRIORITY_VISUAL_LAYOUT, + GLOBAL: PRIORITY_VISUAL_GLOBAL, + CHART: PRIORITY_VISUAL_CHART, + COMPONENT: PRIORITY_VISUAL_COMPONENT, + BRUSH: PRIORITY_VISUAL_BRUSH + } + }; + + module.exports = echarts; + + +/***/ }, +/* 2 */ +/***/ function(module, exports) { + + /** + * echarts设备环境识别 + * + * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。 + * @author firede[firede@firede.us] + * @desc thanks zepto. + */ + + var env = {}; + if (typeof navigator === 'undefined') { + // In node + env = { + browser: {}, + os: {}, + node: true, + // Assume canvas is supported + canvasSupported: true + }; + } + else { + env = detect(navigator.userAgent); + } + + module.exports = env; + + // Zepto.js + // (c) 2010-2013 Thomas Fuchs + // Zepto.js may be freely distributed under the MIT license. + + function detect(ua) { + var os = {}; + var browser = {}; + // var webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/); + // var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); + // var ipad = ua.match(/(iPad).*OS\s([\d_]+)/); + // var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/); + // var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/); + // var webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/); + // var touchpad = webos && ua.match(/TouchPad/); + // var kindle = ua.match(/Kindle\/([\d.]+)/); + // var silk = ua.match(/Silk\/([\d._]+)/); + // var blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/); + // var bb10 = ua.match(/(BB10).*Version\/([\d.]+)/); + // var rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/); + // var playbook = ua.match(/PlayBook/); + // var chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/); + var firefox = ua.match(/Firefox\/([\d.]+)/); + // var safari = webkit && ua.match(/Mobile\//) && !chrome; + // var webview = ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/) && !chrome; + var ie = ua.match(/MSIE\s([\d.]+)/) + // IE 11 Trident/7.0; rv:11.0 + || ua.match(/Trident\/.+?rv:(([\d.]+))/); + var edge = ua.match(/Edge\/([\d.]+)/); // IE 12 and 12+ + + var weChat = (/micromessenger/i).test(ua); + + // Todo: clean this up with a better OS/browser seperation: + // - discern (more) between multiple browsers on android + // - decide if kindle fire in silk mode is android or not + // - Firefox on Android doesn't specify the Android version + // - possibly devide in os, device and browser hashes + + // if (browser.webkit = !!webkit) browser.version = webkit[1]; + + // if (android) os.android = true, os.version = android[2]; + // if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.'); + // if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.'); + // if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null; + // if (webos) os.webos = true, os.version = webos[2]; + // if (touchpad) os.touchpad = true; + // if (blackberry) os.blackberry = true, os.version = blackberry[2]; + // if (bb10) os.bb10 = true, os.version = bb10[2]; + // if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2]; + // if (playbook) browser.playbook = true; + // if (kindle) os.kindle = true, os.version = kindle[1]; + // if (silk) browser.silk = true, browser.version = silk[1]; + // if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true; + // if (chrome) browser.chrome = true, browser.version = chrome[1]; + if (firefox) { + browser.firefox = true; + browser.version = firefox[1]; + } + // if (safari && (ua.match(/Safari/) || !!os.ios)) browser.safari = true; + // if (webview) browser.webview = true; + + if (ie) { + browser.ie = true; + browser.version = ie[1]; + } + + if (edge) { + browser.edge = true; + browser.version = edge[1]; + } + + // It is difficult to detect WeChat in Win Phone precisely, because ua can + // not be set on win phone. So we do not consider Win Phone. + if (weChat) { + browser.weChat = true; + } + + // os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) || + // (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/))); + // os.phone = !!(!os.tablet && !os.ipod && (android || iphone || webos || + // (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) || + // (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/)))); + + return { + browser: browser, + os: os, + node: false, + // 原生canvas支持,改极端点了 + // canvasSupported : !(browser.ie && parseFloat(browser.version) < 9) + canvasSupported : document.createElement('canvas').getContext ? true : false, + // @see + // works on most browsers + // IE10/11 does not support touch event, and MS Edge supports them but not by + // default, so we dont check navigator.maxTouchPoints for them here. + touchEventsSupported: 'ontouchstart' in window && !browser.ie && !browser.edge, + // . + pointerEventsSupported: 'onpointerdown' in window + // Firefox supports pointer but not by default, only MS browsers are reliable on pointer + // events currently. So we dont use that on other browsers unless tested sufficiently. + // Although IE 10 supports pointer event, it use old style and is different from the + // standard. So we exclude that. (IE 10 is hardly used on touch device) + && (browser.edge || (browser.ie && browser.version >= 11)) + }; + } + + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * ECharts global model + * + * @module {echarts/model/Global} + */ + + + + /** + * Caution: If the mechanism should be changed some day, these cases + * should be considered: + * + * (1) In `merge option` mode, if using the same option to call `setOption` + * many times, the result should be the same (try our best to ensure that). + * (2) In `merge option` mode, if a component has no id/name specified, it + * will be merged by index, and the result sequence of the components is + * consistent to the original sequence. + * (3) `reset` feature (in toolbox). Find detailed info in comments about + * `mergeOption` in module:echarts/model/OptionManager. + */ + + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var Model = __webpack_require__(12); + var each = zrUtil.each; + var filter = zrUtil.filter; + var map = zrUtil.map; + var isArray = zrUtil.isArray; + var indexOf = zrUtil.indexOf; + var isObject = zrUtil.isObject; + + var ComponentModel = __webpack_require__(69); + + var globalDefault = __webpack_require__(73); + + var OPTION_INNER_KEY = '\0_ec_inner'; + + /** + * @alias module:echarts/model/Global + * + * @param {Object} option + * @param {module:echarts/model/Model} parentModel + * @param {Object} theme + */ + var GlobalModel = Model.extend({ + + constructor: GlobalModel, + + init: function (option, parentModel, theme, optionManager) { + theme = theme || {}; + + this.option = null; // Mark as not initialized. + + /** + * @type {module:echarts/model/Model} + * @private + */ + this._theme = new Model(theme); + + /** + * @type {module:echarts/model/OptionManager} + */ + this._optionManager = optionManager; + }, + + setOption: function (option, optionPreprocessorFuncs) { + zrUtil.assert( + !(OPTION_INNER_KEY in option), + 'please use chart.getOption()' + ); + //**yuki lebal** here to the first step; + this._optionManager.setOption(option, optionPreprocessorFuncs); + + this.resetOption(null); + }, + + /** + * @param {string} type null/undefined: reset all. + * 'recreate': force recreate all. + * 'timeline': only reset timeline option + * 'media': only reset media query option + * @return {boolean} Whether option changed. + */ + resetOption: function (type) { + var optionChanged = false; + var optionManager = this._optionManager; + + if (!type || type === 'recreate') { + var baseOption = optionManager.mountOption(type === 'recreate'); + + if (!this.option || type === 'recreate') { + initBase.call(this, baseOption); + } + else { + this.restoreData(); + //**yuki**lebal + this.mergeOption(baseOption); + } + optionChanged = true; + } + + if (type === 'timeline' || type === 'media') { + this.restoreData(); + } + + if (!type || type === 'recreate' || type === 'timeline') { + var timelineOption = optionManager.getTimelineOption(this); + timelineOption && (this.mergeOption(timelineOption), optionChanged = true); + } + + if (!type || type === 'recreate' || type === 'media') { + var mediaOptions = optionManager.getMediaOption(this, this._api); + if (mediaOptions.length) { + each(mediaOptions, function (mediaOption) { + this.mergeOption(mediaOption, optionChanged = true); + }, this); + } + } + + return optionChanged; + }, + + /** + * @protected + */ + mergeOption: function (newOption) { + //**yuki**changed begin + //the second step set this.option.series to null; + this.option.series = []; + //**yuki**changed over + var option = this.option; + this._componentsMap._ec_series=[]; + var componentsMap = this._componentsMap; + var newCptTypes = []; + + // 如果不存在对应的 component model 则直接 merge + each(newOption, function (componentOption, mainType) { + if (componentOption == null) { + return; + } + + if (!ComponentModel.hasClass(mainType)) { + //如果不存在对应的 component model 则直接 merge + { + option[mainType] = option[mainType] == null + ? zrUtil.clone(componentOption) + : zrUtil.merge(option[mainType], componentOption, true); + } + } + else { + newCptTypes.push(mainType); + } + }); + + // FIXME OPTION 同步是否要改回原来的 + ComponentModel.topologicalTravel( + newCptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this + ); + //**yuki**changed begin + this._seriesIndices = createSeriesIndices(componentsMap.get('series')); + //this._seriesIndices = this._seriesIndices || []; + //to fake a seriesIndeices + function visitComponent(mainType, dependencies) { + var newCptOptionList = modelUtil.normalizeToArray(newOption[mainType]); + + var mapResult = modelUtil.mappingToExists( + componentsMap.get(mainType), newCptOptionList + ); + + modelUtil.makeIdAndName(mapResult); + + // Set mainType and complete subType. + each(mapResult, function (item, index) { + var opt = item.option; + if (isObject(opt)) { + item.keyInfo.mainType = mainType; + item.keyInfo.subType = determineSubType(mainType, opt, item.exist); + } + }); + + var dependentModels = getComponentsByTypes( + componentsMap, dependencies + ); + + option[mainType] = []; + componentsMap.set(mainType, []); + + each(mapResult, function (resultItem, index) { + var componentModel = resultItem.exist; + var newCptOption = resultItem.option; + + zrUtil.assert( + isObject(newCptOption) || componentModel, + 'Empty component definition' + ); + + // Consider where is no new option and should be merged using {}, + // see removeEdgeAndAdd in topologicalTravel and + // ComponentModel.getAllClassMainTypes. + if (!newCptOption) { + componentModel.mergeOption({}, this); + componentModel.optionUpdated({}, false); + } + else { + var ComponentModelClass = ComponentModel.getClass( + mainType, resultItem.keyInfo.subType, true + ); + + if (componentModel && componentModel instanceof ComponentModelClass) { + componentModel.name = resultItem.keyInfo.name; + componentModel.mergeOption(newCptOption, this); + componentModel.optionUpdated(newCptOption, false); + } + else { + // PENDING Global as parent ? + var extraOpt = zrUtil.extend( + { + dependentModels: dependentModels, + componentIndex: index + }, + resultItem.keyInfo + ); + componentModel = new ComponentModelClass( + newCptOption, this, this, extraOpt + ); + zrUtil.extend(componentModel, extraOpt); + componentModel.init(newCptOption, this, this, extraOpt); + // Call optionUpdated after init. + // newCptOption has been used as componentModel.option + // and may be merged with theme and default, so pass null + // to avoid confusion. + componentModel.optionUpdated(null, true); + } + } + + componentsMap.get(mainType)[index] = componentModel; + option[mainType][index] = componentModel.option; + }, this); + + // Backup series for filtering. + if (mainType === 'series') { + this._seriesIndices = createSeriesIndices(componentsMap.get('series')); + } + } + }, + + /** + * Get option for output (cloned option and inner info removed) + * @public + * @return {Object} + */ + getOption: function () { + var option = zrUtil.clone(this.option); + + each(option, function (opts, mainType) { + if (ComponentModel.hasClass(mainType)) { + var opts = modelUtil.normalizeToArray(opts); + for (var i = opts.length - 1; i >= 0; i--) { + // Remove options with inner id. + if (modelUtil.isIdInner(opts[i])) { + opts.splice(i, 1); + } + } + option[mainType] = opts; + } + }); + + delete option[OPTION_INNER_KEY]; + + return option; + }, + + /** + * @return {module:echarts/model/Model} + */ + getTheme: function () { + return this._theme; + }, + + /** + * @param {string} mainType + * @param {number} [idx=0] + * @return {module:echarts/model/Component} + */ + getComponent: function (mainType, idx) { + var list = this._componentsMap.get(mainType); + if (list) { + return list[idx || 0]; + } + }, + + /** + * If none of index and id and name used, return all components with mainType. + * @param {Object} condition + * @param {string} condition.mainType + * @param {string} [condition.subType] If ignore, only query by mainType + * @param {number|Array.} [condition.index] Either input index or id or name. + * @param {string|Array.} [condition.id] Either input index or id or name. + * @param {string|Array.} [condition.name] Either input index or id or name. + * @return {Array.} + */ + queryComponents: function (condition) { + var mainType = condition.mainType; + if (!mainType) { + return []; + } + + var index = condition.index; + var id = condition.id; + var name = condition.name; + + var cpts = this._componentsMap.get(mainType); + + if (!cpts || !cpts.length) { + return []; + } + + var result; + + if (index != null) { + if (!isArray(index)) { + index = [index]; + } + result = filter(map(index, function (idx) { + return cpts[idx]; + }), function (val) { + return !!val; + }); + } + else if (id != null) { + var isIdArray = isArray(id); + result = filter(cpts, function (cpt) { + return (isIdArray && indexOf(id, cpt.id) >= 0) + || (!isIdArray && cpt.id === id); + }); + } + else if (name != null) { + var isNameArray = isArray(name); + result = filter(cpts, function (cpt) { + return (isNameArray && indexOf(name, cpt.name) >= 0) + || (!isNameArray && cpt.name === name); + }); + } + else { + // Return all components with mainType + result = cpts.slice(); + } + + return filterBySubType(result, condition); + }, + + /** + * The interface is different from queryComponents, + * which is convenient for inner usage. + * + * @usage + * var result = findComponents( + * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}} + * ); + * var result = findComponents( + * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}} + * ); + * var result = findComponents( + * {mainType: 'series'}, + * function (model, index) {...} + * ); + * // result like [component0, componnet1, ...] + * + * @param {Object} condition + * @param {string} condition.mainType Mandatory. + * @param {string} [condition.subType] Optional. + * @param {Object} [condition.query] like {xxxIndex, xxxId, xxxName}, + * where xxx is mainType. + * If query attribute is null/undefined or has no index/id/name, + * do not filtering by query conditions, which is convenient for + * no-payload situations or when target of action is global. + * @param {Function} [condition.filter] parameter: component, return boolean. + * @return {Array.} + */ + findComponents: function (condition) { + var query = condition.query; + var mainType = condition.mainType; + + var queryCond = getQueryCond(query); + var result = queryCond + ? this.queryComponents(queryCond) + : this._componentsMap.get(mainType); + + return doFilter(filterBySubType(result, condition)); + + function getQueryCond(q) { + var indexAttr = mainType + 'Index'; + var idAttr = mainType + 'Id'; + var nameAttr = mainType + 'Name'; + return q && ( + q[indexAttr] != null + || q[idAttr] != null + || q[nameAttr] != null + ) + ? { + mainType: mainType, + // subType will be filtered finally. + index: q[indexAttr], + id: q[idAttr], + name: q[nameAttr] + } + : null; + } + + function doFilter(res) { + return condition.filter + ? filter(res, condition.filter) + : res; + } + }, + + /** + * @usage + * eachComponent('legend', function (legendModel, index) { + * ... + * }); + * eachComponent(function (componentType, model, index) { + * // componentType does not include subType + * // (componentType is 'xxx' but not 'xxx.aa') + * }); + * eachComponent( + * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}, + * function (model, index) {...} + * ); + * eachComponent( + * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}, + * function (model, index) {...} + * ); + * + * @param {string|Object=} mainType When mainType is object, the definition + * is the same as the method 'findComponents'. + * @param {Function} cb + * @param {*} context + */ + eachComponent: function (mainType, cb, context) { + var componentsMap = this._componentsMap; + + if (typeof mainType === 'function') { + context = cb; + cb = mainType; + componentsMap.each(function (components, componentType) { + each(components, function (component, index) { + cb.call(context, componentType, component, index); + }); + }); + } + else if (zrUtil.isString(mainType)) { + each(componentsMap.get(mainType), cb, context); + } + else if (isObject(mainType)) { + var queryResult = this.findComponents(mainType); + each(queryResult, cb, context); + } + }, + + /** + * @param {string} name + * @return {Array.} + */ + getSeriesByName: function (name) { + var series = this._componentsMap.get('series'); + return filter(series, function (oneSeries) { + return oneSeries.name === name; + }); + }, + + /** + * @param {number} seriesIndex + * @return {module:echarts/model/Series} + */ + getSeriesByIndex: function (seriesIndex) { + return this._componentsMap.get('series')[seriesIndex]; + }, + + /** + * @param {string} subType + * @return {Array.} + */ + getSeriesByType: function (subType) { + var series = this._componentsMap.get('series'); + return filter(series, function (oneSeries) { + return oneSeries.subType === subType; + }); + }, + + /** + * @return {Array.} + */ + getSeries: function () { + return this._componentsMap.get('series').slice(); + }, + + /** + * After filtering, series may be different + * frome raw series. + * + * @param {Function} cb + * @param {*} context + */ + eachSeries: function (cb, context) { + assertSeriesInitialized(this); + each(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + cb.call(context, series, rawSeriesIndex); + }, this); + }, + + /** + * Iterate raw series before filtered. + * + * @param {Function} cb + * @param {*} context + */ + eachRawSeries: function (cb, context) { + each(this._componentsMap.get('series'), cb, context); + }, + + /** + * After filtering, series may be different. + * frome raw series. + * + * @parma {string} subType + * @param {Function} cb + * @param {*} context + */ + eachSeriesByType: function (subType, cb, context) { + assertSeriesInitialized(this); + each(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + if (series.subType === subType) { + cb.call(context, series, rawSeriesIndex); + } + }, this); + }, + + /** + * Iterate raw series before filtered of given type. + * + * @parma {string} subType + * @param {Function} cb + * @param {*} context + */ + eachRawSeriesByType: function (subType, cb, context) { + return each(this.getSeriesByType(subType), cb, context); + }, + + /** + * @param {module:echarts/model/Series} seriesModel + */ + isSeriesFiltered: function (seriesModel) { + assertSeriesInitialized(this); + return zrUtil.indexOf(this._seriesIndices, seriesModel.componentIndex) < 0; + }, + + /** + * @return {Array.} + */ + getCurrentSeriesIndices: function () { + return (this._seriesIndices || []).slice(); + }, + + /** + * @param {Function} cb + * @param {*} context + */ + filterSeries: function (cb, context) { + assertSeriesInitialized(this); + var filteredSeries = filter( + this._componentsMap.get('series'), cb, context + ); + this._seriesIndices = createSeriesIndices(filteredSeries); + }, + + restoreData: function () { + var componentsMap = this._componentsMap; + + this._seriesIndices = createSeriesIndices(componentsMap.get('series')); + + var componentTypes = []; + componentsMap.each(function (components, componentType) { + componentTypes.push(componentType); + }); + + ComponentModel.topologicalTravel( + componentTypes, + ComponentModel.getAllClassMainTypes(), + function (componentType, dependencies) { + each(componentsMap.get(componentType), function (component) { + component.restoreData(); + }); + } + ); + } + + }); + + /** + * @inner + */ + function mergeTheme(option, theme) { + zrUtil.each(theme, function (themeItem, name) { + // 如果有 component model 则把具体的 merge 逻辑交给该 model 处理 + if (!ComponentModel.hasClass(name)) { + if (typeof themeItem === 'object') { + option[name] = !option[name] + ? zrUtil.clone(themeItem) + : zrUtil.merge(option[name], themeItem, false); + } + else { + if (option[name] == null) { + option[name] = themeItem; + } + } + } + }); + } + + function initBase(baseOption) { + baseOption = baseOption; + + // Using OPTION_INNER_KEY to mark that this option can not be used outside, + // i.e. `chart.setOption(chart.getModel().option);` is forbiden. + this.option = {}; + this.option[OPTION_INNER_KEY] = 1; + + /** + * Init with series: [], in case of calling findSeries method + * before series initialized. + * @type {Object.>} + * @private + */ + this._componentsMap = zrUtil.createHashMap({series: []}); + + /** + * Mapping between filtered series list and raw series list. + * key: filtered series indices, value: raw series indices. + * @type {Array.} + * @private + */ + this._seriesIndices = null; + + mergeTheme(baseOption, this._theme.option); + + // TODO Needs clone when merging to the unexisted property + zrUtil.merge(baseOption, globalDefault, false); + + this.mergeOption(baseOption); + } + + /** + * @inner + * @param {Array.|string} types model types + * @return {Object} key: {string} type, value: {Array.} models + */ + function getComponentsByTypes(componentsMap, types) { + if (!zrUtil.isArray(types)) { + types = types ? [types] : []; + } + + var ret = {}; + each(types, function (type) { + ret[type] = (componentsMap.get(type) || []).slice(); + }); + + return ret; + } + + /** + * @inner + */ + function determineSubType(mainType, newCptOption, existComponent) { + var subType = newCptOption.type + ? newCptOption.type + : existComponent + ? existComponent.subType + // Use determineSubType only when there is no existComponent. + : ComponentModel.determineSubType(mainType, newCptOption); + + // tooltip, markline, markpoint may always has no subType + return subType; + } + + /** + * @inner + */ + function createSeriesIndices(seriesModels) { + return map(seriesModels, function (series) { + return series.componentIndex; + }) || []; + } + + /** + * @inner + */ + function filterBySubType(components, condition) { + // Using hasOwnProperty for restrict. Consider + // subType is undefined in user payload. + return condition.hasOwnProperty('subType') + ? filter(components, function (cpt) { + return cpt.subType === condition.subType; + }) + : components; + } + + /** + * @inner + */ + function assertSeriesInitialized(ecModel) { + // Components that use _seriesIndices should depends on series component, + // which make sure that their initialization is after series. + if (true) { + if (!ecModel._seriesIndices) { + throw new Error('Option should contains series.'); + } + } + } + + zrUtil.mixin(GlobalModel, __webpack_require__(74)); + + module.exports = GlobalModel; + + +/***/ }, +/* 4 */ +/***/ function(module, exports) { + + /** + * @module zrender/core/util + */ + + + // 用于处理merge时无法遍历Date等对象的问题 + var BUILTIN_OBJECT = { + '[object Function]': 1, + '[object RegExp]': 1, + '[object Date]': 1, + '[object Error]': 1, + '[object CanvasGradient]': 1, + '[object CanvasPattern]': 1, + // For node-canvas + '[object Image]': 1, + '[object Canvas]': 1 + }; + + var TYPED_ARRAY = { + '[object Int8Array]': 1, + '[object Uint8Array]': 1, + '[object Uint8ClampedArray]': 1, + '[object Int16Array]': 1, + '[object Uint16Array]': 1, + '[object Int32Array]': 1, + '[object Uint32Array]': 1, + '[object Float32Array]': 1, + '[object Float64Array]': 1 + }; + + var objToString = Object.prototype.toString; + + var arrayProto = Array.prototype; + var nativeForEach = arrayProto.forEach; + var nativeFilter = arrayProto.filter; + var nativeSlice = arrayProto.slice; + var nativeMap = arrayProto.map; + var nativeReduce = arrayProto.reduce; + + /** + * Those data types can be cloned: + * Plain object, Array, TypedArray, number, string, null, undefined. + * Those data types will be assgined using the orginal data: + * BUILTIN_OBJECT + * Instance of user defined class will be cloned to a plain object, without + * properties in prototype. + * Other data types is not supported (not sure what will happen). + * + * Caution: do not support clone Date, for performance consideration. + * (There might be a large number of date in `series.data`). + * So date should not be modified in and out of echarts. + * + * @param {*} source + * @return {*} new + */ + function clone(source) { + if (source == null || typeof source != 'object') { + return source; + } + + var result = source; + var typeStr = objToString.call(source); + + if (typeStr === '[object Array]') { + result = []; + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + else if (TYPED_ARRAY[typeStr]) { + result = source.constructor.from(source); + } + else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) { + result = {}; + for (var key in source) { + if (source.hasOwnProperty(key)) { + result[key] = clone(source[key]); + } + } + } + + return result; + } + + /** + * @memberOf module:zrender/core/util + * @param {*} target + * @param {*} source + * @param {boolean} [overwrite=false] + */ + function merge(target, source, overwrite) { + // We should escapse that source is string + // and enter for ... in ... + if (!isObject(source) || !isObject(target)) { + return overwrite ? clone(source) : target; + } + + for (var key in source) { + if (source.hasOwnProperty(key)) { + var targetProp = target[key]; + var sourceProp = source[key]; + + if (isObject(sourceProp) + && isObject(targetProp) + && !isArray(sourceProp) + && !isArray(targetProp) + && !isDom(sourceProp) + && !isDom(targetProp) + && !isBuiltInObject(sourceProp) + && !isBuiltInObject(targetProp) + && !isPrimitive(sourceProp) + && !isPrimitive(targetProp) + ) { + // 如果需要递归覆盖,就递归调用merge + merge(targetProp, sourceProp, overwrite); + } + else if (overwrite || !(key in target)) { + // 否则只处理overwrite为true,或者在目标对象中没有此属性的情况 + // NOTE,在 target[key] 不存在的时候也是直接覆盖 + target[key] = clone(source[key], true); + } + } + } + + return target; + } + + /** + * @param {Array} targetAndSources The first item is target, and the rests are source. + * @param {boolean} [overwrite=false] + * @return {*} target + */ + function mergeAll(targetAndSources, overwrite) { + var result = targetAndSources[0]; + for (var i = 1, len = targetAndSources.length; i < len; i++) { + result = merge(result, targetAndSources[i], overwrite); + } + return result; + } + + /** + * @param {*} target + * @param {*} source + * @memberOf module:zrender/core/util + */ + function extend(target, source) { + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key]; + } + } + return target; + } + + /** + * @param {*} target + * @param {*} source + * @param {boolen} [overlay=false] + * @memberOf module:zrender/core/util + */ + function defaults(target, source, overlay) { + for (var key in source) { + if (source.hasOwnProperty(key) + && (overlay ? source[key] != null : target[key] == null) + ) { + target[key] = source[key]; + } + } + return target; + } + + function createCanvas() { + return document.createElement('canvas'); + } + // FIXME + var _ctx; + function getContext() { + if (!_ctx) { + // Use util.createCanvas instead of createCanvas + // because createCanvas may be overwritten in different environment + _ctx = util.createCanvas().getContext('2d'); + } + return _ctx; + } + + /** + * 查询数组中元素的index + * @memberOf module:zrender/core/util + */ + function indexOf(array, value) { + if (array) { + if (array.indexOf) { + return array.indexOf(value); + } + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + } + return -1; + } + + /** + * 构造类继承关系 + * + * @memberOf module:zrender/core/util + * @param {Function} clazz 源类 + * @param {Function} baseClazz 基类 + */ + function inherits(clazz, baseClazz) { + var clazzPrototype = clazz.prototype; + function F() {} + F.prototype = baseClazz.prototype; + clazz.prototype = new F(); + + for (var prop in clazzPrototype) { + clazz.prototype[prop] = clazzPrototype[prop]; + } + clazz.prototype.constructor = clazz; + clazz.superClass = baseClazz; + } + + /** + * @memberOf module:zrender/core/util + * @param {Object|Function} target + * @param {Object|Function} sorce + * @param {boolean} overlay + */ + function mixin(target, source, overlay) { + target = 'prototype' in target ? target.prototype : target; + source = 'prototype' in source ? source.prototype : source; + + defaults(target, source, overlay); + } + + /** + * Consider typed array. + * @param {Array|TypedArray} data + */ + function isArrayLike(data) { + if (! data) { + return; + } + if (typeof data == 'string') { + return false; + } + return typeof data.length == 'number'; + } + + /** + * 数组或对象遍历 + * @memberOf module:zrender/core/util + * @param {Object|Array} obj + * @param {Function} cb + * @param {*} [context] + */ + function each(obj, cb, context) { + if (!(obj && cb)) { + return; + } + if (obj.forEach && obj.forEach === nativeForEach) { + obj.forEach(cb, context); + } + else if (obj.length === +obj.length) { + for (var i = 0, len = obj.length; i < len; i++) { + cb.call(context, obj[i], i, obj); + } + } + else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + cb.call(context, obj[key], key, obj); + } + } + } + } + + /** + * 数组映射 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {Array} + */ + function map(obj, cb, context) { + if (!(obj && cb)) { + return; + } + if (obj.map && obj.map === nativeMap) { + return obj.map(cb, context); + } + else { + var result = []; + for (var i = 0, len = obj.length; i < len; i++) { + result.push(cb.call(context, obj[i], i, obj)); + } + return result; + } + } + + /** + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {Object} [memo] + * @param {*} [context] + * @return {Array} + */ + function reduce(obj, cb, memo, context) { + if (!(obj && cb)) { + return; + } + if (obj.reduce && obj.reduce === nativeReduce) { + return obj.reduce(cb, memo, context); + } + else { + for (var i = 0, len = obj.length; i < len; i++) { + memo = cb.call(context, memo, obj[i], i, obj); + } + return memo; + } + } + + /** + * 数组过滤 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {Array} + */ + function filter(obj, cb, context) { + if (!(obj && cb)) { + return; + } + if (obj.filter && obj.filter === nativeFilter) { + return obj.filter(cb, context); + } + else { + var result = []; + for (var i = 0, len = obj.length; i < len; i++) { + if (cb.call(context, obj[i], i, obj)) { + result.push(obj[i]); + } + } + return result; + } + } + + /** + * 数组项查找 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {Array} + */ + function find(obj, cb, context) { + if (!(obj && cb)) { + return; + } + for (var i = 0, len = obj.length; i < len; i++) { + if (cb.call(context, obj[i], i, obj)) { + return obj[i]; + } + } + } + + /** + * @memberOf module:zrender/core/util + * @param {Function} func + * @param {*} context + * @return {Function} + */ + function bind(func, context) { + var args = nativeSlice.call(arguments, 2); + return function () { + return func.apply(context, args.concat(nativeSlice.call(arguments))); + }; + } + + /** + * @memberOf module:zrender/core/util + * @param {Function} func + * @return {Function} + */ + function curry(func) { + var args = nativeSlice.call(arguments, 1); + return function () { + return func.apply(this, args.concat(nativeSlice.call(arguments))); + }; + } + + /** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + function isArray(value) { + return objToString.call(value) === '[object Array]'; + } + + /** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + function isFunction(value) { + return typeof value === 'function'; + } + + /** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + function isString(value) { + return objToString.call(value) === '[object String]'; + } + + /** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return type === 'function' || (!!value && type == 'object'); + } + + /** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + function isBuiltInObject(value) { + return !!BUILTIN_OBJECT[objToString.call(value)]; + } + + /** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + function isDom(value) { + return typeof value === 'object' + && typeof value.nodeType === 'number' + && typeof value.ownerDocument === 'object'; + } + + /** + * Whether is exactly NaN. Notice isNaN('a') returns true. + * @param {*} value + * @return {boolean} + */ + function eqNaN(value) { + return value !== value; + } + + /** + * If value1 is not null, then return value1, otherwise judget rest of values. + * @memberOf module:zrender/core/util + * @return {*} Final value + */ + function retrieve(values) { + for (var i = 0, len = arguments.length; i < len; i++) { + if (arguments[i] != null) { + return arguments[i]; + } + } + } + + /** + * @memberOf module:zrender/core/util + * @param {Array} arr + * @param {number} startIndex + * @param {number} endIndex + * @return {Array} + */ + function slice() { + return Function.call.apply(nativeSlice, arguments); + } + + /** + * @memberOf module:zrender/core/util + * @param {boolean} condition + * @param {string} message + */ + function assert(condition, message) { + if (!condition) { + throw new Error(message); + } + } + + var primitiveKey = '__ec_primitive__'; + /** + * Set an object as primitive to be ignored traversing children in clone or merge + */ + function setAsPrimitive(obj) { + obj[primitiveKey] = true; + } + + function isPrimitive(obj) { + return obj[primitiveKey]; + } + + /** + * @constructor + * @param {Object} obj Only apply `ownProperty`. + */ + function HashMap(obj) { + obj && each(obj, function (value, key) { + this.set(key, value); + }, this); + } + + // Add prefix to avoid conflict with Object.prototype. + var HASH_MAP_PREFIX = '_ec_'; + var HASH_MAP_PREFIX_LENGTH = 4; + + HashMap.prototype = { + constructor: HashMap, + // Do not provide `has` method to avoid defining what is `has`. + // (We usually treat `null` and `undefined` as the same, different + // from ES6 Map). + get: function (key) { + return this[HASH_MAP_PREFIX + key]; + }, + set: function (key, value) { + this[HASH_MAP_PREFIX + key] = value; + // Comparing with invocation chaining, `return value` is more commonly + // used in this case: `var someVal = map.set('a', genVal());` + return value; + }, + // Although util.each can be performed on this hashMap directly, user + // should not use the exposed keys, who are prefixed. + each: function (cb, context) { + context !== void 0 && (cb = bind(cb, context)); + for (var prefixedKey in this) { + this.hasOwnProperty(prefixedKey) + && cb(this[prefixedKey], prefixedKey.slice(HASH_MAP_PREFIX_LENGTH)); + } + }, + // Do not use this method if performance sensitive. + removeKey: function (key) { + delete this[key]; + } + }; + + function createHashMap(obj) { + return new HashMap(obj); + } + + var util = { + inherits: inherits, + mixin: mixin, + clone: clone, + merge: merge, + mergeAll: mergeAll, + extend: extend, + defaults: defaults, + getContext: getContext, + createCanvas: createCanvas, + indexOf: indexOf, + slice: slice, + find: find, + isArrayLike: isArrayLike, + each: each, + map: map, + reduce: reduce, + filter: filter, + bind: bind, + curry: curry, + isArray: isArray, + isString: isString, + isObject: isObject, + isFunction: isFunction, + isBuiltInObject: isBuiltInObject, + isDom: isDom, + eqNaN: eqNaN, + retrieve: retrieve, + assert: assert, + setAsPrimitive: setAsPrimitive, + createHashMap: createHashMap, + noop: function () {} + }; + module.exports = util; + + + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + + + var formatUtil = __webpack_require__(6); + var nubmerUtil = __webpack_require__(7); + var Model = __webpack_require__(12); + var zrUtil = __webpack_require__(4); + var each = zrUtil.each; + var isObject = zrUtil.isObject; + + var modelUtil = {}; + + /** + * If value is not array, then translate it to array. + * @param {*} value + * @return {Array} [value] or value + */ + modelUtil.normalizeToArray = function (value) { + return value instanceof Array + ? value + : value == null + ? [] + : [value]; + }; + + /** + * Sync default option between normal and emphasis like `position` and `show` + * In case some one will write code like + * label: { + * normal: { + * show: false, + * position: 'outside', + * textStyle: { + * fontSize: 18 + * } + * }, + * emphasis: { + * show: true + * } + * } + * @param {Object} opt + * @param {Array.} subOpts + */ + modelUtil.defaultEmphasis = function (opt, subOpts) { + if (opt) { + var emphasisOpt = opt.emphasis = opt.emphasis || {}; + var normalOpt = opt.normal = opt.normal || {}; + + // Default emphasis option from normal + each(subOpts, function (subOptName) { + var val = zrUtil.retrieve(emphasisOpt[subOptName], normalOpt[subOptName]); + if (val != null) { + emphasisOpt[subOptName] = val; + } + }); + } + }; + + modelUtil.LABEL_OPTIONS = ['position', 'offset', 'show', 'textStyle', 'distance', 'formatter']; + + /** + * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] + * This helper method retieves value from data. + * @param {string|number|Date|Array|Object} dataItem + * @return {number|string|Date|Array.} + */ + modelUtil.getDataItemValue = function (dataItem) { + // Performance sensitive. + return dataItem && (dataItem.value == null ? dataItem : dataItem.value); + }; + + /** + * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] + * This helper method determine if dataItem has extra option besides value + * @param {string|number|Date|Array|Object} dataItem + */ + modelUtil.isDataItemOption = function (dataItem) { + return isObject(dataItem) + && !(dataItem instanceof Array); + // // markLine data can be array + // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array)); + }; + + /** + * This helper method convert value in data. + * @param {string|number|Date} value + * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'. + */ + modelUtil.converDataValue = function (value, dimInfo) { + // Performance sensitive. + var dimType = dimInfo && dimInfo.type; + if (dimType === 'ordinal') { + return value; + } + + if (dimType === 'time' + // spead up when using timestamp + && typeof value !== 'number' + && value != null + && value !== '-' + ) { + value = +nubmerUtil.parseDate(value); + } + + // dimType defaults 'number'. + // If dimType is not ordinal and value is null or undefined or NaN or '-', + // parse to NaN. + return (value == null || value === '') + ? NaN : +value; // If string (like '-'), using '+' parse to NaN + }; + + /** + * Create a model proxy to be used in tooltip for edge data, markLine data, markPoint data. + * @param {module:echarts/data/List} data + * @param {Object} opt + * @param {string} [opt.seriesIndex] + * @param {Object} [opt.name] + * @param {Object} [opt.mainType] + * @param {Object} [opt.subType] + */ + modelUtil.createDataFormatModel = function (data, opt) { + var model = new Model(); + zrUtil.mixin(model, modelUtil.dataFormatMixin); + model.seriesIndex = opt.seriesIndex; + model.name = opt.name || ''; + model.mainType = opt.mainType; + model.subType = opt.subType; + + model.getData = function () { + return data; + }; + return model; + }; + + // PENDING A little ugly + modelUtil.dataFormatMixin = { + /** + * Get params for formatter + * @param {number} dataIndex + * @param {string} [dataType] + * @return {Object} + */ + getDataParams: function (dataIndex, dataType) { + var data = this.getData(dataType); + var rawValue = this.getRawValue(dataIndex, dataType); + var rawDataIndex = data.getRawIndex(dataIndex); + var name = data.getName(dataIndex, true); + var itemOpt = data.getRawDataItem(dataIndex); + var color = data.getItemVisual(dataIndex, 'color'); + + return { + componentType: this.mainType, + componentSubType: this.subType, + seriesType: this.mainType === 'series' ? this.subType : null, + seriesIndex: this.seriesIndex, + seriesId: this.id, + seriesName: this.name, + name: name, + dataIndex: rawDataIndex, + data: itemOpt, + dataType: dataType, + value: rawValue, + color: color, + marker: formatUtil.getTooltipMarker(color), + + // Param name list for mapping `a`, `b`, `c`, `d`, `e` + $vars: ['seriesName', 'name', 'value'] + }; + }, + + /** + * Format label + * @param {number} dataIndex + * @param {string} [status='normal'] 'normal' or 'emphasis' + * @param {string} [dataType] + * @param {number} [dimIndex] + * @param {string} [labelProp='label'] + * @return {string} + */ + getFormattedLabel: function (dataIndex, status, dataType, dimIndex, labelProp) { + status = status || 'normal'; + var data = this.getData(dataType); + var itemModel = data.getItemModel(dataIndex); + + var params = this.getDataParams(dataIndex, dataType); + if (dimIndex != null && (params.value instanceof Array)) { + params.value = params.value[dimIndex]; + } + + var formatter = itemModel.get([labelProp || 'label', status, 'formatter']); + + if (typeof formatter === 'function') { + params.status = status; + return formatter(params); + } + else if (typeof formatter === 'string') { + return formatUtil.formatTpl(formatter, params); + } + }, + + /** + * Get raw value in option + * @param {number} idx + * @param {string} [dataType] + * @return {Object} + */ + getRawValue: function (idx, dataType) { + var data = this.getData(dataType); + var dataItem = data.getRawDataItem(idx); + if (dataItem != null) { + return (isObject(dataItem) && !(dataItem instanceof Array)) + ? dataItem.value : dataItem; + } + }, + + /** + * Should be implemented. + * @param {number} dataIndex + * @param {boolean} [multipleSeries=false] + * @param {number} [dataType] + * @return {string} tooltip string + */ + formatTooltip: zrUtil.noop + }; + + /** + * Mapping to exists for merge. + * + * @public + * @param {Array.|Array.} exists + * @param {Object|Array.} newCptOptions + * @return {Array.} Result, like [{exist: ..., option: ...}, {}], + * index of which is the same as exists. + */ + modelUtil.mappingToExists = function (exists, newCptOptions) { + // Mapping by the order by original option (but not order of + // new option) in merge mode. Because we should ensure + // some specified index (like xAxisIndex) is consistent with + // original option, which is easy to understand, espatially in + // media query. And in most case, merge option is used to + // update partial option but not be expected to change order. + newCptOptions = (newCptOptions || []).slice(); + + var result = zrUtil.map(exists || [], function (obj, index) { + return {exist: obj}; + }); + + // Mapping by id or name if specified. + each(newCptOptions, function (cptOption, index) { + if (!isObject(cptOption)) { + return; + } + + // id has highest priority. + for (var i = 0; i < result.length; i++) { + if (!result[i].option // Consider name: two map to one. + && cptOption.id != null + && result[i].exist.id === cptOption.id + '' + ) { + result[i].option = cptOption; + newCptOptions[index] = null; + return; + } + } + + for (var i = 0; i < result.length; i++) { + var exist = result[i].exist; + if (!result[i].option // Consider name: two map to one. + // Can not match when both ids exist but different. + && (exist.id == null || cptOption.id == null) + && cptOption.name != null + && !modelUtil.isIdInner(cptOption) + && !modelUtil.isIdInner(exist) + && exist.name === cptOption.name + '' + ) { + result[i].option = cptOption; + newCptOptions[index] = null; + return; + } + } + }); + + // Otherwise mapping by index. + each(newCptOptions, function (cptOption, index) { + if (!isObject(cptOption)) { + return; + } + + var i = 0; + for (; i < result.length; i++) { + var exist = result[i].exist; + if (!result[i].option + // Existing model that already has id should be able to + // mapped to (because after mapping performed model may + // be assigned with a id, whish should not affect next + // mapping), except those has inner id. + && !modelUtil.isIdInner(exist) + // Caution: + // Do not overwrite id. But name can be overwritten, + // because axis use name as 'show label text'. + // 'exist' always has id and name and we dont + // need to check it. + && cptOption.id == null + ) { + result[i].option = cptOption; + break; + } + } + + if (i >= result.length) { + result.push({option: cptOption}); + } + }); + + return result; + }; + + /** + * Make id and name for mapping result (result of mappingToExists) + * into `keyInfo` field. + * + * @public + * @param {Array.} Result, like [{exist: ..., option: ...}, {}], + * which order is the same as exists. + * @return {Array.} The input. + */ + modelUtil.makeIdAndName = function (mapResult) { + // We use this id to hash component models and view instances + // in echarts. id can be specified by user, or auto generated. + + // The id generation rule ensures new view instance are able + // to mapped to old instance when setOption are called in + // no-merge mode. So we generate model id by name and plus + // type in view id. + + // name can be duplicated among components, which is convenient + // to specify multi components (like series) by one name. + + // Ensure that each id is distinct. + var idMap = zrUtil.createHashMap(); + + each(mapResult, function (item, index) { + var existCpt = item.exist; + existCpt && idMap.set(existCpt.id, item); + }); + + each(mapResult, function (item, index) { + var opt = item.option; + + zrUtil.assert( + !opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item, + 'id duplicates: ' + (opt && opt.id) + ); + + opt && opt.id != null && idMap.set(opt.id, item); + !item.keyInfo && (item.keyInfo = {}); + }); + + // Make name and id. + each(mapResult, function (item, index) { + var existCpt = item.exist; + var opt = item.option; + var keyInfo = item.keyInfo; + + if (!isObject(opt)) { + return; + } + + // name can be overwitten. Consider case: axis.name = '20km'. + // But id generated by name will not be changed, which affect + // only in that case: setOption with 'not merge mode' and view + // instance will be recreated, which can be accepted. + keyInfo.name = opt.name != null + ? opt.name + '' + : existCpt + ? existCpt.name + : '\0-'; // name may be displayed on screen, so use '-'. + + if (existCpt) { + keyInfo.id = existCpt.id; + } + else if (opt.id != null) { + keyInfo.id = opt.id + ''; + } + else { + // Consider this situatoin: + // optionA: [{name: 'a'}, {name: 'a'}, {..}] + // optionB [{..}, {name: 'a'}, {name: 'a'}] + // Series with the same name between optionA and optionB + // should be mapped. + var idNum = 0; + do { + keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++; + } + while (idMap.get(keyInfo.id)); + } + + idMap.set(keyInfo.id, item); + }); + }; + + /** + * @public + * @param {Object} cptOption + * @return {boolean} + */ + modelUtil.isIdInner = function (cptOption) { + return isObject(cptOption) + && cptOption.id + && (cptOption.id + '').indexOf('\0_ec_\0') === 0; + }; + + /** + * A helper for removing duplicate items between batchA and batchB, + * and in themselves, and categorize by series. + * + * @param {Array.} batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] + * @param {Array.} batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] + * @return {Array., Array.>} result: [resultBatchA, resultBatchB] + */ + modelUtil.compressBatches = function (batchA, batchB) { + var mapA = {}; + var mapB = {}; + + makeMap(batchA || [], mapA); + makeMap(batchB || [], mapB, mapA); + + return [mapToArray(mapA), mapToArray(mapB)]; + + function makeMap(sourceBatch, map, otherMap) { + for (var i = 0, len = sourceBatch.length; i < len; i++) { + var seriesId = sourceBatch[i].seriesId; + var dataIndices = modelUtil.normalizeToArray(sourceBatch[i].dataIndex); + var otherDataIndices = otherMap && otherMap[seriesId]; + + for (var j = 0, lenj = dataIndices.length; j < lenj; j++) { + var dataIndex = dataIndices[j]; + + if (otherDataIndices && otherDataIndices[dataIndex]) { + otherDataIndices[dataIndex] = null; + } + else { + (map[seriesId] || (map[seriesId] = {}))[dataIndex] = 1; + } + } + } + } + + function mapToArray(map, isData) { + var result = []; + for (var i in map) { + if (map.hasOwnProperty(i) && map[i] != null) { + if (isData) { + result.push(+i); + } + else { + var dataIndices = mapToArray(map[i], true); + dataIndices.length && result.push({seriesId: i, dataIndex: dataIndices}); + } + } + } + return result; + } + }; + + /** + * @param {module:echarts/data/List} data + * @param {Object} payload Contains dataIndex (means rawIndex) / dataIndexInside / name + * each of which can be Array or primary type. + * @return {number|Array.} dataIndex If not found, return undefined/null. + */ + modelUtil.queryDataIndex = function (data, payload) { + if (payload.dataIndexInside != null) { + return payload.dataIndexInside; + } + else if (payload.dataIndex != null) { + return zrUtil.isArray(payload.dataIndex) + ? zrUtil.map(payload.dataIndex, function (value) { + return data.indexOfRawIndex(value); + }) + : data.indexOfRawIndex(payload.dataIndex); + } + else if (payload.name != null) { + return zrUtil.isArray(payload.name) + ? zrUtil.map(payload.name, function (value) { + return data.indexOfName(value); + }) + : data.indexOfName(payload.name); + } + }; + + /** + * Enable property storage to any host object. + * Notice: Serialization is not supported. + * + * For example: + * var get = modelUitl.makeGetter(); + * + * function some(hostObj) { + * get(hostObj)._someProperty = 1212; + * ... + * } + * + * @return {Function} + */ + modelUtil.makeGetter = (function () { + var index = 0; + return function () { + var key = '\0__ec_prop_getter_' + index++; + return function (hostObj) { + return hostObj[key] || (hostObj[key] = {}); + }; + }; + })(); + + /** + * @param {module:echarts/model/Global} ecModel + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex, seriesId, seriesName, + * geoIndex, geoId, geoName, + * bmapIndex, bmapId, bmapName, + * xAxisIndex, xAxisId, xAxisName, + * yAxisIndex, yAxisId, yAxisName, + * gridIndex, gridId, gridName, + * ... (can be extended) + * } + * Each properties can be number|string|Array.|Array. + * For example, a finder could be + * { + * seriesIndex: 3, + * geoId: ['aa', 'cc'], + * gridName: ['xx', 'rr'] + * } + * xxxIndex can be set as 'all' (means all xxx) or 'none' (means not specify) + * If nothing or null/undefined specified, return nothing. + * @param {Object} [opt] + * @param {string} [opt.defaultMainType] + * @param {Array.} [opt.includeMainTypes] + * @return {Object} result like: + * { + * seriesModels: [seriesModel1, seriesModel2], + * seriesModel: seriesModel1, // The first model + * geoModels: [geoModel1, geoModel2], + * geoModel: geoModel1, // The first model + * ... + * } + */ + modelUtil.parseFinder = function (ecModel, finder, opt) { + if (zrUtil.isString(finder)) { + var obj = {}; + obj[finder + 'Index'] = 0; + finder = obj; + } + + var defaultMainType = opt && opt.defaultMainType; + if (defaultMainType + && !has(finder, defaultMainType + 'Index') + && !has(finder, defaultMainType + 'Id') + && !has(finder, defaultMainType + 'Name') + ) { + finder[defaultMainType + 'Index'] = 0; + } + + var result = {}; + + each(finder, function (value, key) { + var value = finder[key]; + + // Exclude 'dataIndex' and other illgal keys. + if (key === 'dataIndex' || key === 'dataIndexInside') { + result[key] = value; + return; + } + + var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || []; + var mainType = parsedKey[1]; + var queryType = (parsedKey[2] || '').toLowerCase(); + + if (!mainType + || !queryType + || value == null + || (queryType === 'index' && value === 'none') + || (opt && opt.includeMainTypes && zrUtil.indexOf(opt.includeMainTypes, mainType) < 0) + ) { + return; + } + + var queryParam = {mainType: mainType}; + if (queryType !== 'index' || value !== 'all') { + queryParam[queryType] = value; + } + + var models = ecModel.queryComponents(queryParam); + result[mainType + 'Models'] = models; + result[mainType + 'Model'] = models[0]; + }); + + return result; + }; + + /** + * @see {module:echarts/data/helper/completeDimensions} + * @param {module:echarts/data/List} data + * @param {string|number} dataDim + * @return {string} + */ + modelUtil.dataDimToCoordDim = function (data, dataDim) { + var dimensions = data.dimensions; + dataDim = data.getDimension(dataDim); + for (var i = 0; i < dimensions.length; i++) { + var dimItem = data.getDimensionInfo(dimensions[i]); + if (dimItem.name === dataDim) { + return dimItem.coordDim; + } + } + }; + + /** + * @see {module:echarts/data/helper/completeDimensions} + * @param {module:echarts/data/List} data + * @param {string} coordDim + * @return {Array.} data dimensions on the coordDim. + */ + modelUtil.coordDimToDataDim = function (data, coordDim) { + var dataDim = []; + each(data.dimensions, function (dimName) { + var dimItem = data.getDimensionInfo(dimName); + if (dimItem.coordDim === coordDim) { + dataDim[dimItem.coordDimIndex] = dimItem.name; + } + }); + return dataDim; + }; + + /** + * @see {module:echarts/data/helper/completeDimensions} + * @param {module:echarts/data/List} data + * @param {string} otherDim Can be `otherDims` + * like 'label' or 'tooltip'. + * @return {Array.} data dimensions on the otherDim. + */ + modelUtil.otherDimToDataDim = function (data, otherDim) { + var dataDim = []; + each(data.dimensions, function (dimName) { + var dimItem = data.getDimensionInfo(dimName); + var otherDims = dimItem.otherDims; + var dimIndex = otherDims[otherDim]; + if (dimIndex != null && dimIndex !== false) { + dataDim[dimIndex] = dimItem.name; + } + }); + return dataDim; + }; + + function has(obj, prop) { + return obj && obj.hasOwnProperty(prop); + } + + module.exports = modelUtil; + + + +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var textContain = __webpack_require__(8); + + var formatUtil = {}; + + /** + * 每三位默认加,格式化 + * @param {string|number} x + * @return {string} + */ + formatUtil.addCommas = function (x) { + if (isNaN(x)) { + return '-'; + } + x = (x + '').split('.'); + return x[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,'$1,') + + (x.length > 1 ? ('.' + x[1]) : ''); + }; + + /** + * @param {string} str + * @param {boolean} [upperCaseFirst=false] + * @return {string} str + */ + formatUtil.toCamelCase = function (str, upperCaseFirst) { + str = (str || '').toLowerCase().replace(/-(.)/g, function(match, group1) { + return group1.toUpperCase(); + }); + + if (upperCaseFirst && str) { + str = str.charAt(0).toUpperCase() + str.slice(1); + } + + return str; + }; + + /** + * Normalize css liked array configuration + * e.g. + * 3 => [3, 3, 3, 3] + * [4, 2] => [4, 2, 4, 2] + * [4, 3, 2] => [4, 3, 2, 3] + * @param {number|Array.} val + */ + formatUtil.normalizeCssArray = function (val) { + var len = val.length; + if (typeof (val) === 'number') { + return [val, val, val, val]; + } + else if (len === 2) { + // vertical | horizontal + return [val[0], val[1], val[0], val[1]]; + } + else if (len === 3) { + // top | horizontal | bottom + return [val[0], val[1], val[2], val[1]]; + } + return val; + }; + + var encodeHTML = formatUtil.encodeHTML = function (source) { + return String(source) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }; + + var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + + var wrapVar = function (varName, seriesIdx) { + return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}'; + }; + + /** + * Template formatter + * @param {string} tpl + * @param {Array.|Object} paramsList + * @param {boolean} [encode=false] + * @return {string} + */ + formatUtil.formatTpl = function (tpl, paramsList, encode) { + if (!zrUtil.isArray(paramsList)) { + paramsList = [paramsList]; + } + var seriesLen = paramsList.length; + if (!seriesLen) { + return ''; + } + + var $vars = paramsList[0].$vars || []; + for (var i = 0; i < $vars.length; i++) { + var alias = TPL_VAR_ALIAS[i]; + var val = wrapVar(alias, 0); + tpl = tpl.replace(wrapVar(alias), encode ? encodeHTML(val) : val); + } + for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) { + for (var k = 0; k < $vars.length; k++) { + var val = paramsList[seriesIdx][$vars[k]]; + tpl = tpl.replace( + wrapVar(TPL_VAR_ALIAS[k], seriesIdx), + encode ? encodeHTML(val) : val + ); + } + } + + return tpl; + }; + + /** + * simple Template formatter + * + * @param {string} tpl + * @param {Object} param + * @param {boolean} [encode=false] + * @return {string} + */ + formatUtil.formatTplSimple = function (tpl, param, encode) { + zrUtil.each(param, function (value, key) { + tpl = tpl.replace( + '{' + key + '}', + encode ? encodeHTML(value) : value + ); + }); + return tpl; + }; + + /** + * @param {string} color + * @param {string} [extraCssText] + * @return {string} + */ + formatUtil.getTooltipMarker = function (color, extraCssText) { + return color + ? '' + : ''; + }; + + /** + * @param {string} str + * @return {string} + * @inner + */ + var s2d = function (str) { + return str < 10 ? ('0' + str) : str; + }; + + /** + * ISO Date format + * @param {string} tpl + * @param {number} value + * @param {boolean} [isUTC=false] Default in local time. + * see `module:echarts/scale/Time` + * and `module:echarts/util/number#parseDate`. + * @inner + */ + formatUtil.formatTime = function (tpl, value, isUTC) { + if (tpl === 'week' + || tpl === 'month' + || tpl === 'quarter' + || tpl === 'half-year' + || tpl === 'year' + ) { + tpl = 'MM-dd\nyyyy'; + } + + var date = numberUtil.parseDate(value); + var utc = isUTC ? 'UTC' : ''; + var y = date['get' + utc + 'FullYear'](); + var M = date['get' + utc + 'Month']() + 1; + var d = date['get' + utc + 'Date'](); + var h = date['get' + utc + 'Hours'](); + var m = date['get' + utc + 'Minutes'](); + var s = date['get' + utc + 'Seconds'](); + + tpl = tpl.replace('MM', s2d(M)) + .toLowerCase() + .replace('yyyy', y) + .replace('yy', y % 100) + .replace('dd', s2d(d)) + .replace('d', d) + .replace('hh', s2d(h)) + .replace('h', h) + .replace('mm', s2d(m)) + .replace('m', m) + .replace('ss', s2d(s)) + .replace('s', s); + + return tpl; + }; + + /** + * Capital first + * @param {string} str + * @return {string} + */ + formatUtil.capitalFirst = function (str) { + return str ? str.charAt(0).toUpperCase() + str.substr(1) : str; + }; + + formatUtil.truncateText = textContain.truncateText; + + module.exports = formatUtil; + + + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 数值处理模块 + * @module echarts/util/number + */ + + + + var zrUtil = __webpack_require__(4); + + var number = {}; + + var RADIAN_EPSILON = 1e-4; + + function _trim(str) { + return str.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + /** + * Linear mapping a value from domain to range + * @memberOf module:echarts/util/number + * @param {(number|Array.)} val + * @param {Array.} domain Domain extent domain[0] can be bigger than domain[1] + * @param {Array.} range Range extent range[0] can be bigger than range[1] + * @param {boolean} clamp + * @return {(number|Array.} + */ + number.linearMap = function (val, domain, range, clamp) { + var subDomain = domain[1] - domain[0]; + var subRange = range[1] - range[0]; + + if (subDomain === 0) { + return subRange === 0 + ? range[0] + : (range[0] + range[1]) / 2; + } + + // Avoid accuracy problem in edge, such as + // 146.39 - 62.83 === 83.55999999999999. + // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError + // It is a little verbose for efficiency considering this method + // is a hotspot. + if (clamp) { + if (subDomain > 0) { + if (val <= domain[0]) { + return range[0]; + } + else if (val >= domain[1]) { + return range[1]; + } + } + else { + if (val >= domain[0]) { + return range[0]; + } + else if (val <= domain[1]) { + return range[1]; + } + } + } + else { + if (val === domain[0]) { + return range[0]; + } + if (val === domain[1]) { + return range[1]; + } + } + + return (val - domain[0]) / subDomain * subRange + range[0]; + }; + + /** + * Convert a percent string to absolute number. + * Returns NaN if percent is not a valid string or number + * @memberOf module:echarts/util/number + * @param {string|number} percent + * @param {number} all + * @return {number} + */ + number.parsePercent = function(percent, all) { + switch (percent) { + case 'center': + case 'middle': + percent = '50%'; + break; + case 'left': + case 'top': + percent = '0%'; + break; + case 'right': + case 'bottom': + percent = '100%'; + break; + } + if (typeof percent === 'string') { + if (_trim(percent).match(/%$/)) { + return parseFloat(percent) / 100 * all; + } + + return parseFloat(percent); + } + + return percent == null ? NaN : +percent; + }; + + /** + * (1) Fix rounding error of float numbers. + * (2) Support return string to avoid scientific notation like '3.5e-7'. + * + * @param {number} x + * @param {number} [precision] + * @param {boolean} [returnStr] + * @return {number|string} + */ + number.round = function (x, precision, returnStr) { + if (precision == null) { + precision = 10; + } + // Avoid range error + precision = Math.min(Math.max(0, precision), 20); + x = (+x).toFixed(precision); + return returnStr ? x : +x; + }; + + number.asc = function (arr) { + arr.sort(function (a, b) { + return a - b; + }); + return arr; + }; + + /** + * Get precision + * @param {number} val + */ + number.getPrecision = function (val) { + val = +val; + if (isNaN(val)) { + return 0; + } + // It is much faster than methods converting number to string as follows + // var tmp = val.toString(); + // return tmp.length - 1 - tmp.indexOf('.'); + // especially when precision is low + var e = 1; + var count = 0; + while (Math.round(val * e) / e !== val) { + e *= 10; + count++; + } + return count; + }; + + /** + * @param {string|number} val + * @return {number} + */ + number.getPrecisionSafe = function (val) { + var str = val.toString(); + + // Consider scientific notation: '3.4e-12' '3.4e+12' + var eIndex = str.indexOf('e'); + if (eIndex > 0) { + var precision = +str.slice(eIndex + 1); + return precision < 0 ? -precision : 0; + } + else { + var dotIndex = str.indexOf('.'); + return dotIndex < 0 ? 0 : str.length - 1 - dotIndex; + } + }; + + /** + * Minimal dicernible data precisioin according to a single pixel. + * + * @param {Array.} dataExtent + * @param {Array.} pixelExtent + * @return {number} precision + */ + number.getPixelPrecision = function (dataExtent, pixelExtent) { + var log = Math.log; + var LN10 = Math.LN10; + var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10); + var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); + // toFixed() digits argument must be between 0 and 20. + var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20); + return !isFinite(precision) ? 20 : precision; + }; + + /** + * Get a data of given precision, assuring the sum of percentages + * in valueList is 1. + * The largest remainer method is used. + * https://en.wikipedia.org/wiki/Largest_remainder_method + * + * @param {Array.} valueList a list of all data + * @param {number} idx index of the data to be processed in valueList + * @param {number} precision integer number showing digits of precision + * @return {number} percent ranging from 0 to 100 + */ + number.getPercentWithPrecision = function (valueList, idx, precision) { + if (!valueList[idx]) { + return 0; + } + + var sum = zrUtil.reduce(valueList, function (acc, val) { + return acc + (isNaN(val) ? 0 : val); + }, 0); + if (sum === 0) { + return 0; + } + + var digits = Math.pow(10, precision); + var votesPerQuota = zrUtil.map(valueList, function (val) { + return (isNaN(val) ? 0 : val) / sum * digits * 100; + }); + var targetSeats = digits * 100; + + var seats = zrUtil.map(votesPerQuota, function (votes) { + // Assign automatic seats. + return Math.floor(votes); + }); + var currentSum = zrUtil.reduce(seats, function (acc, val) { + return acc + val; + }, 0); + + var remainder = zrUtil.map(votesPerQuota, function (votes, idx) { + return votes - seats[idx]; + }); + + // Has remainding votes. + while (currentSum < targetSeats) { + // Find next largest remainder. + var max = Number.NEGATIVE_INFINITY; + var maxId = null; + for (var i = 0, len = remainder.length; i < len; ++i) { + if (remainder[i] > max) { + max = remainder[i]; + maxId = i; + } + } + + // Add a vote to max remainder. + ++seats[maxId]; + remainder[maxId] = 0; + ++currentSum; + } + + return seats[idx] / digits; + }; + + // Number.MAX_SAFE_INTEGER, ie do not support. + number.MAX_SAFE_INTEGER = 9007199254740991; + + /** + * To 0 - 2 * PI, considering negative radian. + * @param {number} radian + * @return {number} + */ + number.remRadian = function (radian) { + var pi2 = Math.PI * 2; + return (radian % pi2 + pi2) % pi2; + }; + + /** + * @param {type} radian + * @return {boolean} + */ + number.isRadianAroundZero = function (val) { + return val > -RADIAN_EPSILON && val < RADIAN_EPSILON; + }; + + var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line + + /** + * @return {number} in minutes + */ + number.getTimezoneOffset = function () { + return (new Date()).getTimezoneOffset(); + }; + + /** + * @param {string|Date|number} value These values can be accepted: + * + An instance of Date, represent a time in its own time zone. + * + Or string in a subset of ISO 8601, only including: + * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06', + * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123', + * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00', + * all of which will be treated as local time if time zone is not specified + * (see ). + * + Or other string format, including (all of which will be treated as loacal time): + * '2012', '2012-3-1', '2012/3/1', '2012/03/01', + * '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123' + * + a timestamp, which represent a time in UTC. + * @return {Date} date + */ + number.parseDate = function (value) { + if (value instanceof Date) { + return value; + } + else if (typeof value === 'string') { + // Different browsers parse date in different way, so we parse it manually. + // Some other issues: + // new Date('1970-01-01') is UTC, + // new Date('1970/01/01') and new Date('1970-1-01') is local. + // See issue #3623 + var match = TIME_REG.exec(value); + + if (!match) { + // return Invalid Date. + return new Date(NaN); + } + + var timezoneOffset = number.getTimezoneOffset(); + var timeOffset = !match[8] + ? 0 + : match[8].toUpperCase() === 'Z' + ? timezoneOffset + : +match[8].slice(0, 3) * 60 + timezoneOffset; + + // match[n] can only be string or undefined. + // But take care of '12' + 1 => '121'. + return new Date( + +match[1], + +(match[2] || 1) - 1, + +match[3] || 1, + +match[4] || 0, + +(match[5] || 0) - timeOffset, + +match[6] || 0, + +match[7] || 0 + ); + } + else if (value == null) { + return new Date(NaN); + } + + return new Date(Math.round(value)); + }; + + /** + * Quantity of a number. e.g. 0.1, 1, 10, 100 + * + * @param {number} val + * @return {number} + */ + number.quantity = function (val) { + return Math.pow(10, quantityExponent(val)); + }; + + function quantityExponent(val) { + return Math.floor(Math.log(val) / Math.LN10); + } + + /** + * find a “nice” number approximately equal to x. Round the number if round = true, + * take ceiling if round = false. The primary observation is that the “nicest” + * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers. + * + * See "Nice Numbers for Graph Labels" of Graphic Gems. + * + * @param {number} val Non-negative value. + * @param {boolean} round + * @return {number} + */ + number.nice = function (val, round) { + var exponent = quantityExponent(val); + var exp10 = Math.pow(10, exponent); + var f = val / exp10; // 1 <= f < 10 + var nf; + if (round) { + if (f < 1.5) { nf = 1; } + else if (f < 2.5) { nf = 2; } + else if (f < 4) { nf = 3; } + else if (f < 7) { nf = 5; } + else { nf = 10; } + } + else { + if (f < 1) { nf = 1; } + else if (f < 2) { nf = 2; } + else if (f < 3) { nf = 3; } + else if (f < 5) { nf = 5; } + else { nf = 10; } + } + val = nf * exp10; + + // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754). + // 20 is the uppper bound of toFixed. + return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val; + }; + + /** + * Order intervals asc, and split them when overlap. + * expect(numberUtil.reformIntervals([ + * {interval: [18, 62], close: [1, 1]}, + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [1, 1]}, + * {interval: [62, 150], close: [1, 1]}, + * {interval: [106, 150], close: [1, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ])).toEqual([ + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [0, 1]}, + * {interval: [18, 62], close: [0, 1]}, + * {interval: [62, 150], close: [0, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ]); + * @param {Array.} list, where `close` mean open or close + * of the interval, and Infinity can be used. + * @return {Array.} The origin list, which has been reformed. + */ + number.reformIntervals = function (list) { + list.sort(function (a, b) { + return littleThan(a, b, 0) ? -1 : 1; + }); + + var curr = -Infinity; + var currClose = 1; + for (var i = 0; i < list.length;) { + var interval = list[i].interval; + var close = list[i].close; + + for (var lg = 0; lg < 2; lg++) { + if (interval[lg] <= curr) { + interval[lg] = curr; + close[lg] = !lg ? 1 - currClose : 1; + } + curr = interval[lg]; + currClose = close[lg]; + } + + if (interval[0] === interval[1] && close[0] * close[1] !== 1) { + list.splice(i, 1); + } + else { + i++; + } + } + + return list; + + function littleThan(a, b, lg) { + return a.interval[lg] < b.interval[lg] + || ( + a.interval[lg] === b.interval[lg] + && ( + (a.close[lg] - b.close[lg] === (!lg ? 1 : -1)) + || (!lg && littleThan(a, b, 1)) + ) + ); + } + }; + + /** + * parseFloat NaNs numeric-cast false positives (null|true|false|"") + * ...but misinterprets leading-number strings, particularly hex literals ("0x...") + * subtraction forces infinities to NaN + * + * @param {*} v + * @return {boolean} + */ + number.isNumeric = function (v) { + return v - parseFloat(v) >= 0; + }; + + module.exports = number; + + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + + + var textWidthCache = {}; + var textWidthCacheCounter = 0; + var TEXT_CACHE_MAX = 5000; + + var util = __webpack_require__(4); + var BoundingRect = __webpack_require__(9); + var retrieve = util.retrieve; + + function getTextWidth(text, textFont) { + var key = text + ':' + textFont; + if (textWidthCache[key]) { + return textWidthCache[key]; + } + + var textLines = (text + '').split('\n'); + var width = 0; + + for (var i = 0, l = textLines.length; i < l; i++) { + // measureText 可以被覆盖以兼容不支持 Canvas 的环境 + width = Math.max(textContain.measureText(textLines[i], textFont).width, width); + } + + if (textWidthCacheCounter > TEXT_CACHE_MAX) { + textWidthCacheCounter = 0; + textWidthCache = {}; + } + textWidthCacheCounter++; + textWidthCache[key] = width; + + return width; + } + + function getTextRect(text, textFont, textAlign, textBaseline) { + var textLineLen = ((text || '') + '').split('\n').length; + + var width = getTextWidth(text, textFont); + // FIXME 高度计算比较粗暴 + var lineHeight = getTextWidth('国', textFont); + var height = textLineLen * lineHeight; + + var rect = new BoundingRect(0, 0, width, height); + // Text has a special line height property + rect.lineHeight = lineHeight; + + switch (textBaseline) { + case 'bottom': + case 'alphabetic': + rect.y -= lineHeight; + break; + case 'middle': + rect.y -= lineHeight / 2; + break; + // case 'hanging': + // case 'top': + } + + // FIXME Right to left language + switch (textAlign) { + case 'end': + case 'right': + rect.x -= rect.width; + break; + case 'center': + rect.x -= rect.width / 2; + break; + // case 'start': + // case 'left': + } + + return rect; + } + + function adjustTextPositionOnRect(textPosition, rect, textRect, distance) { + + var x = rect.x; + var y = rect.y; + + var height = rect.height; + var width = rect.width; + + var textHeight = textRect.height; + + var lineHeight = textRect.lineHeight; + var halfHeight = height / 2 - textHeight / 2 + lineHeight; + + var textAlign = 'left'; + + switch (textPosition) { + case 'left': + x -= distance; + y += halfHeight; + textAlign = 'right'; + break; + case 'right': + x += distance + width; + y += halfHeight; + textAlign = 'left'; + break; + case 'top': + x += width / 2; + y -= distance + textHeight - lineHeight; + textAlign = 'center'; + break; + case 'bottom': + x += width / 2; + y += height + distance + lineHeight; + textAlign = 'center'; + break; + case 'inside': + x += width / 2; + y += halfHeight; + textAlign = 'center'; + break; + case 'insideLeft': + x += distance; + y += halfHeight; + textAlign = 'left'; + break; + case 'insideRight': + x += width - distance; + y += halfHeight; + textAlign = 'right'; + break; + case 'insideTop': + x += width / 2; + y += distance + lineHeight; + textAlign = 'center'; + break; + case 'insideBottom': + x += width / 2; + y += height - textHeight - distance + lineHeight; + textAlign = 'center'; + break; + case 'insideTopLeft': + x += distance; + y += distance + lineHeight; + textAlign = 'left'; + break; + case 'insideTopRight': + x += width - distance; + y += distance + lineHeight; + textAlign = 'right'; + break; + case 'insideBottomLeft': + x += distance; + y += height - textHeight - distance + lineHeight; + break; + case 'insideBottomRight': + x += width - distance; + y += height - textHeight - distance + lineHeight; + textAlign = 'right'; + break; + } + + return { + x: x, + y: y, + textAlign: textAlign, + textBaseline: 'alphabetic' + }; + } + + /** + * Show ellipsis if overflow. + * + * @param {string} text + * @param {string} containerWidth + * @param {string} textFont + * @param {number} [ellipsis='...'] + * @param {Object} [options] + * @param {number} [options.maxIterations=3] + * @param {number} [options.minChar=0] If truncate result are less + * then minChar, ellipsis will not show, which is + * better for user hint in some cases. + * @param {number} [options.placeholder=''] When all truncated, use the placeholder. + * @return {string} + */ + function truncateText(text, containerWidth, textFont, ellipsis, options) { + if (!containerWidth) { + return ''; + } + + options = options || {}; + + ellipsis = retrieve(ellipsis, '...'); + var maxIterations = retrieve(options.maxIterations, 2); + var minChar = retrieve(options.minChar, 0); + // FIXME + // Other languages? + var cnCharWidth = getTextWidth('国', textFont); + // FIXME + // Consider proportional font? + var ascCharWidth = getTextWidth('a', textFont); + var placeholder = retrieve(options.placeholder, ''); + + // Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'. + // Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'. + var contentWidth = containerWidth = Math.max(0, containerWidth - 1); // Reserve some gap. + for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) { + contentWidth -= ascCharWidth; + } + + var ellipsisWidth = getTextWidth(ellipsis); + if (ellipsisWidth > contentWidth) { + ellipsis = ''; + ellipsisWidth = 0; + } + + contentWidth = containerWidth - ellipsisWidth; + + var textLines = (text + '').split('\n'); + + for (var i = 0, len = textLines.length; i < len; i++) { + var textLine = textLines[i]; + var lineWidth = getTextWidth(textLine, textFont); + + if (lineWidth <= containerWidth) { + continue; + } + + for (var j = 0;; j++) { + if (lineWidth <= contentWidth || j >= maxIterations) { + textLine += ellipsis; + break; + } + + var subLength = j === 0 + ? estimateLength(textLine, contentWidth, ascCharWidth, cnCharWidth) + : lineWidth > 0 + ? Math.floor(textLine.length * contentWidth / lineWidth) + : 0; + + textLine = textLine.substr(0, subLength); + lineWidth = getTextWidth(textLine, textFont); + } + + if (textLine === '') { + textLine = placeholder; + } + + textLines[i] = textLine; + } + + return textLines.join('\n'); + } + + function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) { + var width = 0; + var i = 0; + for (var len = text.length; i < len && width < contentWidth; i++) { + var charCode = text.charCodeAt(i); + width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth; + } + return i; + } + + var textContain = { + + getWidth: getTextWidth, + + getBoundingRect: getTextRect, + + adjustTextPositionOnRect: adjustTextPositionOnRect, + + truncateText: truncateText, + + measureText: function (text, textFont) { + var ctx = util.getContext(); + ctx.font = textFont || '12px sans-serif'; + return ctx.measureText(text); + } + }; + + module.exports = textContain; + + +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * @module echarts/core/BoundingRect + */ + + + var vec2 = __webpack_require__(10); + var matrix = __webpack_require__(11); + + var v2ApplyTransform = vec2.applyTransform; + var mathMin = Math.min; + var mathMax = Math.max; + /** + * @alias module:echarts/core/BoundingRect + */ + function BoundingRect(x, y, width, height) { + + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + + /** + * @type {number} + */ + this.x = x; + /** + * @type {number} + */ + this.y = y; + /** + * @type {number} + */ + this.width = width; + /** + * @type {number} + */ + this.height = height; + } + + BoundingRect.prototype = { + + constructor: BoundingRect, + + /** + * @param {module:echarts/core/BoundingRect} other + */ + union: function (other) { + var x = mathMin(other.x, this.x); + var y = mathMin(other.y, this.y); + + this.width = mathMax( + other.x + other.width, + this.x + this.width + ) - x; + this.height = mathMax( + other.y + other.height, + this.y + this.height + ) - y; + this.x = x; + this.y = y; + }, + + /** + * @param {Array.} m + * @methods + */ + applyTransform: (function () { + var lt = []; + var rb = []; + var lb = []; + var rt = []; + return function (m) { + // In case usage like this + // el.getBoundingRect().applyTransform(el.transform) + // And element has no transform + if (!m) { + return; + } + lt[0] = lb[0] = this.x; + lt[1] = rt[1] = this.y; + rb[0] = rt[0] = this.x + this.width; + rb[1] = lb[1] = this.y + this.height; + + v2ApplyTransform(lt, lt, m); + v2ApplyTransform(rb, rb, m); + v2ApplyTransform(lb, lb, m); + v2ApplyTransform(rt, rt, m); + + this.x = mathMin(lt[0], rb[0], lb[0], rt[0]); + this.y = mathMin(lt[1], rb[1], lb[1], rt[1]); + var maxX = mathMax(lt[0], rb[0], lb[0], rt[0]); + var maxY = mathMax(lt[1], rb[1], lb[1], rt[1]); + this.width = maxX - this.x; + this.height = maxY - this.y; + }; + })(), + + /** + * Calculate matrix of transforming from self to target rect + * @param {module:zrender/core/BoundingRect} b + * @return {Array.} + */ + calculateTransform: function (b) { + var a = this; + var sx = b.width / a.width; + var sy = b.height / a.height; + + var m = matrix.create(); + + // 矩阵右乘 + matrix.translate(m, m, [-a.x, -a.y]); + matrix.scale(m, m, [sx, sy]); + matrix.translate(m, m, [b.x, b.y]); + + return m; + }, + + /** + * @param {(module:echarts/core/BoundingRect|Object)} b + * @return {boolean} + */ + intersect: function (b) { + if (!b) { + return false; + } + + if (!(b instanceof BoundingRect)) { + // Normalize negative width/height. + b = BoundingRect.create(b); + } + + var a = this; + var ax0 = a.x; + var ax1 = a.x + a.width; + var ay0 = a.y; + var ay1 = a.y + a.height; + + var bx0 = b.x; + var bx1 = b.x + b.width; + var by0 = b.y; + var by1 = b.y + b.height; + + return ! (ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0); + }, + + contain: function (x, y) { + var rect = this; + return x >= rect.x + && x <= (rect.x + rect.width) + && y >= rect.y + && y <= (rect.y + rect.height); + }, + + /** + * @return {module:echarts/core/BoundingRect} + */ + clone: function () { + return new BoundingRect(this.x, this.y, this.width, this.height); + }, + + /** + * Copy from another rect + */ + copy: function (other) { + this.x = other.x; + this.y = other.y; + this.width = other.width; + this.height = other.height; + }, + + plain: function () { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height + }; + } + }; + + /** + * @param {Object|module:zrender/core/BoundingRect} rect + * @param {number} rect.x + * @param {number} rect.y + * @param {number} rect.width + * @param {number} rect.height + * @return {module:zrender/core/BoundingRect} + */ + BoundingRect.create = function (rect) { + return new BoundingRect(rect.x, rect.y, rect.width, rect.height); + }; + + module.exports = BoundingRect; + + +/***/ }, +/* 10 */ +/***/ function(module, exports) { + + + var ArrayCtor = typeof Float32Array === 'undefined' + ? Array + : Float32Array; + + /** + * @typedef {Float32Array|Array.} Vector2 + */ + /** + * 二维向量类 + * @exports zrender/tool/vector + */ + var vector = { + /** + * 创建一个向量 + * @param {number} [x=0] + * @param {number} [y=0] + * @return {Vector2} + */ + create: function (x, y) { + var out = new ArrayCtor(2); + if (x == null) { + x = 0; + } + if (y == null) { + y = 0; + } + out[0] = x; + out[1] = y; + return out; + }, + + /** + * 复制向量数据 + * @param {Vector2} out + * @param {Vector2} v + * @return {Vector2} + */ + copy: function (out, v) { + out[0] = v[0]; + out[1] = v[1]; + return out; + }, + + /** + * 克隆一个向量 + * @param {Vector2} v + * @return {Vector2} + */ + clone: function (v) { + var out = new ArrayCtor(2); + out[0] = v[0]; + out[1] = v[1]; + return out; + }, + + /** + * 设置向量的两个项 + * @param {Vector2} out + * @param {number} a + * @param {number} b + * @return {Vector2} 结果 + */ + set: function (out, a, b) { + out[0] = a; + out[1] = b; + return out; + }, + + /** + * 向量相加 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + add: function (out, v1, v2) { + out[0] = v1[0] + v2[0]; + out[1] = v1[1] + v2[1]; + return out; + }, + + /** + * 向量缩放后相加 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + * @param {number} a + */ + scaleAndAdd: function (out, v1, v2, a) { + out[0] = v1[0] + v2[0] * a; + out[1] = v1[1] + v2[1] * a; + return out; + }, + + /** + * 向量相减 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + sub: function (out, v1, v2) { + out[0] = v1[0] - v2[0]; + out[1] = v1[1] - v2[1]; + return out; + }, + + /** + * 向量长度 + * @param {Vector2} v + * @return {number} + */ + len: function (v) { + return Math.sqrt(this.lenSquare(v)); + }, + + /** + * 向量长度平方 + * @param {Vector2} v + * @return {number} + */ + lenSquare: function (v) { + return v[0] * v[0] + v[1] * v[1]; + }, + + /** + * 向量乘法 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + mul: function (out, v1, v2) { + out[0] = v1[0] * v2[0]; + out[1] = v1[1] * v2[1]; + return out; + }, + + /** + * 向量除法 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + div: function (out, v1, v2) { + out[0] = v1[0] / v2[0]; + out[1] = v1[1] / v2[1]; + return out; + }, + + /** + * 向量点乘 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ + dot: function (v1, v2) { + return v1[0] * v2[0] + v1[1] * v2[1]; + }, + + /** + * 向量缩放 + * @param {Vector2} out + * @param {Vector2} v + * @param {number} s + */ + scale: function (out, v, s) { + out[0] = v[0] * s; + out[1] = v[1] * s; + return out; + }, + + /** + * 向量归一化 + * @param {Vector2} out + * @param {Vector2} v + */ + normalize: function (out, v) { + var d = vector.len(v); + if (d === 0) { + out[0] = 0; + out[1] = 0; + } + else { + out[0] = v[0] / d; + out[1] = v[1] / d; + } + return out; + }, + + /** + * 计算向量间距离 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ + distance: function (v1, v2) { + return Math.sqrt( + (v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1]) + ); + }, + + /** + * 向量距离平方 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ + distanceSquare: function (v1, v2) { + return (v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1]); + }, + + /** + * 求负向量 + * @param {Vector2} out + * @param {Vector2} v + */ + negate: function (out, v) { + out[0] = -v[0]; + out[1] = -v[1]; + return out; + }, + + /** + * 插值两个点 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + * @param {number} t + */ + lerp: function (out, v1, v2, t) { + out[0] = v1[0] + t * (v2[0] - v1[0]); + out[1] = v1[1] + t * (v2[1] - v1[1]); + return out; + }, + + /** + * 矩阵左乘向量 + * @param {Vector2} out + * @param {Vector2} v + * @param {Vector2} m + */ + applyTransform: function (out, v, m) { + var x = v[0]; + var y = v[1]; + out[0] = m[0] * x + m[2] * y + m[4]; + out[1] = m[1] * x + m[3] * y + m[5]; + return out; + }, + /** + * 求两个向量最小值 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + min: function (out, v1, v2) { + out[0] = Math.min(v1[0], v2[0]); + out[1] = Math.min(v1[1], v2[1]); + return out; + }, + /** + * 求两个向量最大值 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + max: function (out, v1, v2) { + out[0] = Math.max(v1[0], v2[0]); + out[1] = Math.max(v1[1], v2[1]); + return out; + } + }; + + vector.length = vector.len; + vector.lengthSquare = vector.lenSquare; + vector.dist = vector.distance; + vector.distSquare = vector.distanceSquare; + + module.exports = vector; + + + +/***/ }, +/* 11 */ +/***/ function(module, exports) { + + + var ArrayCtor = typeof Float32Array === 'undefined' + ? Array + : Float32Array; + /** + * 3x2矩阵操作类 + * @exports zrender/tool/matrix + */ + var matrix = { + /** + * 创建一个单位矩阵 + * @return {Float32Array|Array.} + */ + create : function() { + var out = new ArrayCtor(6); + matrix.identity(out); + + return out; + }, + /** + * 设置矩阵为单位矩阵 + * @param {Float32Array|Array.} out + */ + identity : function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; + }, + /** + * 复制矩阵 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} m + */ + copy: function(out, m) { + out[0] = m[0]; + out[1] = m[1]; + out[2] = m[2]; + out[3] = m[3]; + out[4] = m[4]; + out[5] = m[5]; + return out; + }, + /** + * 矩阵相乘 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} m1 + * @param {Float32Array|Array.} m2 + */ + mul : function (out, m1, m2) { + // Consider matrix.mul(m, m2, m); + // where out is the same as m2. + // So use temp variable to escape error. + var out0 = m1[0] * m2[0] + m1[2] * m2[1]; + var out1 = m1[1] * m2[0] + m1[3] * m2[1]; + var out2 = m1[0] * m2[2] + m1[2] * m2[3]; + var out3 = m1[1] * m2[2] + m1[3] * m2[3]; + var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4]; + var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5]; + out[0] = out0; + out[1] = out1; + out[2] = out2; + out[3] = out3; + out[4] = out4; + out[5] = out5; + return out; + }, + /** + * 平移变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {Float32Array|Array.} v + */ + translate : function(out, a, v) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4] + v[0]; + out[5] = a[5] + v[1]; + return out; + }, + /** + * 旋转变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {number} rad + */ + rotate : function(out, a, rad) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var st = Math.sin(rad); + var ct = Math.cos(rad); + + out[0] = aa * ct + ab * st; + out[1] = -aa * st + ab * ct; + out[2] = ac * ct + ad * st; + out[3] = -ac * st + ct * ad; + out[4] = ct * atx + st * aty; + out[5] = ct * aty - st * atx; + return out; + }, + /** + * 缩放变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {Float32Array|Array.} v + */ + scale : function(out, a, v) { + var vx = v[0]; + var vy = v[1]; + out[0] = a[0] * vx; + out[1] = a[1] * vy; + out[2] = a[2] * vx; + out[3] = a[3] * vy; + out[4] = a[4] * vx; + out[5] = a[5] * vy; + return out; + }, + /** + * 求逆矩阵 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + */ + invert : function(out, a) { + + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + + var det = aa * ad - ab * ac; + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = ad * det; + out[1] = -ab * det; + out[2] = -ac * det; + out[3] = aa * det; + out[4] = (ac * aty - ad * atx) * det; + out[5] = (ab * atx - aa * aty) * det; + return out; + } + }; + + module.exports = matrix; + + + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/model/Model + */ + + + var zrUtil = __webpack_require__(4); + var clazzUtil = __webpack_require__(13); + var env = __webpack_require__(2); + + /** + * @alias module:echarts/model/Model + * @constructor + * @param {Object} option + * @param {module:echarts/model/Model} [parentModel] + * @param {module:echarts/model/Global} [ecModel] + */ + function Model(option, parentModel, ecModel) { + /** + * @type {module:echarts/model/Model} + * @readOnly + */ + this.parentModel = parentModel; + + /** + * @type {module:echarts/model/Global} + * @readOnly + */ + this.ecModel = ecModel; + + /** + * @type {Object} + * @protected + */ + this.option = option; + + // Simple optimization + // if (this.init) { + // if (arguments.length <= 4) { + // this.init(option, parentModel, ecModel, extraOpt); + // } + // else { + // this.init.apply(this, arguments); + // } + // } + } + + Model.prototype = { + + constructor: Model, + + /** + * Model 的初始化函数 + * @param {Object} option + */ + init: null, + + /** + * 从新的 Option merge + */ + mergeOption: function (option) { + zrUtil.merge(this.option, option, true); + }, + + /** + * @param {string|Array.} path + * @param {boolean} [ignoreParent=false] + * @return {*} + */ + get: function (path, ignoreParent) { + if (path == null) { + return this.option; + } + + return doGet( + this.option, + this.parsePath(path), + !ignoreParent && getParent(this, path) + ); + }, + + /** + * @param {string} key + * @param {boolean} [ignoreParent=false] + * @return {*} + */ + getShallow: function (key, ignoreParent) { + var option = this.option; + + var val = option == null ? option : option[key]; + var parentModel = !ignoreParent && getParent(this, key); + if (val == null && parentModel) { + val = parentModel.getShallow(key); + } + return val; + }, + + /** + * @param {string|Array.} [path] + * @param {module:echarts/model/Model} [parentModel] + * @return {module:echarts/model/Model} + */ + getModel: function (path, parentModel) { + var obj = path == null + ? this.option + : doGet(this.option, path = this.parsePath(path)); + + var thisParentModel; + parentModel = parentModel || ( + (thisParentModel = getParent(this, path)) + && thisParentModel.getModel(path) + ); + + return new Model(obj, parentModel, this.ecModel); + }, + + /** + * If model has option + */ + isEmpty: function () { + return this.option == null; + }, + + restoreData: function () {}, + + // Pending + clone: function () { + var Ctor = this.constructor; + return new Ctor(zrUtil.clone(this.option)); + }, + + setReadOnly: function (properties) { + clazzUtil.setReadOnly(this, properties); + }, + + // If path is null/undefined, return null/undefined. + parsePath: function(path) { + if (typeof path === 'string') { + path = path.split('.'); + } + return path; + }, + + /** + * @param {Function} getParentMethod + * param {Array.|string} path + * return {module:echarts/model/Model} + */ + customizeGetParent: function (getParentMethod) { + clazzUtil.set(this, 'getParent', getParentMethod); + }, + + isAnimationEnabled: function () { + if (!env.node) { + if (this.option.animation != null) { + return !!this.option.animation; + } + else if (this.parentModel) { + return this.parentModel.isAnimationEnabled(); + } + } + } + }; + + function doGet(obj, pathArr, parentModel) { + for (var i = 0; i < pathArr.length; i++) { + // Ignore empty + if (!pathArr[i]) { + continue; + } + // obj could be number/string/... (like 0) + obj = (obj && typeof obj === 'object') ? obj[pathArr[i]] : null; + if (obj == null) { + break; + } + } + if (obj == null && parentModel) { + obj = parentModel.get(pathArr); + } + return obj; + } + + // `path` can be null/undefined + function getParent(model, path) { + var getParentMethod = clazzUtil.get(model, 'getParent'); + return getParentMethod ? getParentMethod.call(model, path) : model.parentModel; + } + + // Enable Model.extend. + clazzUtil.enableClassExtend(Model); + + var mixin = zrUtil.mixin; + mixin(Model, __webpack_require__(14)); + mixin(Model, __webpack_require__(16)); + mixin(Model, __webpack_require__(17)); + mixin(Model, __webpack_require__(68)); + + module.exports = Model; + + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var clazz = {}; + + var TYPE_DELIMITER = '.'; + var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___'; + var MEMBER_PRIFIX = '\0ec_\0'; + + /** + * Hide private class member. + * The same behavior as `host[name] = value;` (can be right-value) + * @public + */ + clazz.set = function (host, name, value) { + return (host[MEMBER_PRIFIX + name] = value); + }; + + /** + * Hide private class member. + * The same behavior as `host[name];` + * @public + */ + clazz.get = function (host, name) { + return host[MEMBER_PRIFIX + name]; + }; + + /** + * For hidden private class member. + * The same behavior as `host.hasOwnProperty(name);` + * @public + */ + clazz.hasOwn = function (host, name) { + return host.hasOwnProperty(MEMBER_PRIFIX + name); + }; + + /** + * Notice, parseClassType('') should returns {main: '', sub: ''} + * @public + */ + var parseClassType = clazz.parseClassType = function (componentType) { + var ret = {main: '', sub: ''}; + if (componentType) { + componentType = componentType.split(TYPE_DELIMITER); + ret.main = componentType[0] || ''; + ret.sub = componentType[1] || ''; + } + return ret; + }; + + /** + * @public + */ + function checkClassType(componentType) { + zrUtil.assert( + /^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), + 'componentType "' + componentType + '" illegal' + ); + } + + /** + * @public + */ + clazz.enableClassExtend = function (RootClass, mandatoryMethods) { + + RootClass.$constructor = RootClass; + RootClass.extend = function (proto) { + + if (true) { + zrUtil.each(mandatoryMethods, function (method) { + if (!proto[method]) { + console.warn( + 'Method `' + method + '` should be implemented' + + (proto.type ? ' in ' + proto.type : '') + '.' + ); + } + }); + } + + var superClass = this; + var ExtendedClass = function () { + if (!proto.$constructor) { + superClass.apply(this, arguments); + } + else { + proto.$constructor.apply(this, arguments); + } + }; + + zrUtil.extend(ExtendedClass.prototype, proto); + + ExtendedClass.extend = this.extend; + ExtendedClass.superCall = superCall; + ExtendedClass.superApply = superApply; + zrUtil.inherits(ExtendedClass, this); + ExtendedClass.superClass = superClass; + + return ExtendedClass; + }; + }; + + // superCall should have class info, which can not be fetch from 'this'. + // Consider this case: + // class A has method f, + // class B inherits class A, overrides method f, f call superApply('f'), + // class C inherits class B, do not overrides method f, + // then when method of class C is called, dead loop occured. + function superCall(context, methodName) { + var args = zrUtil.slice(arguments, 2); + return this.superClass.prototype[methodName].apply(context, args); + } + + function superApply(context, methodName, args) { + return this.superClass.prototype[methodName].apply(context, args); + } + + /** + * @param {Object} entity + * @param {Object} options + * @param {boolean} [options.registerWhenExtend] + * @public + */ + clazz.enableClassManagement = function (entity, options) { + options = options || {}; + + /** + * Component model classes + * key: componentType, + * value: + * componentClass, when componentType is 'xxx' + * or Object., when componentType is 'xxx.yy' + * @type {Object} + */ + var storage = {}; + + entity.registerClass = function (Clazz, componentType) { + if (componentType) { + checkClassType(componentType); + componentType = parseClassType(componentType); + + if (!componentType.sub) { + if (true) { + if (storage[componentType.main]) { + console.warn(componentType.main + ' exists.'); + } + } + storage[componentType.main] = Clazz; + } + else if (componentType.sub !== IS_CONTAINER) { + var container = makeContainer(componentType); + container[componentType.sub] = Clazz; + } + } + return Clazz; + }; + + entity.getClass = function (componentMainType, subType, throwWhenNotFound) { + var Clazz = storage[componentMainType]; + + if (Clazz && Clazz[IS_CONTAINER]) { + Clazz = subType ? Clazz[subType] : null; + } + + if (throwWhenNotFound && !Clazz) { + throw new Error( + !subType + ? componentMainType + '.' + 'type should be specified.' + : 'Component ' + componentMainType + '.' + (subType || '') + ' not exists. Load it first.' + ); + } + + return Clazz; + }; + + entity.getClassesByMainType = function (componentType) { + componentType = parseClassType(componentType); + + var result = []; + var obj = storage[componentType.main]; + + if (obj && obj[IS_CONTAINER]) { + zrUtil.each(obj, function (o, type) { + type !== IS_CONTAINER && result.push(o); + }); + } + else { + result.push(obj); + } + + return result; + }; + + entity.hasClass = function (componentType) { + // Just consider componentType.main. + componentType = parseClassType(componentType); + return !!storage[componentType.main]; + }; + + /** + * @return {Array.} Like ['aa', 'bb'], but can not be ['aa.xx'] + */ + entity.getAllClassMainTypes = function () { + var types = []; + zrUtil.each(storage, function (obj, type) { + types.push(type); + }); + return types; + }; + + /** + * If a main type is container and has sub types + * @param {string} mainType + * @return {boolean} + */ + entity.hasSubTypes = function (componentType) { + componentType = parseClassType(componentType); + var obj = storage[componentType.main]; + return obj && obj[IS_CONTAINER]; + }; + + entity.parseClassType = parseClassType; + + function makeContainer(componentType) { + var container = storage[componentType.main]; + if (!container || !container[IS_CONTAINER]) { + container = storage[componentType.main] = {}; + container[IS_CONTAINER] = true; + } + return container; + } + + if (options.registerWhenExtend) { + var originalExtend = entity.extend; + if (originalExtend) { + entity.extend = function (proto) { + var ExtendedClass = originalExtend.call(this, proto); + return entity.registerClass(ExtendedClass, proto.type); + }; + } + } + + return entity; + }; + + /** + * @param {string|Array.} properties + */ + clazz.setReadOnly = function (obj, properties) { + // FIXME It seems broken in IE8 simulation of IE11 + // if (!zrUtil.isArray(properties)) { + // properties = properties != null ? [properties] : []; + // } + // zrUtil.each(properties, function (prop) { + // var value = obj[prop]; + + // Object.defineProperty + // && Object.defineProperty(obj, prop, { + // value: value, writable: false + // }); + // zrUtil.isArray(obj[prop]) + // && Object.freeze + // && Object.freeze(obj[prop]); + // }); + }; + + module.exports = clazz; + + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + + var getLineStyle = __webpack_require__(15)( + [ + ['lineWidth', 'width'], + ['stroke', 'color'], + ['opacity'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['shadowColor'] + ] + ); + module.exports = { + getLineStyle: function (excludes) { + var style = getLineStyle.call(this, excludes); + var lineDash = this.getLineDash(style.lineWidth); + lineDash && (style.lineDash = lineDash); + return style; + }, + + getLineDash: function (lineWidth) { + if (lineWidth == null) { + lineWidth = 1; + } + var lineType = this.get('type'); + var dotSize = Math.max(lineWidth, 2); + var dashSize = lineWidth * 4; + return (lineType === 'solid' || lineType == null) ? null + : (lineType === 'dashed' ? [dashSize, dashSize] : [dotSize, dotSize]); + } + }; + + +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { + + // TODO Parse shadow style + // TODO Only shallow path support + + var zrUtil = __webpack_require__(4); + + module.exports = function (properties) { + // Normalize + for (var i = 0; i < properties.length; i++) { + if (!properties[i][1]) { + properties[i][1] = properties[i][0]; + } + } + return function (excludes, includes) { + var style = {}; + for (var i = 0; i < properties.length; i++) { + var propName = properties[i][1]; + if ((excludes && zrUtil.indexOf(excludes, propName) >= 0) + || (includes && zrUtil.indexOf(includes, propName) < 0) + ) { + continue; + } + var val = this.getShallow(propName); + if (val != null) { + style[properties[i][0]] = val; + } + } + return style; + }; + }; + + +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { + + + module.exports = { + getAreaStyle: __webpack_require__(15)( + [ + ['fill', 'color'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['opacity'], + ['shadowColor'] + ] + ) + }; + + +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + + + + var textContain = __webpack_require__(8); + var graphicUtil = __webpack_require__(18); + + module.exports = { + /** + * Get color property or get color from option.textStyle.color + * @return {string} + */ + getTextColor: function () { + var ecModel = this.ecModel; + return this.getShallow('color') + || (ecModel && ecModel.get('textStyle.color')); + }, + + /** + * Create font string from fontStyle, fontWeight, fontSize, fontFamily + * @return {string} + */ + getFont: function () { + return graphicUtil.getFont({ + fontStyle: this.getShallow('fontStyle'), + fontWeight: this.getShallow('fontWeight'), + fontSize: this.getShallow('fontSize'), + fontFamily: this.getShallow('fontFamily') + }, this.ecModel); + }, + + getTextRect: function (text) { + return textContain.getBoundingRect( + text, + this.getFont(), + this.getShallow('align'), + this.getShallow('baseline') + ); + }, + + truncateText: function (text, containerWidth, ellipsis, options) { + return textContain.truncateText( + text, containerWidth, this.getFont(), ellipsis, options + ); + } + }; + + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + + var pathTool = __webpack_require__(19); + var Path = __webpack_require__(20); + var colorTool = __webpack_require__(31); + var matrix = __webpack_require__(11); + var vector = __webpack_require__(10); + var Transformable = __webpack_require__(26); + var BoundingRect = __webpack_require__(9); + + var round = Math.round; + var mathMax = Math.max; + var mathMin = Math.min; + + var graphic = {}; + + graphic.Group = __webpack_require__(48); + + graphic.Image = __webpack_require__(49); + + graphic.Text = __webpack_require__(50); + + graphic.Circle = __webpack_require__(51); + + graphic.Sector = __webpack_require__(52); + + graphic.Ring = __webpack_require__(53); + + graphic.Polygon = __webpack_require__(54); + + graphic.Polyline = __webpack_require__(58); + + graphic.Rect = __webpack_require__(59); + + graphic.Line = __webpack_require__(61); + + graphic.BezierCurve = __webpack_require__(62); + + graphic.Arc = __webpack_require__(63); + + graphic.CompoundPath = __webpack_require__(64); + + graphic.LinearGradient = __webpack_require__(65); + + graphic.RadialGradient = __webpack_require__(67); + + graphic.BoundingRect = BoundingRect; + + /** + * Extend shape with parameters + */ + graphic.extendShape = function (opts) { + return Path.extend(opts); + }; + + /** + * Extend path + */ + graphic.extendPath = function (pathData, opts) { + return pathTool.extendFromString(pathData, opts); + }; + + /** + * Create a path element from path data string + * @param {string} pathData + * @param {Object} opts + * @param {module:zrender/core/BoundingRect} rect + * @param {string} [layout=cover] 'center' or 'cover' + */ + graphic.makePath = function (pathData, opts, rect, layout) { + var path = pathTool.createFromString(pathData, opts); + var boundingRect = path.getBoundingRect(); + if (rect) { + var aspect = boundingRect.width / boundingRect.height; + + if (layout === 'center') { + // Set rect to center, keep width / height ratio. + var width = rect.height * aspect; + var height; + if (width <= rect.width) { + height = rect.height; + } + else { + width = rect.width; + height = width / aspect; + } + var cx = rect.x + rect.width / 2; + var cy = rect.y + rect.height / 2; + + rect.x = cx - width / 2; + rect.y = cy - height / 2; + rect.width = width; + rect.height = height; + } + + graphic.resizePath(path, rect); + } + return path; + }; + + graphic.mergePath = pathTool.mergePath, + + /** + * Resize a path to fit the rect + * @param {module:zrender/graphic/Path} path + * @param {Object} rect + */ + graphic.resizePath = function (path, rect) { + if (!path.applyTransform) { + return; + } + + var pathRect = path.getBoundingRect(); + + var m = pathRect.calculateTransform(rect); + + path.applyTransform(m); + }; + + /** + * Sub pixel optimize line for canvas + * + * @param {Object} param + * @param {Object} [param.shape] + * @param {number} [param.shape.x1] + * @param {number} [param.shape.y1] + * @param {number} [param.shape.x2] + * @param {number} [param.shape.y2] + * @param {Object} [param.style] + * @param {number} [param.style.lineWidth] + * @return {Object} Modified param + */ + graphic.subPixelOptimizeLine = function (param) { + var subPixelOptimize = graphic.subPixelOptimize; + var shape = param.shape; + var lineWidth = param.style.lineWidth; + + if (round(shape.x1 * 2) === round(shape.x2 * 2)) { + shape.x1 = shape.x2 = subPixelOptimize(shape.x1, lineWidth, true); + } + if (round(shape.y1 * 2) === round(shape.y2 * 2)) { + shape.y1 = shape.y2 = subPixelOptimize(shape.y1, lineWidth, true); + } + return param; + }; + + /** + * Sub pixel optimize rect for canvas + * + * @param {Object} param + * @param {Object} [param.shape] + * @param {number} [param.shape.x] + * @param {number} [param.shape.y] + * @param {number} [param.shape.width] + * @param {number} [param.shape.height] + * @param {Object} [param.style] + * @param {number} [param.style.lineWidth] + * @return {Object} Modified param + */ + graphic.subPixelOptimizeRect = function (param) { + var subPixelOptimize = graphic.subPixelOptimize; + var shape = param.shape; + var lineWidth = param.style.lineWidth; + var originX = shape.x; + var originY = shape.y; + var originWidth = shape.width; + var originHeight = shape.height; + shape.x = subPixelOptimize(shape.x, lineWidth, true); + shape.y = subPixelOptimize(shape.y, lineWidth, true); + shape.width = Math.max( + subPixelOptimize(originX + originWidth, lineWidth, false) - shape.x, + originWidth === 0 ? 0 : 1 + ); + shape.height = Math.max( + subPixelOptimize(originY + originHeight, lineWidth, false) - shape.y, + originHeight === 0 ? 0 : 1 + ); + return param; + }; + + /** + * Sub pixel optimize for canvas + * + * @param {number} position Coordinate, such as x, y + * @param {number} lineWidth Should be nonnegative integer. + * @param {boolean=} positiveOrNegative Default false (negative). + * @return {number} Optimized position. + */ + graphic.subPixelOptimize = function (position, lineWidth, positiveOrNegative) { + // Assure that (position + lineWidth / 2) is near integer edge, + // otherwise line will be fuzzy in canvas. + var doubledPosition = round(position * 2); + return (doubledPosition + round(lineWidth)) % 2 === 0 + ? doubledPosition / 2 + : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2; + }; + + function hasFillOrStroke(fillOrStroke) { + return fillOrStroke != null && fillOrStroke != 'none'; + } + + function liftColor(color) { + return typeof color === 'string' ? colorTool.lift(color, -0.1) : color; + } + + /** + * @private + */ + function cacheElementStl(el) { + if (el.__hoverStlDirty) { + var stroke = el.style.stroke; + var fill = el.style.fill; + + // Create hoverStyle on mouseover + var hoverStyle = el.__hoverStl; + hoverStyle.fill = hoverStyle.fill + || (hasFillOrStroke(fill) ? liftColor(fill) : null); + hoverStyle.stroke = hoverStyle.stroke + || (hasFillOrStroke(stroke) ? liftColor(stroke) : null); + + var normalStyle = {}; + for (var name in hoverStyle) { + if (hoverStyle.hasOwnProperty(name)) { + normalStyle[name] = el.style[name]; + } + } + + el.__normalStl = normalStyle; + + el.__hoverStlDirty = false; + } + } + + /** + * @private + */ + function doSingleEnterHover(el) { + if (el.__isHover) { + return; + } + + cacheElementStl(el); + + if (el.useHoverLayer) { + el.__zr && el.__zr.addHover(el, el.__hoverStl); + } + else { + el.setStyle(el.__hoverStl); + el.z2 += 1; + } + + el.__isHover = true; + } + + /** + * @inner + */ + function doSingleLeaveHover(el) { + if (!el.__isHover) { + return; + } + + var normalStl = el.__normalStl; + if (el.useHoverLayer) { + el.__zr && el.__zr.removeHover(el); + } + else { + normalStl && el.setStyle(normalStl); + el.z2 -= 1; + } + + el.__isHover = false; + } + + /** + * @inner + */ + function doEnterHover(el) { + el.type === 'group' + ? el.traverse(function (child) { + if (child.type !== 'group') { + doSingleEnterHover(child); + } + }) + : doSingleEnterHover(el); + } + + function doLeaveHover(el) { + el.type === 'group' + ? el.traverse(function (child) { + if (child.type !== 'group') { + doSingleLeaveHover(child); + } + }) + : doSingleLeaveHover(el); + } + + /** + * @inner + */ + function setElementHoverStl(el, hoverStl) { + // If element has sepcified hoverStyle, then use it instead of given hoverStyle + // Often used when item group has a label element and it's hoverStyle is different + el.__hoverStl = el.hoverStyle || hoverStl || {}; + el.__hoverStlDirty = true; + + if (el.__isHover) { + cacheElementStl(el); + } + } + + /** + * @inner + */ + function onElementMouseOver(e) { + if (this.__hoverSilentOnTouch && e.zrByTouch) { + return; + } + + // Only if element is not in emphasis status + !this.__isEmphasis && doEnterHover(this); + } + + /** + * @inner + */ + function onElementMouseOut(e) { + if (this.__hoverSilentOnTouch && e.zrByTouch) { + return; + } + + // Only if element is not in emphasis status + !this.__isEmphasis && doLeaveHover(this); + } + + /** + * @inner + */ + function enterEmphasis() { + this.__isEmphasis = true; + doEnterHover(this); + } + + /** + * @inner + */ + function leaveEmphasis() { + this.__isEmphasis = false; + doLeaveHover(this); + } + + /** + * Set hover style of element. + * This method can be called repeatly without side-effects. + * @param {module:zrender/Element} el + * @param {Object} [hoverStyle] + * @param {Object} [opt] + * @param {boolean} [opt.hoverSilentOnTouch=false] + * In touch device, mouseover event will be trigger on touchstart event + * (see module:zrender/dom/HandlerProxy). By this mechanism, we can + * conviniently use hoverStyle when tap on touch screen without additional + * code for compatibility. + * But if the chart/component has select feature, which usually also use + * hoverStyle, there might be conflict between 'select-highlight' and + * 'hover-highlight' especially when roam is enabled (see geo for example). + * In this case, hoverSilentOnTouch should be used to disable hover-highlight + * on touch device. + */ + graphic.setHoverStyle = function (el, hoverStyle, opt) { + el.__hoverSilentOnTouch = opt && opt.hoverSilentOnTouch; + + el.type === 'group' + ? el.traverse(function (child) { + if (child.type !== 'group') { + setElementHoverStl(child, hoverStyle); + } + }) + : setElementHoverStl(el, hoverStyle); + + // Duplicated function will be auto-ignored, see Eventful.js. + el.on('mouseover', onElementMouseOver) + .on('mouseout', onElementMouseOut); + + // Emphasis, normal can be triggered manually + el.on('emphasis', enterEmphasis) + .on('normal', leaveEmphasis); + }; + + /** + * Set text option in the style + * @param {Object} textStyle + * @param {module:echarts/model/Model} labelModel + * @param {string} color + */ + graphic.setText = function (textStyle, labelModel, color) { + var labelPosition = labelModel.getShallow('position') || 'inside'; + var labelOffset = labelModel.getShallow('offset'); + var labelColor = labelPosition.indexOf('inside') >= 0 ? 'white' : color; + var textStyleModel = labelModel.getModel('textStyle'); + zrUtil.extend(textStyle, { + textDistance: labelModel.getShallow('distance') || 5, + textFont: textStyleModel.getFont(), + textPosition: labelPosition, + textOffset: labelOffset, + textFill: textStyleModel.getTextColor() || labelColor + }); + }; + + graphic.getFont = function (opt, ecModel) { + var gTextStyleModel = ecModel && ecModel.getModel('textStyle'); + return [ + // FIXME in node-canvas fontWeight is before fontStyle + opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', + opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', + (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', + opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif' + ].join(' '); + }; + + function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb) { + if (typeof dataIndex === 'function') { + cb = dataIndex; + dataIndex = null; + } + // Do not check 'animation' property directly here. Consider this case: + // animation model is an `itemModel`, whose does not have `isAnimationEnabled` + // but its parent model (`seriesModel`) does. + var animationEnabled = animatableModel && animatableModel.isAnimationEnabled(); + + if (animationEnabled) { + var postfix = isUpdate ? 'Update' : ''; + var duration = animatableModel.getShallow('animationDuration' + postfix); + var animationEasing = animatableModel.getShallow('animationEasing' + postfix); + var animationDelay = animatableModel.getShallow('animationDelay' + postfix); + if (typeof animationDelay === 'function') { + animationDelay = animationDelay( + dataIndex, + animatableModel.getAnimationDelayParams + ? animatableModel.getAnimationDelayParams(el, dataIndex) + : null + ); + } + if (typeof duration === 'function') { + duration = duration(dataIndex); + } + + duration > 0 + ? el.animateTo(props, duration, animationDelay || 0, animationEasing, cb) + : (el.stopAnimation(), el.attr(props), cb && cb()); + } + else { + el.stopAnimation(); + el.attr(props); + cb && cb(); + } + } + + /** + * Update graphic element properties with or without animation according to the configuration in series + * @param {module:zrender/Element} el + * @param {Object} props + * @param {module:echarts/model/Model} [animatableModel] + * @param {number} [dataIndex] + * @param {Function} [cb] + * @example + * graphic.updateProps(el, { + * position: [100, 100] + * }, seriesModel, dataIndex, function () { console.log('Animation done!'); }); + * // Or + * graphic.updateProps(el, { + * position: [100, 100] + * }, seriesModel, function () { console.log('Animation done!'); }); + */ + graphic.updateProps = function (el, props, animatableModel, dataIndex, cb) { + animateOrSetProps(true, el, props, animatableModel, dataIndex, cb); + }; + + /** + * Init graphic element properties with or without animation according to the configuration in series + * @param {module:zrender/Element} el + * @param {Object} props + * @param {module:echarts/model/Model} [animatableModel] + * @param {number} [dataIndex] + * @param {Function} cb + */ + graphic.initProps = function (el, props, animatableModel, dataIndex, cb) { + animateOrSetProps(false, el, props, animatableModel, dataIndex, cb); + }; + + /** + * Get transform matrix of target (param target), + * in coordinate of its ancestor (param ancestor) + * + * @param {module:zrender/mixin/Transformable} target + * @param {module:zrender/mixin/Transformable} [ancestor] + */ + graphic.getTransform = function (target, ancestor) { + var mat = matrix.identity([]); + + while (target && target !== ancestor) { + matrix.mul(mat, target.getLocalTransform(), mat); + target = target.parent; + } + + return mat; + }; + + /** + * Apply transform to an vertex. + * @param {Array.} target [x, y] + * @param {Array.|TypedArray.|Object} transform Can be: + * + Transform matrix: like [1, 0, 0, 1, 0, 0] + * + {position, rotation, scale}, the same as `zrender/Transformable`. + * @param {boolean=} invert Whether use invert matrix. + * @return {Array.} [x, y] + */ + graphic.applyTransform = function (target, transform, invert) { + if (transform && !zrUtil.isArrayLike(transform)) { + transform = Transformable.getLocalTransform(transform); + } + + if (invert) { + transform = matrix.invert([], transform); + } + return vector.applyTransform([], target, transform); + }; + + /** + * @param {string} direction 'left' 'right' 'top' 'bottom' + * @param {Array.} transform Transform matrix: like [1, 0, 0, 1, 0, 0] + * @param {boolean=} invert Whether use invert matrix. + * @return {string} Transformed direction. 'left' 'right' 'top' 'bottom' + */ + graphic.transformDirection = function (direction, transform, invert) { + + // Pick a base, ensure that transform result will not be (0, 0). + var hBase = (transform[4] === 0 || transform[5] === 0 || transform[0] === 0) + ? 1 : Math.abs(2 * transform[4] / transform[0]); + var vBase = (transform[4] === 0 || transform[5] === 0 || transform[2] === 0) + ? 1 : Math.abs(2 * transform[4] / transform[2]); + + var vertex = [ + direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, + direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0 + ]; + + vertex = graphic.applyTransform(vertex, transform, invert); + + return Math.abs(vertex[0]) > Math.abs(vertex[1]) + ? (vertex[0] > 0 ? 'right' : 'left') + : (vertex[1] > 0 ? 'bottom' : 'top'); + }; + + /** + * Apply group transition animation from g1 to g2. + * If no animatableModel, no animation. + */ + graphic.groupTransition = function (g1, g2, animatableModel, cb) { + if (!g1 || !g2) { + return; + } + + function getElMap(g) { + var elMap = {}; + g.traverse(function (el) { + if (!el.isGroup && el.anid) { + elMap[el.anid] = el; + } + }); + return elMap; + } + function getAnimatableProps(el) { + var obj = { + position: vector.clone(el.position), + rotation: el.rotation + }; + if (el.shape) { + obj.shape = zrUtil.extend({}, el.shape); + } + return obj; + } + var elMap1 = getElMap(g1); + + g2.traverse(function (el) { + if (!el.isGroup && el.anid) { + var oldEl = elMap1[el.anid]; + if (oldEl) { + var newProp = getAnimatableProps(el); + el.attr(getAnimatableProps(oldEl)); + graphic.updateProps(el, newProp, animatableModel, el.dataIndex); + } + // else { + // if (el.previousProps) { + // graphic.updateProps + // } + // } + } + }); + }; + + /** + * @param {Array.>} points Like: [[23, 44], [53, 66], ...] + * @param {Object} rect {x, y, width, height} + * @return {Array.>} A new clipped points. + */ + graphic.clipPointsByRect = function (points, rect) { + return zrUtil.map(points, function (point) { + var x = point[0]; + x = mathMax(x, rect.x); + x = mathMin(x, rect.x + rect.width); + var y = point[1]; + y = mathMax(y, rect.y); + y = mathMin(y, rect.y + rect.height); + return [x, y]; + }); + }; + + /** + * @param {Object} targetRect {x, y, width, height} + * @param {Object} rect {x, y, width, height} + * @return {Object} A new clipped rect. If rect size are negative, return undefined. + */ + graphic.clipRectByRect = function (targetRect, rect) { + var x = mathMax(targetRect.x, rect.x); + var x2 = mathMin(targetRect.x + targetRect.width, rect.x + rect.width); + var y = mathMax(targetRect.y, rect.y); + var y2 = mathMin(targetRect.y + targetRect.height, rect.y + rect.height); + + if (x2 >= x && y2 >= y) { + return { + x: x, + y: y, + width: x2 - x, + height: y2 - y + }; + } + }; + + module.exports = graphic; + + + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + + + var Path = __webpack_require__(20); + var PathProxy = __webpack_require__(36); + var transformPath = __webpack_require__(47); + + // command chars + var cc = [ + 'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z', + 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A' + ]; + + var mathSqrt = Math.sqrt; + var mathSin = Math.sin; + var mathCos = Math.cos; + var PI = Math.PI; + + var vMag = function(v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1]); + }; + var vRatio = function(u, v) { + return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); + }; + var vAngle = function(u, v) { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) + * Math.acos(vRatio(u, v)); + }; + + function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) { + var psi = psiDeg * (PI / 180.0); + var xp = mathCos(psi) * (x1 - x2) / 2.0 + + mathSin(psi) * (y1 - y2) / 2.0; + var yp = -1 * mathSin(psi) * (x1 - x2) / 2.0 + + mathCos(psi) * (y1 - y2) / 2.0; + + var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); + + if (lambda > 1) { + rx *= mathSqrt(lambda); + ry *= mathSqrt(lambda); + } + + var f = (fa === fs ? -1 : 1) + * mathSqrt((((rx * rx) * (ry * ry)) + - ((rx * rx) * (yp * yp)) + - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp) + + (ry * ry) * (xp * xp)) + ) || 0; + + var cxp = f * rx * yp / ry; + var cyp = f * -ry * xp / rx; + + var cx = (x1 + x2) / 2.0 + + mathCos(psi) * cxp + - mathSin(psi) * cyp; + var cy = (y1 + y2) / 2.0 + + mathSin(psi) * cxp + + mathCos(psi) * cyp; + + var theta = vAngle([ 1, 0 ], [ (xp - cxp) / rx, (yp - cyp) / ry ]); + var u = [ (xp - cxp) / rx, (yp - cyp) / ry ]; + var v = [ (-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry ]; + var dTheta = vAngle(u, v); + + if (vRatio(u, v) <= -1) { + dTheta = PI; + } + if (vRatio(u, v) >= 1) { + dTheta = 0; + } + if (fs === 0 && dTheta > 0) { + dTheta = dTheta - 2 * PI; + } + if (fs === 1 && dTheta < 0) { + dTheta = dTheta + 2 * PI; + } + + path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs); + } + + function createPathProxyFromString(data) { + if (!data) { + return []; + } + + // command string + var cs = data.replace(/-/g, ' -') + .replace(/ /g, ' ') + .replace(/ /g, ',') + .replace(/,,/g, ','); + + var n; + // create pipes so that we can split the data + for (n = 0; n < cc.length; n++) { + cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]); + } + + // create array + var arr = cs.split('|'); + // init context point + var cpx = 0; + var cpy = 0; + + var path = new PathProxy(); + var CMD = PathProxy.CMD; + + var prevCmd; + for (n = 1; n < arr.length; n++) { + var str = arr[n]; + var c = str.charAt(0); + var off = 0; + var p = str.slice(1).replace(/e,-/g, 'e-').split(','); + var cmd; + + if (p.length > 0 && p[0] === '') { + p.shift(); + } + + for (var i = 0; i < p.length; i++) { + p[i] = parseFloat(p[i]); + } + while (off < p.length && !isNaN(p[off])) { + if (isNaN(p[0])) { + break; + } + var ctlPtx; + var ctlPty; + + var rx; + var ry; + var psi; + var fa; + var fs; + + var x1 = cpx; + var y1 = cpy; + + // convert l, H, h, V, and v to L + switch (c) { + case 'l': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'L': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'm': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + c = 'l'; + break; + case 'M': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + c = 'L'; + break; + case 'h': + cpx += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'H': + cpx = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'v': + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'V': + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'C': + cmd = CMD.C; + path.addData( + cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++] + ); + cpx = p[off - 2]; + cpy = p[off - 1]; + break; + case 'c': + cmd = CMD.C; + path.addData( + cmd, + p[off++] + cpx, p[off++] + cpy, + p[off++] + cpx, p[off++] + cpy, + p[off++] + cpx, p[off++] + cpy + ); + cpx += p[off - 2]; + cpy += p[off - 1]; + break; + case 'S': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 's': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = cpx + p[off++]; + y1 = cpy + p[off++]; + cpx += p[off++]; + cpy += p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 'Q': + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'q': + x1 = p[off++] + cpx; + y1 = p[off++] + cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'T': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 't': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 'A': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + + x1 = cpx, y1 = cpy; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.A; + processArc( + x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path + ); + break; + case 'a': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + + x1 = cpx, y1 = cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.A; + processArc( + x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path + ); + break; + } + } + + if (c === 'z' || c === 'Z') { + cmd = CMD.Z; + path.addData(cmd); + } + + prevCmd = cmd; + } + + path.toStatic(); + + return path; + } + + // TODO Optimize double memory cost problem + function createPathOptions(str, opts) { + var pathProxy = createPathProxyFromString(str); + opts = opts || {}; + opts.buildPath = function (path) { + if (path.setData) { + path.setData(pathProxy.data); + // Svg and vml renderer don't have context + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx); + } + } + else { + var ctx = path; + pathProxy.rebuildPath(ctx); + } + }; + + opts.applyTransform = function (m) { + transformPath(pathProxy, m); + + this.dirty(true); + }; + + return opts; + } + + module.exports = { + /** + * Create a Path object from path string data + * http://www.w3.org/TR/SVG/paths.html#PathData + * @param {Object} opts Other options + */ + createFromString: function (str, opts) { + return new Path(createPathOptions(str, opts)); + }, + + /** + * Create a Path class from path string data + * @param {string} str + * @param {Object} opts Other options + */ + extendFromString: function (str, opts) { + return Path.extend(createPathOptions(str, opts)); + }, + + /** + * Merge multiple paths + */ + // TODO Apply transform + // TODO stroke dash + // TODO Optimize double memory cost problem + mergePath: function (pathEls, opts) { + var pathList = []; + var len = pathEls.length; + for (var i = 0; i < len; i++) { + var pathEl = pathEls[i]; + if (!pathEl.path) { + pathEl.createPathProxy(); + } + if (pathEl.__dirtyPath) { + pathEl.buildPath(pathEl.path, pathEl.shape, true); + } + pathList.push(pathEl.path); + } + + var pathBundle = new Path(opts); + // Need path proxy. + pathBundle.createPathProxy(); + pathBundle.buildPath = function (path) { + path.appendPath(pathList); + // Svg and vml renderer don't have context + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx); + } + }; + + return pathBundle; + } + }; + + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Path element + * @module zrender/graphic/Path + */ + + + + var Displayable = __webpack_require__(21); + var zrUtil = __webpack_require__(4); + var PathProxy = __webpack_require__(36); + var pathContain = __webpack_require__(39); + + var Pattern = __webpack_require__(46); + var getCanvasPattern = Pattern.prototype.getCanvasPattern; + + var abs = Math.abs; + + var pathProxyForDraw = new PathProxy(true); + /** + * @alias module:zrender/graphic/Path + * @extends module:zrender/graphic/Displayable + * @constructor + * @param {Object} opts + */ + function Path(opts) { + Displayable.call(this, opts); + + /** + * @type {module:zrender/core/PathProxy} + * @readOnly + */ + this.path = null; + } + + Path.prototype = { + + constructor: Path, + + type: 'path', + + __dirtyPath: true, + + strokeContainThreshold: 5, + + brush: function (ctx, prevEl) { + var style = this.style; + var path = this.path || pathProxyForDraw; + var hasStroke = style.hasStroke(); + var hasFill = style.hasFill(); + var fill = style.fill; + var stroke = style.stroke; + var hasFillGradient = hasFill && !!(fill.colorStops); + var hasStrokeGradient = hasStroke && !!(stroke.colorStops); + var hasFillPattern = hasFill && !!(fill.image); + var hasStrokePattern = hasStroke && !!(stroke.image); + + style.bind(ctx, this, prevEl); + this.setTransform(ctx); + + if (this.__dirty) { + var rect; + // Update gradient because bounding rect may changed + if (hasFillGradient) { + rect = rect || this.getBoundingRect(); + this._fillGradient = style.getGradient(ctx, fill, rect); + } + if (hasStrokeGradient) { + rect = rect || this.getBoundingRect(); + this._strokeGradient = style.getGradient(ctx, stroke, rect); + } + } + // Use the gradient or pattern + if (hasFillGradient) { + // PENDING If may have affect the state + ctx.fillStyle = this._fillGradient; + } + else if (hasFillPattern) { + ctx.fillStyle = getCanvasPattern.call(fill, ctx); + } + if (hasStrokeGradient) { + ctx.strokeStyle = this._strokeGradient; + } + else if (hasStrokePattern) { + ctx.strokeStyle = getCanvasPattern.call(stroke, ctx); + } + + var lineDash = style.lineDash; + var lineDashOffset = style.lineDashOffset; + + var ctxLineDash = !!ctx.setLineDash; + + // Update path sx, sy + var scale = this.getGlobalScale(); + path.setScale(scale[0], scale[1]); + + // Proxy context + // Rebuild path in following 2 cases + // 1. Path is dirty + // 2. Path needs javascript implemented lineDash stroking. + // In this case, lineDash information will not be saved in PathProxy + if (this.__dirtyPath + || (lineDash && !ctxLineDash && hasStroke) + ) { + path.beginPath(ctx); + + // Setting line dash before build path + if (lineDash && !ctxLineDash) { + path.setLineDash(lineDash); + path.setLineDashOffset(lineDashOffset); + } + + this.buildPath(path, this.shape, false); + + // Clear path dirty flag + if (this.path) { + this.__dirtyPath = false; + } + } + else { + // Replay path building + ctx.beginPath(); + this.path.rebuildPath(ctx); + } + + hasFill && path.fill(ctx); + + if (lineDash && ctxLineDash) { + ctx.setLineDash(lineDash); + ctx.lineDashOffset = lineDashOffset; + } + + hasStroke && path.stroke(ctx); + + if (lineDash && ctxLineDash) { + // PENDING + // Remove lineDash + ctx.setLineDash([]); + } + + + this.restoreTransform(ctx); + + // Draw rect text + if (style.text != null) { + this.drawRectText(ctx, this.getBoundingRect()); + } + }, + + // When bundling path, some shape may decide if use moveTo to begin a new subpath or closePath + // Like in circle + buildPath: function (ctx, shapeCfg, inBundle) {}, + + createPathProxy: function () { + this.path = new PathProxy(); + }, + + getBoundingRect: function () { + var rect = this._rect; + var style = this.style; + var needsUpdateRect = !rect; + if (needsUpdateRect) { + var path = this.path; + if (!path) { + // Create path on demand. + path = this.path = new PathProxy(); + } + if (this.__dirtyPath) { + path.beginPath(); + this.buildPath(path, this.shape, false); + } + rect = path.getBoundingRect(); + } + this._rect = rect; + + if (style.hasStroke()) { + // Needs update rect with stroke lineWidth when + // 1. Element changes scale or lineWidth + // 2. Shape is changed + var rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone()); + if (this.__dirty || needsUpdateRect) { + rectWithStroke.copy(rect); + // FIXME Must after updateTransform + var w = style.lineWidth; + // PENDING, Min line width is needed when line is horizontal or vertical + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + + // Only add extra hover lineWidth when there are no fill + if (!style.hasFill()) { + w = Math.max(w, this.strokeContainThreshold || 4); + } + // Consider line width + // Line scale can't be 0; + if (lineScale > 1e-10) { + rectWithStroke.width += w / lineScale; + rectWithStroke.height += w / lineScale; + rectWithStroke.x -= w / lineScale / 2; + rectWithStroke.y -= w / lineScale / 2; + } + } + + // Return rect with stroke + return rectWithStroke; + } + + return rect; + }, + + contain: function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + var style = this.style; + x = localPos[0]; + y = localPos[1]; + + if (rect.contain(x, y)) { + var pathData = this.path.data; + if (style.hasStroke()) { + var lineWidth = style.lineWidth; + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + // Line scale can't be 0; + if (lineScale > 1e-10) { + // Only add extra hover lineWidth when there are no fill + if (!style.hasFill()) { + lineWidth = Math.max(lineWidth, this.strokeContainThreshold); + } + if (pathContain.containStroke( + pathData, lineWidth / lineScale, x, y + )) { + return true; + } + } + } + if (style.hasFill()) { + return pathContain.contain(pathData, x, y); + } + } + return false; + }, + + /** + * @param {boolean} dirtyPath + */ + dirty: function (dirtyPath) { + if (dirtyPath == null) { + dirtyPath = true; + } + // Only mark dirty, not mark clean + if (dirtyPath) { + this.__dirtyPath = dirtyPath; + this._rect = null; + } + + this.__dirty = true; + + this.__zr && this.__zr.refresh(); + + // Used as a clipping path + if (this.__clipTarget) { + this.__clipTarget.dirty(); + } + }, + + /** + * Alias for animate('shape') + * @param {boolean} loop + */ + animateShape: function (loop) { + return this.animate('shape', loop); + }, + + // Overwrite attrKV + attrKV: function (key, value) { + // FIXME + if (key === 'shape') { + this.setShape(value); + this.__dirtyPath = true; + this._rect = null; + } + else { + Displayable.prototype.attrKV.call(this, key, value); + } + }, + + /** + * @param {Object|string} key + * @param {*} value + */ + setShape: function (key, value) { + var shape = this.shape; + // Path from string may not have shape + if (shape) { + if (zrUtil.isObject(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + shape[name] = key[name]; + } + } + } + else { + shape[key] = value; + } + this.dirty(true); + } + return this; + }, + + getLineScale: function () { + var m = this.transform; + // Get the line scale. + // Determinant of `m` means how much the area is enlarged by the + // transformation. So its square root can be used as a scale factor + // for width. + return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10 + ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1])) + : 1; + } + }; + + /** + * 扩展一个 Path element, 比如星形,圆等。 + * Extend a path element + * @param {Object} props + * @param {string} props.type Path type + * @param {Function} props.init Initialize + * @param {Function} props.buildPath Overwrite buildPath method + * @param {Object} [props.style] Extended default style config + * @param {Object} [props.shape] Extended default shape config + */ + Path.extend = function (defaults) { + var Sub = function (opts) { + Path.call(this, opts); + + if (defaults.style) { + // Extend default style + this.style.extendFrom(defaults.style, false); + } + + // Extend default shape + var defaultShape = defaults.shape; + if (defaultShape) { + this.shape = this.shape || {}; + var thisShape = this.shape; + for (var name in defaultShape) { + if ( + ! thisShape.hasOwnProperty(name) + && defaultShape.hasOwnProperty(name) + ) { + thisShape[name] = defaultShape[name]; + } + } + } + + defaults.init && defaults.init.call(this, opts); + }; + + zrUtil.inherits(Sub, Path); + + // FIXME 不能 extend position, rotation 等引用对象 + for (var name in defaults) { + // Extending prototype values and methods + if (name !== 'style' && name !== 'shape') { + Sub.prototype[name] = defaults[name]; + } + } + + return Sub; + }; + + zrUtil.inherits(Path, Displayable); + + module.exports = Path; + + +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 可绘制的图形基类 + * Base class of all displayable graphic objects + * @module zrender/graphic/Displayable + */ + + + + var zrUtil = __webpack_require__(4); + + var Style = __webpack_require__(22); + + var Element = __webpack_require__(23); + var RectText = __webpack_require__(35); + // var Stateful = require('./mixin/Stateful'); + + /** + * @alias module:zrender/graphic/Displayable + * @extends module:zrender/Element + * @extends module:zrender/graphic/mixin/RectText + */ + function Displayable(opts) { + + opts = opts || {}; + + Element.call(this, opts); + + // Extend properties + for (var name in opts) { + if ( + opts.hasOwnProperty(name) && + name !== 'style' + ) { + this[name] = opts[name]; + } + } + + /** + * @type {module:zrender/graphic/Style} + */ + this.style = new Style(opts.style); + + this._rect = null; + // Shapes for cascade clipping. + this.__clipPaths = []; + + // FIXME Stateful must be mixined after style is setted + // Stateful.call(this, opts); + } + + Displayable.prototype = { + + constructor: Displayable, + + type: 'displayable', + + /** + * Displayable 是否为脏,Painter 中会根据该标记判断是否需要是否需要重新绘制 + * Dirty flag. From which painter will determine if this displayable object needs brush + * @name module:zrender/graphic/Displayable#__dirty + * @type {boolean} + */ + __dirty: true, + + /** + * 图形是否可见,为true时不绘制图形,但是仍能触发鼠标事件 + * If ignore drawing of the displayable object. Mouse event will still be triggered + * @name module:/zrender/graphic/Displayable#invisible + * @type {boolean} + * @default false + */ + invisible: false, + + /** + * @name module:/zrender/graphic/Displayable#z + * @type {number} + * @default 0 + */ + z: 0, + + /** + * @name module:/zrender/graphic/Displayable#z + * @type {number} + * @default 0 + */ + z2: 0, + + /** + * z层level,决定绘画在哪层canvas中 + * @name module:/zrender/graphic/Displayable#zlevel + * @type {number} + * @default 0 + */ + zlevel: 0, + + /** + * 是否可拖拽 + * @name module:/zrender/graphic/Displayable#draggable + * @type {boolean} + * @default false + */ + draggable: false, + + /** + * 是否正在拖拽 + * @name module:/zrender/graphic/Displayable#draggable + * @type {boolean} + * @default false + */ + dragging: false, + + /** + * 是否相应鼠标事件 + * @name module:/zrender/graphic/Displayable#silent + * @type {boolean} + * @default false + */ + silent: false, + + /** + * If enable culling + * @type {boolean} + * @default false + */ + culling: false, + + /** + * Mouse cursor when hovered + * @name module:/zrender/graphic/Displayable#cursor + * @type {string} + */ + cursor: 'pointer', + + /** + * If hover area is bounding rect + * @name module:/zrender/graphic/Displayable#rectHover + * @type {string} + */ + rectHover: false, + + /** + * Render the element progressively when the value >= 0, + * usefull for large data. + * @type {number} + */ + progressive: -1, + + beforeBrush: function (ctx) {}, + + afterBrush: function (ctx) {}, + + /** + * 图形绘制方法 + * @param {Canvas2DRenderingContext} ctx + */ + // Interface + brush: function (ctx, prevEl) {}, + + /** + * 获取最小包围盒 + * @return {module:zrender/core/BoundingRect} + */ + // Interface + getBoundingRect: function () {}, + + /** + * 判断坐标 x, y 是否在图形上 + * If displayable element contain coord x, y + * @param {number} x + * @param {number} y + * @return {boolean} + */ + contain: function (x, y) { + return this.rectContain(x, y); + }, + + /** + * @param {Function} cb + * @param {} context + */ + traverse: function (cb, context) { + cb.call(context, this); + }, + + /** + * 判断坐标 x, y 是否在图形的包围盒上 + * If bounding rect of element contain coord x, y + * @param {number} x + * @param {number} y + * @return {boolean} + */ + rectContain: function (x, y) { + var coord = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + return rect.contain(coord[0], coord[1]); + }, + + /** + * 标记图形元素为脏,并且在下一帧重绘 + * Mark displayable element dirty and refresh next frame + */ + dirty: function () { + this.__dirty = true; + + this._rect = null; + + this.__zr && this.__zr.refresh(); + }, + + /** + * 图形是否会触发事件 + * If displayable object binded any event + * @return {boolean} + */ + // TODO, 通过 bind 绑定的事件 + // isSilent: function () { + // return !( + // this.hoverable || this.draggable + // || this.onmousemove || this.onmouseover || this.onmouseout + // || this.onmousedown || this.onmouseup || this.onclick + // || this.ondragenter || this.ondragover || this.ondragleave + // || this.ondrop + // ); + // }, + /** + * Alias for animate('style') + * @param {boolean} loop + */ + animateStyle: function (loop) { + return this.animate('style', loop); + }, + + attrKV: function (key, value) { + if (key !== 'style') { + Element.prototype.attrKV.call(this, key, value); + } + else { + this.style.set(value); + } + }, + + /** + * @param {Object|string} key + * @param {*} value + */ + setStyle: function (key, value) { + this.style.set(key, value); + this.dirty(false); + return this; + }, + + /** + * Use given style object + * @param {Object} obj + */ + useStyle: function (obj) { + this.style = new Style(obj); + this.dirty(false); + return this; + } + }; + + zrUtil.inherits(Displayable, Element); + + zrUtil.mixin(Displayable, RectText); + // zrUtil.mixin(Displayable, Stateful); + + module.exports = Displayable; + + +/***/ }, +/* 22 */ +/***/ function(module, exports) { + + /** + * @module zrender/graphic/Style + */ + + + var STYLE_COMMON_PROPS = [ + ['shadowBlur', 0], ['shadowOffsetX', 0], ['shadowOffsetY', 0], ['shadowColor', '#000'], + ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10] + ]; + + // var SHADOW_PROPS = STYLE_COMMON_PROPS.slice(0, 4); + // var LINE_PROPS = STYLE_COMMON_PROPS.slice(4); + + var Style = function (opts) { + this.extendFrom(opts); + }; + + function createLinearGradient(ctx, obj, rect) { + var x = obj.x == null ? 0 : obj.x; + var x2 = obj.x2 == null ? 1 : obj.x2; + var y = obj.y == null ? 0 : obj.y; + var y2 = obj.y2 == null ? 0 : obj.y2; + + if (!obj.global) { + x = x * rect.width + rect.x; + x2 = x2 * rect.width + rect.x; + y = y * rect.height + rect.y; + y2 = y2 * rect.height + rect.y; + } + + var canvasGradient = ctx.createLinearGradient(x, y, x2, y2); + + return canvasGradient; + } + + function createRadialGradient(ctx, obj, rect) { + var width = rect.width; + var height = rect.height; + var min = Math.min(width, height); + + var x = obj.x == null ? 0.5 : obj.x; + var y = obj.y == null ? 0.5 : obj.y; + var r = obj.r == null ? 0.5 : obj.r; + if (!obj.global) { + x = x * width + rect.x; + y = y * height + rect.y; + r = r * min; + } + + var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r); + + return canvasGradient; + } + + + Style.prototype = { + + constructor: Style, + + /** + * @type {string} + */ + fill: '#000000', + + /** + * @type {string} + */ + stroke: null, + + /** + * @type {number} + */ + opacity: 1, + + /** + * @type {Array.} + */ + lineDash: null, + + /** + * @type {number} + */ + lineDashOffset: 0, + + /** + * @type {number} + */ + shadowBlur: 0, + + /** + * @type {number} + */ + shadowOffsetX: 0, + + /** + * @type {number} + */ + shadowOffsetY: 0, + + /** + * @type {number} + */ + lineWidth: 1, + + /** + * If stroke ignore scale + * @type {Boolean} + */ + strokeNoScale: false, + + // Bounding rect text configuration + // Not affected by element transform + /** + * @type {string} + */ + text: null, + + /** + * @type {string} + */ + textFill: '#000', + + /** + * @type {string} + */ + textStroke: null, + + /** + * 'inside', 'left', 'right', 'top', 'bottom' + * [x, y] + * @type {string|Array.} + * @default 'inside' + */ + textPosition: 'inside', + + /** + * If not specified, use the boundingRect of a `displayable`. + * @type {Object} + */ + textPositionRect: null, + + /** + * [x, y] + * @type {Array.} + */ + textOffset: null, + + /** + * @type {string} + */ + textBaseline: null, + + /** + * @type {string} + */ + textAlign: null, + + /** + * @type {string} + */ + textVerticalAlign: null, + + /** + * Only useful in Path and Image element + * @type {number} + */ + textDistance: 5, + + /** + * Only useful in Path and Image element + * @type {number} + */ + textShadowBlur: 0, + + /** + * Only useful in Path and Image element + * @type {number} + */ + textShadowOffsetX: 0, + + /** + * Only useful in Path and Image element + * @type {number} + */ + textShadowOffsetY: 0, + + /** + * If transform text + * Only useful in Path and Image element + * @type {boolean} + */ + textTransform: false, + + /** + * Text rotate around position of Path or Image + * Only useful in Path and Image element and textTransform is false. + */ + textRotation: 0, + + /** + * @type {string} + * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation + */ + blend: null, + + /** + * @param {CanvasRenderingContext2D} ctx + */ + bind: function (ctx, el, prevEl) { + var style = this; + var prevStyle = prevEl && prevEl.style; + var firstDraw = !prevStyle; + + for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) { + var prop = STYLE_COMMON_PROPS[i]; + var styleName = prop[0]; + + if (firstDraw || style[styleName] !== prevStyle[styleName]) { + // FIXME Invalid property value will cause style leak from previous element. + ctx[styleName] = style[styleName] || prop[1]; + } + } + + if ((firstDraw || style.fill !== prevStyle.fill)) { + ctx.fillStyle = style.fill; + } + if ((firstDraw || style.stroke !== prevStyle.stroke)) { + ctx.strokeStyle = style.stroke; + } + if ((firstDraw || style.opacity !== prevStyle.opacity)) { + ctx.globalAlpha = style.opacity == null ? 1 : style.opacity; + } + + if ((firstDraw || style.blend !== prevStyle.blend)) { + ctx.globalCompositeOperation = style.blend || 'source-over'; + } + if (this.hasStroke()) { + var lineWidth = style.lineWidth; + ctx.lineWidth = lineWidth / ( + (this.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1 + ); + } + }, + + hasFill: function () { + var fill = this.fill; + return fill != null && fill !== 'none'; + }, + + hasStroke: function () { + var stroke = this.stroke; + return stroke != null && stroke !== 'none' && this.lineWidth > 0; + }, + + /** + * Extend from other style + * @param {zrender/graphic/Style} otherStyle + * @param {boolean} overwrite + */ + extendFrom: function (otherStyle, overwrite) { + if (otherStyle) { + var target = this; + for (var name in otherStyle) { + if (otherStyle.hasOwnProperty(name) + && (overwrite || ! target.hasOwnProperty(name)) + ) { + target[name] = otherStyle[name]; + } + } + } + }, + + /** + * Batch setting style with a given object + * @param {Object|string} obj + * @param {*} [obj] + */ + set: function (obj, value) { + if (typeof obj === 'string') { + this[obj] = value; + } + else { + this.extendFrom(obj, true); + } + }, + + /** + * Clone + * @return {zrender/graphic/Style} [description] + */ + clone: function () { + var newStyle = new this.constructor(); + newStyle.extendFrom(this, true); + return newStyle; + }, + + getGradient: function (ctx, obj, rect) { + var method = obj.type === 'radial' ? createRadialGradient : createLinearGradient; + var canvasGradient = method(ctx, obj, rect); + var colorStops = obj.colorStops; + for (var i = 0; i < colorStops.length; i++) { + canvasGradient.addColorStop( + colorStops[i].offset, colorStops[i].color + ); + } + return canvasGradient; + } + }; + + var styleProto = Style.prototype; + for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) { + var prop = STYLE_COMMON_PROPS[i]; + if (!(prop[0] in styleProto)) { + styleProto[prop[0]] = prop[1]; + } + } + + // Provide for others + Style.getGradient = styleProto.getGradient; + + module.exports = Style; + + +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * @module zrender/Element + */ + + + var guid = __webpack_require__(24); + var Eventful = __webpack_require__(25); + var Transformable = __webpack_require__(26); + var Animatable = __webpack_require__(27); + var zrUtil = __webpack_require__(4); + + /** + * @alias module:zrender/Element + * @constructor + * @extends {module:zrender/mixin/Animatable} + * @extends {module:zrender/mixin/Transformable} + * @extends {module:zrender/mixin/Eventful} + */ + var Element = function (opts) { + + Transformable.call(this, opts); + Eventful.call(this, opts); + Animatable.call(this, opts); + + /** + * 画布元素ID + * @type {string} + */ + this.id = opts.id || guid(); + }; + + Element.prototype = { + + /** + * 元素类型 + * Element type + * @type {string} + */ + type: 'element', + + /** + * 元素名字 + * Element name + * @type {string} + */ + name: '', + + /** + * ZRender 实例对象,会在 element 添加到 zrender 实例中后自动赋值 + * ZRender instance will be assigned when element is associated with zrender + * @name module:/zrender/Element#__zr + * @type {module:zrender/ZRender} + */ + __zr: null, + + /** + * 图形是否忽略,为true时忽略图形的绘制以及事件触发 + * If ignore drawing and events of the element object + * @name module:/zrender/Element#ignore + * @type {boolean} + * @default false + */ + ignore: false, + + /** + * 用于裁剪的路径(shape),所有 Group 内的路径在绘制时都会被这个路径裁剪 + * 该路径会继承被裁减对象的变换 + * @type {module:zrender/graphic/Path} + * @see http://www.w3.org/TR/2dcontext/#clipping-region + * @readOnly + */ + clipPath: null, + + /** + * Drift element + * @param {number} dx dx on the global space + * @param {number} dy dy on the global space + */ + drift: function (dx, dy) { + switch (this.draggable) { + case 'horizontal': + dy = 0; + break; + case 'vertical': + dx = 0; + break; + } + + var m = this.transform; + if (!m) { + m = this.transform = [1, 0, 0, 1, 0, 0]; + } + m[4] += dx; + m[5] += dy; + + this.decomposeTransform(); + this.dirty(false); + }, + + /** + * Hook before update + */ + beforeUpdate: function () {}, + /** + * Hook after update + */ + afterUpdate: function () {}, + /** + * Update each frame + */ + update: function () { + this.updateTransform(); + }, + + /** + * @param {Function} cb + * @param {} context + */ + traverse: function (cb, context) {}, + + /** + * @protected + */ + attrKV: function (key, value) { + if (key === 'position' || key === 'scale' || key === 'origin') { + // Copy the array + if (value) { + var target = this[key]; + if (!target) { + target = this[key] = []; + } + target[0] = value[0]; + target[1] = value[1]; + } + } + else { + this[key] = value; + } + }, + + /** + * Hide the element + */ + hide: function () { + this.ignore = true; + this.__zr && this.__zr.refresh(); + }, + + /** + * Show the element + */ + show: function () { + this.ignore = false; + this.__zr && this.__zr.refresh(); + }, + + /** + * @param {string|Object} key + * @param {*} value + */ + attr: function (key, value) { + if (typeof key === 'string') { + this.attrKV(key, value); + } + else if (zrUtil.isObject(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + this.attrKV(name, key[name]); + } + } + } + + this.dirty(false); + + return this; + }, + + /** + * @param {module:zrender/graphic/Path} clipPath + */ + setClipPath: function (clipPath) { + var zr = this.__zr; + if (zr) { + clipPath.addSelfToZr(zr); + } + + // Remove previous clip path + if (this.clipPath && this.clipPath !== clipPath) { + this.removeClipPath(); + } + + this.clipPath = clipPath; + clipPath.__zr = zr; + clipPath.__clipTarget = this; + + this.dirty(false); + }, + + /** + */ + removeClipPath: function () { + var clipPath = this.clipPath; + if (clipPath) { + if (clipPath.__zr) { + clipPath.removeSelfFromZr(clipPath.__zr); + } + + clipPath.__zr = null; + clipPath.__clipTarget = null; + this.clipPath = null; + + this.dirty(false); + } + }, + + /** + * Add self from zrender instance. + * Not recursively because it will be invoked when element added to storage. + * @param {module:zrender/ZRender} zr + */ + addSelfToZr: function (zr) { + this.__zr = zr; + // 添加动画 + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.addAnimator(animators[i]); + } + } + + if (this.clipPath) { + this.clipPath.addSelfToZr(zr); + } + }, + + /** + * Remove self from zrender instance. + * Not recursively because it will be invoked when element added to storage. + * @param {module:zrender/ZRender} zr + */ + removeSelfFromZr: function (zr) { + this.__zr = null; + // 移除动画 + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.removeAnimator(animators[i]); + } + } + + if (this.clipPath) { + this.clipPath.removeSelfFromZr(zr); + } + } + }; + + zrUtil.mixin(Element, Animatable); + zrUtil.mixin(Element, Transformable); + zrUtil.mixin(Element, Eventful); + + module.exports = Element; + + +/***/ }, +/* 24 */ +/***/ function(module, exports) { + + /** + * zrender: 生成唯一id + * + * @author errorrik (errorrik@gmail.com) + */ + + + var idStart = 0x0907; + + module.exports = function () { + return idStart++; + }; + + + +/***/ }, +/* 25 */ +/***/ function(module, exports) { + + /** + * 事件扩展 + * @module zrender/mixin/Eventful + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + * pissang (https://www.github.com/pissang) + */ + + + var arrySlice = Array.prototype.slice; + + /** + * 事件分发器 + * @alias module:zrender/mixin/Eventful + * @constructor + */ + var Eventful = function () { + this._$handlers = {}; + }; + + Eventful.prototype = { + + constructor: Eventful, + + /** + * 单次触发绑定,trigger后销毁 + * + * @param {string} event 事件名 + * @param {Function} handler 响应函数 + * @param {Object} context + */ + one: function (event, handler, context) { + var _h = this._$handlers; + + if (!handler || !event) { + return this; + } + + if (!_h[event]) { + _h[event] = []; + } + + for (var i = 0; i < _h[event].length; i++) { + if (_h[event][i].h === handler) { + return this; + } + } + + _h[event].push({ + h: handler, + one: true, + ctx: context || this + }); + + return this; + }, + + /** + * 绑定事件 + * @param {string} event 事件名 + * @param {Function} handler 事件处理函数 + * @param {Object} [context] + */ + on: function (event, handler, context) { + var _h = this._$handlers; + + if (!handler || !event) { + return this; + } + + if (!_h[event]) { + _h[event] = []; + } + + for (var i = 0; i < _h[event].length; i++) { + if (_h[event][i].h === handler) { + return this; + } + } + + _h[event].push({ + h: handler, + one: false, + ctx: context || this + }); + + return this; + }, + + /** + * 是否绑定了事件 + * @param {string} event + * @return {boolean} + */ + isSilent: function (event) { + var _h = this._$handlers; + return _h[event] && _h[event].length; + }, + + /** + * 解绑事件 + * @param {string} event 事件名 + * @param {Function} [handler] 事件处理函数 + */ + off: function (event, handler) { + var _h = this._$handlers; + + if (!event) { + this._$handlers = {}; + return this; + } + + if (handler) { + if (_h[event]) { + var newList = []; + for (var i = 0, l = _h[event].length; i < l; i++) { + if (_h[event][i]['h'] != handler) { + newList.push(_h[event][i]); + } + } + _h[event] = newList; + } + + if (_h[event] && _h[event].length === 0) { + delete _h[event]; + } + } + else { + delete _h[event]; + } + + return this; + }, + + /** + * 事件分发 + * + * @param {string} type 事件类型 + */ + trigger: function (type) { + if (this._$handlers[type]) { + var args = arguments; + var argLen = args.length; + + if (argLen > 3) { + args = arrySlice.call(args, 1); + } + + var _h = this._$handlers[type]; + var len = _h.length; + for (var i = 0; i < len;) { + // Optimize advise from backbone + switch (argLen) { + case 1: + _h[i]['h'].call(_h[i]['ctx']); + break; + case 2: + + _h[i]['h'].call(_h[i]['ctx'], args[1]); + break; + case 3: + _h[i]['h'].call(_h[i]['ctx'], args[1], args[2]); + break; + default: + // have more than 2 given arguments + _h[i]['h'].apply(_h[i]['ctx'], args); + break; + } + + if (_h[i]['one']) { + _h.splice(i, 1); + len--; + } + else { + i++; + } + } + } + + return this; + }, + + /** + * 带有context的事件分发, 最后一个参数是事件回调的context + * @param {string} type 事件类型 + */ + triggerWithContext: function (type) { + if (this._$handlers[type]) { + var args = arguments; + var argLen = args.length; + + if (argLen > 4) { + args = arrySlice.call(args, 1, args.length - 1); + } + var ctx = args[args.length - 1]; + + var _h = this._$handlers[type]; + var len = _h.length; + for (var i = 0; i < len;) { + // Optimize advise from backbone + switch (argLen) { + case 1: + _h[i]['h'].call(ctx); + break; + case 2: + _h[i]['h'].call(ctx, args[1]); + break; + case 3: + _h[i]['h'].call(ctx, args[1], args[2]); + break; + default: + // have more than 2 given arguments + _h[i]['h'].apply(ctx, args); + break; + } + + if (_h[i]['one']) { + _h.splice(i, 1); + len--; + } + else { + i++; + } + } + } + + return this; + } + }; + + // 对象可以通过 onxxxx 绑定事件 + /** + * @event module:zrender/mixin/Eventful#onclick + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#onmouseover + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#onmouseout + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#onmousemove + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#onmousewheel + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#onmousedown + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#onmouseup + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#ondrag + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#ondragstart + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#ondragend + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#ondragenter + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#ondragleave + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#ondragover + * @type {Function} + * @default null + */ + /** + * @event module:zrender/mixin/Eventful#ondrop + * @type {Function} + * @default null + */ + + module.exports = Eventful; + + + +/***/ }, +/* 26 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * 提供变换扩展 + * @module zrender/mixin/Transformable + * @author pissang (https://www.github.com/pissang) + */ + + + var matrix = __webpack_require__(11); + var vector = __webpack_require__(10); + var mIdentity = matrix.identity; + + var EPSILON = 5e-5; + + function isNotAroundZero(val) { + return val > EPSILON || val < -EPSILON; + } + + /** + * @alias module:zrender/mixin/Transformable + * @constructor + */ + var Transformable = function (opts) { + opts = opts || {}; + // If there are no given position, rotation, scale + if (!opts.position) { + /** + * 平移 + * @type {Array.} + * @default [0, 0] + */ + this.position = [0, 0]; + } + if (opts.rotation == null) { + /** + * 旋转 + * @type {Array.} + * @default 0 + */ + this.rotation = 0; + } + if (!opts.scale) { + /** + * 缩放 + * @type {Array.} + * @default [1, 1] + */ + this.scale = [1, 1]; + } + /** + * 旋转和缩放的原点 + * @type {Array.} + * @default null + */ + this.origin = this.origin || null; + }; + + var transformableProto = Transformable.prototype; + transformableProto.transform = null; + + /** + * 判断是否需要有坐标变换 + * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵 + */ + transformableProto.needLocalTransform = function () { + return isNotAroundZero(this.rotation) + || isNotAroundZero(this.position[0]) + || isNotAroundZero(this.position[1]) + || isNotAroundZero(this.scale[0] - 1) + || isNotAroundZero(this.scale[1] - 1); + }; + + transformableProto.updateTransform = function () { + var parent = this.parent; + var parentHasTransform = parent && parent.transform; + var needLocalTransform = this.needLocalTransform(); + + var m = this.transform; + if (!(needLocalTransform || parentHasTransform)) { + m && mIdentity(m); + return; + } + + m = m || matrix.create(); + + if (needLocalTransform) { + this.getLocalTransform(m); + } + else { + mIdentity(m); + } + + // 应用父节点变换 + if (parentHasTransform) { + if (needLocalTransform) { + matrix.mul(m, parent.transform, m); + } + else { + matrix.copy(m, parent.transform); + } + } + // 保存这个变换矩阵 + this.transform = m; + + this.invTransform = this.invTransform || matrix.create(); + matrix.invert(this.invTransform, m); + }; + + transformableProto.getLocalTransform = function (m) { + return Transformable.getLocalTransform(this, m); + }; + + /** + * 将自己的transform应用到context上 + * @param {Context2D} ctx + */ + transformableProto.setTransform = function (ctx) { + var m = this.transform; + var dpr = ctx.dpr || 1; + if (m) { + ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]); + } + else { + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + } + }; + + transformableProto.restoreTransform = function (ctx) { + var dpr = ctx.dpr || 1; + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + }; + + var tmpTransform = []; + + /** + * 分解`transform`矩阵到`position`, `rotation`, `scale` + */ + transformableProto.decomposeTransform = function () { + if (!this.transform) { + return; + } + var parent = this.parent; + var m = this.transform; + if (parent && parent.transform) { + // Get local transform and decompose them to position, scale, rotation + matrix.mul(tmpTransform, parent.invTransform, m); + m = tmpTransform; + } + var sx = m[0] * m[0] + m[1] * m[1]; + var sy = m[2] * m[2] + m[3] * m[3]; + var position = this.position; + var scale = this.scale; + if (isNotAroundZero(sx - 1)) { + sx = Math.sqrt(sx); + } + if (isNotAroundZero(sy - 1)) { + sy = Math.sqrt(sy); + } + if (m[0] < 0) { + sx = -sx; + } + if (m[3] < 0) { + sy = -sy; + } + position[0] = m[4]; + position[1] = m[5]; + scale[0] = sx; + scale[1] = sy; + this.rotation = Math.atan2(-m[1] / sy, m[0] / sx); + }; + + /** + * Get global scale + * @return {Array.} + */ + transformableProto.getGlobalScale = function () { + var m = this.transform; + if (!m) { + return [1, 1]; + } + var sx = Math.sqrt(m[0] * m[0] + m[1] * m[1]); + var sy = Math.sqrt(m[2] * m[2] + m[3] * m[3]); + if (m[0] < 0) { + sx = -sx; + } + if (m[3] < 0) { + sy = -sy; + } + return [sx, sy]; + }; + /** + * 变换坐标位置到 shape 的局部坐标空间 + * @method + * @param {number} x + * @param {number} y + * @return {Array.} + */ + transformableProto.transformCoordToLocal = function (x, y) { + var v2 = [x, y]; + var invTransform = this.invTransform; + if (invTransform) { + vector.applyTransform(v2, v2, invTransform); + } + return v2; + }; + + /** + * 变换局部坐标位置到全局坐标空间 + * @method + * @param {number} x + * @param {number} y + * @return {Array.} + */ + transformableProto.transformCoordToGlobal = function (x, y) { + var v2 = [x, y]; + var transform = this.transform; + if (transform) { + vector.applyTransform(v2, v2, transform); + } + return v2; + }; + + /** + * @static + * @param {Object} target + * @param {Array.} target.origin + * @param {number} target.rotation + * @param {Array.} target.position + * @param {Array.} [m] + */ + Transformable.getLocalTransform = function (target, m) { + m = m || []; + mIdentity(m); + + var origin = target.origin; + var scale = target.scale || [1, 1]; + var rotation = target.rotation || 0; + var position = target.position || [0, 0]; + + if (origin) { + // Translate to origin + m[4] -= origin[0]; + m[5] -= origin[1]; + } + matrix.scale(m, m, scale); + if (rotation) { + matrix.rotate(m, m, rotation); + } + if (origin) { + // Translate back from origin + m[4] += origin[0]; + m[5] += origin[1]; + } + + m[4] += position[0]; + m[5] += position[1]; + + return m; + }; + + module.exports = Transformable; + + + +/***/ }, +/* 27 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * @module zrender/mixin/Animatable + */ + + + var Animator = __webpack_require__(28); + var util = __webpack_require__(4); + var isString = util.isString; + var isFunction = util.isFunction; + var isObject = util.isObject; + var log = __webpack_require__(33); + + /** + * @alias modue:zrender/mixin/Animatable + * @constructor + */ + var Animatable = function () { + + /** + * @type {Array.} + * @readOnly + */ + this.animators = []; + }; + + Animatable.prototype = { + + constructor: Animatable, + + /** + * 动画 + * + * @param {string} path 需要添加动画的属性获取路径,可以通过a.b.c来获取深层的属性 + * @param {boolean} [loop] 动画是否循环 + * @return {module:zrender/animation/Animator} + * @example: + * el.animate('style', false) + * .when(1000, {x: 10} ) + * .done(function(){ // Animation done }) + * .start() + */ + animate: function (path, loop) { + var target; + var animatingShape = false; + var el = this; + var zr = this.__zr; + if (path) { + var pathSplitted = path.split('.'); + var prop = el; + // If animating shape + animatingShape = pathSplitted[0] === 'shape'; + for (var i = 0, l = pathSplitted.length; i < l; i++) { + if (!prop) { + continue; + } + prop = prop[pathSplitted[i]]; + } + if (prop) { + target = prop; + } + } + else { + target = el; + } + + if (!target) { + log( + 'Property "' + + path + + '" is not existed in element ' + + el.id + ); + return; + } + + var animators = el.animators; + + var animator = new Animator(target, loop); + + animator.during(function (target) { + el.dirty(animatingShape); + }) + .done(function () { + // FIXME Animator will not be removed if use `Animator#stop` to stop animation + animators.splice(util.indexOf(animators, animator), 1); + }); + + animators.push(animator); + + // If animate after added to the zrender + if (zr) { + zr.animation.addAnimator(animator); + } + + return animator; + }, + + /** + * 停止动画 + * @param {boolean} forwardToLast If move to last frame before stop + */ + stopAnimation: function (forwardToLast) { + var animators = this.animators; + var len = animators.length; + for (var i = 0; i < len; i++) { + animators[i].stop(forwardToLast); + } + animators.length = 0; + + return this; + }, + + /** + * @param {Object} target + * @param {number} [time=500] Time in ms + * @param {string} [easing='linear'] + * @param {number} [delay=0] + * @param {Function} [callback] + * + * @example + * // Animate position + * el.animateTo({ + * position: [10, 10] + * }, function () { // done }) + * + * // Animate shape, style and position in 100ms, delayed 100ms, with cubicOut easing + * el.animateTo({ + * shape: { + * width: 500 + * }, + * style: { + * fill: 'red' + * } + * position: [10, 10] + * }, 100, 100, 'cubicOut', function () { // done }) + */ + // TODO Return animation key + animateTo: function (target, time, delay, easing, callback) { + // animateTo(target, time, easing, callback); + if (isString(delay)) { + callback = easing; + easing = delay; + delay = 0; + } + // animateTo(target, time, delay, callback); + else if (isFunction(easing)) { + callback = easing; + easing = 'linear'; + delay = 0; + } + // animateTo(target, time, callback); + else if (isFunction(delay)) { + callback = delay; + delay = 0; + } + // animateTo(target, callback) + else if (isFunction(time)) { + callback = time; + time = 500; + } + // animateTo(target) + else if (!time) { + time = 500; + } + // Stop all previous animations + this.stopAnimation(); + this._animateToShallow('', this, target, time, delay, easing, callback); + + // Animators may be removed immediately after start + // if there is nothing to animate + var animators = this.animators.slice(); + var count = animators.length; + function done() { + count--; + if (!count) { + callback && callback(); + } + } + + // No animators. This should be checked before animators[i].start(), + // because 'done' may be executed immediately if no need to animate. + if (!count) { + callback && callback(); + } + // Start after all animators created + // Incase any animator is done immediately when all animation properties are not changed + for (var i = 0; i < animators.length; i++) { + animators[i] + .done(done) + .start(easing); + } + }, + + /** + * @private + * @param {string} path='' + * @param {Object} source=this + * @param {Object} target + * @param {number} [time=500] + * @param {number} [delay=0] + * + * @example + * // Animate position + * el._animateToShallow({ + * position: [10, 10] + * }) + * + * // Animate shape, style and position in 100ms, delayed 100ms + * el._animateToShallow({ + * shape: { + * width: 500 + * }, + * style: { + * fill: 'red' + * } + * position: [10, 10] + * }, 100, 100) + */ + _animateToShallow: function (path, source, target, time, delay) { + var objShallow = {}; + var propertyCount = 0; + for (var name in target) { + if (!target.hasOwnProperty(name)) { + continue; + } + + if (source[name] != null) { + if (isObject(target[name]) && !util.isArrayLike(target[name])) { + this._animateToShallow( + path ? path + '.' + name : name, + source[name], + target[name], + time, + delay + ); + } + else { + objShallow[name] = target[name]; + propertyCount++; + } + } + else if (target[name] != null) { + // Attr directly if not has property + // FIXME, if some property not needed for element ? + if (!path) { + this.attr(name, target[name]); + } + else { // Shape or style + var props = {}; + props[path] = {}; + props[path][name] = target[name]; + this.attr(props); + } + } + } + + if (propertyCount > 0) { + this.animate(path, false) + .when(time == null ? 500 : time, objShallow) + .delay(delay || 0); + } + + return this; + } + }; + + module.exports = Animatable; + + +/***/ }, +/* 28 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/animation/Animator + */ + + + var Clip = __webpack_require__(29); + var color = __webpack_require__(31); + var util = __webpack_require__(4); + var isArrayLike = util.isArrayLike; + + var arraySlice = Array.prototype.slice; + + function defaultGetter(target, key) { + return target[key]; + } + + function defaultSetter(target, key, value) { + target[key] = value; + } + + /** + * @param {number} p0 + * @param {number} p1 + * @param {number} percent + * @return {number} + */ + function interpolateNumber(p0, p1, percent) { + return (p1 - p0) * percent + p0; + } + + /** + * @param {string} p0 + * @param {string} p1 + * @param {number} percent + * @return {string} + */ + function interpolateString(p0, p1, percent) { + return percent > 0.5 ? p1 : p0; + } + + /** + * @param {Array} p0 + * @param {Array} p1 + * @param {number} percent + * @param {Array} out + * @param {number} arrDim + */ + function interpolateArray(p0, p1, percent, out, arrDim) { + var len = p0.length; + if (arrDim == 1) { + for (var i = 0; i < len; i++) { + out[i] = interpolateNumber(p0[i], p1[i], percent); + } + } + else { + var len2 = len && p0[0].length; + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + out[i][j] = interpolateNumber( + p0[i][j], p1[i][j], percent + ); + } + } + } + } + + // arr0 is source array, arr1 is target array. + // Do some preprocess to avoid error happened when interpolating from arr0 to arr1 + function fillArr(arr0, arr1, arrDim) { + var arr0Len = arr0.length; + var arr1Len = arr1.length; + if (arr0Len !== arr1Len) { + // FIXME Not work for TypedArray + var isPreviousLarger = arr0Len > arr1Len; + if (isPreviousLarger) { + // Cut the previous + arr0.length = arr1Len; + } + else { + // Fill the previous + for (var i = arr0Len; i < arr1Len; i++) { + arr0.push( + arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]) + ); + } + } + } + // Handling NaN value + var len2 = arr0[0] && arr0[0].length; + for (var i = 0; i < arr0.length; i++) { + if (arrDim === 1) { + if (isNaN(arr0[i])) { + arr0[i] = arr1[i]; + } + } + else { + for (var j = 0; j < len2; j++) { + if (isNaN(arr0[i][j])) { + arr0[i][j] = arr1[i][j]; + } + } + } + } + } + + /** + * @param {Array} arr0 + * @param {Array} arr1 + * @param {number} arrDim + * @return {boolean} + */ + function isArraySame(arr0, arr1, arrDim) { + if (arr0 === arr1) { + return true; + } + var len = arr0.length; + if (len !== arr1.length) { + return false; + } + if (arrDim === 1) { + for (var i = 0; i < len; i++) { + if (arr0[i] !== arr1[i]) { + return false; + } + } + } + else { + var len2 = arr0[0].length; + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + if (arr0[i][j] !== arr1[i][j]) { + return false; + } + } + } + } + return true; + } + + /** + * Catmull Rom interpolate array + * @param {Array} p0 + * @param {Array} p1 + * @param {Array} p2 + * @param {Array} p3 + * @param {number} t + * @param {number} t2 + * @param {number} t3 + * @param {Array} out + * @param {number} arrDim + */ + function catmullRomInterpolateArray( + p0, p1, p2, p3, t, t2, t3, out, arrDim + ) { + var len = p0.length; + if (arrDim == 1) { + for (var i = 0; i < len; i++) { + out[i] = catmullRomInterpolate( + p0[i], p1[i], p2[i], p3[i], t, t2, t3 + ); + } + } + else { + var len2 = p0[0].length; + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + out[i][j] = catmullRomInterpolate( + p0[i][j], p1[i][j], p2[i][j], p3[i][j], + t, t2, t3 + ); + } + } + } + } + + /** + * Catmull Rom interpolate number + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @param {number} t2 + * @param {number} t3 + * @return {number} + */ + function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + return (2 * (p1 - p2) + v0 + v1) * t3 + + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + + v0 * t + p1; + } + + function cloneValue(value) { + if (isArrayLike(value)) { + var len = value.length; + if (isArrayLike(value[0])) { + var ret = []; + for (var i = 0; i < len; i++) { + ret.push(arraySlice.call(value[i])); + } + return ret; + } + + return arraySlice.call(value); + } + + return value; + } + + function rgba2String(rgba) { + rgba[0] = Math.floor(rgba[0]); + rgba[1] = Math.floor(rgba[1]); + rgba[2] = Math.floor(rgba[2]); + + return 'rgba(' + rgba.join(',') + ')'; + } + + function getArrayDim(keyframes) { + var lastValue = keyframes[keyframes.length - 1].value; + return isArrayLike(lastValue && lastValue[0]) ? 2 : 1; + } + + function createTrackClip (animator, easing, oneTrackDone, keyframes, propName) { + var getter = animator._getter; + var setter = animator._setter; + var useSpline = easing === 'spline'; + + var trackLen = keyframes.length; + if (!trackLen) { + return; + } + // Guess data type + var firstVal = keyframes[0].value; + var isValueArray = isArrayLike(firstVal); + var isValueColor = false; + var isValueString = false; + + // For vertices morphing + var arrDim = isValueArray ? getArrayDim(keyframes) : 0; + + var trackMaxTime; + // Sort keyframe as ascending + keyframes.sort(function(a, b) { + return a.time - b.time; + }); + + trackMaxTime = keyframes[trackLen - 1].time; + // Percents of each keyframe + var kfPercents = []; + // Value of each keyframe + var kfValues = []; + var prevValue = keyframes[0].value; + var isAllValueEqual = true; + for (var i = 0; i < trackLen; i++) { + kfPercents.push(keyframes[i].time / trackMaxTime); + // Assume value is a color when it is a string + var value = keyframes[i].value; + + // Check if value is equal, deep check if value is array + if (!((isValueArray && isArraySame(value, prevValue, arrDim)) + || (!isValueArray && value === prevValue))) { + isAllValueEqual = false; + } + prevValue = value; + + // Try converting a string to a color array + if (typeof value == 'string') { + var colorArray = color.parse(value); + if (colorArray) { + value = colorArray; + isValueColor = true; + } + else { + isValueString = true; + } + } + kfValues.push(value); + } + if (isAllValueEqual) { + return; + } + + var lastValue = kfValues[trackLen - 1]; + // Polyfill array and NaN value + for (var i = 0; i < trackLen - 1; i++) { + if (isValueArray) { + fillArr(kfValues[i], lastValue, arrDim); + } + else { + if (isNaN(kfValues[i]) && !isNaN(lastValue) && !isValueString && !isValueColor) { + kfValues[i] = lastValue; + } + } + } + isValueArray && fillArr(getter(animator._target, propName), lastValue, arrDim); + + // Cache the key of last frame to speed up when + // animation playback is sequency + var lastFrame = 0; + var lastFramePercent = 0; + var start; + var w; + var p0; + var p1; + var p2; + var p3; + + if (isValueColor) { + var rgba = [0, 0, 0, 0]; + } + + var onframe = function (target, percent) { + // Find the range keyframes + // kf1-----kf2---------current--------kf3 + // find kf2 and kf3 and do interpolation + var frame; + // In the easing function like elasticOut, percent may less than 0 + if (percent < 0) { + frame = 0; + } + else if (percent < lastFramePercent) { + // Start from next key + // PENDING start from lastFrame ? + start = Math.min(lastFrame + 1, trackLen - 1); + for (frame = start; frame >= 0; frame--) { + if (kfPercents[frame] <= percent) { + break; + } + } + // PENDING really need to do this ? + frame = Math.min(frame, trackLen - 2); + } + else { + for (frame = lastFrame; frame < trackLen; frame++) { + if (kfPercents[frame] > percent) { + break; + } + } + frame = Math.min(frame - 1, trackLen - 2); + } + lastFrame = frame; + lastFramePercent = percent; + + var range = (kfPercents[frame + 1] - kfPercents[frame]); + if (range === 0) { + return; + } + else { + w = (percent - kfPercents[frame]) / range; + } + if (useSpline) { + p1 = kfValues[frame]; + p0 = kfValues[frame === 0 ? frame : frame - 1]; + p2 = kfValues[frame > trackLen - 2 ? trackLen - 1 : frame + 1]; + p3 = kfValues[frame > trackLen - 3 ? trackLen - 1 : frame + 2]; + if (isValueArray) { + catmullRomInterpolateArray( + p0, p1, p2, p3, w, w * w, w * w * w, + getter(target, propName), + arrDim + ); + } + else { + var value; + if (isValueColor) { + value = catmullRomInterpolateArray( + p0, p1, p2, p3, w, w * w, w * w * w, + rgba, 1 + ); + value = rgba2String(rgba); + } + else if (isValueString) { + // String is step(0.5) + return interpolateString(p1, p2, w); + } + else { + value = catmullRomInterpolate( + p0, p1, p2, p3, w, w * w, w * w * w + ); + } + setter( + target, + propName, + value + ); + } + } + else { + if (isValueArray) { + interpolateArray( + kfValues[frame], kfValues[frame + 1], w, + getter(target, propName), + arrDim + ); + } + else { + var value; + if (isValueColor) { + interpolateArray( + kfValues[frame], kfValues[frame + 1], w, + rgba, 1 + ); + value = rgba2String(rgba); + } + else if (isValueString) { + // String is step(0.5) + return interpolateString(kfValues[frame], kfValues[frame + 1], w); + } + else { + value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w); + } + setter( + target, + propName, + value + ); + } + } + }; + + var clip = new Clip({ + target: animator._target, + life: trackMaxTime, + loop: animator._loop, + delay: animator._delay, + onframe: onframe, + ondestroy: oneTrackDone + }); + + if (easing && easing !== 'spline') { + clip.easing = easing; + } + + return clip; + } + + /** + * @alias module:zrender/animation/Animator + * @constructor + * @param {Object} target + * @param {boolean} loop + * @param {Function} getter + * @param {Function} setter + */ + var Animator = function(target, loop, getter, setter) { + this._tracks = {}; + this._target = target; + + this._loop = loop || false; + + this._getter = getter || defaultGetter; + this._setter = setter || defaultSetter; + + this._clipCount = 0; + + this._delay = 0; + + this._doneList = []; + + this._onframeList = []; + + this._clipList = []; + }; + + Animator.prototype = { + /** + * 设置动画关键帧 + * @param {number} time 关键帧时间,单位是ms + * @param {Object} props 关键帧的属性值,key-value表示 + * @return {module:zrender/animation/Animator} + */ + when: function(time /* ms */, props) { + var tracks = this._tracks; + for (var propName in props) { + if (!props.hasOwnProperty(propName)) { + continue; + } + + if (!tracks[propName]) { + tracks[propName] = []; + // Invalid value + var value = this._getter(this._target, propName); + if (value == null) { + // zrLog('Invalid property ' + propName); + continue; + } + // If time is 0 + // Then props is given initialize value + // Else + // Initialize value from current prop value + if (time !== 0) { + tracks[propName].push({ + time: 0, + value: cloneValue(value) + }); + } + } + tracks[propName].push({ + time: time, + value: props[propName] + }); + } + return this; + }, + /** + * 添加动画每一帧的回调函数 + * @param {Function} callback + * @return {module:zrender/animation/Animator} + */ + during: function (callback) { + this._onframeList.push(callback); + return this; + }, + + pause: function () { + for (var i = 0; i < this._clipList.length; i++) { + this._clipList[i].pause(); + } + this._paused = true; + }, + + resume: function () { + for (var i = 0; i < this._clipList.length; i++) { + this._clipList[i].resume(); + } + this._paused = false; + }, + + isPaused: function () { + return !!this._paused; + }, + + _doneCallback: function () { + // Clear all tracks + this._tracks = {}; + // Clear all clips + this._clipList.length = 0; + + var doneList = this._doneList; + var len = doneList.length; + for (var i = 0; i < len; i++) { + doneList[i].call(this); + } + }, + /** + * 开始执行动画 + * @param {string|Function} easing + * 动画缓动函数,详见{@link module:zrender/animation/easing} + * @return {module:zrender/animation/Animator} + */ + start: function (easing) { + + var self = this; + var clipCount = 0; + + var oneTrackDone = function() { + clipCount--; + if (!clipCount) { + self._doneCallback(); + } + }; + + var lastClip; + for (var propName in this._tracks) { + if (!this._tracks.hasOwnProperty(propName)) { + continue; + } + var clip = createTrackClip( + this, easing, oneTrackDone, + this._tracks[propName], propName + ); + if (clip) { + this._clipList.push(clip); + clipCount++; + + // If start after added to animation + if (this.animation) { + this.animation.addClip(clip); + } + + lastClip = clip; + } + } + + // Add during callback on the last clip + if (lastClip) { + var oldOnFrame = lastClip.onframe; + lastClip.onframe = function (target, percent) { + oldOnFrame(target, percent); + + for (var i = 0; i < self._onframeList.length; i++) { + self._onframeList[i](target, percent); + } + }; + } + + if (!clipCount) { + this._doneCallback(); + } + return this; + }, + /** + * 停止动画 + * @param {boolean} forwardToLast If move to last frame before stop + */ + stop: function (forwardToLast) { + var clipList = this._clipList; + var animation = this.animation; + for (var i = 0; i < clipList.length; i++) { + var clip = clipList[i]; + if (forwardToLast) { + // Move to last frame before stop + clip.onframe(this._target, 1); + } + animation && animation.removeClip(clip); + } + clipList.length = 0; + }, + /** + * 设置动画延迟开始的时间 + * @param {number} time 单位ms + * @return {module:zrender/animation/Animator} + */ + delay: function (time) { + this._delay = time; + return this; + }, + /** + * 添加动画结束的回调 + * @param {Function} cb + * @return {module:zrender/animation/Animator} + */ + done: function(cb) { + if (cb) { + this._doneList.push(cb); + } + return this; + }, + + /** + * @return {Array.} + */ + getClips: function () { + return this._clipList; + } + }; + + module.exports = Animator; + + +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 动画主控制器 + * @config target 动画对象,可以是数组,如果是数组的话会批量分发onframe等事件 + * @config life(1000) 动画时长 + * @config delay(0) 动画延迟时间 + * @config loop(true) + * @config gap(0) 循环的间隔时间 + * @config onframe + * @config easing(optional) + * @config ondestroy(optional) + * @config onrestart(optional) + * + * TODO pause + */ + + + var easingFuncs = __webpack_require__(30); + + function Clip(options) { + + this._target = options.target; + + // 生命周期 + this._life = options.life || 1000; + // 延时 + this._delay = options.delay || 0; + // 开始时间 + // this._startTime = new Date().getTime() + this._delay;// 单位毫秒 + this._initialized = false; + + // 是否循环 + this.loop = options.loop == null ? false : options.loop; + + this.gap = options.gap || 0; + + this.easing = options.easing || 'Linear'; + + this.onframe = options.onframe; + this.ondestroy = options.ondestroy; + this.onrestart = options.onrestart; + + this._pausedTime = 0; + this._paused = false; + } + + Clip.prototype = { + + constructor: Clip, + + step: function (globalTime, deltaTime) { + // Set startTime on first step, or _startTime may has milleseconds different between clips + // PENDING + if (!this._initialized) { + this._startTime = globalTime + this._delay; + this._initialized = true; + } + + if (this._paused) { + this._pausedTime += deltaTime; + return; + } + + var percent = (globalTime - this._startTime - this._pausedTime) / this._life; + + // 还没开始 + if (percent < 0) { + return; + } + + percent = Math.min(percent, 1); + + var easing = this.easing; + var easingFunc = typeof easing == 'string' ? easingFuncs[easing] : easing; + var schedule = typeof easingFunc === 'function' + ? easingFunc(percent) + : percent; + + this.fire('frame', schedule); + + // 结束 + if (percent == 1) { + if (this.loop) { + this.restart (globalTime); + // 重新开始周期 + // 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件 + return 'restart'; + } + + // 动画完成将这个控制器标识为待删除 + // 在Animation.update中进行批量删除 + this._needsRemove = true; + return 'destroy'; + } + + return null; + }, + + restart: function (globalTime) { + var remainder = (globalTime - this._startTime - this._pausedTime) % this._life; + this._startTime = globalTime - remainder + this.gap; + this._pausedTime = 0; + + this._needsRemove = false; + }, + + fire: function (eventType, arg) { + eventType = 'on' + eventType; + if (this[eventType]) { + this[eventType](this._target, arg); + } + }, + + pause: function () { + this._paused = true; + }, + + resume: function () { + this._paused = false; + } + }; + + module.exports = Clip; + + + +/***/ }, +/* 30 */ +/***/ function(module, exports) { + + /** + * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js + * @see http://sole.github.io/tween.js/examples/03_graphs.html + * @exports zrender/animation/easing + */ + + var easing = { + /** + * @param {number} k + * @return {number} + */ + linear: function (k) { + return k; + }, + + /** + * @param {number} k + * @return {number} + */ + quadraticIn: function (k) { + return k * k; + }, + /** + * @param {number} k + * @return {number} + */ + quadraticOut: function (k) { + return k * (2 - k); + }, + /** + * @param {number} k + * @return {number} + */ + quadraticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k; + } + return -0.5 * (--k * (k - 2) - 1); + }, + + // 三次方的缓动(t^3) + /** + * @param {number} k + * @return {number} + */ + cubicIn: function (k) { + return k * k * k; + }, + /** + * @param {number} k + * @return {number} + */ + cubicOut: function (k) { + return --k * k * k + 1; + }, + /** + * @param {number} k + * @return {number} + */ + cubicInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k; + } + return 0.5 * ((k -= 2) * k * k + 2); + }, + + // 四次方的缓动(t^4) + /** + * @param {number} k + * @return {number} + */ + quarticIn: function (k) { + return k * k * k * k; + }, + /** + * @param {number} k + * @return {number} + */ + quarticOut: function (k) { + return 1 - (--k * k * k * k); + }, + /** + * @param {number} k + * @return {number} + */ + quarticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k; + } + return -0.5 * ((k -= 2) * k * k * k - 2); + }, + + // 五次方的缓动(t^5) + /** + * @param {number} k + * @return {number} + */ + quinticIn: function (k) { + return k * k * k * k * k; + }, + /** + * @param {number} k + * @return {number} + */ + quinticOut: function (k) { + return --k * k * k * k * k + 1; + }, + /** + * @param {number} k + * @return {number} + */ + quinticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k * k; + } + return 0.5 * ((k -= 2) * k * k * k * k + 2); + }, + + // 正弦曲线的缓动(sin(t)) + /** + * @param {number} k + * @return {number} + */ + sinusoidalIn: function (k) { + return 1 - Math.cos(k * Math.PI / 2); + }, + /** + * @param {number} k + * @return {number} + */ + sinusoidalOut: function (k) { + return Math.sin(k * Math.PI / 2); + }, + /** + * @param {number} k + * @return {number} + */ + sinusoidalInOut: function (k) { + return 0.5 * (1 - Math.cos(Math.PI * k)); + }, + + // 指数曲线的缓动(2^t) + /** + * @param {number} k + * @return {number} + */ + exponentialIn: function (k) { + return k === 0 ? 0 : Math.pow(1024, k - 1); + }, + /** + * @param {number} k + * @return {number} + */ + exponentialOut: function (k) { + return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); + }, + /** + * @param {number} k + * @return {number} + */ + exponentialInOut: function (k) { + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if ((k *= 2) < 1) { + return 0.5 * Math.pow(1024, k - 1); + } + return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); + }, + + // 圆形曲线的缓动(sqrt(1-t^2)) + /** + * @param {number} k + * @return {number} + */ + circularIn: function (k) { + return 1 - Math.sqrt(1 - k * k); + }, + /** + * @param {number} k + * @return {number} + */ + circularOut: function (k) { + return Math.sqrt(1 - (--k * k)); + }, + /** + * @param {number} k + * @return {number} + */ + circularInOut: function (k) { + if ((k *= 2) < 1) { + return -0.5 * (Math.sqrt(1 - k * k) - 1); + } + return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); + }, + + // 创建类似于弹簧在停止前来回振荡的动画 + /** + * @param {number} k + * @return {number} + */ + elasticIn: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return -(a * Math.pow(2, 10 * (k -= 1)) * + Math.sin((k - s) * (2 * Math.PI) / p)); + }, + /** + * @param {number} k + * @return {number} + */ + elasticOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return (a * Math.pow(2, -10 * k) * + Math.sin((k - s) * (2 * Math.PI) / p) + 1); + }, + /** + * @param {number} k + * @return {number} + */ + elasticInOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + if ((k *= 2) < 1) { + return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p)); + } + return a * Math.pow(2, -10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1; + + }, + + // 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动 + /** + * @param {number} k + * @return {number} + */ + backIn: function (k) { + var s = 1.70158; + return k * k * ((s + 1) * k - s); + }, + /** + * @param {number} k + * @return {number} + */ + backOut: function (k) { + var s = 1.70158; + return --k * k * ((s + 1) * k + s) + 1; + }, + /** + * @param {number} k + * @return {number} + */ + backInOut: function (k) { + var s = 1.70158 * 1.525; + if ((k *= 2) < 1) { + return 0.5 * (k * k * ((s + 1) * k - s)); + } + return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); + }, + + // 创建弹跳效果 + /** + * @param {number} k + * @return {number} + */ + bounceIn: function (k) { + return 1 - easing.bounceOut(1 - k); + }, + /** + * @param {number} k + * @return {number} + */ + bounceOut: function (k) { + if (k < (1 / 2.75)) { + return 7.5625 * k * k; + } + else if (k < (2 / 2.75)) { + return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; + } + else if (k < (2.5 / 2.75)) { + return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; + } + else { + return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; + } + }, + /** + * @param {number} k + * @return {number} + */ + bounceInOut: function (k) { + if (k < 0.5) { + return easing.bounceIn(k * 2) * 0.5; + } + return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5; + } + }; + + module.exports = easing; + + + + +/***/ }, +/* 31 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module zrender/tool/color + */ + + + var LRU = __webpack_require__(32); + + var kCSSColorTable = { + 'transparent': [0,0,0,0], 'aliceblue': [240,248,255,1], + 'antiquewhite': [250,235,215,1], 'aqua': [0,255,255,1], + 'aquamarine': [127,255,212,1], 'azure': [240,255,255,1], + 'beige': [245,245,220,1], 'bisque': [255,228,196,1], + 'black': [0,0,0,1], 'blanchedalmond': [255,235,205,1], + 'blue': [0,0,255,1], 'blueviolet': [138,43,226,1], + 'brown': [165,42,42,1], 'burlywood': [222,184,135,1], + 'cadetblue': [95,158,160,1], 'chartreuse': [127,255,0,1], + 'chocolate': [210,105,30,1], 'coral': [255,127,80,1], + 'cornflowerblue': [100,149,237,1], 'cornsilk': [255,248,220,1], + 'crimson': [220,20,60,1], 'cyan': [0,255,255,1], + 'darkblue': [0,0,139,1], 'darkcyan': [0,139,139,1], + 'darkgoldenrod': [184,134,11,1], 'darkgray': [169,169,169,1], + 'darkgreen': [0,100,0,1], 'darkgrey': [169,169,169,1], + 'darkkhaki': [189,183,107,1], 'darkmagenta': [139,0,139,1], + 'darkolivegreen': [85,107,47,1], 'darkorange': [255,140,0,1], + 'darkorchid': [153,50,204,1], 'darkred': [139,0,0,1], + 'darksalmon': [233,150,122,1], 'darkseagreen': [143,188,143,1], + 'darkslateblue': [72,61,139,1], 'darkslategray': [47,79,79,1], + 'darkslategrey': [47,79,79,1], 'darkturquoise': [0,206,209,1], + 'darkviolet': [148,0,211,1], 'deeppink': [255,20,147,1], + 'deepskyblue': [0,191,255,1], 'dimgray': [105,105,105,1], + 'dimgrey': [105,105,105,1], 'dodgerblue': [30,144,255,1], + 'firebrick': [178,34,34,1], 'floralwhite': [255,250,240,1], + 'forestgreen': [34,139,34,1], 'fuchsia': [255,0,255,1], + 'gainsboro': [220,220,220,1], 'ghostwhite': [248,248,255,1], + 'gold': [255,215,0,1], 'goldenrod': [218,165,32,1], + 'gray': [128,128,128,1], 'green': [0,128,0,1], + 'greenyellow': [173,255,47,1], 'grey': [128,128,128,1], + 'honeydew': [240,255,240,1], 'hotpink': [255,105,180,1], + 'indianred': [205,92,92,1], 'indigo': [75,0,130,1], + 'ivory': [255,255,240,1], 'khaki': [240,230,140,1], + 'lavender': [230,230,250,1], 'lavenderblush': [255,240,245,1], + 'lawngreen': [124,252,0,1], 'lemonchiffon': [255,250,205,1], + 'lightblue': [173,216,230,1], 'lightcoral': [240,128,128,1], + 'lightcyan': [224,255,255,1], 'lightgoldenrodyellow': [250,250,210,1], + 'lightgray': [211,211,211,1], 'lightgreen': [144,238,144,1], + 'lightgrey': [211,211,211,1], 'lightpink': [255,182,193,1], + 'lightsalmon': [255,160,122,1], 'lightseagreen': [32,178,170,1], + 'lightskyblue': [135,206,250,1], 'lightslategray': [119,136,153,1], + 'lightslategrey': [119,136,153,1], 'lightsteelblue': [176,196,222,1], + 'lightyellow': [255,255,224,1], 'lime': [0,255,0,1], + 'limegreen': [50,205,50,1], 'linen': [250,240,230,1], + 'magenta': [255,0,255,1], 'maroon': [128,0,0,1], + 'mediumaquamarine': [102,205,170,1], 'mediumblue': [0,0,205,1], + 'mediumorchid': [186,85,211,1], 'mediumpurple': [147,112,219,1], + 'mediumseagreen': [60,179,113,1], 'mediumslateblue': [123,104,238,1], + 'mediumspringgreen': [0,250,154,1], 'mediumturquoise': [72,209,204,1], + 'mediumvioletred': [199,21,133,1], 'midnightblue': [25,25,112,1], + 'mintcream': [245,255,250,1], 'mistyrose': [255,228,225,1], + 'moccasin': [255,228,181,1], 'navajowhite': [255,222,173,1], + 'navy': [0,0,128,1], 'oldlace': [253,245,230,1], + 'olive': [128,128,0,1], 'olivedrab': [107,142,35,1], + 'orange': [255,165,0,1], 'orangered': [255,69,0,1], + 'orchid': [218,112,214,1], 'palegoldenrod': [238,232,170,1], + 'palegreen': [152,251,152,1], 'paleturquoise': [175,238,238,1], + 'palevioletred': [219,112,147,1], 'papayawhip': [255,239,213,1], + 'peachpuff': [255,218,185,1], 'peru': [205,133,63,1], + 'pink': [255,192,203,1], 'plum': [221,160,221,1], + 'powderblue': [176,224,230,1], 'purple': [128,0,128,1], + 'red': [255,0,0,1], 'rosybrown': [188,143,143,1], + 'royalblue': [65,105,225,1], 'saddlebrown': [139,69,19,1], + 'salmon': [250,128,114,1], 'sandybrown': [244,164,96,1], + 'seagreen': [46,139,87,1], 'seashell': [255,245,238,1], + 'sienna': [160,82,45,1], 'silver': [192,192,192,1], + 'skyblue': [135,206,235,1], 'slateblue': [106,90,205,1], + 'slategray': [112,128,144,1], 'slategrey': [112,128,144,1], + 'snow': [255,250,250,1], 'springgreen': [0,255,127,1], + 'steelblue': [70,130,180,1], 'tan': [210,180,140,1], + 'teal': [0,128,128,1], 'thistle': [216,191,216,1], + 'tomato': [255,99,71,1], 'turquoise': [64,224,208,1], + 'violet': [238,130,238,1], 'wheat': [245,222,179,1], + 'white': [255,255,255,1], 'whitesmoke': [245,245,245,1], + 'yellow': [255,255,0,1], 'yellowgreen': [154,205,50,1] + }; + + function clampCssByte(i) { // Clamp to integer 0 .. 255. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + return i < 0 ? 0 : i > 255 ? 255 : i; + } + + function clampCssAngle(i) { // Clamp to integer 0 .. 360. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + return i < 0 ? 0 : i > 360 ? 360 : i; + } + + function clampCssFloat(f) { // Clamp to float 0.0 .. 1.0. + return f < 0 ? 0 : f > 1 ? 1 : f; + } + + function parseCssInt(str) { // int or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssByte(parseFloat(str) / 100 * 255); + } + return clampCssByte(parseInt(str, 10)); + } + + function parseCssFloat(str) { // float or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssFloat(parseFloat(str) / 100); + } + return clampCssFloat(parseFloat(str)); + } + + function cssHueToRgb(m1, m2, h) { + if (h < 0) { + h += 1; + } + else if (h > 1) { + h -= 1; + } + + if (h * 6 < 1) { + return m1 + (m2 - m1) * h * 6; + } + if (h * 2 < 1) { + return m2; + } + if (h * 3 < 2) { + return m1 + (m2 - m1) * (2/3 - h) * 6; + } + return m1; + } + + function lerp(a, b, p) { + return a + (b - a) * p; + } + + function setRgba(out, r, g, b, a) { + out[0] = r; out[1] = g; out[2] = b; out[3] = a; + return out; + } + function copyRgba(out, a) { + out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; + return out; + } + var colorCache = new LRU(20); + var lastRemovedArr = null; + function putToCache(colorStr, rgbaArr) { + // Reuse removed array + if (lastRemovedArr) { + copyRgba(lastRemovedArr, rgbaArr); + } + lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice())); + } + /** + * @param {string} colorStr + * @param {Array.} out + * @return {Array.} + * @memberOf module:zrender/util/color + */ + function parse(colorStr, rgbaArr) { + if (!colorStr) { + return; + } + rgbaArr = rgbaArr || []; + + var cached = colorCache.get(colorStr); + if (cached) { + return copyRgba(rgbaArr, cached); + } + + // colorStr may be not string + colorStr = colorStr + ''; + // Remove all whitespace, not compliant, but should just be more accepting. + var str = colorStr.replace(/ /g, '').toLowerCase(); + + // Color keywords (and transparent) lookup. + if (str in kCSSColorTable) { + copyRgba(rgbaArr, kCSSColorTable[str]); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + + // #abc and #abc123 syntax. + if (str.charAt(0) === '#') { + if (str.length === 4) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xfff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + setRgba(rgbaArr, + ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), + (iv & 0xf0) | ((iv & 0xf0) >> 4), + (iv & 0xf) | ((iv & 0xf) << 4), + 1 + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + else if (str.length === 7) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xffffff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + setRgba(rgbaArr, + (iv & 0xff0000) >> 16, + (iv & 0xff00) >> 8, + iv & 0xff, + 1 + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + + return; + } + var op = str.indexOf('('), ep = str.indexOf(')'); + if (op !== -1 && ep + 1 === str.length) { + var fname = str.substr(0, op); + var params = str.substr(op + 1, ep - (op + 1)).split(','); + var alpha = 1; // To allow case fallthrough. + switch (fname) { + case 'rgba': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + alpha = parseCssFloat(params.pop()); // jshint ignore:line + // Fall through. + case 'rgb': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, + parseCssInt(params[0]), + parseCssInt(params[1]), + parseCssInt(params[2]), + alpha + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsla': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + params[3] = parseCssFloat(params[3]); + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsl': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + default: + return; + } + } + + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + + /** + * @param {Array.} hsla + * @param {Array.} rgba + * @return {Array.} rgba + */ + function hsla2rgba(hsla, rgba) { + var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360; // 0 .. 1 + // NOTE(deanm): According to the CSS spec s/l should only be + // percentages, but we don't bother and let float or percentage. + var s = parseCssFloat(hsla[1]); + var l = parseCssFloat(hsla[2]); + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + rgba = rgba || []; + setRgba(rgba, + clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), + clampCssByte(cssHueToRgb(m1, m2, h) * 255), + clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), + 1 + ); + + if (hsla.length === 4) { + rgba[3] = hsla[3]; + } + + return rgba; + } + + /** + * @param {Array.} rgba + * @return {Array.} hsla + */ + function rgba2hsla(rgba) { + if (!rgba) { + return; + } + + // RGB from 0 to 255 + var R = rgba[0] / 255; + var G = rgba[1] / 255; + var B = rgba[2] / 255; + + var vMin = Math.min(R, G, B); // Min. value of RGB + var vMax = Math.max(R, G, B); // Max. value of RGB + var delta = vMax - vMin; // Delta RGB value + + var L = (vMax + vMin) / 2; + var H; + var S; + // HSL results from 0 to 1 + if (delta === 0) { + H = 0; + S = 0; + } + else { + if (L < 0.5) { + S = delta / (vMax + vMin); + } + else { + S = delta / (2 - vMax - vMin); + } + + var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta; + var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta; + var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta; + + if (R === vMax) { + H = deltaB - deltaG; + } + else if (G === vMax) { + H = (1 / 3) + deltaR - deltaB; + } + else if (B === vMax) { + H = (2 / 3) + deltaG - deltaR; + } + + if (H < 0) { + H += 1; + } + + if (H > 1) { + H -= 1; + } + } + + var hsla = [H * 360, S, L]; + + if (rgba[3] != null) { + hsla.push(rgba[3]); + } + + return hsla; + } + + /** + * @param {string} color + * @param {number} level + * @return {string} + * @memberOf module:zrender/util/color + */ + function lift(color, level) { + var colorArr = parse(color); + if (colorArr) { + for (var i = 0; i < 3; i++) { + if (level < 0) { + colorArr[i] = colorArr[i] * (1 - level) | 0; + } + else { + colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0; + } + } + return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); + } + } + + /** + * @param {string} color + * @return {string} + * @memberOf module:zrender/util/color + */ + function toHex(color, level) { + var colorArr = parse(color); + if (colorArr) { + return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1); + } + } + + /** + * Map value to color. Faster than mapToColor methods because color is represented by rgba array. + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.>} colors List of rgba color array + * @param {Array.} [out] Mapped gba color array + * @return {Array.} will be null/undefined if input illegal. + */ + function fastMapToColor(normalizedValue, colors, out) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1) + ) { + return; + } + + out = out || []; + + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = colors[leftIndex]; + var rightColor = colors[rightIndex]; + var dv = value - leftIndex; + out[0] = clampCssByte(lerp(leftColor[0], rightColor[0], dv)); + out[1] = clampCssByte(lerp(leftColor[1], rightColor[1], dv)); + out[2] = clampCssByte(lerp(leftColor[2], rightColor[2], dv)); + out[3] = clampCssFloat(lerp(leftColor[3], rightColor[3], dv)); + + return out; + } + /** + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.} colors Color list. + * @param {boolean=} fullOutput Default false. + * @return {(string|Object)} Result color. If fullOutput, + * return {color: ..., leftIndex: ..., rightIndex: ..., value: ...}, + * @memberOf module:zrender/util/color + */ + function mapToColor(normalizedValue, colors, fullOutput) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1) + ) { + return; + } + + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = parse(colors[leftIndex]); + var rightColor = parse(colors[rightIndex]); + var dv = value - leftIndex; + + var color = stringify( + [ + clampCssByte(lerp(leftColor[0], rightColor[0], dv)), + clampCssByte(lerp(leftColor[1], rightColor[1], dv)), + clampCssByte(lerp(leftColor[2], rightColor[2], dv)), + clampCssFloat(lerp(leftColor[3], rightColor[3], dv)) + ], + 'rgba' + ); + + return fullOutput + ? { + color: color, + leftIndex: leftIndex, + rightIndex: rightIndex, + value: value + } + : color; + } + + /** + * @param {string} color + * @param {number=} h 0 ~ 360, ignore when null. + * @param {number=} s 0 ~ 1, ignore when null. + * @param {number=} l 0 ~ 1, ignore when null. + * @return {string} Color string in rgba format. + * @memberOf module:zrender/util/color + */ + function modifyHSL(color, h, s, l) { + color = parse(color); + + if (color) { + color = rgba2hsla(color); + h != null && (color[0] = clampCssAngle(h)); + s != null && (color[1] = parseCssFloat(s)); + l != null && (color[2] = parseCssFloat(l)); + + return stringify(hsla2rgba(color), 'rgba'); + } + } + + /** + * @param {string} color + * @param {number=} alpha 0 ~ 1 + * @return {string} Color string in rgba format. + * @memberOf module:zrender/util/color + */ + function modifyAlpha(color, alpha) { + color = parse(color); + + if (color && alpha != null) { + color[3] = clampCssFloat(alpha); + return stringify(color, 'rgba'); + } + } + + /** + * @param {Array.} arrColor like [12,33,44,0.4] + * @param {string} type 'rgba', 'hsva', ... + * @return {string} Result color. (If input illegal, return undefined). + */ + function stringify(arrColor, type) { + if (!arrColor || !arrColor.length) { + return; + } + var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; + if (type === 'rgba' || type === 'hsva' || type === 'hsla') { + colorStr += ',' + arrColor[3]; + } + return type + '(' + colorStr + ')'; + } + + module.exports = { + parse: parse, + lift: lift, + toHex: toHex, + fastMapToColor: fastMapToColor, + mapToColor: mapToColor, + modifyHSL: modifyHSL, + modifyAlpha: modifyAlpha, + stringify: stringify + }; + + + + +/***/ }, +/* 32 */ +/***/ function(module, exports) { + + // Simple LRU cache use doubly linked list + // @module zrender/core/LRU + + + /** + * Simple double linked list. Compared with array, it has O(1) remove operation. + * @constructor + */ + var LinkedList = function () { + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.head = null; + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.tail = null; + + this._len = 0; + }; + + var linkedListProto = LinkedList.prototype; + /** + * Insert a new value at the tail + * @param {} val + * @return {module:zrender/core/LRU~Entry} + */ + linkedListProto.insert = function (val) { + var entry = new Entry(val); + this.insertEntry(entry); + return entry; + }; + + /** + * Insert an entry at the tail + * @param {module:zrender/core/LRU~Entry} entry + */ + linkedListProto.insertEntry = function (entry) { + if (!this.head) { + this.head = this.tail = entry; + } + else { + this.tail.next = entry; + entry.prev = this.tail; + entry.next = null; + this.tail = entry; + } + this._len++; + }; + + /** + * Remove entry. + * @param {module:zrender/core/LRU~Entry} entry + */ + linkedListProto.remove = function (entry) { + var prev = entry.prev; + var next = entry.next; + if (prev) { + prev.next = next; + } + else { + // Is head + this.head = next; + } + if (next) { + next.prev = prev; + } + else { + // Is tail + this.tail = prev; + } + entry.next = entry.prev = null; + this._len--; + }; + + /** + * @return {number} + */ + linkedListProto.len = function () { + return this._len; + }; + + /** + * Clear list + */ + linkedListProto.clear = function () { + this.head = this.tail = null; + this._len = 0; + }; + + /** + * @constructor + * @param {} val + */ + var Entry = function (val) { + /** + * @type {} + */ + this.value = val; + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.next; + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.prev; + }; + + /** + * LRU Cache + * @constructor + * @alias module:zrender/core/LRU + */ + var LRU = function (maxSize) { + + this._list = new LinkedList(); + + this._map = {}; + + this._maxSize = maxSize || 10; + + this._lastRemovedEntry = null; + }; + + var LRUProto = LRU.prototype; + + /** + * @param {string} key + * @param {} value + * @return {} Removed value + */ + LRUProto.put = function (key, value) { + var list = this._list; + var map = this._map; + var removed = null; + if (map[key] == null) { + var len = list.len(); + // Reuse last removed entry + var entry = this._lastRemovedEntry; + + if (len >= this._maxSize && len > 0) { + // Remove the least recently used + var leastUsedEntry = list.head; + list.remove(leastUsedEntry); + delete map[leastUsedEntry.key]; + + removed = leastUsedEntry.value; + this._lastRemovedEntry = leastUsedEntry; + } + + if (entry) { + entry.value = value; + } + else { + entry = new Entry(value); + } + entry.key = key; + list.insertEntry(entry); + map[key] = entry; + } + + return removed; + }; + + /** + * @param {string} key + * @return {} + */ + LRUProto.get = function (key) { + var entry = this._map[key]; + var list = this._list; + if (entry != null) { + // Put the latest used entry in the tail + if (entry !== list.tail) { + list.remove(entry); + list.insertEntry(entry); + } + + return entry.value; + } + }; + + /** + * Clear the cache + */ + LRUProto.clear = function () { + this._list.clear(); + this._map = {}; + }; + + module.exports = LRU; + + +/***/ }, +/* 33 */ +/***/ function(module, exports, __webpack_require__) { + + + var config = __webpack_require__(34); + + /** + * @exports zrender/tool/log + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + */ + module.exports = function() { + if (config.debugMode === 0) { + return; + } + else if (config.debugMode == 1) { + for (var k in arguments) { + throw new Error(arguments[k]); + } + } + else if (config.debugMode > 1) { + for (var k in arguments) { + console.log(arguments[k]); + } + } + }; + + /* for debug + return function(mes) { + document.getElementById('wrong-message').innerHTML = + mes + ' ' + (new Date() - 0) + + '
' + + document.getElementById('wrong-message').innerHTML; + }; + */ + + + +/***/ }, +/* 34 */ +/***/ function(module, exports) { + + + var dpr = 1; + // If in browser environment + if (typeof window !== 'undefined') { + dpr = Math.max(window.devicePixelRatio || 1, 1); + } + /** + * config默认配置项 + * @exports zrender/config + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + */ + var config = { + /** + * debug日志选项:catchBrushException为true下有效 + * 0 : 不生成debug数据,发布用 + * 1 : 异常抛出,调试用 + * 2 : 控制台输出,调试用 + */ + debugMode: 0, + + // retina 屏幕优化 + devicePixelRatio: dpr + }; + module.exports = config; + + + + +/***/ }, +/* 35 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Mixin for drawing text in a element bounding rect + * @module zrender/mixin/RectText + */ + + + + var textContain = __webpack_require__(8); + var BoundingRect = __webpack_require__(9); + + var tmpRect = new BoundingRect(); + + var RectText = function () {}; + + function parsePercent(value, maxValue) { + if (typeof value === 'string') { + if (value.lastIndexOf('%') >= 0) { + return parseFloat(value) / 100 * maxValue; + } + return parseFloat(value); + } + return value; + } + + RectText.prototype = { + + constructor: RectText, + + /** + * Draw text in a rect with specified position. + * @param {CanvasRenderingContext} ctx + * @param {Object} rect Displayable rect + * @return {Object} textRect Alternative precalculated text bounding rect + */ + drawRectText: function (ctx, rect, textRect) { + var style = this.style; + var text = style.text; + // Convert to string + text != null && (text += ''); + if (!text) { + return; + } + + // FIXME + ctx.save(); + + var x; + var y; + var textPosition = style.textPosition; + var textOffset = style.textOffset; + var distance = style.textDistance; + var align = style.textAlign; + var font = style.textFont || style.font; + var baseline = style.textBaseline; + var verticalAlign = style.textVerticalAlign; + rect = style.textPositionRect || rect; + + textRect = textRect || textContain.getBoundingRect(text, font, align, baseline); + + // Transform rect to view space + var transform = this.transform; + if (!style.textTransform) { + if (transform) { + tmpRect.copy(rect); + tmpRect.applyTransform(transform); + rect = tmpRect; + } + } + else { + this.setTransform(ctx); + } + + // Text position represented by coord + if (textPosition instanceof Array) { + // Percent + x = rect.x + parsePercent(textPosition[0], rect.width); + y = rect.y + parsePercent(textPosition[1], rect.height); + align = align || 'left'; + baseline = baseline || 'top'; + + if (verticalAlign) { + switch (verticalAlign) { + case 'middle': + y -= textRect.height / 2 - textRect.lineHeight / 2; + break; + case 'bottom': + y -= textRect.height - textRect.lineHeight / 2; + break; + default: + y += textRect.lineHeight / 2; + } + // Force bseline to be middle + baseline = 'middle'; + } + } + else { + var res = textContain.adjustTextPositionOnRect( + textPosition, rect, textRect, distance + ); + x = res.x; + y = res.y; + // Default align and baseline when has textPosition + align = align || res.textAlign; + baseline = baseline || res.textBaseline; + } + + if (textOffset) { + x += textOffset[0]; + y += textOffset[1]; + } + + // Use canvas default left textAlign. Giving invalid value will cause state not change + ctx.textAlign = align || 'left'; + // Use canvas default alphabetic baseline + ctx.textBaseline = baseline || 'alphabetic'; + + var textFill = style.textFill; + var textStroke = style.textStroke; + textFill && (ctx.fillStyle = textFill); + textStroke && (ctx.strokeStyle = textStroke); + + // TODO Invalid font + ctx.font = font || '12px sans-serif'; + + // Text shadow + // Always set shadowBlur and shadowOffset to avoid leak from displayable + ctx.shadowBlur = style.textShadowBlur; + ctx.shadowColor = style.textShadowColor || 'transparent'; + ctx.shadowOffsetX = style.textShadowOffsetX; + ctx.shadowOffsetY = style.textShadowOffsetY; + + var textLines = text.split('\n'); + + if (style.textRotation) { + transform && ctx.translate(transform[4], transform[5]); + ctx.rotate(style.textRotation); + transform && ctx.translate(-transform[4], -transform[5]); + } + + for (var i = 0; i < textLines.length; i++) { + // Fill after stroke so the outline will not cover the main part. + textStroke && ctx.strokeText(textLines[i], x, y); + textFill && ctx.fillText(textLines[i], x, y); + y += textRect.lineHeight; + } + + ctx.restore(); + } + }; + + module.exports = RectText; + + +/***/ }, +/* 36 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * Path 代理,可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中 + * 可以用于 isInsidePath 判断以及获取boundingRect + * + * @module zrender/core/PathProxy + * @author Yi Shen (http://www.github.com/pissang) + */ + + // TODO getTotalLength, getPointAtLength + + + var curve = __webpack_require__(37); + var vec2 = __webpack_require__(10); + var bbox = __webpack_require__(38); + var BoundingRect = __webpack_require__(9); + var dpr = __webpack_require__(34).devicePixelRatio; + + var CMD = { + M: 1, + L: 2, + C: 3, + Q: 4, + A: 5, + Z: 6, + // Rect + R: 7 + }; + + // var CMD_MEM_SIZE = { + // M: 3, + // L: 3, + // C: 7, + // Q: 5, + // A: 9, + // R: 5, + // Z: 1 + // }; + + var min = []; + var max = []; + var min2 = []; + var max2 = []; + var mathMin = Math.min; + var mathMax = Math.max; + var mathCos = Math.cos; + var mathSin = Math.sin; + var mathSqrt = Math.sqrt; + var mathAbs = Math.abs; + + var hasTypedArray = typeof Float32Array != 'undefined'; + + /** + * @alias module:zrender/core/PathProxy + * @constructor + */ + var PathProxy = function (notSaveData) { + + this._saveData = !(notSaveData || false); + + if (this._saveData) { + /** + * Path data. Stored as flat array + * @type {Array.} + */ + this.data = []; + } + + this._ctx = null; + }; + + /** + * 快速计算Path包围盒(并不是最小包围盒) + * @return {Object} + */ + PathProxy.prototype = { + + constructor: PathProxy, + + _xi: 0, + _yi: 0, + + _x0: 0, + _y0: 0, + // Unit x, Unit y. Provide for avoiding drawing that too short line segment + _ux: 0, + _uy: 0, + + _len: 0, + + _lineDash: null, + + _dashOffset: 0, + + _dashIdx: 0, + + _dashSum: 0, + + /** + * @readOnly + */ + setScale: function (sx, sy) { + this._ux = mathAbs(1 / dpr / sx) || 0; + this._uy = mathAbs(1 / dpr / sy) || 0; + }, + + getContext: function () { + return this._ctx; + }, + + /** + * @param {CanvasRenderingContext2D} ctx + * @return {module:zrender/core/PathProxy} + */ + beginPath: function (ctx) { + + this._ctx = ctx; + + ctx && ctx.beginPath(); + + ctx && (this.dpr = ctx.dpr); + + // Reset + if (this._saveData) { + this._len = 0; + } + + if (this._lineDash) { + this._lineDash = null; + + this._dashOffset = 0; + } + + return this; + }, + + /** + * @param {number} x + * @param {number} y + * @return {module:zrender/core/PathProxy} + */ + moveTo: function (x, y) { + this.addData(CMD.M, x, y); + this._ctx && this._ctx.moveTo(x, y); + + // x0, y0, xi, yi 是记录在 _dashedXXXXTo 方法中使用 + // xi, yi 记录当前点, x0, y0 在 closePath 的时候回到起始点。 + // 有可能在 beginPath 之后直接调用 lineTo,这时候 x0, y0 需要 + // 在 lineTo 方法中记录,这里先不考虑这种情况,dashed line 也只在 IE10- 中不支持 + this._x0 = x; + this._y0 = y; + + this._xi = x; + this._yi = y; + + return this; + }, + + /** + * @param {number} x + * @param {number} y + * @return {module:zrender/core/PathProxy} + */ + lineTo: function (x, y) { + var exceedUnit = mathAbs(x - this._xi) > this._ux + || mathAbs(y - this._yi) > this._uy + // Force draw the first segment + || this._len < 5; + + this.addData(CMD.L, x, y); + + if (this._ctx && exceedUnit) { + this._needsDash() ? this._dashedLineTo(x, y) + : this._ctx.lineTo(x, y); + } + if (exceedUnit) { + this._xi = x; + this._yi = y; + } + + return this; + }, + + /** + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @return {module:zrender/core/PathProxy} + */ + bezierCurveTo: function (x1, y1, x2, y2, x3, y3) { + this.addData(CMD.C, x1, y1, x2, y2, x3, y3); + if (this._ctx) { + this._needsDash() ? this._dashedBezierTo(x1, y1, x2, y2, x3, y3) + : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + } + this._xi = x3; + this._yi = y3; + return this; + }, + + /** + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {module:zrender/core/PathProxy} + */ + quadraticCurveTo: function (x1, y1, x2, y2) { + this.addData(CMD.Q, x1, y1, x2, y2); + if (this._ctx) { + this._needsDash() ? this._dashedQuadraticTo(x1, y1, x2, y2) + : this._ctx.quadraticCurveTo(x1, y1, x2, y2); + } + this._xi = x2; + this._yi = y2; + return this; + }, + + /** + * @param {number} cx + * @param {number} cy + * @param {number} r + * @param {number} startAngle + * @param {number} endAngle + * @param {boolean} anticlockwise + * @return {module:zrender/core/PathProxy} + */ + arc: function (cx, cy, r, startAngle, endAngle, anticlockwise) { + this.addData( + CMD.A, cx, cy, r, r, startAngle, endAngle - startAngle, 0, anticlockwise ? 0 : 1 + ); + this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); + + this._xi = mathCos(endAngle) * r + cx; + this._yi = mathSin(endAngle) * r + cx; + return this; + }, + + // TODO + arcTo: function (x1, y1, x2, y2, radius) { + if (this._ctx) { + this._ctx.arcTo(x1, y1, x2, y2, radius); + } + return this; + }, + + // TODO + rect: function (x, y, w, h) { + this._ctx && this._ctx.rect(x, y, w, h); + this.addData(CMD.R, x, y, w, h); + return this; + }, + + /** + * @return {module:zrender/core/PathProxy} + */ + closePath: function () { + this.addData(CMD.Z); + + var ctx = this._ctx; + var x0 = this._x0; + var y0 = this._y0; + if (ctx) { + this._needsDash() && this._dashedLineTo(x0, y0); + ctx.closePath(); + } + + this._xi = x0; + this._yi = y0; + return this; + }, + + /** + * Context 从外部传入,因为有可能是 rebuildPath 完之后再 fill。 + * stroke 同样 + * @param {CanvasRenderingContext2D} ctx + * @return {module:zrender/core/PathProxy} + */ + fill: function (ctx) { + ctx && ctx.fill(); + this.toStatic(); + }, + + /** + * @param {CanvasRenderingContext2D} ctx + * @return {module:zrender/core/PathProxy} + */ + stroke: function (ctx) { + ctx && ctx.stroke(); + this.toStatic(); + }, + + /** + * 必须在其它绘制命令前调用 + * Must be invoked before all other path drawing methods + * @return {module:zrender/core/PathProxy} + */ + setLineDash: function (lineDash) { + if (lineDash instanceof Array) { + this._lineDash = lineDash; + + this._dashIdx = 0; + + var lineDashSum = 0; + for (var i = 0; i < lineDash.length; i++) { + lineDashSum += lineDash[i]; + } + this._dashSum = lineDashSum; + } + return this; + }, + + /** + * 必须在其它绘制命令前调用 + * Must be invoked before all other path drawing methods + * @return {module:zrender/core/PathProxy} + */ + setLineDashOffset: function (offset) { + this._dashOffset = offset; + return this; + }, + + /** + * + * @return {boolean} + */ + len: function () { + return this._len; + }, + + /** + * 直接设置 Path 数据 + */ + setData: function (data) { + + var len = data.length; + + if (! (this.data && this.data.length == len) && hasTypedArray) { + this.data = new Float32Array(len); + } + + for (var i = 0; i < len; i++) { + this.data[i] = data[i]; + } + + this._len = len; + }, + + /** + * 添加子路径 + * @param {module:zrender/core/PathProxy|Array.} path + */ + appendPath: function (path) { + if (!(path instanceof Array)) { + path = [path]; + } + var len = path.length; + var appendSize = 0; + var offset = this._len; + for (var i = 0; i < len; i++) { + appendSize += path[i].len(); + } + if (hasTypedArray && (this.data instanceof Float32Array)) { + this.data = new Float32Array(offset + appendSize); + } + for (var i = 0; i < len; i++) { + var appendPathData = path[i].data; + for (var k = 0; k < appendPathData.length; k++) { + this.data[offset++] = appendPathData[k]; + } + } + this._len = offset; + }, + + /** + * 填充 Path 数据。 + * 尽量复用而不申明新的数组。大部分图形重绘的指令数据长度都是不变的。 + */ + addData: function (cmd) { + if (!this._saveData) { + return; + } + + var data = this.data; + if (this._len + arguments.length > data.length) { + // 因为之前的数组已经转换成静态的 Float32Array + // 所以不够用时需要扩展一个新的动态数组 + this._expandData(); + data = this.data; + } + for (var i = 0; i < arguments.length; i++) { + data[this._len++] = arguments[i]; + } + + this._prevCmd = cmd; + }, + + _expandData: function () { + // Only if data is Float32Array + if (!(this.data instanceof Array)) { + var newData = []; + for (var i = 0; i < this._len; i++) { + newData[i] = this.data[i]; + } + this.data = newData; + } + }, + + /** + * If needs js implemented dashed line + * @return {boolean} + * @private + */ + _needsDash: function () { + return this._lineDash; + }, + + _dashedLineTo: function (x1, y1) { + var dashSum = this._dashSum; + var offset = this._dashOffset; + var lineDash = this._lineDash; + var ctx = this._ctx; + + var x0 = this._xi; + var y0 = this._yi; + var dx = x1 - x0; + var dy = y1 - y0; + var dist = mathSqrt(dx * dx + dy * dy); + var x = x0; + var y = y0; + var dash; + var nDash = lineDash.length; + var idx; + dx /= dist; + dy /= dist; + + if (offset < 0) { + // Convert to positive offset + offset = dashSum + offset; + } + offset %= dashSum; + x -= offset * dx; + y -= offset * dy; + + while ((dx > 0 && x <= x1) || (dx < 0 && x >= x1) + || (dx == 0 && ((dy > 0 && y <= y1) || (dy < 0 && y >= y1)))) { + idx = this._dashIdx; + dash = lineDash[idx]; + x += dx * dash; + y += dy * dash; + this._dashIdx = (idx + 1) % nDash; + // Skip positive offset + if ((dx > 0 && x < x0) || (dx < 0 && x > x0) || (dy > 0 && y < y0) || (dy < 0 && y > y0)) { + continue; + } + ctx[idx % 2 ? 'moveTo' : 'lineTo']( + dx >= 0 ? mathMin(x, x1) : mathMax(x, x1), + dy >= 0 ? mathMin(y, y1) : mathMax(y, y1) + ); + } + // Offset for next lineTo + dx = x - x1; + dy = y - y1; + this._dashOffset = -mathSqrt(dx * dx + dy * dy); + }, + + // Not accurate dashed line to + _dashedBezierTo: function (x1, y1, x2, y2, x3, y3) { + var dashSum = this._dashSum; + var offset = this._dashOffset; + var lineDash = this._lineDash; + var ctx = this._ctx; + + var x0 = this._xi; + var y0 = this._yi; + var t; + var dx; + var dy; + var cubicAt = curve.cubicAt; + var bezierLen = 0; + var idx = this._dashIdx; + var nDash = lineDash.length; + + var x; + var y; + + var tmpLen = 0; + + if (offset < 0) { + // Convert to positive offset + offset = dashSum + offset; + } + offset %= dashSum; + // Bezier approx length + for (t = 0; t < 1; t += 0.1) { + dx = cubicAt(x0, x1, x2, x3, t + 0.1) + - cubicAt(x0, x1, x2, x3, t); + dy = cubicAt(y0, y1, y2, y3, t + 0.1) + - cubicAt(y0, y1, y2, y3, t); + bezierLen += mathSqrt(dx * dx + dy * dy); + } + + // Find idx after add offset + for (; idx < nDash; idx++) { + tmpLen += lineDash[idx]; + if (tmpLen > offset) { + break; + } + } + t = (tmpLen - offset) / bezierLen; + + while (t <= 1) { + + x = cubicAt(x0, x1, x2, x3, t); + y = cubicAt(y0, y1, y2, y3, t); + + // Use line to approximate dashed bezier + // Bad result if dash is long + idx % 2 ? ctx.moveTo(x, y) + : ctx.lineTo(x, y); + + t += lineDash[idx] / bezierLen; + + idx = (idx + 1) % nDash; + } + + // Finish the last segment and calculate the new offset + (idx % 2 !== 0) && ctx.lineTo(x3, y3); + dx = x3 - x; + dy = y3 - y; + this._dashOffset = -mathSqrt(dx * dx + dy * dy); + }, + + _dashedQuadraticTo: function (x1, y1, x2, y2) { + // Convert quadratic to cubic using degree elevation + var x3 = x2; + var y3 = y2; + x2 = (x2 + 2 * x1) / 3; + y2 = (y2 + 2 * y1) / 3; + x1 = (this._xi + 2 * x1) / 3; + y1 = (this._yi + 2 * y1) / 3; + + this._dashedBezierTo(x1, y1, x2, y2, x3, y3); + }, + + /** + * 转成静态的 Float32Array 减少堆内存占用 + * Convert dynamic array to static Float32Array + */ + toStatic: function () { + var data = this.data; + if (data instanceof Array) { + data.length = this._len; + if (hasTypedArray) { + this.data = new Float32Array(data); + } + } + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getBoundingRect: function () { + min[0] = min[1] = min2[0] = min2[1] = Number.MAX_VALUE; + max[0] = max[1] = max2[0] = max2[1] = -Number.MAX_VALUE; + + var data = this.data; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + + if (i == 1) { + // 如果第一个命令是 L, C, Q + // 则 previous point 同绘制命令的第一个 point + // + // 第一个命令为 Arc 的情况下会在后面特殊处理 + xi = data[i]; + yi = data[i + 1]; + + x0 = xi; + y0 = yi; + } + + switch (cmd) { + case CMD.M: + // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点 + // 在 closePath 的时候使用 + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + min2[0] = x0; + min2[1] = y0; + max2[0] = x0; + max2[1] = y0; + break; + case CMD.L: + bbox.fromLine(xi, yi, data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.C: + bbox.fromCubic( + xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], + min2, max2 + ); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.Q: + bbox.fromQuadratic( + xi, yi, data[i++], data[i++], data[i], data[i + 1], + min2, max2 + ); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.A: + // TODO Arc 判断的开销比较大 + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var endAngle = data[i++] + startAngle; + // TODO Arc 旋转 + var psi = data[i++]; + var anticlockwise = 1 - data[i++]; + + if (i == 1) { + // 直接使用 arc 命令 + // 第一个命令起点还未定义 + x0 = mathCos(startAngle) * rx + cx; + y0 = mathSin(startAngle) * ry + cy; + } + + bbox.fromArc( + cx, cy, rx, ry, startAngle, endAngle, + anticlockwise, min2, max2 + ); + + xi = mathCos(endAngle) * rx + cx; + yi = mathSin(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + // Use fromLine + bbox.fromLine(x0, y0, x0 + width, y0 + height, min2, max2); + break; + case CMD.Z: + xi = x0; + yi = y0; + break; + } + + // Union + vec2.min(min, min, min2); + vec2.max(max, max, max2); + } + + // No data + if (i === 0) { + min[0] = min[1] = max[0] = max[1] = 0; + } + + return new BoundingRect( + min[0], min[1], max[0] - min[0], max[1] - min[1] + ); + }, + + /** + * Rebuild path from current data + * Rebuild path will not consider javascript implemented line dash. + * @param {CanvasRenderingContext} ctx + */ + rebuildPath: function (ctx) { + var d = this.data; + var x0, y0; + var xi, yi; + var x, y; + var ux = this._ux; + var uy = this._uy; + var len = this._len; + for (var i = 0; i < len;) { + var cmd = d[i++]; + + if (i == 1) { + // 如果第一个命令是 L, C, Q + // 则 previous point 同绘制命令的第一个 point + // + // 第一个命令为 Arc 的情况下会在后面特殊处理 + xi = d[i]; + yi = d[i + 1]; + + x0 = xi; + y0 = yi; + } + switch (cmd) { + case CMD.M: + x0 = xi = d[i++]; + y0 = yi = d[i++]; + ctx.moveTo(xi, yi); + break; + case CMD.L: + x = d[i++]; + y = d[i++]; + // Not draw too small seg between + if (mathAbs(x - xi) > ux || mathAbs(y - yi) > uy || i === len - 1) { + ctx.lineTo(x, y); + xi = x; + yi = y; + } + break; + case CMD.C: + ctx.bezierCurveTo( + d[i++], d[i++], d[i++], d[i++], d[i++], d[i++] + ); + xi = d[i - 2]; + yi = d[i - 1]; + break; + case CMD.Q: + ctx.quadraticCurveTo(d[i++], d[i++], d[i++], d[i++]); + xi = d[i - 2]; + yi = d[i - 1]; + break; + case CMD.A: + var cx = d[i++]; + var cy = d[i++]; + var rx = d[i++]; + var ry = d[i++]; + var theta = d[i++]; + var dTheta = d[i++]; + var psi = d[i++]; + var fs = d[i++]; + var r = (rx > ry) ? rx : ry; + var scaleX = (rx > ry) ? 1 : rx / ry; + var scaleY = (rx > ry) ? ry / rx : 1; + var isEllipse = Math.abs(rx - ry) > 1e-3; + var endAngle = theta + dTheta; + if (isEllipse) { + ctx.translate(cx, cy); + ctx.rotate(psi); + ctx.scale(scaleX, scaleY); + ctx.arc(0, 0, r, theta, endAngle, 1 - fs); + ctx.scale(1 / scaleX, 1 / scaleY); + ctx.rotate(-psi); + ctx.translate(-cx, -cy); + } + else { + ctx.arc(cx, cy, r, theta, endAngle, 1 - fs); + } + + if (i == 1) { + // 直接使用 arc 命令 + // 第一个命令起点还未定义 + x0 = mathCos(theta) * rx + cx; + y0 = mathSin(theta) * ry + cy; + } + xi = mathCos(endAngle) * rx + cx; + yi = mathSin(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = d[i]; + y0 = yi = d[i + 1]; + ctx.rect(d[i++], d[i++], d[i++], d[i++]); + break; + case CMD.Z: + ctx.closePath(); + xi = x0; + yi = y0; + } + } + } + }; + + PathProxy.CMD = CMD; + + module.exports = PathProxy; + + +/***/ }, +/* 37 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * 曲线辅助模块 + * @module zrender/core/curve + * @author pissang(https://www.github.com/pissang) + */ + + + var vec2 = __webpack_require__(10); + var v2Create = vec2.create; + var v2DistSquare = vec2.distSquare; + var mathPow = Math.pow; + var mathSqrt = Math.sqrt; + + var EPSILON = 1e-8; + var EPSILON_NUMERIC = 1e-4; + + var THREE_SQRT = mathSqrt(3); + var ONE_THIRD = 1 / 3; + + // 临时变量 + var _v0 = v2Create(); + var _v1 = v2Create(); + var _v2 = v2Create(); + // var _v3 = vec2.create(); + + function isAroundZero(val) { + return val > -EPSILON && val < EPSILON; + } + function isNotAroundZero(val) { + return val > EPSILON || val < -EPSILON; + } + /** + * 计算三次贝塞尔值 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @return {number} + */ + function cubicAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return onet * onet * (onet * p0 + 3 * t * p1) + + t * t * (t * p3 + 3 * onet * p2); + } + + /** + * 计算三次贝塞尔导数值 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @return {number} + */ + function cubicDerivativeAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return 3 * ( + ((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + + (p3 - p2) * t * t + ); + } + + /** + * 计算三次贝塞尔方程根,使用盛金公式 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} val + * @param {Array.} roots + * @return {number} 有效根数目 + */ + function cubicRootAt(p0, p1, p2, p3, val, roots) { + // Evaluate roots of cubic functions + var a = p3 + 3 * (p1 - p2) - p0; + var b = 3 * (p2 - p1 * 2 + p0); + var c = 3 * (p1 - p0); + var d = p0 - val; + + var A = b * b - 3 * a * c; + var B = b * c - 9 * a * d; + var C = c * c - 3 * b * d; + + var n = 0; + + if (isAroundZero(A) && isAroundZero(B)) { + if (isAroundZero(b)) { + roots[0] = 0; + } + else { + var t1 = -c / b; //t1, t2, t3, b is not zero + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = B * B - 4 * A * C; + + if (isAroundZero(disc)) { + var K = B / A; + var t1 = -b / a + K; // t1, a is not zero + var t2 = -K / 2; // t2, t3 + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var Y1 = A * b + 1.5 * a * (-B + discSqrt); + var Y2 = A * b + 1.5 * a * (-B - discSqrt); + if (Y1 < 0) { + Y1 = -mathPow(-Y1, ONE_THIRD); + } + else { + Y1 = mathPow(Y1, ONE_THIRD); + } + if (Y2 < 0) { + Y2 = -mathPow(-Y2, ONE_THIRD); + } + else { + Y2 = mathPow(Y2, ONE_THIRD); + } + var t1 = (-b - (Y1 + Y2)) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else { + var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt(A * A * A)); + var theta = Math.acos(T) / 3; + var ASqrt = mathSqrt(A); + var tmp = Math.cos(theta); + + var t1 = (-b - 2 * ASqrt * tmp) / (3 * a); + var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a); + var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + if (t3 >= 0 && t3 <= 1) { + roots[n++] = t3; + } + } + } + return n; + } + + /** + * 计算三次贝塞尔方程极限值的位置 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {Array.} extrema + * @return {number} 有效数目 + */ + function cubicExtrema(p0, p1, p2, p3, extrema) { + var b = 6 * p2 - 12 * p1 + 6 * p0; + var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2; + var c = 3 * p1 - 3 * p0; + + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <=1) { + extrema[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + extrema[0] = -b / (2 * a); + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + extrema[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + extrema[n++] = t2; + } + } + } + return n; + } + + /** + * 细分三次贝塞尔曲线 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @param {Array.} out + */ + function cubicSubdivide(p0, p1, p2, p3, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p23 = (p3 - p2) * t + p2; + + var p012 = (p12 - p01) * t + p01; + var p123 = (p23 - p12) * t + p12; + + var p0123 = (p123 - p012) * t + p012; + // Seg0 + out[0] = p0; + out[1] = p01; + out[2] = p012; + out[3] = p0123; + // Seg1 + out[4] = p0123; + out[5] = p123; + out[6] = p23; + out[7] = p3; + } + + /** + * 投射点到三次贝塞尔曲线上,返回投射距离。 + * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @param {number} x + * @param {number} y + * @param {Array.} [out] 投射点 + * @return {number} + */ + function cubicProjectPoint( + x0, y0, x1, y1, x2, y2, x3, y3, + x, y, out + ) { + // http://pomax.github.io/bezierinfo/#projections + var t; + var interval = 0.005; + var d = Infinity; + var prev; + var next; + var d1; + var d2; + + _v0[0] = x; + _v0[1] = y; + + // 先粗略估计一下可能的最小距离的 t 值 + // PENDING + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = cubicAt(x0, x1, x2, x3, _t); + _v1[1] = cubicAt(y0, y1, y2, y3, _t); + d1 = v2DistSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + + // At most 32 iteration + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + prev = t - interval; + next = t + interval; + // t - interval + _v1[0] = cubicAt(x0, x1, x2, x3, prev); + _v1[1] = cubicAt(y0, y1, y2, y3, prev); + + d1 = v2DistSquare(_v1, _v0); + + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + // t + interval + _v2[0] = cubicAt(x0, x1, x2, x3, next); + _v2[1] = cubicAt(y0, y1, y2, y3, next); + d2 = v2DistSquare(_v2, _v0); + + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + // t + if (out) { + out[0] = cubicAt(x0, x1, x2, x3, t); + out[1] = cubicAt(y0, y1, y2, y3, t); + } + // console.log(interval, i); + return mathSqrt(d); + } + + /** + * 计算二次方贝塞尔值 + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @return {number} + */ + function quadraticAt(p0, p1, p2, t) { + var onet = 1 - t; + return onet * (onet * p0 + 2 * t * p1) + t * t * p2; + } + + /** + * 计算二次方贝塞尔导数值 + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @return {number} + */ + function quadraticDerivativeAt(p0, p1, p2, t) { + return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1)); + } + + /** + * 计算二次方贝塞尔方程根 + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @param {Array.} roots + * @return {number} 有效根数目 + */ + function quadraticRootAt(p0, p1, p2, val, roots) { + var a = p0 - 2 * p1 + p2; + var b = 2 * (p1 - p0); + var c = p0 - val; + + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + var t1 = -b / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + } + return n; + } + + /** + * 计算二次贝塞尔方程极限值 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @return {number} + */ + function quadraticExtremum(p0, p1, p2) { + var divider = p0 + p2 - 2 * p1; + if (divider === 0) { + // p1 is center of p0 and p2 + return 0.5; + } + else { + return (p0 - p1) / divider; + } + } + + /** + * 细分二次贝塞尔曲线 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @param {Array.} out + */ + function quadraticSubdivide(p0, p1, p2, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p012 = (p12 - p01) * t + p01; + + // Seg0 + out[0] = p0; + out[1] = p01; + out[2] = p012; + + // Seg1 + out[3] = p012; + out[4] = p12; + out[5] = p2; + } + + /** + * 投射点到二次贝塞尔曲线上,返回投射距离。 + * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x + * @param {number} y + * @param {Array.} out 投射点 + * @return {number} + */ + function quadraticProjectPoint( + x0, y0, x1, y1, x2, y2, + x, y, out + ) { + // http://pomax.github.io/bezierinfo/#projections + var t; + var interval = 0.005; + var d = Infinity; + + _v0[0] = x; + _v0[1] = y; + + // 先粗略估计一下可能的最小距离的 t 值 + // PENDING + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = quadraticAt(x0, x1, x2, _t); + _v1[1] = quadraticAt(y0, y1, y2, _t); + var d1 = v2DistSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + + // At most 32 iteration + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + var prev = t - interval; + var next = t + interval; + // t - interval + _v1[0] = quadraticAt(x0, x1, x2, prev); + _v1[1] = quadraticAt(y0, y1, y2, prev); + + var d1 = v2DistSquare(_v1, _v0); + + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + // t + interval + _v2[0] = quadraticAt(x0, x1, x2, next); + _v2[1] = quadraticAt(y0, y1, y2, next); + var d2 = v2DistSquare(_v2, _v0); + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + // t + if (out) { + out[0] = quadraticAt(x0, x1, x2, t); + out[1] = quadraticAt(y0, y1, y2, t); + } + // console.log(interval, i); + return mathSqrt(d); + } + + module.exports = { + + cubicAt: cubicAt, + + cubicDerivativeAt: cubicDerivativeAt, + + cubicRootAt: cubicRootAt, + + cubicExtrema: cubicExtrema, + + cubicSubdivide: cubicSubdivide, + + cubicProjectPoint: cubicProjectPoint, + + quadraticAt: quadraticAt, + + quadraticDerivativeAt: quadraticDerivativeAt, + + quadraticRootAt: quadraticRootAt, + + quadraticExtremum: quadraticExtremum, + + quadraticSubdivide: quadraticSubdivide, + + quadraticProjectPoint: quadraticProjectPoint + }; + + +/***/ }, +/* 38 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @author Yi Shen(https://github.com/pissang) + */ + + + var vec2 = __webpack_require__(10); + var curve = __webpack_require__(37); + + var bbox = {}; + var mathMin = Math.min; + var mathMax = Math.max; + var mathSin = Math.sin; + var mathCos = Math.cos; + + var start = vec2.create(); + var end = vec2.create(); + var extremity = vec2.create(); + + var PI2 = Math.PI * 2; + /** + * 从顶点数组中计算出最小包围盒,写入`min`和`max`中 + * @module zrender/core/bbox + * @param {Array} points 顶点数组 + * @param {number} min + * @param {number} max + */ + bbox.fromPoints = function(points, min, max) { + if (points.length === 0) { + return; + } + var p = points[0]; + var left = p[0]; + var right = p[0]; + var top = p[1]; + var bottom = p[1]; + var i; + + for (i = 1; i < points.length; i++) { + p = points[i]; + left = mathMin(left, p[0]); + right = mathMax(right, p[0]); + top = mathMin(top, p[1]); + bottom = mathMax(bottom, p[1]); + } + + min[0] = left; + min[1] = top; + max[0] = right; + max[1] = bottom; + }; + + /** + * @memberOf module:zrender/core/bbox + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {Array.} min + * @param {Array.} max + */ + bbox.fromLine = function (x0, y0, x1, y1, min, max) { + min[0] = mathMin(x0, x1); + min[1] = mathMin(y0, y1); + max[0] = mathMax(x0, x1); + max[1] = mathMax(y0, y1); + }; + + var xDim = []; + var yDim = []; + /** + * 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒,写入`min`和`max`中 + * @memberOf module:zrender/core/bbox + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @param {Array.} min + * @param {Array.} max + */ + bbox.fromCubic = function( + x0, y0, x1, y1, x2, y2, x3, y3, min, max + ) { + var cubicExtrema = curve.cubicExtrema; + var cubicAt = curve.cubicAt; + var i; + var n = cubicExtrema(x0, x1, x2, x3, xDim); + min[0] = Infinity; + min[1] = Infinity; + max[0] = -Infinity; + max[1] = -Infinity; + + for (i = 0; i < n; i++) { + var x = cubicAt(x0, x1, x2, x3, xDim[i]); + min[0] = mathMin(x, min[0]); + max[0] = mathMax(x, max[0]); + } + n = cubicExtrema(y0, y1, y2, y3, yDim); + for (i = 0; i < n; i++) { + var y = cubicAt(y0, y1, y2, y3, yDim[i]); + min[1] = mathMin(y, min[1]); + max[1] = mathMax(y, max[1]); + } + + min[0] = mathMin(x0, min[0]); + max[0] = mathMax(x0, max[0]); + min[0] = mathMin(x3, min[0]); + max[0] = mathMax(x3, max[0]); + + min[1] = mathMin(y0, min[1]); + max[1] = mathMax(y0, max[1]); + min[1] = mathMin(y3, min[1]); + max[1] = mathMax(y3, max[1]); + }; + + /** + * 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒,写入`min`和`max`中 + * @memberOf module:zrender/core/bbox + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {Array.} min + * @param {Array.} max + */ + bbox.fromQuadratic = function(x0, y0, x1, y1, x2, y2, min, max) { + var quadraticExtremum = curve.quadraticExtremum; + var quadraticAt = curve.quadraticAt; + // Find extremities, where derivative in x dim or y dim is zero + var tx = + mathMax( + mathMin(quadraticExtremum(x0, x1, x2), 1), 0 + ); + var ty = + mathMax( + mathMin(quadraticExtremum(y0, y1, y2), 1), 0 + ); + + var x = quadraticAt(x0, x1, x2, tx); + var y = quadraticAt(y0, y1, y2, ty); + + min[0] = mathMin(x0, x2, x); + min[1] = mathMin(y0, y2, y); + max[0] = mathMax(x0, x2, x); + max[1] = mathMax(y0, y2, y); + }; + + /** + * 从圆弧中计算出最小包围盒,写入`min`和`max`中 + * @method + * @memberOf module:zrender/core/bbox + * @param {number} x + * @param {number} y + * @param {number} rx + * @param {number} ry + * @param {number} startAngle + * @param {number} endAngle + * @param {number} anticlockwise + * @param {Array.} min + * @param {Array.} max + */ + bbox.fromArc = function ( + x, y, rx, ry, startAngle, endAngle, anticlockwise, min, max + ) { + var vec2Min = vec2.min; + var vec2Max = vec2.max; + + var diff = Math.abs(startAngle - endAngle); + + + if (diff % PI2 < 1e-4 && diff > 1e-4) { + // Is a circle + min[0] = x - rx; + min[1] = y - ry; + max[0] = x + rx; + max[1] = y + ry; + return; + } + + start[0] = mathCos(startAngle) * rx + x; + start[1] = mathSin(startAngle) * ry + y; + + end[0] = mathCos(endAngle) * rx + x; + end[1] = mathSin(endAngle) * ry + y; + + vec2Min(min, start, end); + vec2Max(max, start, end); + + // Thresh to [0, Math.PI * 2] + startAngle = startAngle % (PI2); + if (startAngle < 0) { + startAngle = startAngle + PI2; + } + endAngle = endAngle % (PI2); + if (endAngle < 0) { + endAngle = endAngle + PI2; + } + + if (startAngle > endAngle && !anticlockwise) { + endAngle += PI2; + } + else if (startAngle < endAngle && anticlockwise) { + startAngle += PI2; + } + if (anticlockwise) { + var tmp = endAngle; + endAngle = startAngle; + startAngle = tmp; + } + + // var number = 0; + // var step = (anticlockwise ? -Math.PI : Math.PI) / 2; + for (var angle = 0; angle < endAngle; angle += Math.PI / 2) { + if (angle > startAngle) { + extremity[0] = mathCos(angle) * rx + x; + extremity[1] = mathSin(angle) * ry + y; + + vec2Min(min, extremity, min); + vec2Max(max, extremity, max); + } + } + }; + + module.exports = bbox; + + + +/***/ }, +/* 39 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var CMD = __webpack_require__(36).CMD; + var line = __webpack_require__(40); + var cubic = __webpack_require__(41); + var quadratic = __webpack_require__(42); + var arc = __webpack_require__(43); + var normalizeRadian = __webpack_require__(44).normalizeRadian; + var curve = __webpack_require__(37); + + var windingLine = __webpack_require__(45); + + var containStroke = line.containStroke; + + var PI2 = Math.PI * 2; + + var EPSILON = 1e-4; + + function isAroundEqual(a, b) { + return Math.abs(a - b) < EPSILON; + } + + // 临时数组 + var roots = [-1, -1, -1]; + var extrema = [-1, -1]; + + function swapExtrema() { + var tmp = extrema[0]; + extrema[0] = extrema[1]; + extrema[1] = tmp; + } + + function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) { + // Quick reject + if ( + (y > y0 && y > y1 && y > y2 && y > y3) + || (y < y0 && y < y1 && y < y2 && y < y3) + ) { + return 0; + } + var nRoots = curve.cubicRootAt(y0, y1, y2, y3, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var w = 0; + var nExtrema = -1; + var y0_, y1_; + for (var i = 0; i < nRoots; i++) { + var t = roots[i]; + + // Avoid winding error when intersection point is the connect point of two line of polygon + var unit = (t === 0 || t === 1) ? 0.5 : 1; + + var x_ = curve.cubicAt(x0, x1, x2, x3, t); + if (x_ < x) { // Quick reject + continue; + } + if (nExtrema < 0) { + nExtrema = curve.cubicExtrema(y0, y1, y2, y3, extrema); + if (extrema[1] < extrema[0] && nExtrema > 1) { + swapExtrema(); + } + y0_ = curve.cubicAt(y0, y1, y2, y3, extrema[0]); + if (nExtrema > 1) { + y1_ = curve.cubicAt(y0, y1, y2, y3, extrema[1]); + } + } + if (nExtrema == 2) { + // 分成三段单调函数 + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else if (t < extrema[1]) { + w += y1_ < y0_ ? unit : -unit; + } + else { + w += y3 < y1_ ? unit : -unit; + } + } + else { + // 分成两段单调函数 + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else { + w += y3 < y0_ ? unit : -unit; + } + } + } + return w; + } + } + + function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) { + // Quick reject + if ( + (y > y0 && y > y1 && y > y2) + || (y < y0 && y < y1 && y < y2) + ) { + return 0; + } + var nRoots = curve.quadraticRootAt(y0, y1, y2, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var t = curve.quadraticExtremum(y0, y1, y2); + if (t >= 0 && t <= 1) { + var w = 0; + var y_ = curve.quadraticAt(y0, y1, y2, t); + for (var i = 0; i < nRoots; i++) { + // Remove one endpoint. + var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1; + + var x_ = curve.quadraticAt(x0, x1, x2, roots[i]); + if (x_ < x) { // Quick reject + continue; + } + if (roots[i] < t) { + w += y_ < y0 ? unit : -unit; + } + else { + w += y2 < y_ ? unit : -unit; + } + } + return w; + } + else { + // Remove one endpoint. + var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1; + + var x_ = curve.quadraticAt(x0, x1, x2, roots[0]); + if (x_ < x) { // Quick reject + return 0; + } + return y2 < y0 ? unit : -unit; + } + } + } + + // TODO + // Arc 旋转 + function windingArc( + cx, cy, r, startAngle, endAngle, anticlockwise, x, y + ) { + y -= cy; + if (y > r || y < -r) { + return 0; + } + var tmp = Math.sqrt(r * r - y * y); + roots[0] = -tmp; + roots[1] = tmp; + + var diff = Math.abs(startAngle - endAngle); + if (diff < 1e-4) { + return 0; + } + if (diff % PI2 < 1e-4) { + // Is a circle + startAngle = 0; + endAngle = PI2; + var dir = anticlockwise ? 1 : -1; + if (x >= roots[0] + cx && x <= roots[1] + cx) { + return dir; + } else { + return 0; + } + } + + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } + else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + if (startAngle > endAngle) { + endAngle += PI2; + } + + var w = 0; + for (var i = 0; i < 2; i++) { + var x_ = roots[i]; + if (x_ + cx > x) { + var angle = Math.atan2(y, x_); + var dir = anticlockwise ? 1 : -1; + if (angle < 0) { + angle = PI2 + angle; + } + if ( + (angle >= startAngle && angle <= endAngle) + || (angle + PI2 >= startAngle && angle + PI2 <= endAngle) + ) { + if (angle > Math.PI / 2 && angle < Math.PI * 1.5) { + dir = -dir; + } + w += dir; + } + } + } + return w; + } + + function containPath(data, lineWidth, isStroke, x, y) { + var w = 0; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + // Begin a new subpath + if (cmd === CMD.M && i > 1) { + // Close previous subpath + if (!isStroke) { + w += windingLine(xi, yi, x0, y0, x, y); + } + // 如果被任何一个 subpath 包含 + // if (w !== 0) { + // return true; + // } + } + + if (i == 1) { + // 如果第一个命令是 L, C, Q + // 则 previous point 同绘制命令的第一个 point + // + // 第一个命令为 Arc 的情况下会在后面特殊处理 + xi = data[i]; + yi = data[i + 1]; + + x0 = xi; + y0 = yi; + } + + switch (cmd) { + case CMD.M: + // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点 + // 在 closePath 的时候使用 + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + break; + case CMD.L: + if (isStroke) { + if (containStroke(xi, yi, data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + // NOTE 在第一个命令为 L, C, Q 的时候会计算出 NaN + w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD.C: + if (isStroke) { + if (cubic.containStroke(xi, yi, + data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], + lineWidth, x, y + )) { + return true; + } + } + else { + w += windingCubic( + xi, yi, + data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], + x, y + ) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD.Q: + if (isStroke) { + if (quadratic.containStroke(xi, yi, + data[i++], data[i++], data[i], data[i + 1], + lineWidth, x, y + )) { + return true; + } + } + else { + w += windingQuadratic( + xi, yi, + data[i++], data[i++], data[i], data[i + 1], + x, y + ) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD.A: + // TODO Arc 判断的开销比较大 + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var theta = data[i++]; + var dTheta = data[i++]; + // TODO Arc 旋转 + var psi = data[i++]; + var anticlockwise = 1 - data[i++]; + var x1 = Math.cos(theta) * rx + cx; + var y1 = Math.sin(theta) * ry + cy; + // 不是直接使用 arc 命令 + if (i > 1) { + w += windingLine(xi, yi, x1, y1, x, y); + } + else { + // 第一个命令起点还未定义 + x0 = x1; + y0 = y1; + } + // zr 使用scale来模拟椭圆, 这里也对x做一定的缩放 + var _x = (x - cx) * ry / rx + cx; + if (isStroke) { + if (arc.containStroke( + cx, cy, ry, theta, theta + dTheta, anticlockwise, + lineWidth, _x, y + )) { + return true; + } + } + else { + w += windingArc( + cx, cy, ry, theta, theta + dTheta, anticlockwise, + _x, y + ); + } + xi = Math.cos(theta + dTheta) * rx + cx; + yi = Math.sin(theta + dTheta) * ry + cy; + break; + case CMD.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + var x1 = x0 + width; + var y1 = y0 + height; + if (isStroke) { + if (containStroke(x0, y0, x1, y0, lineWidth, x, y) + || containStroke(x1, y0, x1, y1, lineWidth, x, y) + || containStroke(x1, y1, x0, y1, lineWidth, x, y) + || containStroke(x0, y1, x0, y0, lineWidth, x, y) + ) { + return true; + } + } + else { + // FIXME Clockwise ? + w += windingLine(x1, y0, x1, y1, x, y); + w += windingLine(x0, y1, x0, y0, x, y); + } + break; + case CMD.Z: + if (isStroke) { + if (containStroke( + xi, yi, x0, y0, lineWidth, x, y + )) { + return true; + } + } + else { + // Close a subpath + w += windingLine(xi, yi, x0, y0, x, y); + // 如果被任何一个 subpath 包含 + // FIXME subpaths may overlap + // if (w !== 0) { + // return true; + // } + } + xi = x0; + yi = y0; + break; + } + } + if (!isStroke && !isAroundEqual(yi, y0)) { + w += windingLine(xi, yi, x0, y0, x, y) || 0; + } + return w !== 0; + } + + module.exports = { + contain: function (pathData, x, y) { + return containPath(pathData, 0, false, x, y); + }, + + containStroke: function (pathData, lineWidth, x, y) { + return containPath(pathData, lineWidth, true, x, y); + } + }; + + +/***/ }, +/* 40 */ +/***/ function(module, exports) { + + + module.exports = { + /** + * 线段包含判断 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {boolean} + */ + containStroke: function (x0, y0, x1, y1, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + var _a = 0; + var _b = x0; + // Quick reject + if ( + (y > y0 + _l && y > y1 + _l) + || (y < y0 - _l && y < y1 - _l) + || (x > x0 + _l && x > x1 + _l) + || (x < x0 - _l && x < x1 - _l) + ) { + return false; + } + + if (x0 !== x1) { + _a = (y0 - y1) / (x0 - x1); + _b = (x0 * y1 - x1 * y0) / (x0 - x1) ; + } + else { + return Math.abs(x - x0) <= _l / 2; + } + var tmp = _a * x - y + _b; + var _s = tmp * tmp / (_a * _a + 1); + return _s <= _l / 2 * _l / 2; + } + }; + + +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + + + + var curve = __webpack_require__(37); + + module.exports = { + /** + * 三次贝塞尔曲线描边包含判断 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {boolean} + */ + containStroke: function(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + // Quick reject + if ( + (y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l) + ) { + return false; + } + var d = curve.cubicProjectPoint( + x0, y0, x1, y1, x2, y2, x3, y3, + x, y, null + ); + return d <= _l / 2; + } + }; + + +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { + + + + var curve = __webpack_require__(37); + + module.exports = { + /** + * 二次贝塞尔曲线描边包含判断 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {boolean} + */ + containStroke: function (x0, y0, x1, y1, x2, y2, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + // Quick reject + if ( + (y > y0 + _l && y > y1 + _l && y > y2 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l) + ) { + return false; + } + var d = curve.quadraticProjectPoint( + x0, y0, x1, y1, x2, y2, + x, y, null + ); + return d <= _l / 2; + } + }; + + +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { + + + + var normalizeRadian = __webpack_require__(44).normalizeRadian; + var PI2 = Math.PI * 2; + + module.exports = { + /** + * 圆弧描边包含判断 + * @param {number} cx + * @param {number} cy + * @param {number} r + * @param {number} startAngle + * @param {number} endAngle + * @param {boolean} anticlockwise + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {Boolean} + */ + containStroke: function ( + cx, cy, r, startAngle, endAngle, anticlockwise, + lineWidth, x, y + ) { + + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + + x -= cx; + y -= cy; + var d = Math.sqrt(x * x + y * y); + + if ((d - _l > r) || (d + _l < r)) { + return false; + } + if (Math.abs(startAngle - endAngle) % PI2 < 1e-4) { + // Is a circle + return true; + } + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + if (startAngle > endAngle) { + endAngle += PI2; + } + + var angle = Math.atan2(y, x); + if (angle < 0) { + angle += PI2; + } + return (angle >= startAngle && angle <= endAngle) + || (angle + PI2 >= startAngle && angle + PI2 <= endAngle); + } + }; + + +/***/ }, +/* 44 */ +/***/ function(module, exports) { + + + + var PI2 = Math.PI * 2; + module.exports = { + normalizeRadian: function(angle) { + angle %= PI2; + if (angle < 0) { + angle += PI2; + } + return angle; + } + }; + + +/***/ }, +/* 45 */ +/***/ function(module, exports) { + + + module.exports = function windingLine(x0, y0, x1, y1, x, y) { + if ((y > y0 && y > y1) || (y < y0 && y < y1)) { + return 0; + } + // Ignore horizontal line + if (y1 === y0) { + return 0; + } + var dir = y1 < y0 ? 1 : -1; + var t = (y - y0) / (y1 - y0); + + // Avoid winding error when intersection point is the connect point of two line of polygon + if (t === 1 || t === 0) { + dir = y1 < y0 ? 0.5 : -0.5; + } + + var x_ = t * (x1 - x0) + x0; + + return x_ > x ? dir : 0; + }; + + +/***/ }, +/* 46 */ +/***/ function(module, exports) { + + + + var Pattern = function (image, repeat) { + // Should do nothing more in this constructor. Because gradient can be + // declard by `color: {image: ...}`, where this constructor will not be called. + + this.image = image; + this.repeat = repeat; + + // Can be cloned + this.type = 'pattern'; + }; + + Pattern.prototype.getCanvasPattern = function (ctx) { + return ctx.createPattern(this.image, this.repeat || 'repeat'); + }; + + module.exports = Pattern; + + +/***/ }, +/* 47 */ +/***/ function(module, exports, __webpack_require__) { + + + + var CMD = __webpack_require__(36).CMD; + var vec2 = __webpack_require__(10); + var v2ApplyTransform = vec2.applyTransform; + + var points = [[], [], []]; + var mathSqrt = Math.sqrt; + var mathAtan2 = Math.atan2; + function transformPath(path, m) { + var data = path.data; + var cmd; + var nPoint; + var i; + var j; + var k; + var p; + + var M = CMD.M; + var C = CMD.C; + var L = CMD.L; + var R = CMD.R; + var A = CMD.A; + var Q = CMD.Q; + + for (i = 0, j = 0; i < data.length;) { + cmd = data[i++]; + j = i; + nPoint = 0; + + switch (cmd) { + case M: + nPoint = 1; + break; + case L: + nPoint = 1; + break; + case C: + nPoint = 3; + break; + case Q: + nPoint = 2; + break; + case A: + var x = m[4]; + var y = m[5]; + var sx = mathSqrt(m[0] * m[0] + m[1] * m[1]); + var sy = mathSqrt(m[2] * m[2] + m[3] * m[3]); + var angle = mathAtan2(-m[1] / sy, m[0] / sx); + // cx + data[i] *= sx; + data[i++] += x; + // cy + data[i] *= sy; + data[i++] += y; + // Scale rx and ry + // FIXME Assume psi is 0 here + data[i++] *= sx; + data[i++] *= sy; + + // Start angle + data[i++] += angle; + // end angle + data[i++] += angle; + // FIXME psi + i += 2; + j = i; + break; + case R: + // x0, y0 + p[0] = data[i++]; + p[1] = data[i++]; + v2ApplyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + // x1, y1 + p[0] += data[i++]; + p[1] += data[i++]; + v2ApplyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + } + + for (k = 0; k < nPoint; k++) { + var p = points[k]; + p[0] = data[i++]; + p[1] = data[i++]; + + v2ApplyTransform(p, p, m); + // Write back + data[j++] = p[0]; + data[j++] = p[1]; + } + } + } + + module.exports = transformPath; + + +/***/ }, +/* 48 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上 + * @module zrender/graphic/Group + * @example + * var Group = require('zrender/lib/container/Group'); + * var Circle = require('zrender/lib/graphic/shape/Circle'); + * var g = new Group(); + * g.position[0] = 100; + * g.position[1] = 100; + * g.add(new Circle({ + * style: { + * x: 100, + * y: 100, + * r: 20, + * } + * })); + * zr.add(g); + */ + + + var zrUtil = __webpack_require__(4); + var Element = __webpack_require__(23); + var BoundingRect = __webpack_require__(9); + + /** + * @alias module:zrender/graphic/Group + * @constructor + * @extends module:zrender/mixin/Transformable + * @extends module:zrender/mixin/Eventful + */ + var Group = function (opts) { + + opts = opts || {}; + + Element.call(this, opts); + + for (var key in opts) { + if (opts.hasOwnProperty(key)) { + this[key] = opts[key]; + } + } + + this._children = []; + + this.__storage = null; + + this.__dirty = true; + }; + + Group.prototype = { + + constructor: Group, + + isGroup: true, + + /** + * @type {string} + */ + type: 'group', + + /** + * 所有子孙元素是否响应鼠标事件 + * @name module:/zrender/container/Group#silent + * @type {boolean} + * @default false + */ + silent: false, + + /** + * @return {Array.} + */ + children: function () { + return this._children.slice(); + }, + + /** + * 获取指定 index 的儿子节点 + * @param {number} idx + * @return {module:zrender/Element} + */ + childAt: function (idx) { + return this._children[idx]; + }, + + /** + * 获取指定名字的儿子节点 + * @param {string} name + * @return {module:zrender/Element} + */ + childOfName: function (name) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + if (children[i].name === name) { + return children[i]; + } + } + }, + + /** + * @return {number} + */ + childCount: function () { + return this._children.length; + }, + + /** + * 添加子节点到最后 + * @param {module:zrender/Element} child + */ + add: function (child) { + if (child && child !== this && child.parent !== this) { + + this._children.push(child); + + this._doAdd(child); + } + + return this; + }, + + /** + * 添加子节点在 nextSibling 之前 + * @param {module:zrender/Element} child + * @param {module:zrender/Element} nextSibling + */ + addBefore: function (child, nextSibling) { + if (child && child !== this && child.parent !== this + && nextSibling && nextSibling.parent === this) { + + var children = this._children; + var idx = children.indexOf(nextSibling); + + if (idx >= 0) { + children.splice(idx, 0, child); + this._doAdd(child); + } + } + + return this; + }, + + _doAdd: function (child) { + if (child.parent) { + child.parent.remove(child); + } + + child.parent = this; + + var storage = this.__storage; + var zr = this.__zr; + if (storage && storage !== child.__storage) { + + storage.addToStorage(child); + + if (child instanceof Group) { + child.addChildrenToStorage(storage); + } + } + + zr && zr.refresh(); + }, + + /** + * 移除子节点 + * @param {module:zrender/Element} child + */ + remove: function (child) { + var zr = this.__zr; + var storage = this.__storage; + var children = this._children; + + var idx = zrUtil.indexOf(children, child); + if (idx < 0) { + return this; + } + children.splice(idx, 1); + + child.parent = null; + + if (storage) { + + storage.delFromStorage(child); + + if (child instanceof Group) { + child.delChildrenFromStorage(storage); + } + } + + zr && zr.refresh(); + + return this; + }, + + /** + * 移除所有子节点 + */ + removeAll: function () { + var children = this._children; + var storage = this.__storage; + var child; + var i; + for (i = 0; i < children.length; i++) { + child = children[i]; + if (storage) { + storage.delFromStorage(child); + if (child instanceof Group) { + child.delChildrenFromStorage(storage); + } + } + child.parent = null; + } + children.length = 0; + + return this; + }, + + /** + * 遍历所有子节点 + * @param {Function} cb + * @param {} context + */ + eachChild: function (cb, context) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + cb.call(context, child, i); + } + return this; + }, + + /** + * 深度优先遍历所有子孙节点 + * @param {Function} cb + * @param {} context + */ + traverse: function (cb, context) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + cb.call(context, child); + + if (child.type === 'group') { + child.traverse(cb, context); + } + } + return this; + }, + + addChildrenToStorage: function (storage) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + storage.addToStorage(child); + if (child instanceof Group) { + child.addChildrenToStorage(storage); + } + } + }, + + delChildrenFromStorage: function (storage) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + storage.delFromStorage(child); + if (child instanceof Group) { + child.delChildrenFromStorage(storage); + } + } + }, + + dirty: function () { + this.__dirty = true; + this.__zr && this.__zr.refresh(); + return this; + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getBoundingRect: function (includeChildren) { + // TODO Caching + var rect = null; + var tmpRect = new BoundingRect(0, 0, 0, 0); + var children = includeChildren || this._children; + var tmpMat = []; + + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child.ignore || child.invisible) { + continue; + } + + var childRect = child.getBoundingRect(); + var transform = child.getLocalTransform(tmpMat); + // TODO + // The boundingRect cacluated by transforming original + // rect may be bigger than the actual bundingRect when rotation + // is used. (Consider a circle rotated aginst its center, where + // the actual boundingRect should be the same as that not be + // rotated.) But we can not find better approach to calculate + // actual boundingRect yet, considering performance. + if (transform) { + tmpRect.copy(childRect); + tmpRect.applyTransform(transform); + rect = rect || tmpRect.clone(); + rect.union(tmpRect); + } + else { + rect = rect || childRect.clone(); + rect.union(childRect); + } + } + return rect || tmpRect; + } + }; + + zrUtil.inherits(Group, Element); + + module.exports = Group; + + +/***/ }, +/* 49 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Image element + * @module zrender/graphic/Image + */ + + + + var Displayable = __webpack_require__(21); + var BoundingRect = __webpack_require__(9); + var zrUtil = __webpack_require__(4); + + var LRU = __webpack_require__(32); + var globalImageCache = new LRU(50); + /** + * @alias zrender/graphic/Image + * @extends module:zrender/graphic/Displayable + * @constructor + * @param {Object} opts + */ + function ZImage(opts) { + Displayable.call(this, opts); + } + + ZImage.prototype = { + + constructor: ZImage, + + type: 'image', + + brush: function (ctx, prevEl) { + var style = this.style; + var src = style.image; + var image; + + // Must bind each time + style.bind(ctx, this, prevEl); + // style.image is a url string + if (typeof src === 'string') { + image = this._image; + } + // style.image is an HTMLImageElement or HTMLCanvasElement or Canvas + else { + image = src; + } + // FIXME Case create many images with src + if (!image && src) { + // Try get from global image cache + var cachedImgObj = globalImageCache.get(src); + if (!cachedImgObj) { + // Create a new image + image = new Image(); + image.onload = function () { + image.onload = null; + for (var i = 0; i < cachedImgObj.pending.length; i++) { + cachedImgObj.pending[i].dirty(); + } + }; + cachedImgObj = { + image: image, + pending: [this] + }; + image.src = src; + globalImageCache.put(src, cachedImgObj); + this._image = image; + return; + } + else { + image = cachedImgObj.image; + this._image = image; + // Image is not complete finish, add to pending list + if (!image.width || !image.height) { + cachedImgObj.pending.push(this); + return; + } + } + } + + if (image) { + // 图片已经加载完成 + // if (image.nodeName.toUpperCase() == 'IMG') { + // if (!image.complete) { + // return; + // } + // } + // Else is canvas + + var x = style.x || 0; + var y = style.y || 0; + // 图片加载失败 + if (!image.width || !image.height) { + return; + } + var width = style.width; + var height = style.height; + var aspect = image.width / image.height; + if (width == null && height != null) { + // Keep image/height ratio + width = height * aspect; + } + else if (height == null && width != null) { + height = width / aspect; + } + else if (width == null && height == null) { + width = image.width; + height = image.height; + } + + // 设置transform + this.setTransform(ctx); + + if (style.sWidth && style.sHeight) { + var sx = style.sx || 0; + var sy = style.sy || 0; + ctx.drawImage( + image, + sx, sy, style.sWidth, style.sHeight, + x, y, width, height + ); + } + else if (style.sx && style.sy) { + var sx = style.sx; + var sy = style.sy; + var sWidth = width - sx; + var sHeight = height - sy; + ctx.drawImage( + image, + sx, sy, sWidth, sHeight, + x, y, width, height + ); + } + else { + ctx.drawImage(image, x, y, width, height); + } + + this.restoreTransform(ctx); + + // Draw rect text + if (style.text != null) { + this.drawRectText(ctx, this.getBoundingRect()); + } + + } + }, + + getBoundingRect: function () { + var style = this.style; + if (! this._rect) { + this._rect = new BoundingRect( + style.x || 0, style.y || 0, style.width || 0, style.height || 0 + ); + } + return this._rect; + } + }; + + zrUtil.inherits(ZImage, Displayable); + + module.exports = ZImage; + + +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Text element + * @module zrender/graphic/Text + * + * TODO Wrapping + * + * Text not support gradient + */ + + + + var Displayable = __webpack_require__(21); + var zrUtil = __webpack_require__(4); + var textContain = __webpack_require__(8); + + /** + * @alias zrender/graphic/Text + * @extends module:zrender/graphic/Displayable + * @constructor + * @param {Object} opts + */ + var Text = function (opts) { + Displayable.call(this, opts); + }; + + Text.prototype = { + + constructor: Text, + + type: 'text', + + brush: function (ctx, prevEl) { + var style = this.style; + var x = style.x || 0; + var y = style.y || 0; + // Convert to string + var text = style.text; + + // Convert to string + text != null && (text += ''); + + // Always bind style + style.bind(ctx, this, prevEl); + + if (text) { + + this.setTransform(ctx); + + var textBaseline; + var textAlign = style.textAlign; + var font = style.textFont || style.font; + if (style.textVerticalAlign) { + var rect = textContain.getBoundingRect( + text, font, style.textAlign, 'top' + ); + // Ignore textBaseline + textBaseline = 'middle'; + switch (style.textVerticalAlign) { + case 'middle': + y -= rect.height / 2 - rect.lineHeight / 2; + break; + case 'bottom': + y -= rect.height - rect.lineHeight / 2; + break; + default: + y += rect.lineHeight / 2; + } + } + else { + textBaseline = style.textBaseline; + } + + // TODO Invalid font + ctx.font = font || '12px sans-serif'; + ctx.textAlign = textAlign || 'left'; + // Use canvas default left textAlign. Giving invalid value will cause state not change + if (ctx.textAlign !== textAlign) { + ctx.textAlign = 'left'; + } + // FIXME in text contain default is top + ctx.textBaseline = textBaseline || 'alphabetic'; + // Use canvas default alphabetic baseline + if (ctx.textBaseline !== textBaseline) { + ctx.textBaseline = 'alphabetic'; + } + + var lineHeight = textContain.measureText('国', ctx.font).width; + + var textLines = text.split('\n'); + for (var i = 0; i < textLines.length; i++) { + // Fill after stroke so the outline will not cover the main part. + style.hasStroke() && ctx.strokeText(textLines[i], x, y); + style.hasFill() && ctx.fillText(textLines[i], x, y); + y += lineHeight; + } + + this.restoreTransform(ctx); + } + }, + + getBoundingRect: function () { + var style = this.style; + if (!this._rect) { + var textVerticalAlign = style.textVerticalAlign; + var rect = textContain.getBoundingRect( + style.text + '', style.textFont || style.font, style.textAlign, + textVerticalAlign ? 'top' : style.textBaseline + ); + switch (textVerticalAlign) { + case 'middle': + rect.y -= rect.height / 2; + break; + case 'bottom': + rect.y -= rect.height; + break; + } + rect.x += style.x || 0; + rect.y += style.y || 0; + if (style.hasStroke()) { + var w = style.lineWidth; + rect.x -= w / 2; + rect.y -= w / 2; + rect.width += w; + rect.height += w; + } + this._rect = rect; + } + + return this._rect; + } + }; + + zrUtil.inherits(Text, Displayable); + + module.exports = Text; + + +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * 圆形 + * @module zrender/shape/Circle + */ + + + + module.exports = __webpack_require__(20).extend({ + + type: 'circle', + + shape: { + cx: 0, + cy: 0, + r: 0 + }, + + + buildPath : function (ctx, shape, inBundle) { + // Better stroking in ShapeBundle + // Always do it may have performence issue ( fill may be 2x more cost) + if (inBundle) { + ctx.moveTo(shape.cx + shape.r, shape.cy); + } + // else { + // if (ctx.allocate && !ctx.data.length) { + // ctx.allocate(ctx.CMD_MEM_SIZE.A); + // } + // } + // Better stroking in ShapeBundle + // ctx.moveTo(shape.cx + shape.r, shape.cy); + ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2, true); + } + }); + + + +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 扇形 + * @module zrender/graphic/shape/Sector + */ + + + + var env = __webpack_require__(2); + var Path = __webpack_require__(20); + + var shadowTemp = [ + ['shadowBlur', 0], + ['shadowColor', '#000'], + ['shadowOffsetX', 0], + ['shadowOffsetY', 0] + ]; + + module.exports = Path.extend({ + + type: 'sector', + + shape: { + + cx: 0, + + cy: 0, + + r0: 0, + + r: 0, + + startAngle: 0, + + endAngle: Math.PI * 2, + + clockwise: true + }, + + brush: (env.browser.ie && env.browser.version >= 11) // version: '11.0' + // Fix weird bug in some version of IE11 (like 11.0.9600.17801), + // where exception "unexpected call to method or property access" + // might be thrown when calling ctx.fill after a path whose area size + // is zero is drawn and ctx.clip() is called and shadowBlur is set. + // (e.g., + // ctx.moveTo(10, 10); + // ctx.lineTo(20, 10); + // ctx.closePath(); + // ctx.clip(); + // ctx.shadowBlur = 10; + // ... + // ctx.fill(); + // ) + ? function () { + var clipPaths = this.__clipPaths; + var style = this.style; + var modified; + + if (clipPaths) { + for (var i = 0; i < clipPaths.length; i++) { + var shape = clipPaths[i] && clipPaths[i].shape; + if (shape && shape.startAngle === shape.endAngle) { + for (var j = 0; j < shadowTemp.length; j++) { + shadowTemp[j][2] = style[shadowTemp[j][0]]; + style[shadowTemp[j][0]] = shadowTemp[j][1]; + } + modified = true; + break; + } + } + } + + Path.prototype.brush.apply(this, arguments); + + if (modified) { + for (var j = 0; j < shadowTemp.length; j++) { + style[shadowTemp[j][0]] = shadowTemp[j][2]; + } + } + } + : Path.prototype.brush, + + buildPath: function (ctx, shape) { + + var x = shape.cx; + var y = shape.cy; + var r0 = Math.max(shape.r0 || 0, 0); + var r = Math.max(shape.r, 0); + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + + var unitX = Math.cos(startAngle); + var unitY = Math.sin(startAngle); + + ctx.moveTo(unitX * r0 + x, unitY * r0 + y); + + ctx.lineTo(unitX * r + x, unitY * r + y); + + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + + ctx.lineTo( + Math.cos(endAngle) * r0 + x, + Math.sin(endAngle) * r0 + y + ); + + if (r0 !== 0) { + ctx.arc(x, y, r0, endAngle, startAngle, clockwise); + } + + ctx.closePath(); + } + }); + + + +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 圆环 + * @module zrender/graphic/shape/Ring + */ + + + module.exports = __webpack_require__(20).extend({ + + type: 'ring', + + shape: { + cx: 0, + cy: 0, + r: 0, + r0: 0 + }, + + buildPath: function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var PI2 = Math.PI * 2; + ctx.moveTo(x + shape.r, y); + ctx.arc(x, y, shape.r, 0, PI2, false); + ctx.moveTo(x + shape.r0, y); + ctx.arc(x, y, shape.r0, 0, PI2, true); + } + }); + + + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 多边形 + * @module zrender/shape/Polygon + */ + + + var polyHelper = __webpack_require__(55); + + module.exports = __webpack_require__(20).extend({ + + type: 'polygon', + + shape: { + points: null, + + smooth: false, + + smoothConstraint: null + }, + + buildPath: function (ctx, shape) { + polyHelper.buildPath(ctx, shape, true); + } + }); + + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + + + var smoothSpline = __webpack_require__(56); + var smoothBezier = __webpack_require__(57); + + module.exports = { + buildPath: function (ctx, shape, closePath) { + var points = shape.points; + var smooth = shape.smooth; + if (points && points.length >= 2) { + if (smooth && smooth !== 'spline') { + var controlPoints = smoothBezier( + points, smooth, closePath, shape.smoothConstraint + ); + + ctx.moveTo(points[0][0], points[0][1]); + var len = points.length; + for (var i = 0; i < (closePath ? len : len - 1); i++) { + var cp1 = controlPoints[i * 2]; + var cp2 = controlPoints[i * 2 + 1]; + var p = points[(i + 1) % len]; + ctx.bezierCurveTo( + cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1] + ); + } + } + else { + if (smooth === 'spline') { + points = smoothSpline(points, closePath); + } + + ctx.moveTo(points[0][0], points[0][1]); + for (var i = 1, l = points.length; i < l; i++) { + ctx.lineTo(points[i][0], points[i][1]); + } + } + + closePath && ctx.closePath(); + } + } + }; + + +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Catmull-Rom spline 插值折线 + * @module zrender/shape/util/smoothSpline + * @author pissang (https://www.github.com/pissang) + * Kener (@Kener-林峰, kener.linfeng@gmail.com) + * errorrik (errorrik@gmail.com) + */ + + var vec2 = __webpack_require__(10); + + /** + * @inner + */ + function interpolate(p0, p1, p2, p3, t, t2, t3) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + return (2 * (p1 - p2) + v0 + v1) * t3 + + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + + v0 * t + p1; + } + + /** + * @alias module:zrender/shape/util/smoothSpline + * @param {Array} points 线段顶点数组 + * @param {boolean} isLoop + * @return {Array} + */ + module.exports = function (points, isLoop) { + var len = points.length; + var ret = []; + + var distance = 0; + for (var i = 1; i < len; i++) { + distance += vec2.distance(points[i - 1], points[i]); + } + + var segs = distance / 2; + segs = segs < len ? len : segs; + for (var i = 0; i < segs; i++) { + var pos = i / (segs - 1) * (isLoop ? len : len - 1); + var idx = Math.floor(pos); + + var w = pos - idx; + + var p0; + var p1 = points[idx % len]; + var p2; + var p3; + if (!isLoop) { + p0 = points[idx === 0 ? idx : idx - 1]; + p2 = points[idx > len - 2 ? len - 1 : idx + 1]; + p3 = points[idx > len - 3 ? len - 1 : idx + 2]; + } + else { + p0 = points[(idx - 1 + len) % len]; + p2 = points[(idx + 1) % len]; + p3 = points[(idx + 2) % len]; + } + + var w2 = w * w; + var w3 = w * w2; + + ret.push([ + interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3), + interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3) + ]); + } + return ret; + }; + + + +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 贝塞尔平滑曲线 + * @module zrender/shape/util/smoothBezier + * @author pissang (https://www.github.com/pissang) + * Kener (@Kener-林峰, kener.linfeng@gmail.com) + * errorrik (errorrik@gmail.com) + */ + + + var vec2 = __webpack_require__(10); + var v2Min = vec2.min; + var v2Max = vec2.max; + var v2Scale = vec2.scale; + var v2Distance = vec2.distance; + var v2Add = vec2.add; + + /** + * 贝塞尔平滑曲线 + * @alias module:zrender/shape/util/smoothBezier + * @param {Array} points 线段顶点数组 + * @param {number} smooth 平滑等级, 0-1 + * @param {boolean} isLoop + * @param {Array} constraint 将计算出来的控制点约束在一个包围盒内 + * 比如 [[0, 0], [100, 100]], 这个包围盒会与 + * 整个折线的包围盒做一个并集用来约束控制点。 + * @param {Array} 计算出来的控制点数组 + */ + module.exports = function (points, smooth, isLoop, constraint) { + var cps = []; + + var v = []; + var v1 = []; + var v2 = []; + var prevPoint; + var nextPoint; + + var min, max; + if (constraint) { + min = [Infinity, Infinity]; + max = [-Infinity, -Infinity]; + for (var i = 0, len = points.length; i < len; i++) { + v2Min(min, min, points[i]); + v2Max(max, max, points[i]); + } + // 与指定的包围盒做并集 + v2Min(min, min, constraint[0]); + v2Max(max, max, constraint[1]); + } + + for (var i = 0, len = points.length; i < len; i++) { + var point = points[i]; + + if (isLoop) { + prevPoint = points[i ? i - 1 : len - 1]; + nextPoint = points[(i + 1) % len]; + } + else { + if (i === 0 || i === len - 1) { + cps.push(vec2.clone(points[i])); + continue; + } + else { + prevPoint = points[i - 1]; + nextPoint = points[i + 1]; + } + } + + vec2.sub(v, nextPoint, prevPoint); + + // use degree to scale the handle length + v2Scale(v, v, smooth); + + var d0 = v2Distance(point, prevPoint); + var d1 = v2Distance(point, nextPoint); + var sum = d0 + d1; + if (sum !== 0) { + d0 /= sum; + d1 /= sum; + } + + v2Scale(v1, v, -d0); + v2Scale(v2, v, d1); + var cp0 = v2Add([], point, v1); + var cp1 = v2Add([], point, v2); + if (constraint) { + v2Max(cp0, cp0, min); + v2Min(cp0, cp0, max); + v2Max(cp1, cp1, min); + v2Min(cp1, cp1, max); + } + cps.push(cp0); + cps.push(cp1); + } + + if (isLoop) { + cps.push(cps.shift()); + } + + return cps; + }; + + + +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module zrender/graphic/shape/Polyline + */ + + + var polyHelper = __webpack_require__(55); + + module.exports = __webpack_require__(20).extend({ + + type: 'polyline', + + shape: { + points: null, + + smooth: false, + + smoothConstraint: null + }, + + style: { + stroke: '#000', + + fill: null + }, + + buildPath: function (ctx, shape) { + polyHelper.buildPath(ctx, shape, false); + } + }); + + +/***/ }, +/* 59 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 矩形 + * @module zrender/graphic/shape/Rect + */ + + + var roundRectHelper = __webpack_require__(60); + + module.exports = __webpack_require__(20).extend({ + + type: 'rect', + + shape: { + // 左上、右上、右下、左下角的半径依次为r1、r2、r3、r4 + // r缩写为1 相当于 [1, 1, 1, 1] + // r缩写为[1] 相当于 [1, 1, 1, 1] + // r缩写为[1, 2] 相当于 [1, 2, 1, 2] + // r缩写为[1, 2, 3] 相当于 [1, 2, 3, 2] + r: 0, + + x: 0, + y: 0, + width: 0, + height: 0 + }, + + buildPath: function (ctx, shape) { + var x = shape.x; + var y = shape.y; + var width = shape.width; + var height = shape.height; + if (!shape.r) { + ctx.rect(x, y, width, height); + } + else { + roundRectHelper.buildPath(ctx, shape); + } + ctx.closePath(); + return; + } + }); + + + +/***/ }, +/* 60 */ +/***/ function(module, exports) { + + + + module.exports = { + buildPath: function (ctx, shape) { + var x = shape.x; + var y = shape.y; + var width = shape.width; + var height = shape.height; + var r = shape.r; + var r1; + var r2; + var r3; + var r4; + + // Convert width and height to positive for better borderRadius + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + + if (typeof r === 'number') { + r1 = r2 = r3 = r4 = r; + } + else if (r instanceof Array) { + if (r.length === 1) { + r1 = r2 = r3 = r4 = r[0]; + } + else if (r.length === 2) { + r1 = r3 = r[0]; + r2 = r4 = r[1]; + } + else if (r.length === 3) { + r1 = r[0]; + r2 = r4 = r[1]; + r3 = r[2]; + } + else { + r1 = r[0]; + r2 = r[1]; + r3 = r[2]; + r4 = r[3]; + } + } + else { + r1 = r2 = r3 = r4 = 0; + } + + var total; + if (r1 + r2 > width) { + total = r1 + r2; + r1 *= width / total; + r2 *= width / total; + } + if (r3 + r4 > width) { + total = r3 + r4; + r3 *= width / total; + r4 *= width / total; + } + if (r2 + r3 > height) { + total = r2 + r3; + r2 *= height / total; + r3 *= height / total; + } + if (r1 + r4 > height) { + total = r1 + r4; + r1 *= height / total; + r4 *= height / total; + } + ctx.moveTo(x + r1, y); + ctx.lineTo(x + width - r2, y); + r2 !== 0 && ctx.quadraticCurveTo( + x + width, y, x + width, y + r2 + ); + ctx.lineTo(x + width, y + height - r3); + r3 !== 0 && ctx.quadraticCurveTo( + x + width, y + height, x + width - r3, y + height + ); + ctx.lineTo(x + r4, y + height); + r4 !== 0 && ctx.quadraticCurveTo( + x, y + height, x, y + height - r4 + ); + ctx.lineTo(x, y + r1); + r1 !== 0 && ctx.quadraticCurveTo(x, y, x + r1, y); + } + }; + + +/***/ }, +/* 61 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 直线 + * @module zrender/graphic/shape/Line + */ + + module.exports = __webpack_require__(20).extend({ + + type: 'line', + + shape: { + // Start point + x1: 0, + y1: 0, + // End point + x2: 0, + y2: 0, + + percent: 1 + }, + + style: { + stroke: '#000', + fill: null + }, + + buildPath: function (ctx, shape) { + var x1 = shape.x1; + var y1 = shape.y1; + var x2 = shape.x2; + var y2 = shape.y2; + var percent = shape.percent; + + if (percent === 0) { + return; + } + + ctx.moveTo(x1, y1); + + if (percent < 1) { + x2 = x1 * (1 - percent) + x2 * percent; + y2 = y1 * (1 - percent) + y2 * percent; + } + ctx.lineTo(x2, y2); + }, + + /** + * Get point at percent + * @param {number} percent + * @return {Array.} + */ + pointAt: function (p) { + var shape = this.shape; + return [ + shape.x1 * (1 - p) + shape.x2 * p, + shape.y1 * (1 - p) + shape.y2 * p + ]; + } + }); + + + +/***/ }, +/* 62 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * 贝塞尔曲线 + * @module zrender/shape/BezierCurve + */ + + + var curveTool = __webpack_require__(37); + var vec2 = __webpack_require__(10); + var quadraticSubdivide = curveTool.quadraticSubdivide; + var cubicSubdivide = curveTool.cubicSubdivide; + var quadraticAt = curveTool.quadraticAt; + var cubicAt = curveTool.cubicAt; + var quadraticDerivativeAt = curveTool.quadraticDerivativeAt; + var cubicDerivativeAt = curveTool.cubicDerivativeAt; + + var out = []; + + function someVectorAt(shape, t, isTangent) { + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + if (cpx2 === null || cpy2 === null) { + return [ + (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t), + (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t) + ]; + } + else { + return [ + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t), + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t) + ]; + } + } + module.exports = __webpack_require__(20).extend({ + + type: 'bezier-curve', + + shape: { + x1: 0, + y1: 0, + x2: 0, + y2: 0, + cpx1: 0, + cpy1: 0, + // cpx2: 0, + // cpy2: 0 + + // Curve show percent, for animating + percent: 1 + }, + + style: { + stroke: '#000', + fill: null + }, + + buildPath: function (ctx, shape) { + var x1 = shape.x1; + var y1 = shape.y1; + var x2 = shape.x2; + var y2 = shape.y2; + var cpx1 = shape.cpx1; + var cpy1 = shape.cpy1; + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + var percent = shape.percent; + if (percent === 0) { + return; + } + + ctx.moveTo(x1, y1); + + if (cpx2 == null || cpy2 == null) { + if (percent < 1) { + quadraticSubdivide( + x1, cpx1, x2, percent, out + ); + cpx1 = out[1]; + x2 = out[2]; + quadraticSubdivide( + y1, cpy1, y2, percent, out + ); + cpy1 = out[1]; + y2 = out[2]; + } + + ctx.quadraticCurveTo( + cpx1, cpy1, + x2, y2 + ); + } + else { + if (percent < 1) { + cubicSubdivide( + x1, cpx1, cpx2, x2, percent, out + ); + cpx1 = out[1]; + cpx2 = out[2]; + x2 = out[3]; + cubicSubdivide( + y1, cpy1, cpy2, y2, percent, out + ); + cpy1 = out[1]; + cpy2 = out[2]; + y2 = out[3]; + } + ctx.bezierCurveTo( + cpx1, cpy1, + cpx2, cpy2, + x2, y2 + ); + } + }, + + /** + * Get point at percent + * @param {number} t + * @return {Array.} + */ + pointAt: function (t) { + return someVectorAt(this.shape, t, false); + }, + + /** + * Get tangent at percent + * @param {number} t + * @return {Array.} + */ + tangentAt: function (t) { + var p = someVectorAt(this.shape, t, true); + return vec2.normalize(p, p); + } + }); + + + +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * 圆弧 + * @module zrender/graphic/shape/Arc + */ + + + module.exports = __webpack_require__(20).extend({ + + type: 'arc', + + shape: { + + cx: 0, + + cy: 0, + + r: 0, + + startAngle: 0, + + endAngle: Math.PI * 2, + + clockwise: true + }, + + style: { + + stroke: '#000', + + fill: null + }, + + buildPath: function (ctx, shape) { + + var x = shape.cx; + var y = shape.cy; + var r = Math.max(shape.r, 0); + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + + var unitX = Math.cos(startAngle); + var unitY = Math.sin(startAngle); + + ctx.moveTo(unitX * r + x, unitY * r + y); + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + } + }); + + +/***/ }, +/* 64 */ +/***/ function(module, exports, __webpack_require__) { + + // CompoundPath to improve performance + + + var Path = __webpack_require__(20); + + module.exports = Path.extend({ + + type: 'compound', + + shape: { + + paths: null + }, + + _updatePathDirty: function () { + var dirtyPath = this.__dirtyPath; + var paths = this.shape.paths; + for (var i = 0; i < paths.length; i++) { + // Mark as dirty if any subpath is dirty + dirtyPath = dirtyPath || paths[i].__dirtyPath; + } + this.__dirtyPath = dirtyPath; + this.__dirty = this.__dirty || dirtyPath; + }, + + beforeBrush: function () { + this._updatePathDirty(); + var paths = this.shape.paths || []; + var scale = this.getGlobalScale(); + // Update path scale + for (var i = 0; i < paths.length; i++) { + if (!paths[i].path) { + paths[i].createPathProxy(); + } + paths[i].path.setScale(scale[0], scale[1]); + } + }, + + buildPath: function (ctx, shape) { + var paths = shape.paths || []; + for (var i = 0; i < paths.length; i++) { + paths[i].buildPath(ctx, paths[i].shape, true); + } + }, + + afterBrush: function () { + var paths = this.shape.paths; + for (var i = 0; i < paths.length; i++) { + paths[i].__dirtyPath = false; + } + }, + + getBoundingRect: function () { + this._updatePathDirty(); + return Path.prototype.getBoundingRect.call(this); + } + }); + + +/***/ }, +/* 65 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + + var Gradient = __webpack_require__(66); + + /** + * x, y, x2, y2 are all percent from 0 to 1 + * @param {number} [x=0] + * @param {number} [y=0] + * @param {number} [x2=1] + * @param {number} [y2=0] + * @param {Array.} colorStops + * @param {boolean} [globalCoord=false] + */ + var LinearGradient = function (x, y, x2, y2, colorStops, globalCoord) { + // Should do nothing more in this constructor. Because gradient can be + // declard by `color: {type: 'linear', colorStops: ...}`, where + // this constructor will not be called. + + this.x = x == null ? 0 : x; + + this.y = y == null ? 0 : y; + + this.x2 = x2 == null ? 1 : x2; + + this.y2 = y2 == null ? 0 : y2; + + // Can be cloned + this.type = 'linear'; + + // If use global coord + this.global = globalCoord || false; + + Gradient.call(this, colorStops); + }; + + LinearGradient.prototype = { + + constructor: LinearGradient + }; + + zrUtil.inherits(LinearGradient, Gradient); + + module.exports = LinearGradient; + + +/***/ }, +/* 66 */ +/***/ function(module, exports) { + + + + /** + * @param {Array.} colorStops + */ + var Gradient = function (colorStops) { + + this.colorStops = colorStops || []; + }; + + Gradient.prototype = { + + constructor: Gradient, + + addColorStop: function (offset, color) { + this.colorStops.push({ + + offset: offset, + + color: color + }); + } + }; + + module.exports = Gradient; + + +/***/ }, +/* 67 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + + var Gradient = __webpack_require__(66); + + /** + * x, y, r are all percent from 0 to 1 + * @param {number} [x=0.5] + * @param {number} [y=0.5] + * @param {number} [r=0.5] + * @param {Array.} [colorStops] + * @param {boolean} [globalCoord=false] + */ + var RadialGradient = function (x, y, r, colorStops, globalCoord) { + // Should do nothing more in this constructor. Because gradient can be + // declard by `color: {type: 'radial', colorStops: ...}`, where + // this constructor will not be called. + + this.x = x == null ? 0.5 : x; + + this.y = y == null ? 0.5 : y; + + this.r = r == null ? 0.5 : r; + + // Can be cloned + this.type = 'radial'; + + // If use global coord + this.global = globalCoord || false; + + Gradient.call(this, colorStops); + }; + + RadialGradient.prototype = { + + constructor: RadialGradient + }; + + zrUtil.inherits(RadialGradient, Gradient); + + module.exports = RadialGradient; + + +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { + + + var getItemStyle = __webpack_require__(15)( + [ + ['fill', 'color'], + ['stroke', 'borderColor'], + ['lineWidth', 'borderWidth'], + ['opacity'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['shadowColor'], + ['textPosition'], + ['textAlign'] + ] + ); + module.exports = { + getItemStyle: function (excludes, includes) { + var style = getItemStyle.call(this, excludes, includes); + var lineDash = this.getBorderLineDash(); + lineDash && (style.lineDash = lineDash); + return style; + }, + + getBorderLineDash: function () { + var lineType = this.get('borderType'); + return (lineType === 'solid' || lineType == null) ? null + : (lineType === 'dashed' ? [5, 5] : [1, 1]); + } + }; + + +/***/ }, +/* 69 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Component model + * + * @module echarts/model/Component + */ + + + var Model = __webpack_require__(12); + var zrUtil = __webpack_require__(4); + var arrayPush = Array.prototype.push; + var componentUtil = __webpack_require__(70); + var clazzUtil = __webpack_require__(13); + var layout = __webpack_require__(71); + + /** + * @alias module:echarts/model/Component + * @constructor + * @param {Object} option + * @param {module:echarts/model/Model} parentModel + * @param {module:echarts/model/Model} ecModel + */ + var ComponentModel = Model.extend({ + + type: 'component', + + /** + * @readOnly + * @type {string} + */ + id: '', + + /** + * @readOnly + */ + name: '', + + /** + * @readOnly + * @type {string} + */ + mainType: '', + + /** + * @readOnly + * @type {string} + */ + subType: '', + + /** + * @readOnly + * @type {number} + */ + componentIndex: 0, + + /** + * @type {Object} + * @protected + */ + defaultOption: null, + + /** + * @type {module:echarts/model/Global} + * @readOnly + */ + ecModel: null, + + /** + * key: componentType + * value: Component model list, can not be null. + * @type {Object.>} + * @readOnly + */ + dependentModels: [], + + /** + * @type {string} + * @readOnly + */ + uid: null, + + /** + * Support merge layout params. + * Only support 'box' now (left/right/top/bottom/width/height). + * @type {string|Object} Object can be {ignoreSize: true} + * @readOnly + */ + layoutMode: null, + + $constructor: function (option, parentModel, ecModel, extraOpt) { + Model.call(this, option, parentModel, ecModel, extraOpt); + + this.uid = componentUtil.getUID('componentModel'); + }, + + + init: function (option, parentModel, ecModel, extraOpt) { + this.mergeDefaultAndTheme(option, ecModel); + }, + + mergeDefaultAndTheme: function (option, ecModel) { + var layoutMode = this.layoutMode; + var inputPositionParams = layoutMode + ? layout.getLayoutParams(option) : {}; + + var themeModel = ecModel.getTheme(); + zrUtil.merge(option, themeModel.get(this.mainType)); + zrUtil.merge(option, this.getDefaultOption()); + + if (layoutMode) { + layout.mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }, + + mergeOption: function (option, extraOpt) { + zrUtil.merge(this.option, option, true); + + var layoutMode = this.layoutMode; + if (layoutMode) { + layout.mergeLayoutParam(this.option, option, layoutMode); + } + }, + + // Hooker after init or mergeOption + optionUpdated: function (newCptOption, isInit) {}, + + getDefaultOption: function () { + if (!clazzUtil.hasOwn(this, '__defaultOption')) { + var optList = []; + var Class = this.constructor; + while (Class) { + var opt = Class.prototype.defaultOption; + opt && optList.push(opt); + Class = Class.superClass; + } + + var defaultOption = {}; + for (var i = optList.length - 1; i >= 0; i--) { + defaultOption = zrUtil.merge(defaultOption, optList[i], true); + } + clazzUtil.set(this, '__defaultOption', defaultOption); + } + return clazzUtil.get(this, '__defaultOption'); + }, + + getReferringComponents: function (mainType) { + return this.ecModel.queryComponents({ + mainType: mainType, + index: this.get(mainType + 'Index', true), + id: this.get(mainType + 'Id', true) + }); + } + + }); + + // Reset ComponentModel.extend, add preConstruct. + // clazzUtil.enableClassExtend( + // ComponentModel, + // function (option, parentModel, ecModel, extraOpt) { + // // Set dependentModels, componentIndex, name, id, mainType, subType. + // zrUtil.extend(this, extraOpt); + + // this.uid = componentUtil.getUID('componentModel'); + + // // this.setReadOnly([ + // // 'type', 'id', 'uid', 'name', 'mainType', 'subType', + // // 'dependentModels', 'componentIndex' + // // ]); + // } + // ); + + // Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on. + clazzUtil.enableClassManagement( + ComponentModel, {registerWhenExtend: true} + ); + componentUtil.enableSubTypeDefaulter(ComponentModel); + + // Add capability of ComponentModel.topologicalTravel. + componentUtil.enableTopologicalTravel(ComponentModel, getDependencies); + + function getDependencies(componentType) { + var deps = []; + zrUtil.each(ComponentModel.getClassesByMainType(componentType), function (Clazz) { + arrayPush.apply(deps, Clazz.prototype.dependencies || []); + }); + // Ensure main type + return zrUtil.map(deps, function (type) { + return clazzUtil.parseClassType(type).main; + }); + } + + zrUtil.mixin(ComponentModel, __webpack_require__(72)); + + module.exports = ComponentModel; + + +/***/ }, +/* 70 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var clazz = __webpack_require__(13); + + var parseClassType = clazz.parseClassType; + + var base = 0; + + var componentUtil = {}; + + var DELIMITER = '_'; + + /** + * @public + * @param {string} type + * @return {string} + */ + componentUtil.getUID = function (type) { + // Considering the case of crossing js context, + // use Math.random to make id as unique as possible. + return [(type || ''), base++, Math.random()].join(DELIMITER); + }; + + /** + * @inner + */ + componentUtil.enableSubTypeDefaulter = function (entity) { + + var subTypeDefaulters = {}; + + entity.registerSubTypeDefaulter = function (componentType, defaulter) { + componentType = parseClassType(componentType); + subTypeDefaulters[componentType.main] = defaulter; + }; + + entity.determineSubType = function (componentType, option) { + var type = option.type; + if (!type) { + var componentTypeMain = parseClassType(componentType).main; + if (entity.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) { + type = subTypeDefaulters[componentTypeMain](option); + } + } + return type; + }; + + return entity; + }; + + /** + * Topological travel on Activity Network (Activity On Vertices). + * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis']. + * + * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology. + * + * If there is circle dependencey, Error will be thrown. + * + */ + componentUtil.enableTopologicalTravel = function (entity, dependencyGetter) { + + /** + * @public + * @param {Array.} targetNameList Target Component type list. + * Can be ['aa', 'bb', 'aa.xx'] + * @param {Array.} fullNameList By which we can build dependency graph. + * @param {Function} callback Params: componentType, dependencies. + * @param {Object} context Scope of callback. + */ + entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) { + if (!targetNameList.length) { + return; + } + + var result = makeDepndencyGraph(fullNameList); + var graph = result.graph; + var stack = result.noEntryList; + + var targetNameSet = {}; + zrUtil.each(targetNameList, function (name) { + targetNameSet[name] = true; + }); + + while (stack.length) { + var currComponentType = stack.pop(); + var currVertex = graph[currComponentType]; + var isInTargetNameSet = !!targetNameSet[currComponentType]; + if (isInTargetNameSet) { + callback.call(context, currComponentType, currVertex.originalDeps.slice()); + delete targetNameSet[currComponentType]; + } + zrUtil.each( + currVertex.successor, + isInTargetNameSet ? removeEdgeAndAdd : removeEdge + ); + } + + zrUtil.each(targetNameSet, function () { + throw new Error('Circle dependency may exists'); + }); + + function removeEdge(succComponentType) { + graph[succComponentType].entryCount--; + if (graph[succComponentType].entryCount === 0) { + stack.push(succComponentType); + } + } + + // Consider this case: legend depends on series, and we call + // chart.setOption({series: [...]}), where only series is in option. + // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will + // not be called, but only sereis.mergeOption is called. Thus legend + // have no chance to update its local record about series (like which + // name of series is available in legend). + function removeEdgeAndAdd(succComponentType) { + targetNameSet[succComponentType] = true; + removeEdge(succComponentType); + } + }; + + /** + * DepndencyGraph: {Object} + * key: conponentType, + * value: { + * successor: [conponentTypes...], + * originalDeps: [conponentTypes...], + * entryCount: {number} + * } + */ + function makeDepndencyGraph(fullNameList) { + var graph = {}; + var noEntryList = []; + + zrUtil.each(fullNameList, function (name) { + + var thisItem = createDependencyGraphItem(graph, name); + var originalDeps = thisItem.originalDeps = dependencyGetter(name); + + var availableDeps = getAvailableDependencies(originalDeps, fullNameList); + thisItem.entryCount = availableDeps.length; + if (thisItem.entryCount === 0) { + noEntryList.push(name); + } + + zrUtil.each(availableDeps, function (dependentName) { + if (zrUtil.indexOf(thisItem.predecessor, dependentName) < 0) { + thisItem.predecessor.push(dependentName); + } + var thatItem = createDependencyGraphItem(graph, dependentName); + if (zrUtil.indexOf(thatItem.successor, dependentName) < 0) { + thatItem.successor.push(name); + } + }); + }); + + return {graph: graph, noEntryList: noEntryList}; + } + + function createDependencyGraphItem(graph, name) { + if (!graph[name]) { + graph[name] = {predecessor: [], successor: []}; + } + return graph[name]; + } + + function getAvailableDependencies(originalDeps, fullNameList) { + var availableDeps = []; + zrUtil.each(originalDeps, function (dep) { + zrUtil.indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep); + }); + return availableDeps; + } + }; + + module.exports = componentUtil; + + +/***/ }, +/* 71 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + // Layout helpers for each component positioning + + + var zrUtil = __webpack_require__(4); + var BoundingRect = __webpack_require__(9); + var numberUtil = __webpack_require__(7); + var formatUtil = __webpack_require__(6); + var parsePercent = numberUtil.parsePercent; + var each = zrUtil.each; + + var layout = {}; + + /** + * @public + */ + var LOCATION_PARAMS = layout.LOCATION_PARAMS = [ + 'left', 'right', 'top', 'bottom', 'width', 'height' + ]; + + /** + * @public + */ + var HV_NAMES = layout.HV_NAMES = [ + ['width', 'left', 'right'], + ['height', 'top', 'bottom'] + ]; + + function boxLayout(orient, group, gap, maxWidth, maxHeight) { + var x = 0; + var y = 0; + if (maxWidth == null) { + maxWidth = Infinity; + } + if (maxHeight == null) { + maxHeight = Infinity; + } + var currentLineMaxSize = 0; + group.eachChild(function (child, idx) { + var position = child.position; + var rect = child.getBoundingRect(); + var nextChild = group.childAt(idx + 1); + var nextChildRect = nextChild && nextChild.getBoundingRect(); + var nextX; + var nextY; + if (orient === 'horizontal') { + var moveX = rect.width + (nextChildRect ? (-nextChildRect.x + rect.x) : 0); + nextX = x + moveX; + // Wrap when width exceeds maxWidth or meet a `newline` group + if (nextX > maxWidth || child.newline) { + x = 0; + nextX = moveX; + y += currentLineMaxSize + gap; + currentLineMaxSize = rect.height; + } + else { + currentLineMaxSize = Math.max(currentLineMaxSize, rect.height); + } + } + else { + var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0); + nextY = y + moveY; + // Wrap when width exceeds maxHeight or meet a `newline` group + if (nextY > maxHeight || child.newline) { + x += currentLineMaxSize + gap; + y = 0; + nextY = moveY; + currentLineMaxSize = rect.width; + } + else { + currentLineMaxSize = Math.max(currentLineMaxSize, rect.width); + } + } + + if (child.newline) { + return; + } + + position[0] = x; + position[1] = y; + + orient === 'horizontal' + ? (x = nextX + gap) + : (y = nextY + gap); + }); + } + + /** + * VBox or HBox layouting + * @param {string} orient + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + layout.box = boxLayout; + + /** + * VBox layouting + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + layout.vbox = zrUtil.curry(boxLayout, 'vertical'); + + /** + * HBox layouting + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + layout.hbox = zrUtil.curry(boxLayout, 'horizontal'); + + /** + * If x or x2 is not specified or 'center' 'left' 'right', + * the width would be as long as possible. + * If y or y2 is not specified or 'middle' 'top' 'bottom', + * the height would be as long as possible. + * + * @param {Object} positionInfo + * @param {number|string} [positionInfo.x] + * @param {number|string} [positionInfo.y] + * @param {number|string} [positionInfo.x2] + * @param {number|string} [positionInfo.y2] + * @param {Object} containerRect + * @param {string|number} margin + * @return {Object} {width, height} + */ + layout.getAvailableSize = function (positionInfo, containerRect, margin) { + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + + var x = parsePercent(positionInfo.x, containerWidth); + var y = parsePercent(positionInfo.y, containerHeight); + var x2 = parsePercent(positionInfo.x2, containerWidth); + var y2 = parsePercent(positionInfo.y2, containerHeight); + + (isNaN(x) || isNaN(parseFloat(positionInfo.x))) && (x = 0); + (isNaN(x2) || isNaN(parseFloat(positionInfo.x2))) && (x2 = containerWidth); + (isNaN(y) || isNaN(parseFloat(positionInfo.y))) && (y = 0); + (isNaN(y2) || isNaN(parseFloat(positionInfo.y2))) && (y2 = containerHeight); + + margin = formatUtil.normalizeCssArray(margin || 0); + + return { + width: Math.max(x2 - x - margin[1] - margin[3], 0), + height: Math.max(y2 - y - margin[0] - margin[2], 0) + }; + }; + + /** + * Parse position info. + * + * @param {Object} positionInfo + * @param {number|string} [positionInfo.left] + * @param {number|string} [positionInfo.top] + * @param {number|string} [positionInfo.right] + * @param {number|string} [positionInfo.bottom] + * @param {number|string} [positionInfo.width] + * @param {number|string} [positionInfo.height] + * @param {number|string} [positionInfo.aspect] Aspect is width / height + * @param {Object} containerRect + * @param {string|number} [margin] + * + * @return {module:zrender/core/BoundingRect} + */ + layout.getLayoutRect = function ( + positionInfo, containerRect, margin + ) { + margin = formatUtil.normalizeCssArray(margin || 0); + + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + + var left = parsePercent(positionInfo.left, containerWidth); + var top = parsePercent(positionInfo.top, containerHeight); + var right = parsePercent(positionInfo.right, containerWidth); + var bottom = parsePercent(positionInfo.bottom, containerHeight); + var width = parsePercent(positionInfo.width, containerWidth); + var height = parsePercent(positionInfo.height, containerHeight); + + var verticalMargin = margin[2] + margin[0]; + var horizontalMargin = margin[1] + margin[3]; + var aspect = positionInfo.aspect; + + // If width is not specified, calculate width from left and right + if (isNaN(width)) { + width = containerWidth - right - horizontalMargin - left; + } + if (isNaN(height)) { + height = containerHeight - bottom - verticalMargin - top; + } + + // If width and height are not given + // 1. Graph should not exceeds the container + // 2. Aspect must be keeped + // 3. Graph should take the space as more as possible + if (isNaN(width) && isNaN(height)) { + if (aspect > containerWidth / containerHeight) { + width = containerWidth * 0.8; + } + else { + height = containerHeight * 0.8; + } + } + + if (aspect != null) { + // Calculate width or height with given aspect + if (isNaN(width)) { + width = aspect * height; + } + if (isNaN(height)) { + height = width / aspect; + } + } + + // If left is not specified, calculate left from right and width + if (isNaN(left)) { + left = containerWidth - right - width - horizontalMargin; + } + if (isNaN(top)) { + top = containerHeight - bottom - height - verticalMargin; + } + + // Align left and top + switch (positionInfo.left || positionInfo.right) { + case 'center': + left = containerWidth / 2 - width / 2 - margin[3]; + break; + case 'right': + left = containerWidth - width - horizontalMargin; + break; + } + switch (positionInfo.top || positionInfo.bottom) { + case 'middle': + case 'center': + top = containerHeight / 2 - height / 2 - margin[0]; + break; + case 'bottom': + top = containerHeight - height - verticalMargin; + break; + } + // If something is wrong and left, top, width, height are calculated as NaN + left = left || 0; + top = top || 0; + if (isNaN(width)) { + // Width may be NaN if only one value is given except width + width = containerWidth - left - (right || 0); + } + if (isNaN(height)) { + // Height may be NaN if only one value is given except height + height = containerHeight - top - (bottom || 0); + } + + var rect = new BoundingRect(left + margin[3], top + margin[0], width, height); + rect.margin = margin; + return rect; + }; + + + /** + * Position a zr element in viewport + * Group position is specified by either + * {left, top}, {right, bottom} + * If all properties exists, right and bottom will be igonred. + * + * Logic: + * 1. Scale (against origin point in parent coord) + * 2. Rotate (against origin point in parent coord) + * 3. Traslate (with el.position by this method) + * So this method only fixes the last step 'Traslate', which does not affect + * scaling and rotating. + * + * If be called repeatly with the same input el, the same result will be gotten. + * + * @param {module:zrender/Element} el Should have `getBoundingRect` method. + * @param {Object} positionInfo + * @param {number|string} [positionInfo.left] + * @param {number|string} [positionInfo.top] + * @param {number|string} [positionInfo.right] + * @param {number|string} [positionInfo.bottom] + * @param {Object} containerRect + * @param {string|number} margin + * @param {Object} [opt] + * @param {Array.} [opt.hv=[1,1]] Only horizontal or only vertical. + * @param {Array.} [opt.boundingMode='all'] + * Specify how to calculate boundingRect when locating. + * 'all': Position the boundingRect that is transformed and uioned + * both itself and its descendants. + * This mode simplies confine the elements in the bounding + * of their container (e.g., using 'right: 0'). + * 'raw': Position the boundingRect that is not transformed and only itself. + * This mode is useful when you want a element can overflow its + * container. (Consider a rotated circle needs to be located in a corner.) + * In this mode positionInfo.width/height can only be number. + */ + layout.positionElement = function (el, positionInfo, containerRect, margin, opt) { + var h = !opt || !opt.hv || opt.hv[0]; + var v = !opt || !opt.hv || opt.hv[1]; + var boundingMode = opt && opt.boundingMode || 'all'; + + if (!h && !v) { + return; + } + + var rect; + if (boundingMode === 'raw') { + rect = el.type === 'group' + ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0) + : el.getBoundingRect(); + } + else { + rect = el.getBoundingRect(); + if (el.needLocalTransform()) { + var transform = el.getLocalTransform(); + // Notice: raw rect may be inner object of el, + // which should not be modified. + rect = rect.clone(); + rect.applyTransform(transform); + } + } + + positionInfo = layout.getLayoutRect( + zrUtil.defaults( + {width: rect.width, height: rect.height}, + positionInfo + ), + containerRect, + margin + ); + + // Because 'tranlate' is the last step in transform + // (see zrender/core/Transformable#getLocalTransfrom), + // we can just only modify el.position to get final result. + var elPos = el.position; + var dx = h ? positionInfo.x - rect.x : 0; + var dy = v ? positionInfo.y - rect.y : 0; + + el.attr('position', boundingMode === 'raw' ? [dx, dy] : [elPos[0] + dx, elPos[1] + dy]); + }; + + /** + * @param {Object} option Contains some of the properties in HV_NAMES. + * @param {number} hvIdx 0: horizontal; 1: vertical. + */ + layout.sizeCalculable = function (option, hvIdx) { + return option[HV_NAMES[hvIdx][0]] != null + || (option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null); + }; + + /** + * Consider Case: + * When defulat option has {left: 0, width: 100}, and we set {right: 0} + * through setOption or media query, using normal zrUtil.merge will cause + * {right: 0} does not take effect. + * + * @example + * ComponentModel.extend({ + * init: function () { + * ... + * var inputPositionParams = layout.getLayoutParams(option); + * this.mergeOption(inputPositionParams); + * }, + * mergeOption: function (newOption) { + * newOption && zrUtil.merge(thisOption, newOption, true); + * layout.mergeLayoutParam(thisOption, newOption); + * } + * }); + * + * @param {Object} targetOption + * @param {Object} newOption + * @param {Object|string} [opt] + * @param {boolean|Array.} [opt.ignoreSize=false] Some component must has width and height. + */ + layout.mergeLayoutParam = function (targetOption, newOption, opt) { + !zrUtil.isObject(opt) && (opt = {}); + + var ignoreSize = opt.ignoreSize; + !zrUtil.isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]); + + var hResult = merge(HV_NAMES[0], 0); + var vResult = merge(HV_NAMES[1], 1); + + copy(HV_NAMES[0], targetOption, hResult); + copy(HV_NAMES[1], targetOption, vResult); + + function merge(names, hvIdx) { + var newParams = {}; + var newValueCount = 0; + var merged = {}; + var mergedValueCount = 0; + var enoughParamNumber = 2; + + each(names, function (name) { + merged[name] = targetOption[name]; + }); + each(names, function (name) { + // Consider case: newOption.width is null, which is + // set by user for removing width setting. + hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]); + hasValue(newParams, name) && newValueCount++; + hasValue(merged, name) && mergedValueCount++; + }); + + if (ignoreSize[hvIdx]) { + // Only one of left/right is premitted to exist. + if (hasValue(newOption, names[1])) { + merged[names[2]] = null; + } + else if (hasValue(newOption, names[2])) { + merged[names[1]] = null; + } + return merged; + } + + // Case: newOption: {width: ..., right: ...}, + // or targetOption: {right: ...} and newOption: {width: ...}, + // There is no conflict when merged only has params count + // little than enoughParamNumber. + if (mergedValueCount === enoughParamNumber || !newValueCount) { + return merged; + } + // Case: newOption: {width: ..., right: ...}, + // Than we can make sure user only want those two, and ignore + // all origin params in targetOption. + else if (newValueCount >= enoughParamNumber) { + return newParams; + } + else { + // Chose another param from targetOption by priority. + for (var i = 0; i < names.length; i++) { + var name = names[i]; + if (!hasProp(newParams, name) && hasProp(targetOption, name)) { + newParams[name] = targetOption[name]; + break; + } + } + return newParams; + } + } + + function hasProp(obj, name) { + return obj.hasOwnProperty(name); + } + + function hasValue(obj, name) { + return obj[name] != null && obj[name] !== 'auto'; + } + + function copy(names, target, source) { + each(names, function (name) { + target[name] = source[name]; + }); + } + }; + + /** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + * @param {Object} source + * @return {Object} Result contains those props. + */ + layout.getLayoutParams = function (source) { + return layout.copyLayoutParams({}, source); + }; + + /** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + * @param {Object} source + * @return {Object} Result contains those props. + */ + layout.copyLayoutParams = function (target, source) { + source && target && each(LOCATION_PARAMS, function (name) { + source.hasOwnProperty(name) && (target[name] = source[name]); + }); + return target; + }; + + module.exports = layout; + + + +/***/ }, +/* 72 */ +/***/ function(module, exports) { + + + + module.exports = { + getBoxLayoutParams: function () { + return { + left: this.get('left'), + top: this.get('top'), + right: this.get('right'), + bottom: this.get('bottom'), + width: this.get('width'), + height: this.get('height') + }; + } + }; + + +/***/ }, +/* 73 */ +/***/ function(module, exports) { + + + var platform = ''; + // Navigator not exists in node + if (typeof navigator !== 'undefined') { + platform = navigator.platform || ''; + } + module.exports = { + // 全图默认背景 + // backgroundColor: 'rgba(0,0,0,0)', + + // https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization + // color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'], + // 浅色 + // color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'], + // color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'], + // 深色 + color: ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3'], + + // 默认需要 Grid 配置项 + // grid: {}, + // 主题,主题 + textStyle: { + // color: '#000', + // decoration: 'none', + // PENDING + fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif', + // fontFamily: 'Arial, Verdana, sans-serif', + fontSize: 12, + fontStyle: 'normal', + fontWeight: 'normal' + }, + + // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/ + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation + // Default is source-over + blendMode: null, + + animation: 'auto', + animationDuration: 1000, + animationDurationUpdate: 300, + animationEasing: 'exponentialOut', + animationEasingUpdate: 'cubicOut', + + animationThreshold: 2000, + // Configuration for progressive/incremental rendering + progressiveThreshold: 3000, + progressive: 400, + + // Threshold of if use single hover layer to optimize. + // It is recommended that `hoverLayerThreshold` is equivalent to or less than + // `progressiveThreshold`, otherwise hover will cause restart of progressive, + // which is unexpected. + // see example . + hoverLayerThreshold: 3000, + + // See: module:echarts/scale/Time + useUTC: false + }; + + +/***/ }, +/* 74 */ +/***/ function(module, exports, __webpack_require__) { + + + + var classUtil = __webpack_require__(13); + var set = classUtil.set; + var get = classUtil.get; + + module.exports = { + clearColorPalette: function () { + set(this, 'colorIdx', 0); + set(this, 'colorNameMap', {}); + }, + + getColorFromPalette: function (name, scope) { + scope = scope || this; + var colorIdx = get(scope, 'colorIdx') || 0; + var colorNameMap = get(scope, 'colorNameMap') || set(scope, 'colorNameMap', {}); + // Use `hasOwnProperty` to avoid conflict with Object.prototype. + if (colorNameMap.hasOwnProperty(name)) { + return colorNameMap[name]; + } + var colorPalette = this.get('color', true) || []; + if (!colorPalette.length) { + return; + } + + var color = colorPalette[colorIdx]; + if (name) { + colorNameMap[name] = color; + } + set(scope, 'colorIdx', (colorIdx + 1) % colorPalette.length); + + return color; + } + }; + + +/***/ }, +/* 75 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + + var echartsAPIList = [ + 'getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed', + 'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getModel', 'getOption', + 'getViewOfComponentModel', 'getViewOfSeriesModel' + ]; + // And `getCoordinateSystems` and `getComponentByElement` will be injected in echarts.js + + function ExtensionAPI(chartInstance) { + zrUtil.each(echartsAPIList, function (name) { + this[name] = zrUtil.bind(chartInstance[name], chartInstance); + }, this); + } + + module.exports = ExtensionAPI; + + +/***/ }, +/* 76 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + + var coordinateSystemCreators = {}; + + function CoordinateSystemManager() { + + this._coordinateSystems = []; + } + + CoordinateSystemManager.prototype = { + + constructor: CoordinateSystemManager, + + create: function (ecModel, api) { + var coordinateSystems = []; + zrUtil.each(coordinateSystemCreators, function (creater, type) { + var list = creater.create(ecModel, api); + coordinateSystems = coordinateSystems.concat(list || []); + }); + + this._coordinateSystems = coordinateSystems; + }, + + update: function (ecModel, api) { + zrUtil.each(this._coordinateSystems, function (coordSys) { + // FIXME MUST have + coordSys.update && coordSys.update(ecModel, api); + }); + }, + + getCoordinateSystems: function () { + return this._coordinateSystems.slice(); + } + }; + + CoordinateSystemManager.register = function (type, coordinateSystemCreator) { + coordinateSystemCreators[type] = coordinateSystemCreator; + }; + + CoordinateSystemManager.get = function (type) { + return coordinateSystemCreators[type]; + }; + + module.exports = CoordinateSystemManager; + + +/***/ }, +/* 77 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * ECharts option manager + * + * @module {echarts/model/OptionManager} + */ + + + + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var ComponentModel = __webpack_require__(69); + var each = zrUtil.each; + var clone = zrUtil.clone; + var map = zrUtil.map; + var merge = zrUtil.merge; + + var QUERY_REG = /^(min|max)?(.+)$/; + + /** + * TERM EXPLANATIONS: + * + * [option]: + * + * An object that contains definitions of components. For example: + * var option = { + * title: {...}, + * legend: {...}, + * visualMap: {...}, + * series: [ + * {data: [...]}, + * {data: [...]}, + * ... + * ] + * }; + * + * [rawOption]: + * + * An object input to echarts.setOption. 'rawOption' may be an + * 'option', or may be an object contains multi-options. For example: + * var option = { + * baseOption: { + * title: {...}, + * legend: {...}, + * series: [ + * {data: [...]}, + * {data: [...]}, + * ... + * ] + * }, + * timeline: {...}, + * options: [ + * {title: {...}, series: {data: [...]}}, + * {title: {...}, series: {data: [...]}}, + * ... + * ], + * media: [ + * { + * query: {maxWidth: 320}, + * option: {series: {x: 20}, visualMap: {show: false}} + * }, + * { + * query: {minWidth: 320, maxWidth: 720}, + * option: {series: {x: 500}, visualMap: {show: true}} + * }, + * { + * option: {series: {x: 1200}, visualMap: {show: true}} + * } + * ] + * }; + * + * @alias module:echarts/model/OptionManager + * @param {module:echarts/ExtensionAPI} api + */ + function OptionManager(api) { + + /** + * @private + * @type {module:echarts/ExtensionAPI} + */ + this._api = api; + + /** + * @private + * @type {Array.} + */ + this._timelineOptions = []; + + /** + * @private + * @type {Array.} + */ + this._mediaList = []; + + /** + * @private + * @type {Object} + */ + this._mediaDefault; + + /** + * -1, means default. + * empty means no media. + * @private + * @type {Array.} + */ + this._currentMediaIndices = []; + + /** + * @private + * @type {Object} + */ + this._optionBackup; + + /** + * @private + * @type {Object} + */ + this._newBaseOption; + } + + // timeline.notMerge is not supported in ec3. Firstly there is rearly + // case that notMerge is needed. Secondly supporting 'notMerge' requires + // rawOption cloned and backuped when timeline changed, which does no + // good to performance. What's more, that both timeline and setOption + // method supply 'notMerge' brings complex and some problems. + // Consider this case: + // (step1) chart.setOption({timeline: {notMerge: false}, ...}, false); + // (step2) chart.setOption({timeline: {notMerge: true}, ...}, false); + + OptionManager.prototype = { + + constructor: OptionManager, + + /** + * @public + * @param {Object} rawOption Raw option. + * @param {module:echarts/model/Global} ecModel + * @param {Array.} optionPreprocessorFuncs + * @return {Object} Init option + */ + setOption: function (rawOption, optionPreprocessorFuncs) { + rawOption = clone(rawOption, true); + + // FIXME + // 如果 timeline options 或者 media 中设置了某个属性,而baseOption中没有设置,则进行警告。 + + var oldOptionBackup = this._optionBackup; + var newParsedOption = parseRawOption.call( + this, rawOption, optionPreprocessorFuncs, !oldOptionBackup + ); + this._newBaseOption = newParsedOption.baseOption; + + // For setOption at second time (using merge mode); + if (oldOptionBackup) { + // Only baseOption can be merged. + //**yuki**changed Only series shouldn't be merged. + //Here is the first step, ensure that oldOptionBackup doesn't hava series. + oldOptionBackup.baseOption.series=[]; + //**yuki**changed Over. + mergeOption(oldOptionBackup.baseOption, newParsedOption.baseOption); + + // For simplicity, timeline options and media options do not support merge, + // that is, if you `setOption` twice and both has timeline options, the latter + // timeline opitons will not be merged to the formers, but just substitude them. + if (newParsedOption.timelineOptions.length) { + oldOptionBackup.timelineOptions = newParsedOption.timelineOptions; + } + if (newParsedOption.mediaList.length) { + oldOptionBackup.mediaList = newParsedOption.mediaList; + } + if (newParsedOption.mediaDefault) { + oldOptionBackup.mediaDefault = newParsedOption.mediaDefault; + } + } + else { + this._optionBackup = newParsedOption; + } + }, + + /** + * @param {boolean} isRecreate + * @return {Object} + */ + mountOption: function (isRecreate) { + var optionBackup = this._optionBackup; + + // TODO + // 如果没有reset功能则不clone。 + + this._timelineOptions = map(optionBackup.timelineOptions, clone); + this._mediaList = map(optionBackup.mediaList, clone); + this._mediaDefault = clone(optionBackup.mediaDefault); + this._currentMediaIndices = []; + + return clone(isRecreate + // this._optionBackup.baseOption, which is created at the first `setOption` + // called, and is merged into every new option by inner method `mergeOption` + // each time `setOption` called, can be only used in `isRecreate`, because + // its reliability is under suspicion. In other cases option merge is + // performed by `model.mergeOption`. + ? optionBackup.baseOption : this._newBaseOption + ); + }, + + /** + * @param {module:echarts/model/Global} ecModel + * @return {Object} + */ + getTimelineOption: function (ecModel) { + var option; + var timelineOptions = this._timelineOptions; + + if (timelineOptions.length) { + // getTimelineOption can only be called after ecModel inited, + // so we can get currentIndex from timelineModel. + var timelineModel = ecModel.getComponent('timeline'); + if (timelineModel) { + option = clone( + timelineOptions[timelineModel.getCurrentIndex()], + true + ); + } + } + + return option; + }, + + /** + * @param {module:echarts/model/Global} ecModel + * @return {Array.} + */ + getMediaOption: function (ecModel) { + var ecWidth = this._api.getWidth(); + var ecHeight = this._api.getHeight(); + var mediaList = this._mediaList; + var mediaDefault = this._mediaDefault; + var indices = []; + var result = []; + + // No media defined. + if (!mediaList.length && !mediaDefault) { + return result; + } + + // Multi media may be applied, the latter defined media has higher priority. + for (var i = 0, len = mediaList.length; i < len; i++) { + if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) { + indices.push(i); + } + } + + // FIXME + // 是否mediaDefault应该强制用户设置,否则可能修改不能回归。 + if (!indices.length && mediaDefault) { + indices = [-1]; + } + + if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) { + result = map(indices, function (index) { + return clone( + index === -1 ? mediaDefault.option : mediaList[index].option + ); + }); + } + // Otherwise return nothing. + + this._currentMediaIndices = indices; + + return result; + } + }; + + function parseRawOption(rawOption, optionPreprocessorFuncs, isNew) { + var timelineOptions = []; + var mediaList = []; + var mediaDefault; + var baseOption; + + // Compatible with ec2. + var timelineOpt = rawOption.timeline; + + if (rawOption.baseOption) { + baseOption = rawOption.baseOption; + } + + // For timeline + if (timelineOpt || rawOption.options) { + baseOption = baseOption || {}; + timelineOptions = (rawOption.options || []).slice(); + } + + // For media query + if (rawOption.media) { + baseOption = baseOption || {}; + var media = rawOption.media; + each(media, function (singleMedia) { + if (singleMedia && singleMedia.option) { + if (singleMedia.query) { + mediaList.push(singleMedia); + } + else if (!mediaDefault) { + // Use the first media default. + mediaDefault = singleMedia; + } + } + }); + } + + // For normal option + if (!baseOption) { + baseOption = rawOption; + } + + // Set timelineOpt to baseOption in ec3, + // which is convenient for merge option. + if (!baseOption.timeline) { + baseOption.timeline = timelineOpt; + } + + // Preprocess. + each([baseOption].concat(timelineOptions) + .concat(zrUtil.map(mediaList, function (media) { + return media.option; + })), + function (option) { + each(optionPreprocessorFuncs, function (preProcess) { + preProcess(option, isNew); + }); + } + ); + + return { + baseOption: baseOption, + timelineOptions: timelineOptions, + mediaDefault: mediaDefault, + mediaList: mediaList + }; + } + + /** + * @see + * Support: width, height, aspectRatio + * Can use max or min as prefix. + */ + function applyMediaQuery(query, ecWidth, ecHeight) { + var realMap = { + width: ecWidth, + height: ecHeight, + aspectratio: ecWidth / ecHeight // lowser case for convenientce. + }; + + var applicatable = true; + + zrUtil.each(query, function (value, attr) { + var matched = attr.match(QUERY_REG); + + if (!matched || !matched[1] || !matched[2]) { + return; + } + + var operator = matched[1]; + var realAttr = matched[2].toLowerCase(); + + if (!compare(realMap[realAttr], value, operator)) { + applicatable = false; + } + }); + + return applicatable; + } + + function compare(real, expect, operator) { + if (operator === 'min') { + return real >= expect; + } + else if (operator === 'max') { + return real <= expect; + } + else { // Equals + return real === expect; + } + } + + function indicesEquals(indices1, indices2) { + // indices is always order by asc and has only finite number. + return indices1.join(',') === indices2.join(','); + } + + /** + * Consider case: + * `chart.setOption(opt1);` + * Then user do some interaction like dataZoom, dataView changing. + * `chart.setOption(opt2);` + * Then user press 'reset button' in toolbox. + * + * After doing that all of the interaction effects should be reset, the + * chart should be the same as the result of invoke + * `chart.setOption(opt1); chart.setOption(opt2);`. + * + * Although it is not able ensure that + * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to + * `chart.setOption(merge(opt1, opt2));` exactly, + * this might be the only simple way to implement that feature. + * + * MEMO: We've considered some other approaches: + * 1. Each model handle its self restoration but not uniform treatment. + * (Too complex in logic and error-prone) + * 2. Use a shadow ecModel. (Performace expensive) + */ + + function mergeOption(oldOption, newOption) { + newOption = newOption || {}; + + each(newOption, function (newCptOpt, mainType) { + if (newCptOpt == null) { + return; + } + + var oldCptOpt = oldOption[mainType]; + + if (!ComponentModel.hasClass(mainType)) { + oldOption[mainType] = merge(oldCptOpt, newCptOpt, true); + } + else { + newCptOpt = modelUtil.normalizeToArray(newCptOpt); + oldCptOpt = modelUtil.normalizeToArray(oldCptOpt); + + var mapResult = modelUtil.mappingToExists(oldCptOpt, newCptOpt); + + oldOption[mainType] = map(mapResult, function (item) { + return (item.option && item.exist) + ? merge(item.exist, item.option, true) + : (item.exist || item.option); + }); + } + }); + } + + module.exports = OptionManager; + + +/***/ }, +/* 78 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var formatUtil = __webpack_require__(6); + var classUtil = __webpack_require__(13); + var modelUtil = __webpack_require__(5); + var ComponentModel = __webpack_require__(69); + var colorPaletteMixin = __webpack_require__(74); + var env = __webpack_require__(2); + var layout = __webpack_require__(71); + + var set = classUtil.set; + var get = classUtil.get; + var encodeHTML = formatUtil.encodeHTML; + var addCommas = formatUtil.addCommas; + + var SeriesModel = ComponentModel.extend({ + + type: 'series.__base__', + + /** + * @readOnly + */ + seriesIndex: 0, + + // coodinateSystem will be injected in the echarts/CoordinateSystem + coordinateSystem: null, + + /** + * @type {Object} + * @protected + */ + defaultOption: null, + + /** + * Data provided for legend + * @type {Function} + */ + // PENDING + legendDataProvider: null, + + /** + * Access path of color for visual + */ + visualColorAccessPath: 'itemStyle.normal.color', + + /** + * Support merge layout params. + * Only support 'box' now (left/right/top/bottom/width/height). + * @type {string|Object} Object can be {ignoreSize: true} + * @readOnly + */ + layoutMode: null, + + init: function (option, parentModel, ecModel, extraOpt) { + + /** + * @type {number} + * @readOnly + */ + this.seriesIndex = this.componentIndex; + + this.mergeDefaultAndTheme(option, ecModel); + + var data = this.getInitialData(option, ecModel); + if (true) { + zrUtil.assert(data, 'getInitialData returned invalid data.'); + } + /** + * @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph} + * @private + */ + set(this, 'dataBeforeProcessed', data); + + // If we reverse the order (make data firstly, and then make + // dataBeforeProcessed by cloneShallow), cloneShallow will + // cause data.graph.data !== data when using + // module:echarts/data/Graph or module:echarts/data/Tree. + // See module:echarts/data/helper/linkList + this.restoreData(); + }, + + /** + * Util for merge default and theme to option + * @param {Object} option + * @param {module:echarts/model/Global} ecModel + */ + mergeDefaultAndTheme: function (option, ecModel) { + var layoutMode = this.layoutMode; + var inputPositionParams = layoutMode + ? layout.getLayoutParams(option) : {}; + + zrUtil.merge( + option, + ecModel.getTheme().get(this.subType) + ); + zrUtil.merge(option, this.getDefaultOption()); + + // Default label emphasis `position` and `show` + // FIXME Set label in mergeOption + modelUtil.defaultEmphasis(option.label, modelUtil.LABEL_OPTIONS); + + this.fillDataTextStyle(option.data); + + if (layoutMode) { + layout.mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }, + + mergeOption: function (newSeriesOption, ecModel) { + newSeriesOption = zrUtil.merge(this.option, newSeriesOption, true); + this.fillDataTextStyle(newSeriesOption.data); + + var layoutMode = this.layoutMode; + if (layoutMode) { + layout.mergeLayoutParam(this.option, newSeriesOption, layoutMode); + } + + var data = this.getInitialData(newSeriesOption, ecModel); + // TODO Merge data? + if (data) { + set(this, 'data', data); + set(this, 'dataBeforeProcessed', data.cloneShallow()); + } + }, + + fillDataTextStyle: function (data) { + // Default data label emphasis `position` and `show` + // FIXME Tree structure data ? + // FIXME Performance ? + if (data) { + for (var i = 0; i < data.length; i++) { + if (data[i] && data[i].label) { + modelUtil.defaultEmphasis(data[i].label, modelUtil.LABEL_OPTIONS); + } + } + } + }, + + /** + * Init a data structure from data related option in series + * Must be overwritten + */ + getInitialData: function () {}, + + /** + * @param {string} [dataType] + * @return {module:echarts/data/List} + */ + getData: function (dataType) { + var data = get(this, 'data'); + return dataType == null ? data : data.getLinkedData(dataType); + }, + + /** + * @param {module:echarts/data/List} data + */ + setData: function (data) { + set(this, 'data', data); + }, + + /** + * Get data before processed + * @return {module:echarts/data/List} + */ + getRawData: function () { + return get(this, 'dataBeforeProcessed'); + }, + + /** + * Coord dimension to data dimension. + * + * By default the result is the same as dimensions of series data. + * But in some series data dimensions are different from coord dimensions (i.e. + * candlestick and boxplot). Override this method to handle those cases. + * + * Coord dimension to data dimension can be one-to-many + * + * @param {string} coordDim + * @return {Array.} dimensions on the axis. + */ + coordDimToDataDim: function (coordDim) { + return modelUtil.coordDimToDataDim(this.getData(), coordDim); + }, + + /** + * Convert data dimension to coord dimension. + * + * @param {string|number} dataDim + * @return {string} + */ + dataDimToCoordDim: function (dataDim) { + return modelUtil.dataDimToCoordDim(this.getData(), dataDim); + }, + + /** + * Get base axis if has coordinate system and has axis. + * By default use coordSys.getBaseAxis(); + * Can be overrided for some chart. + * @return {type} description + */ + getBaseAxis: function () { + var coordSys = this.coordinateSystem; + return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis(); + }, + + // FIXME + /** + * Default tooltip formatter + * + * @param {number} dataIndex + * @param {boolean} [multipleSeries=false] + * @param {number} [dataType] + */ + formatTooltip: function (dataIndex, multipleSeries, dataType) { + function formatArrayValue(value) { + var vertially = zrUtil.reduce(value, function (vertially, val, idx) { + var dimItem = data.getDimensionInfo(idx); + return vertially |= dimItem && dimItem.tooltip !== false && dimItem.tooltipName != null; + }, 0); + + var result = []; + var tooltipDims = modelUtil.otherDimToDataDim(data, 'tooltip'); + + tooltipDims.length + ? zrUtil.each(tooltipDims, function (dimIdx) { + setEachItem(data.get(dimIdx, dataIndex), dimIdx); + }) + // By default, all dims is used on tooltip. + : zrUtil.each(value, setEachItem); + + function setEachItem(val, dimIdx) { + var dimInfo = data.getDimensionInfo(dimIdx); + // If `dimInfo.tooltip` is not set, show tooltip. + if (!dimInfo || dimInfo.otherDims.tooltip === false) { + return; + } + var dimType = dimInfo.type; + var valStr = (vertially ? '- ' + (dimInfo.tooltipName || dimInfo.name) + ': ' : '') + + (dimType === 'ordinal' + ? val + '' + : dimType === 'time' + ? (multipleSeries ? '' : formatUtil.formatTime('yyyy/MM/dd hh:mm:ss', val)) + : addCommas(val) + ); + valStr && result.push(encodeHTML(valStr)); + } + + return (vertially ? '
' : '') + result.join(vertially ? '
' : ', '); + } + + var data = get(this, 'data'); + + var value = this.getRawValue(dataIndex); + var formattedValue = zrUtil.isArray(value) + ? formatArrayValue(value) : encodeHTML(addCommas(value)); + var name = data.getName(dataIndex); + + var color = data.getItemVisual(dataIndex, 'color'); + if (zrUtil.isObject(color) && color.colorStops) { + color = (color.colorStops[0] || {}).color; + } + color = color || 'transparent'; + + var colorEl = formatUtil.getTooltipMarker(color); + + var seriesName = this.name; + // FIXME + if (seriesName === '\0-') { + // Not show '-' + seriesName = ''; + } + seriesName = seriesName + ? encodeHTML(seriesName) + (!multipleSeries ? '
' : ': ') + : ''; + return !multipleSeries + ? seriesName + colorEl + + (name + ? encodeHTML(name) + ': ' + formattedValue + : formattedValue + ) + : colorEl + seriesName + formattedValue; + }, + + /** + * @return {boolean} + */ + isAnimationEnabled: function () { + if (env.node) { + return false; + } + + var animationEnabled = this.getShallow('animation'); + if (animationEnabled) { + if (this.getData().count() > this.getShallow('animationThreshold')) { + animationEnabled = false; + } + } + return animationEnabled; + }, + + restoreData: function () { + set(this, 'data', get(this, 'dataBeforeProcessed').cloneShallow()); + }, + + getColorFromPalette: function (name, scope) { + var ecModel = this.ecModel; + // PENDING + var color = colorPaletteMixin.getColorFromPalette.call(this, name, scope); + if (!color) { + color = ecModel.getColorFromPalette(name, scope); + } + return color; + }, + + /** + * Get data indices for show tooltip content. See tooltip. + * @abstract + * @param {Array.|string} dim + * @param {Array.} value + * @param {module:echarts/coord/single/SingleAxis} baseAxis + * @return {Object} {dataIndices, nestestValue}. + */ + getAxisTooltipData: null, + + /** + * See tooltip. + * @abstract + * @param {number} dataIndex + * @return {Array.} Point of tooltip. null/undefined can be returned. + */ + getTooltipPosition: null + }); + + zrUtil.mixin(SeriesModel, modelUtil.dataFormatMixin); + zrUtil.mixin(SeriesModel, colorPaletteMixin); + + module.exports = SeriesModel; + + +/***/ }, +/* 79 */ +/***/ function(module, exports, __webpack_require__) { + + + + var Group = __webpack_require__(48); + var componentUtil = __webpack_require__(70); + var clazzUtil = __webpack_require__(13); + + var Component = function () { + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = new Group(); + + /** + * @type {string} + * @readOnly + */ + this.uid = componentUtil.getUID('viewComponent'); + }; + + Component.prototype = { + + constructor: Component, + + init: function (ecModel, api) {}, + + render: function (componentModel, ecModel, api, payload) {}, + + dispose: function () {} + + }; + + var componentProto = Component.prototype; + componentProto.updateView + = componentProto.updateLayout + = componentProto.updateVisual + = function (seriesModel, ecModel, api, payload) { + // Do nothing; + }; + // Enable Component.extend. + clazzUtil.enableClassExtend(Component); + + // Enable capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on. + clazzUtil.enableClassManagement(Component, {registerWhenExtend: true}); + + module.exports = Component; + + +/***/ }, +/* 80 */ +/***/ function(module, exports, __webpack_require__) { + + + + var Group = __webpack_require__(48); + var componentUtil = __webpack_require__(70); + var clazzUtil = __webpack_require__(13); + var modelUtil = __webpack_require__(5); + var zrUtil = __webpack_require__(4); + + function Chart() { + + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = new Group(); + + /** + * @type {string} + * @readOnly + */ + this.uid = componentUtil.getUID('viewChart'); + } + + Chart.prototype = { + + type: 'chart', + + /** + * Init the chart + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + init: function (ecModel, api) {}, + + /** + * Render the chart + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + render: function (seriesModel, ecModel, api, payload) {}, + + /** + * Highlight series or specified data item + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + highlight: function (seriesModel, ecModel, api, payload) { + toggleHighlight(seriesModel.getData(), payload, 'emphasis'); + }, + + /** + * Downplay series or specified data item + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + downplay: function (seriesModel, ecModel, api, payload) { + toggleHighlight(seriesModel.getData(), payload, 'normal'); + }, + + /** + * Remove self + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + remove: function (ecModel, api) { + this.group.removeAll(); + }, + + /** + * Dispose self + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + dispose: function () {} + + /** + * The view contains the given point. + * @interface + * @param {Array.} point + * @return {boolean} + */ + // containPoint: function () {} + + }; + + var chartProto = Chart.prototype; + chartProto.updateView + = chartProto.updateLayout + = chartProto.updateVisual + = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; + + /** + * Set state of single element + * @param {module:zrender/Element} el + * @param {string} state + */ + function elSetState(el, state) { + if (el) { + el.trigger(state); + if (el.type === 'group') { + for (var i = 0; i < el.childCount(); i++) { + elSetState(el.childAt(i), state); + } + } + } + } + /** + * @param {module:echarts/data/List} data + * @param {Object} payload + * @param {string} state 'normal'|'emphasis' + * @inner + */ + function toggleHighlight(data, payload, state) { + var dataIndex = modelUtil.queryDataIndex(data, payload); + + if (dataIndex != null) { + zrUtil.each(modelUtil.normalizeToArray(dataIndex), function (dataIdx) { + elSetState(data.getItemGraphicEl(dataIdx), state); + }); + } + else { + data.eachItemGraphicEl(function (el) { + elSetState(el, state); + }); + } + } + + // Enable Chart.extend. + clazzUtil.enableClassExtend(Chart, ['dispose']); + + // Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on. + clazzUtil.enableClassManagement(Chart, {registerWhenExtend: true}); + + module.exports = Chart; + + +/***/ }, +/* 81 */ +/***/ function(module, exports) { + + + + var lib = {}; + + var ORIGIN_METHOD = '\0__throttleOriginMethod'; + var RATE = '\0__throttleRate'; + var THROTTLE_TYPE = '\0__throttleType'; + + /** + * @public + * @param {(Function)} fn + * @param {number} [delay=0] Unit: ms. + * @param {boolean} [debounce=false] + * true: If call interval less than `delay`, only the last call works. + * false: If call interval less than `delay, call works on fixed rate. + * @return {(Function)} throttled fn. + */ + lib.throttle = function (fn, delay, debounce) { + + var currCall; + var lastCall = 0; + var lastExec = 0; + var timer = null; + var diff; + var scope; + var args; + var debounceNextCall; + + delay = delay || 0; + + function exec() { + lastExec = (new Date()).getTime(); + timer = null; + fn.apply(scope, args || []); + } + + var cb = function () { + currCall = (new Date()).getTime(); + scope = this; + args = arguments; + var thisDelay = debounceNextCall || delay; + var thisDebounce = debounceNextCall || debounce; + debounceNextCall = null; + diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay; + + clearTimeout(timer); + + if (thisDebounce) { + timer = setTimeout(exec, thisDelay); + } + else { + if (diff >= 0) { + exec(); + } + else { + timer = setTimeout(exec, -diff); + } + } + + lastCall = currCall; + }; + + /** + * Clear throttle. + * @public + */ + cb.clear = function () { + if (timer) { + clearTimeout(timer); + timer = null; + } + }; + + /** + * Enable debounce once. + */ + cb.debounceNextCall = function (debounceDelay) { + debounceNextCall = debounceDelay; + }; + + return cb; + }; + + /** + * Create throttle method or update throttle rate. + * + * @example + * ComponentView.prototype.render = function () { + * ... + * throttle.createOrUpdate( + * this, + * '_dispatchAction', + * this.model.get('throttle'), + * 'fixRate' + * ); + * }; + * ComponentView.prototype.remove = function () { + * throttle.clear(this, '_dispatchAction'); + * }; + * ComponentView.prototype.dispose = function () { + * throttle.clear(this, '_dispatchAction'); + * }; + * + * @public + * @param {Object} obj + * @param {string} fnAttr + * @param {number} [rate] + * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce' + * @return {Function} throttled function. + */ + lib.createOrUpdate = function (obj, fnAttr, rate, throttleType) { + var fn = obj[fnAttr]; + + if (!fn) { + return; + } + + var originFn = fn[ORIGIN_METHOD] || fn; + var lastThrottleType = fn[THROTTLE_TYPE]; + var lastRate = fn[RATE]; + + if (lastRate !== rate || lastThrottleType !== throttleType) { + if (rate == null || !throttleType) { + return (obj[fnAttr] = originFn); + } + + fn = obj[fnAttr] = lib.throttle( + originFn, rate, throttleType === 'debounce' + ); + fn[ORIGIN_METHOD] = originFn; + fn[THROTTLE_TYPE] = throttleType; + fn[RATE] = rate; + } + + return fn; + }; + + /** + * Clear throttle. Example see throttle.createOrUpdate. + * + * @public + * @param {Object} obj + * @param {string} fnAttr + */ + lib.clear = function (obj, fnAttr) { + var fn = obj[fnAttr]; + if (fn && fn[ORIGIN_METHOD]) { + obj[fnAttr] = fn[ORIGIN_METHOD]; + } + }; + + module.exports = lib; + + + +/***/ }, +/* 82 */ +/***/ function(module, exports, __webpack_require__) { + + /*! + * ZRender, a high performance 2d drawing library. + * + * Copyright (c) 2013, Baidu Inc. + * All rights reserved. + * + * LICENSE + * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt + */ + // Global defines + + var guid = __webpack_require__(24); + var env = __webpack_require__(2); + var zrUtil = __webpack_require__(4); + + var Handler = __webpack_require__(83); + var Storage = __webpack_require__(85); + var Animation = __webpack_require__(87); + var HandlerProxy = __webpack_require__(90); + + var useVML = !env.canvasSupported; + + var painterCtors = { + canvas: __webpack_require__(92) + }; + + var instances = {}; // ZRender实例map索引 + + var zrender = {}; + + /** + * @type {string} + */ + zrender.version = '3.5.2'; + + /** + * Initializing a zrender instance + * @param {HTMLElement} dom + * @param {Object} opts + * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg' + * @param {number} [opts.devicePixelRatio] + * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined) + * @return {module:zrender/ZRender} + */ + zrender.init = function(dom, opts) { + var zr = new ZRender(guid(), dom, opts); + instances[zr.id] = zr; + return zr; + }; + + /** + * Dispose zrender instance + * @param {module:zrender/ZRender} zr + */ + zrender.dispose = function (zr) { + if (zr) { + zr.dispose(); + } + else { + for (var key in instances) { + if (instances.hasOwnProperty(key)) { + instances[key].dispose(); + } + } + instances = {}; + } + + return zrender; + }; + + /** + * Get zrender instance by id + * @param {string} id zrender instance id + * @return {module:zrender/ZRender} + */ + zrender.getInstance = function (id) { + return instances[id]; + }; + + zrender.registerPainter = function (name, Ctor) { + painterCtors[name] = Ctor; + }; + + function delInstance(id) { + delete instances[id]; + } + + /** + * @module zrender/ZRender + */ + /** + * @constructor + * @alias module:zrender/ZRender + * @param {string} id + * @param {HTMLDomElement} dom + * @param {Object} opts + * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg' + * @param {number} [opts.devicePixelRatio] + * @param {number} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number} [opts.height] Can be 'auto' (the same as null/undefined) + */ + var ZRender = function(id, dom, opts) { + + opts = opts || {}; + + /** + * @type {HTMLDomElement} + */ + this.dom = dom; + + /** + * @type {string} + */ + this.id = id; + + var self = this; + var storage = new Storage(); + + var rendererType = opts.renderer; + // TODO WebGL + if (useVML) { + if (!painterCtors.vml) { + throw new Error('You need to require \'zrender/vml/vml\' to support IE8'); + } + rendererType = 'vml'; + } + else if (!rendererType || !painterCtors[rendererType]) { + rendererType = 'canvas'; + } + var painter = new painterCtors[rendererType](dom, storage, opts); + + this.storage = storage; + this.painter = painter; + + var handerProxy = !env.node ? new HandlerProxy(painter.getViewportRoot()) : null; + this.handler = new Handler(storage, painter, handerProxy, painter.root); + + /** + * @type {module:zrender/animation/Animation} + */ + this.animation = new Animation({ + stage: { + update: zrUtil.bind(this.flush, this) + } + }); + this.animation.start(); + + /** + * @type {boolean} + * @private + */ + this._needsRefresh; + + // 修改 storage.delFromStorage, 每次删除元素之前删除动画 + // FIXME 有点ugly + var oldDelFromStorage = storage.delFromStorage; + var oldAddToStorage = storage.addToStorage; + + storage.delFromStorage = function (el) { + oldDelFromStorage.call(storage, el); + + el && el.removeSelfFromZr(self); + }; + + storage.addToStorage = function (el) { + oldAddToStorage.call(storage, el); + + el.addSelfToZr(self); + }; + }; + + ZRender.prototype = { + + constructor: ZRender, + /** + * 获取实例唯一标识 + * @return {string} + */ + getId: function () { + return this.id; + }, + + /** + * 添加元素 + * @param {module:zrender/Element} el + */ + add: function (el) { + this.storage.addRoot(el); + this._needsRefresh = true; + }, + + /** + * 删除元素 + * @param {module:zrender/Element} el + */ + remove: function (el) { + this.storage.delRoot(el); + this._needsRefresh = true; + }, + + /** + * Change configuration of layer + * @param {string} zLevel + * @param {Object} config + * @param {string} [config.clearColor=0] Clear color + * @param {string} [config.motionBlur=false] If enable motion blur + * @param {number} [config.lastFrameAlpha=0.7] Motion blur factor. Larger value cause longer trailer + */ + configLayer: function (zLevel, config) { + this.painter.configLayer(zLevel, config); + this._needsRefresh = true; + }, + + /** + * Repaint the canvas immediately + */ + refreshImmediately: function () { + // Clear needsRefresh ahead to avoid something wrong happens in refresh + // Or it will cause zrender refreshes again and again. + this._needsRefresh = false; + this.painter.refresh(); + /** + * Avoid trigger zr.refresh in Element#beforeUpdate hook + */ + this._needsRefresh = false; + }, + + /** + * Mark and repaint the canvas in the next frame of browser + */ + refresh: function() { + this._needsRefresh = true; + }, + + /** + * Perform all refresh + */ + flush: function () { + if (this._needsRefresh) { + this.refreshImmediately(); + } + if (this._needsRefreshHover) { + this.refreshHoverImmediately(); + } + }, + + /** + * Add element to hover layer + * @param {module:zrender/Element} el + * @param {Object} style + */ + addHover: function (el, style) { + if (this.painter.addHover) { + this.painter.addHover(el, style); + this.refreshHover(); + } + }, + + /** + * Add element from hover layer + * @param {module:zrender/Element} el + */ + removeHover: function (el) { + if (this.painter.removeHover) { + this.painter.removeHover(el); + this.refreshHover(); + } + }, + + /** + * Clear all hover elements in hover layer + * @param {module:zrender/Element} el + */ + clearHover: function () { + if (this.painter.clearHover) { + this.painter.clearHover(); + this.refreshHover(); + } + }, + + /** + * Refresh hover in next frame + */ + refreshHover: function () { + this._needsRefreshHover = true; + }, + + /** + * Refresh hover immediately + */ + refreshHoverImmediately: function () { + this._needsRefreshHover = false; + this.painter.refreshHover && this.painter.refreshHover(); + }, + + /** + * Resize the canvas. + * Should be invoked when container size is changed + * @param {Object} [opts] + * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined) + */ + resize: function(opts) { + opts = opts || {}; + this.painter.resize(opts.width, opts.height); + this.handler.resize(); + }, + + /** + * Stop and clear all animation immediately + */ + clearAnimation: function () { + this.animation.clear(); + }, + + /** + * Get container width + */ + getWidth: function() { + return this.painter.getWidth(); + }, + + /** + * Get container height + */ + getHeight: function() { + return this.painter.getHeight(); + }, + + /** + * Export the canvas as Base64 URL + * @param {string} type + * @param {string} [backgroundColor='#fff'] + * @return {string} Base64 URL + */ + // toDataURL: function(type, backgroundColor) { + // return this.painter.getRenderedCanvas({ + // backgroundColor: backgroundColor + // }).toDataURL(type); + // }, + + /** + * Converting a path to image. + * It has much better performance of drawing image rather than drawing a vector path. + * @param {module:zrender/graphic/Path} e + * @param {number} width + * @param {number} height + */ + pathToImage: function(e, dpr) { + return this.painter.pathToImage(e, dpr); + }, + + /** + * Set default cursor + * @param {string} [cursorStyle='default'] 例如 crosshair + */ + setCursorStyle: function (cursorStyle) { + this.handler.setCursorStyle(cursorStyle); + }, + + /** + * Find hovered element + * @param {number} x + * @param {number} y + * @return {Object} {target, topTarget} + */ + findHover: function (x, y) { + return this.handler.findHover(x, y); + }, + + /** + * Bind event + * + * @param {string} eventName Event name + * @param {Function} eventHandler Handler function + * @param {Object} [context] Context object + */ + on: function(eventName, eventHandler, context) { + this.handler.on(eventName, eventHandler, context); + }, + + /** + * Unbind event + * @param {string} eventName Event name + * @param {Function} [eventHandler] Handler function + */ + off: function(eventName, eventHandler) { + this.handler.off(eventName, eventHandler); + }, + + /** + * Trigger event manually + * + * @param {string} eventName Event name + * @param {event=} event Event object + */ + trigger: function (eventName, event) { + this.handler.trigger(eventName, event); + }, + + + /** + * Clear all objects and the canvas. + */ + clear: function () { + this.storage.delRoot(); + this.painter.clear(); + }, + + /** + * Dispose self. + */ + dispose: function () { + this.animation.stop(); + + this.clear(); + this.storage.dispose(); + this.painter.dispose(); + this.handler.dispose(); + + this.animation = + this.storage = + this.painter = + this.handler = null; + + delInstance(this.id); + } + }; + + module.exports = zrender; + + + +/***/ }, +/* 83 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * Handler + * @module zrender/Handler + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + * errorrik (errorrik@gmail.com) + * pissang (shenyi.914@gmail.com) + */ + + + var util = __webpack_require__(4); + var Draggable = __webpack_require__(84); + + var Eventful = __webpack_require__(25); + + var SILENT = 'silent'; + + function makeEventPacket(eveType, targetInfo, event) { + return { + type: eveType, + event: event, + // target can only be an element that is not silent. + target: targetInfo.target, + // topTarget can be a silent element. + topTarget: targetInfo.topTarget, + cancelBubble: false, + offsetX: event.zrX, + offsetY: event.zrY, + gestureEvent: event.gestureEvent, + pinchX: event.pinchX, + pinchY: event.pinchY, + pinchScale: event.pinchScale, + wheelDelta: event.zrDelta, + zrByTouch: event.zrByTouch + }; + } + + function EmptyProxy () {} + EmptyProxy.prototype.dispose = function () {}; + + var handlerNames = [ + 'click', 'dblclick', 'mousewheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' + ]; + /** + * @alias module:zrender/Handler + * @constructor + * @extends module:zrender/mixin/Eventful + * @param {module:zrender/Storage} storage Storage instance. + * @param {module:zrender/Painter} painter Painter instance. + * @param {module:zrender/dom/HandlerProxy} proxy HandlerProxy instance. + * @param {HTMLElement} painterRoot painter.root (not painter.getViewportRoot()). + */ + var Handler = function(storage, painter, proxy, painterRoot) { + Eventful.call(this); + + this.storage = storage; + + this.painter = painter; + + this.painterRoot = painterRoot; + + proxy = proxy || new EmptyProxy(); + + /** + * Proxy of event. can be Dom, WebGLSurface, etc. + */ + this.proxy = proxy; + + // Attach handler + proxy.handler = this; + + /** + * {target, topTarget} + * @private + * @type {Object} + */ + this._hovered = {}; + + /** + * @private + * @type {Date} + */ + this._lastTouchMoment; + + /** + * @private + * @type {number} + */ + this._lastX; + + /** + * @private + * @type {number} + */ + this._lastY; + + + Draggable.call(this); + + util.each(handlerNames, function (name) { + proxy.on && proxy.on(name, this[name], this); + }, this); + }; + + Handler.prototype = { + + constructor: Handler, + + mousemove: function (event) { + var x = event.zrX; + var y = event.zrY; + + var lastHovered = this._hovered; + var hovered = this._hovered = this.findHover(x, y); + var hoveredTarget = hovered.target; + var lastHoveredTarget = lastHovered.target; + + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default'); + + // Mouse out on previous hovered element + if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget && lastHoveredTarget.__zr) { + this.dispatchToElement(lastHovered, 'mouseout', event); + } + + // Mouse moving on one element + this.dispatchToElement(hovered, 'mousemove', event); + + // Mouse over on a new element + if (hoveredTarget && hoveredTarget !== lastHoveredTarget) { + this.dispatchToElement(hovered, 'mouseover', event); + } + }, + + mouseout: function (event) { + this.dispatchToElement(this._hovered, 'mouseout', event); + + // There might be some doms created by upper layer application + // at the same level of painter.getViewportRoot() (e.g., tooltip + // dom created by echarts), where 'globalout' event should not + // be triggered when mouse enters these doms. (But 'mouseout' + // should be triggered at the original hovered element as usual). + var element = event.toElement || event.relatedTarget; + var innerDom; + do { + element = element && element.parentNode; + } + while (element && element.nodeType != 9 && !( + innerDom = element === this.painterRoot + )); + + !innerDom && this.trigger('globalout', {event: event}); + }, + + /** + * Resize + */ + resize: function (event) { + this._hovered = {}; + }, + + /** + * Dispatch event + * @param {string} eventName + * @param {event=} eventArgs + */ + dispatch: function (eventName, eventArgs) { + var handler = this[eventName]; + handler && handler.call(this, eventArgs); + }, + + /** + * Dispose + */ + dispose: function () { + + this.proxy.dispose(); + + this.storage = + this.proxy = + this.painter = null; + }, + + /** + * 设置默认的cursor style + * @param {string} [cursorStyle='default'] 例如 crosshair + */ + setCursorStyle: function (cursorStyle) { + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(cursorStyle); + }, + + /** + * 事件分发代理 + * + * @private + * @param {Object} targetInfo {target, topTarget} 目标图形元素 + * @param {string} eventName 事件名称 + * @param {Object} event 事件对象 + */ + dispatchToElement: function (targetInfo, eventName, event) { + targetInfo = targetInfo || {}; + var eventHandler = 'on' + eventName; + var eventPacket = makeEventPacket(eventName, targetInfo, event); + + var el = targetInfo.target; + while (el) { + el[eventHandler] + && (eventPacket.cancelBubble = el[eventHandler].call(el, eventPacket)); + + el.trigger(eventName, eventPacket); + + el = el.parent; + + if (eventPacket.cancelBubble) { + break; + } + } + + if (!eventPacket.cancelBubble) { + // 冒泡到顶级 zrender 对象 + this.trigger(eventName, eventPacket); + // 分发事件到用户自定义层 + // 用户有可能在全局 click 事件中 dispose,所以需要判断下 painter 是否存在 + this.painter && this.painter.eachOtherLayer(function (layer) { + if (typeof(layer[eventHandler]) == 'function') { + layer[eventHandler].call(layer, eventPacket); + } + if (layer.trigger) { + layer.trigger(eventName, eventPacket); + } + }); + } + }, + + /** + * @private + * @param {number} x + * @param {number} y + * @param {module:zrender/graphic/Displayable} exclude + * @return {model:zrender/Element} + * @method + */ + findHover: function(x, y, exclude) { + var list = this.storage.getDisplayList(); + var out = {}; + var selected = new Array();//here the change is for to return a selected set + for (var i = 0; i < list.length ; i++) { + var hoverCheckResult; + if (list[i] !== exclude + // getDisplayList may include ignored item in VML mode + && !list[i].ignore + && (hoverCheckResult = isHover(list[i], x, y)) + ) { + !out.topTarget && (out.topTarget = list[i]); + if (hoverCheckResult !== SILENT) { + out.target = list[i]; + //**yukichange begin + selected.push(list[i]) ; + //**yukichange end + } + } + } + //**yukichange begin + if(out.target){ + out.target.selected = selected; + } + //**yukichange end + return out; + } + }; + + // Common handlers + util.each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) { + Handler.prototype[name] = function (event) { + // Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover + + var hovered = this.findHover(event.zrX, event.zrY); + var hoveredTarget = hovered.target; + + if (name === 'mousedown') { + this._downel = hoveredTarget; + // In case click triggered before mouseup + this._upel = hoveredTarget; + } + else if (name === 'mosueup') { + this._upel = hoveredTarget; + } + else if (name === 'click') { + if (this._downel !== this._upel) { + return; + } + } + + this.dispatchToElement(hovered, name, event); + }; + }); + + function isHover(displayable, x, y) { + if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) { + var el = displayable; + var isSilent; + while (el) { + // If clipped by ancestor. + // FIXME: If clipPath has neither stroke nor fill, + // el.clipPath.contain(x, y) will always return false. + if (el.clipPath && !el.clipPath.contain(x, y)) { + return false; + } + if (el.silent) { + isSilent = true; + } + el = el.parent; + } + return isSilent ? SILENT : true; + } + + return false; + } + + util.mixin(Handler, Eventful); + util.mixin(Handler, Draggable); + + module.exports = Handler; + + + +/***/ }, +/* 84 */ +/***/ function(module, exports) { + + // TODO Draggable for group + // FIXME Draggable on element which has parent rotation or scale + + function Draggable() { + + this.on('mousedown', this._dragStart, this); + this.on('mousemove', this._drag, this); + this.on('mouseup', this._dragEnd, this); + this.on('globalout', this._dragEnd, this); + // this._dropTarget = null; + // this._draggingTarget = null; + + // this._x = 0; + // this._y = 0; + } + + Draggable.prototype = { + + constructor: Draggable, + + _dragStart: function (e) { + var draggingTarget = e.target; + if (draggingTarget && draggingTarget.draggable) { + this._draggingTarget = draggingTarget; + draggingTarget.dragging = true; + this._x = e.offsetX; + this._y = e.offsetY; + + this.dispatchToElement(param(draggingTarget, e), 'dragstart', e.event); + } + }, + + _drag: function (e) { + var draggingTarget = this._draggingTarget; + if (draggingTarget) { + + var x = e.offsetX; + var y = e.offsetY; + + var dx = x - this._x; + var dy = y - this._y; + this._x = x; + this._y = y; + + draggingTarget.drift(dx, dy, e); + this.dispatchToElement(param(draggingTarget, e), 'drag', e.event); + + var dropTarget = this.findHover(x, y, draggingTarget).target; + var lastDropTarget = this._dropTarget; + this._dropTarget = dropTarget; + + if (draggingTarget !== dropTarget) { + if (lastDropTarget && dropTarget !== lastDropTarget) { + this.dispatchToElement(param(lastDropTarget, e), 'dragleave', e.event); + } + if (dropTarget && dropTarget !== lastDropTarget) { + this.dispatchToElement(param(dropTarget, e), 'dragenter', e.event); + } + } + } + }, + + _dragEnd: function (e) { + var draggingTarget = this._draggingTarget; + + if (draggingTarget) { + draggingTarget.dragging = false; + } + + this.dispatchToElement(param(draggingTarget, e), 'dragend', e.event); + + if (this._dropTarget) { + this.dispatchToElement(param(this._dropTarget, e), 'drop', e.event); + } + + this._draggingTarget = null; + this._dropTarget = null; + } + + }; + + function param(target, e) { + return {target: target, topTarget: e && e.topTarget}; + } + + module.exports = Draggable; + + +/***/ }, +/* 85 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * Storage内容仓库模块 + * @module zrender/Storage + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + * @author errorrik (errorrik@gmail.com) + * @author pissang (https://github.com/pissang/) + */ + + + var util = __webpack_require__(4); + var env = __webpack_require__(2); + + var Group = __webpack_require__(48); + + // Use timsort because in most case elements are partially sorted + // https://jsfiddle.net/pissang/jr4x7mdm/8/ + var timsort = __webpack_require__(86); + + function shapeCompareFunc(a, b) { + if (a.zlevel === b.zlevel) { + if (a.z === b.z) { + // if (a.z2 === b.z2) { + // // FIXME Slow has renderidx compare + // // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement + // // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012 + // return a.__renderidx - b.__renderidx; + // } + return a.z2 - b.z2; + } + return a.z - b.z; + } + return a.zlevel - b.zlevel; + } + /** + * 内容仓库 (M) + * @alias module:zrender/Storage + * @constructor + */ + var Storage = function () { + this._roots = []; + + this._displayList = []; + + this._displayListLen = 0; + }; + + Storage.prototype = { + + constructor: Storage, + + /** + * @param {Function} cb + * + */ + traverse: function (cb, context) { + for (var i = 0; i < this._roots.length; i++) { + this._roots[i].traverse(cb, context); + } + }, + + /** + * 返回所有图形的绘制队列 + * @param {boolean} [update=false] 是否在返回前更新该数组 + * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效 + * + * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList} + * @return {Array.} + */ + getDisplayList: function (update, includeIgnore) { + includeIgnore = includeIgnore || false; + if (update) { + this.updateDisplayList(includeIgnore); + } + return this._displayList; + }, + + /** + * 更新图形的绘制队列。 + * 每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中, + * 最后根据绘制的优先级(zlevel > z > 插入顺序)排序得到绘制队列 + * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组 + */ + updateDisplayList: function (includeIgnore) { + this._displayListLen = 0; + var roots = this._roots; + var displayList = this._displayList; + for (var i = 0, len = roots.length; i < len; i++) { + this._updateAndAddDisplayable(roots[i], null, includeIgnore); + } + displayList.length = this._displayListLen; + + // for (var i = 0, len = displayList.length; i < len; i++) { + // displayList[i].__renderidx = i; + // } + + // displayList.sort(shapeCompareFunc); + env.canvasSupported && timsort(displayList, shapeCompareFunc); + }, + + _updateAndAddDisplayable: function (el, clipPaths, includeIgnore) { + + if (el.ignore && !includeIgnore) { + return; + } + + el.beforeUpdate(); + + if (el.__dirty) { + + el.update(); + + } + + el.afterUpdate(); + + var userSetClipPath = el.clipPath; + if (userSetClipPath) { + + // FIXME 效率影响 + if (clipPaths) { + clipPaths = clipPaths.slice(); + } + else { + clipPaths = []; + } + + var currentClipPath = userSetClipPath; + var parentClipPath = el; + // Recursively add clip path + while (currentClipPath) { + // clipPath 的变换是基于使用这个 clipPath 的元素 + currentClipPath.parent = parentClipPath; + currentClipPath.updateTransform(); + + clipPaths.push(currentClipPath); + + parentClipPath = currentClipPath; + currentClipPath = currentClipPath.clipPath; + } + } + + if (el.isGroup) { + var children = el._children; + + for (var i = 0; i < children.length; i++) { + var child = children[i]; + + // Force to mark as dirty if group is dirty + // FIXME __dirtyPath ? + if (el.__dirty) { + child.__dirty = true; + } + + this._updateAndAddDisplayable(child, clipPaths, includeIgnore); + } + + // Mark group clean here + el.__dirty = false; + + } + else { + el.__clipPaths = clipPaths; + + this._displayList[this._displayListLen++] = el; + } + }, + + /** + * 添加图形(Shape)或者组(Group)到根节点 + * @param {module:zrender/Element} el + */ + addRoot: function (el) { + if (el.__storage === this) { + return; + } + + if (el instanceof Group) { + el.addChildrenToStorage(this); + } + + this.addToStorage(el); + this._roots.push(el); + }, + + /** + * 删除指定的图形(Shape)或者组(Group) + * @param {string|Array.} [el] 如果为空清空整个Storage + */ + delRoot: function (el) { + if (el == null) { + // 不指定el清空 + for (var i = 0; i < this._roots.length; i++) { + var root = this._roots[i]; + if (root instanceof Group) { + root.delChildrenFromStorage(this); + } + } + + this._roots = []; + this._displayList = []; + this._displayListLen = 0; + + return; + } + + if (el instanceof Array) { + for (var i = 0, l = el.length; i < l; i++) { + this.delRoot(el[i]); + } + return; + } + + + var idx = util.indexOf(this._roots, el); + if (idx >= 0) { + this.delFromStorage(el); + this._roots.splice(idx, 1); + if (el instanceof Group) { + el.delChildrenFromStorage(this); + } + } + }, + + addToStorage: function (el) { + el.__storage = this; + el.dirty(false); + + return this; + }, + + delFromStorage: function (el) { + if (el) { + el.__storage = null; + } + + return this; + }, + + /** + * 清空并且释放Storage + */ + dispose: function () { + this._renderList = + this._roots = null; + }, + + displayableSortFunc: shapeCompareFunc + }; + + module.exports = Storage; + + + +/***/ }, +/* 86 */ +/***/ function(module, exports) { + + // https://github.com/mziccard/node-timsort + + var DEFAULT_MIN_MERGE = 32; + + var DEFAULT_MIN_GALLOPING = 7; + + var DEFAULT_TMP_STORAGE_LENGTH = 256; + + function minRunLength(n) { + var r = 0; + + while (n >= DEFAULT_MIN_MERGE) { + r |= n & 1; + n >>= 1; + } + + return n + r; + } + + function makeAscendingRun(array, lo, hi, compare) { + var runHi = lo + 1; + + if (runHi === hi) { + return 1; + } + + if (compare(array[runHi++], array[lo]) < 0) { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { + runHi++; + } + + reverseRun(array, lo, runHi); + } + else { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { + runHi++; + } + } + + return runHi - lo; + } + + function reverseRun(array, lo, hi) { + hi--; + + while (lo < hi) { + var t = array[lo]; + array[lo++] = array[hi]; + array[hi--] = t; + } + } + + function binaryInsertionSort(array, lo, hi, start, compare) { + if (start === lo) { + start++; + } + + for (; start < hi; start++) { + var pivot = array[start]; + + var left = lo; + var right = start; + var mid; + + while (left < right) { + mid = left + right >>> 1; + + if (compare(pivot, array[mid]) < 0) { + right = mid; + } + else { + left = mid + 1; + } + } + + var n = start - left; + + switch (n) { + case 3: + array[left + 3] = array[left + 2]; + + case 2: + array[left + 2] = array[left + 1]; + + case 1: + array[left + 1] = array[left]; + break; + default: + while (n > 0) { + array[left + n] = array[left + n - 1]; + n--; + } + } + + array[left] = pivot; + } + } + + function gallopLeft(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + + if (compare(value, array[start + hint]) > 0) { + maxOffset = length - hint; + + while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + lastOffset += hint; + offset += hint; + } + else { + maxOffset = hint + 1; + while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + + lastOffset++; + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + + if (compare(value, array[start + m]) > 0) { + lastOffset = m + 1; + } + else { + offset = m; + } + } + return offset; + } + + function gallopRight(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + + if (compare(value, array[start + hint]) < 0) { + maxOffset = hint + 1; + + while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + else { + maxOffset = length - hint; + + while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + lastOffset += hint; + offset += hint; + } + + lastOffset++; + + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + + if (compare(value, array[start + m]) < 0) { + offset = m; + } + else { + lastOffset = m + 1; + } + } + + return offset; + } + + function TimSort(array, compare) { + var minGallop = DEFAULT_MIN_GALLOPING; + var length = 0; + var tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH; + var stackLength = 0; + var runStart; + var runLength; + var stackSize = 0; + + length = array.length; + + if (length < 2 * DEFAULT_TMP_STORAGE_LENGTH) { + tmpStorageLength = length >>> 1; + } + + var tmp = []; + + stackLength = length < 120 ? 5 : length < 1542 ? 10 : length < 119151 ? 19 : 40; + + runStart = []; + runLength = []; + + function pushRun(_runStart, _runLength) { + runStart[stackSize] = _runStart; + runLength[stackSize] = _runLength; + stackSize += 1; + } + + function mergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + + if (n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1] || n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1]) { + if (runLength[n - 1] < runLength[n + 1]) { + n--; + } + } + else if (runLength[n] > runLength[n + 1]) { + break; + } + mergeAt(n); + } + } + + function forceMergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + + if (n > 0 && runLength[n - 1] < runLength[n + 1]) { + n--; + } + + mergeAt(n); + } + } + + function mergeAt(i) { + var start1 = runStart[i]; + var length1 = runLength[i]; + var start2 = runStart[i + 1]; + var length2 = runLength[i + 1]; + + runLength[i] = length1 + length2; + + if (i === stackSize - 3) { + runStart[i + 1] = runStart[i + 2]; + runLength[i + 1] = runLength[i + 2]; + } + + stackSize--; + + var k = gallopRight(array[start2], array, start1, length1, 0, compare); + start1 += k; + length1 -= k; + + if (length1 === 0) { + return; + } + + length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); + + if (length2 === 0) { + return; + } + + if (length1 <= length2) { + mergeLow(start1, length1, start2, length2); + } + else { + mergeHigh(start1, length1, start2, length2); + } + } + + function mergeLow(start1, length1, start2, length2) { + var i = 0; + + for (i = 0; i < length1; i++) { + tmp[i] = array[start1 + i]; + } + + var cursor1 = 0; + var cursor2 = start2; + var dest = start1; + + array[dest++] = array[cursor2++]; + + if (--length2 === 0) { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + return; + } + + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + return; + } + + var _minGallop = minGallop; + var count1, count2, exit; + + while (1) { + count1 = 0; + count2 = 0; + exit = false; + + do { + if (compare(array[cursor2], tmp[cursor1]) < 0) { + array[dest++] = array[cursor2++]; + count2++; + count1 = 0; + + if (--length2 === 0) { + exit = true; + break; + } + } + else { + array[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--length1 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + + if (exit) { + break; + } + + do { + count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); + + if (count1 !== 0) { + for (i = 0; i < count1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + + dest += count1; + cursor1 += count1; + length1 -= count1; + if (length1 <= 1) { + exit = true; + break; + } + } + + array[dest++] = array[cursor2++]; + + if (--length2 === 0) { + exit = true; + break; + } + + count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); + + if (count2 !== 0) { + for (i = 0; i < count2; i++) { + array[dest + i] = array[cursor2 + i]; + } + + dest += count2; + cursor2 += count2; + length2 -= count2; + + if (length2 === 0) { + exit = true; + break; + } + } + array[dest++] = tmp[cursor1++]; + + if (--length1 === 1) { + exit = true; + break; + } + + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + + if (exit) { + break; + } + + if (_minGallop < 0) { + _minGallop = 0; + } + + _minGallop += 2; + } + + minGallop = _minGallop; + + minGallop < 1 && (minGallop = 1); + + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + } + else if (length1 === 0) { + throw new Error(); + // throw new Error('mergeLow preconditions were not respected'); + } + else { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + } + } + + function mergeHigh (start1, length1, start2, length2) { + var i = 0; + + for (i = 0; i < length2; i++) { + tmp[i] = array[start2 + i]; + } + + var cursor1 = start1 + length1 - 1; + var cursor2 = length2 - 1; + var dest = start2 + length2 - 1; + var customCursor = 0; + var customDest = 0; + + array[dest--] = array[cursor1--]; + + if (--length1 === 0) { + customCursor = dest - (length2 - 1); + + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + + return; + } + + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + array[dest] = tmp[cursor2]; + return; + } + + var _minGallop = minGallop; + + while (true) { + var count1 = 0; + var count2 = 0; + var exit = false; + + do { + if (compare(tmp[cursor2], array[cursor1]) < 0) { + array[dest--] = array[cursor1--]; + count1++; + count2 = 0; + if (--length1 === 0) { + exit = true; + break; + } + } + else { + array[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--length2 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + + if (exit) { + break; + } + + do { + count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); + + if (count1 !== 0) { + dest -= count1; + cursor1 -= count1; + length1 -= count1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = count1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + if (length1 === 0) { + exit = true; + break; + } + } + + array[dest--] = tmp[cursor2--]; + + if (--length2 === 1) { + exit = true; + break; + } + + count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); + + if (count2 !== 0) { + dest -= count2; + cursor2 -= count2; + length2 -= count2; + customDest = dest + 1; + customCursor = cursor2 + 1; + + for (i = 0; i < count2; i++) { + array[customDest + i] = tmp[customCursor + i]; + } + + if (length2 <= 1) { + exit = true; + break; + } + } + + array[dest--] = array[cursor1--]; + + if (--length1 === 0) { + exit = true; + break; + } + + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + + if (exit) { + break; + } + + if (_minGallop < 0) { + _minGallop = 0; + } + + _minGallop += 2; + } + + minGallop = _minGallop; + + if (minGallop < 1) { + minGallop = 1; + } + + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + array[dest] = tmp[cursor2]; + } + else if (length2 === 0) { + throw new Error(); + // throw new Error('mergeHigh preconditions were not respected'); + } + else { + customCursor = dest - (length2 - 1); + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + } + } + + this.mergeRuns = mergeRuns; + this.forceMergeRuns = forceMergeRuns; + this.pushRun = pushRun; + } + + function sort(array, compare, lo, hi) { + if (!lo) { + lo = 0; + } + if (!hi) { + hi = array.length; + } + + var remaining = hi - lo; + + if (remaining < 2) { + return; + } + + var runLength = 0; + + if (remaining < DEFAULT_MIN_MERGE) { + runLength = makeAscendingRun(array, lo, hi, compare); + binaryInsertionSort(array, lo, hi, lo + runLength, compare); + return; + } + + var ts = new TimSort(array, compare); + + var minRun = minRunLength(remaining); + + do { + runLength = makeAscendingRun(array, lo, hi, compare); + if (runLength < minRun) { + var force = remaining; + if (force > minRun) { + force = minRun; + } + + binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); + runLength = force; + } + + ts.pushRun(lo, runLength); + ts.mergeRuns(); + + remaining -= runLength; + lo += runLength; + } while (remaining !== 0); + + ts.forceMergeRuns(); + } + + module.exports = sort; + + +/***/ }, +/* 87 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * 动画主类, 调度和管理所有动画控制器 + * + * @module zrender/animation/Animation + * @author pissang(https://github.com/pissang) + */ + // TODO Additive animation + // http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/ + // https://developer.apple.com/videos/wwdc2014/#236 + + + var util = __webpack_require__(4); + var Dispatcher = __webpack_require__(88).Dispatcher; + + var requestAnimationFrame = __webpack_require__(89); + + var Animator = __webpack_require__(28); + /** + * @typedef {Object} IZRenderStage + * @property {Function} update + */ + + /** + * @alias module:zrender/animation/Animation + * @constructor + * @param {Object} [options] + * @param {Function} [options.onframe] + * @param {IZRenderStage} [options.stage] + * @example + * var animation = new Animation(); + * var obj = { + * x: 100, + * y: 100 + * }; + * animation.animate(node.position) + * .when(1000, { + * x: 500, + * y: 500 + * }) + * .when(2000, { + * x: 100, + * y: 100 + * }) + * .start('spline'); + */ + var Animation = function (options) { + + options = options || {}; + + this.stage = options.stage || {}; + + this.onframe = options.onframe || function() {}; + + // private properties + this._clips = []; + + this._running = false; + + this._time; + + this._pausedTime; + + this._pauseStart; + + this._paused = false; + + Dispatcher.call(this); + }; + + Animation.prototype = { + + constructor: Animation, + /** + * 添加 clip + * @param {module:zrender/animation/Clip} clip + */ + addClip: function (clip) { + this._clips.push(clip); + }, + /** + * 添加 animator + * @param {module:zrender/animation/Animator} animator + */ + addAnimator: function (animator) { + animator.animation = this; + var clips = animator.getClips(); + for (var i = 0; i < clips.length; i++) { + this.addClip(clips[i]); + } + }, + /** + * 删除动画片段 + * @param {module:zrender/animation/Clip} clip + */ + removeClip: function(clip) { + var idx = util.indexOf(this._clips, clip); + if (idx >= 0) { + this._clips.splice(idx, 1); + } + }, + + /** + * 删除动画片段 + * @param {module:zrender/animation/Animator} animator + */ + removeAnimator: function (animator) { + var clips = animator.getClips(); + for (var i = 0; i < clips.length; i++) { + this.removeClip(clips[i]); + } + animator.animation = null; + }, + + _update: function() { + + var time = new Date().getTime() - this._pausedTime; + var delta = time - this._time; + var clips = this._clips; + var len = clips.length; + + var deferredEvents = []; + var deferredClips = []; + for (var i = 0; i < len; i++) { + var clip = clips[i]; + var e = clip.step(time, delta); + // Throw out the events need to be called after + // stage.update, like destroy + if (e) { + deferredEvents.push(e); + deferredClips.push(clip); + } + } + + // Remove the finished clip + for (var i = 0; i < len;) { + if (clips[i]._needsRemove) { + clips[i] = clips[len - 1]; + clips.pop(); + len--; + } + else { + i++; + } + } + + len = deferredEvents.length; + for (var i = 0; i < len; i++) { + deferredClips[i].fire(deferredEvents[i]); + } + + this._time = time; + + this.onframe(delta); + + this.trigger('frame', delta); + + if (this.stage.update) { + this.stage.update(); + } + }, + + _startLoop: function () { + var self = this; + + this._running = true; + + function step() { + if (self._running) { + + requestAnimationFrame(step); + + !self._paused && self._update(); + } + } + + requestAnimationFrame(step); + }, + + /** + * 开始运行动画 + */ + start: function () { + + this._time = new Date().getTime(); + this._pausedTime = 0; + + this._startLoop(); + }, + /** + * 停止运行动画 + */ + stop: function () { + this._running = false; + }, + + /** + * Pause + */ + pause: function () { + if (!this._paused) { + this._pauseStart = new Date().getTime(); + this._paused = true; + } + }, + + /** + * Resume + */ + resume: function () { + if (this._paused) { + this._pausedTime += (new Date().getTime()) - this._pauseStart; + this._paused = false; + } + }, + + /** + * 清除所有动画片段 + */ + clear: function () { + this._clips = []; + }, + /** + * 对一个目标创建一个animator对象,可以指定目标中的属性使用动画 + * @param {Object} target + * @param {Object} options + * @param {boolean} [options.loop=false] 是否循环播放动画 + * @param {Function} [options.getter=null] + * 如果指定getter函数,会通过getter函数取属性值 + * @param {Function} [options.setter=null] + * 如果指定setter函数,会通过setter函数设置属性值 + * @return {module:zrender/animation/Animation~Animator} + */ + // TODO Gap + animate: function (target, options) { + options = options || {}; + + var animator = new Animator( + target, + options.loop, + options.getter, + options.setter + ); + + this.addAnimator(animator); + + return animator; + } + }; + + util.mixin(Animation, Dispatcher); + + module.exports = Animation; + + + +/***/ }, +/* 88 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * 事件辅助类 + * @module zrender/core/event + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + */ + + + var Eventful = __webpack_require__(25); + var env = __webpack_require__(2); + + var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener; + + function getBoundingClientRect(el) { + // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect + return el.getBoundingClientRect ? el.getBoundingClientRect() : {left: 0, top: 0}; + } + + // `calculate` is optional, default false + function clientToLocal(el, e, out, calculate) { + out = out || {}; + + // According to the W3C Working Draft, offsetX and offsetY should be relative + // to the padding edge of the target element. The only browser using this convention + // is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does + // not support the properties. + // (see http://www.jacklmoore.com/notes/mouse-position/) + // In zr painter.dom, padding edge equals to border edge. + + // FIXME + // When mousemove event triggered on ec tooltip, target is not zr painter.dom, and + // offsetX/Y is relative to e.target, where the calculation of zrX/Y via offsetX/Y + // is too complex. So css-transfrom dont support in this case temporarily. + if (calculate || !env.canvasSupported) { + defaultGetZrXY(el, e, out); + } + // Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned + // ancestor element, so we should make sure el is positioned (e.g., not position:static). + // BTW1, Webkit don't return the same results as FF in non-simple cases (like add + // zoom-factor, overflow / opacity layers, transforms ...) + // BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d. + // + // BTW3, In ff, offsetX/offsetY is always 0. + else if (env.browser.firefox && e.layerX != null && e.layerX !== e.offsetX) { + out.zrX = e.layerX; + out.zrY = e.layerY; + } + // For IE6+, chrome, safari, opera. (When will ff support offsetX?) + else if (e.offsetX != null) { + out.zrX = e.offsetX; + out.zrY = e.offsetY; + } + // For some other device, e.g., IOS safari. + else { + defaultGetZrXY(el, e, out); + } + + return out; + } + + function defaultGetZrXY(el, e, out) { + // This well-known method below does not support css transform. + var box = getBoundingClientRect(el); + out.zrX = e.clientX - box.left; + out.zrY = e.clientY - box.top; + } + + /** + * 如果存在第三方嵌入的一些dom触发的事件,或touch事件,需要转换一下事件坐标. + * `calculate` is optional, default false. + */ + function normalizeEvent(el, e, calculate) { + + e = e || window.event; + + if (e.zrX != null) { + return e; + } + + var eventType = e.type; + var isTouch = eventType && eventType.indexOf('touch') >= 0; + + if (!isTouch) { + clientToLocal(el, e, e, calculate); + e.zrDelta = (e.wheelDelta) ? e.wheelDelta / 120 : -(e.detail || 0) / 3; + } + else { + var touch = eventType != 'touchend' + ? e.targetTouches[0] + : e.changedTouches[0]; + touch && clientToLocal(el, touch, e, calculate); + } + + return e; + } + + function addEventListener(el, name, handler) { + if (isDomLevel2) { + el.addEventListener(name, handler); + } + else { + el.attachEvent('on' + name, handler); + } + } + + function removeEventListener(el, name, handler) { + if (isDomLevel2) { + el.removeEventListener(name, handler); + } + else { + el.detachEvent('on' + name, handler); + } + } + + /** + * preventDefault and stopPropagation. + * Notice: do not do that in zrender. Upper application + * do that if necessary. + * + * @memberOf module:zrender/core/event + * @method + * @param {Event} e : event对象 + */ + var stop = isDomLevel2 + ? function (e) { + e.preventDefault(); + e.stopPropagation(); + e.cancelBubble = true; + } + : function (e) { + e.returnValue = false; + e.cancelBubble = true; + }; + + module.exports = { + clientToLocal: clientToLocal, + normalizeEvent: normalizeEvent, + addEventListener: addEventListener, + removeEventListener: removeEventListener, + + stop: stop, + // 做向上兼容 + Dispatcher: Eventful + }; + + + +/***/ }, +/* 89 */ +/***/ function(module, exports) { + + + + module.exports = (typeof window !== 'undefined' && + ((window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) + // https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809 + || (window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window)) + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame) + ) + || function (func) { + setTimeout(func, 16); + }; + + + +/***/ }, +/* 90 */ +/***/ function(module, exports, __webpack_require__) { + + + + var eventTool = __webpack_require__(88); + var zrUtil = __webpack_require__(4); + var Eventful = __webpack_require__(25); + var env = __webpack_require__(2); + var GestureMgr = __webpack_require__(91); + + var addEventListener = eventTool.addEventListener; + var removeEventListener = eventTool.removeEventListener; + var normalizeEvent = eventTool.normalizeEvent; + + var TOUCH_CLICK_DELAY = 300; + + var mouseHandlerNames = [ + 'click', 'dblclick', 'mousewheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' + ]; + + var touchHandlerNames = [ + 'touchstart', 'touchend', 'touchmove' + ]; + + var pointerEventNames = { + pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1 + }; + + var pointerHandlerNames = zrUtil.map(mouseHandlerNames, function (name) { + var nm = name.replace('mouse', 'pointer'); + return pointerEventNames[nm] ? nm : name; + }); + + function eventNameFix(name) { + return (name === 'mousewheel' && env.browser.firefox) ? 'DOMMouseScroll' : name; + } + + function processGesture(proxy, event, stage) { + var gestureMgr = proxy._gestureMgr; + + stage === 'start' && gestureMgr.clear(); + + var gestureInfo = gestureMgr.recognize( + event, + proxy.handler.findHover(event.zrX, event.zrY, null).target, + proxy.dom + ); + + stage === 'end' && gestureMgr.clear(); + + // Do not do any preventDefault here. Upper application do that if necessary. + if (gestureInfo) { + var type = gestureInfo.type; + event.gestureEvent = type; + + proxy.handler.dispatchToElement({target: gestureInfo.target}, type, gestureInfo.event); + } + } + + // function onMSGestureChange(proxy, event) { + // if (event.translationX || event.translationY) { + // // mousemove is carried by MSGesture to reduce the sensitivity. + // proxy.handler.dispatchToElement(event.target, 'mousemove', event); + // } + // if (event.scale !== 1) { + // event.pinchX = event.offsetX; + // event.pinchY = event.offsetY; + // event.pinchScale = event.scale; + // proxy.handler.dispatchToElement(event.target, 'pinch', event); + // } + // } + + /** + * Prevent mouse event from being dispatched after Touch Events action + * @see + * 1. Mobile browsers dispatch mouse events 300ms after touchend. + * 2. Chrome for Android dispatch mousedown for long-touch about 650ms + * Result: Blocking Mouse Events for 700ms. + */ + function setTouchTimer(instance) { + instance._touching = true; + clearTimeout(instance._touchTimer); + instance._touchTimer = setTimeout(function () { + instance._touching = false; + }, 700); + } + + + var domHandlers = { + /** + * Mouse move handler + * @inner + * @param {Event} event + */ + mousemove: function (event) { + event = normalizeEvent(this.dom, event); + + this.trigger('mousemove', event); + }, + + /** + * Mouse out handler + * @inner + * @param {Event} event + */ + mouseout: function (event) { + event = normalizeEvent(this.dom, event); + + var element = event.toElement || event.relatedTarget; + if (element != this.dom) { + while (element && element.nodeType != 9) { + // 忽略包含在root中的dom引起的mouseOut + if (element === this.dom) { + return; + } + + element = element.parentNode; + } + } + + this.trigger('mouseout', event); + }, + + /** + * Touch开始响应函数 + * @inner + * @param {Event} event + */ + touchstart: function (event) { + // Default mouse behaviour should not be disabled here. + // For example, page may needs to be slided. + event = normalizeEvent(this.dom, event); + + // Mark touch, which is useful in distinguish touch and + // mouse event in upper applicatoin. + event.zrByTouch = true; + + this._lastTouchMoment = new Date(); + + processGesture(this, event, 'start'); + + // In touch device, trigger `mousemove`(`mouseover`) should + // be triggered, and must before `mousedown` triggered. + domHandlers.mousemove.call(this, event); + + domHandlers.mousedown.call(this, event); + + setTouchTimer(this); + }, + + /** + * Touch移动响应函数 + * @inner + * @param {Event} event + */ + touchmove: function (event) { + + event = normalizeEvent(this.dom, event); + + // Mark touch, which is useful in distinguish touch and + // mouse event in upper applicatoin. + event.zrByTouch = true; + + processGesture(this, event, 'change'); + + // Mouse move should always be triggered no matter whether + // there is gestrue event, because mouse move and pinch may + // be used at the same time. + domHandlers.mousemove.call(this, event); + + setTouchTimer(this); + }, + + /** + * Touch结束响应函数 + * @inner + * @param {Event} event + */ + touchend: function (event) { + + event = normalizeEvent(this.dom, event); + + // Mark touch, which is useful in distinguish touch and + // mouse event in upper applicatoin. + event.zrByTouch = true; + + processGesture(this, event, 'end'); + + domHandlers.mouseup.call(this, event); + + // Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is + // triggered in `touchstart`. This seems to be illogical, but by this mechanism, + // we can conveniently implement "hover style" in both PC and touch device just + // by listening to `mouseover` to add "hover style" and listening to `mouseout` + // to remove "hover style" on an element, without any additional code for + // compatibility. (`mouseout` will not be triggered in `touchend`, so "hover + // style" will remain for user view) + + // click event should always be triggered no matter whether + // there is gestrue event. System click can not be prevented. + if (+new Date() - this._lastTouchMoment < TOUCH_CLICK_DELAY) { + domHandlers.click.call(this, event); + } + + setTouchTimer(this); + }, + + pointerdown: function (event) { + domHandlers.mousedown.call(this, event); + + // if (useMSGuesture(this, event)) { + // this._msGesture.addPointer(event.pointerId); + // } + }, + + pointermove: function (event) { + // FIXME + // pointermove is so sensitive that it always triggered when + // tap(click) on touch screen, which affect some judgement in + // upper application. So, we dont support mousemove on MS touch + // device yet. + if (!isPointerFromTouch(event)) { + domHandlers.mousemove.call(this, event); + } + }, + + pointerup: function (event) { + domHandlers.mouseup.call(this, event); + }, + + pointerout: function (event) { + // pointerout will be triggered when tap on touch screen + // (IE11+/Edge on MS Surface) after click event triggered, + // which is inconsistent with the mousout behavior we defined + // in touchend. So we unify them. + // (check domHandlers.touchend for detailed explanation) + if (!isPointerFromTouch(event)) { + domHandlers.mouseout.call(this, event); + } + } + }; + + function isPointerFromTouch(event) { + var pointerType = event.pointerType; + return pointerType === 'pen' || pointerType === 'touch'; + } + + // function useMSGuesture(handlerProxy, event) { + // return isPointerFromTouch(event) && !!handlerProxy._msGesture; + // } + + // Common handlers + zrUtil.each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) { + domHandlers[name] = function (event) { + event = normalizeEvent(this.dom, event); + this.trigger(name, event); + }; + }); + + /** + * 为控制类实例初始化dom 事件处理函数 + * + * @inner + * @param {module:zrender/Handler} instance 控制类实例 + */ + function initDomHandler(instance) { + zrUtil.each(touchHandlerNames, function (name) { + instance._handlers[name] = zrUtil.bind(domHandlers[name], instance); + }); + + zrUtil.each(pointerHandlerNames, function (name) { + instance._handlers[name] = zrUtil.bind(domHandlers[name], instance); + }); + + zrUtil.each(mouseHandlerNames, function (name) { + instance._handlers[name] = makeMouseHandler(domHandlers[name], instance); + }); + + function makeMouseHandler(fn, instance) { + return function () { + if (instance._touching) { + return; + } + return fn.apply(instance, arguments); + }; + } + } + + + function HandlerDomProxy(dom) { + Eventful.call(this); + + this.dom = dom; + + /** + * @private + * @type {boolean} + */ + this._touching = false; + + /** + * @private + * @type {number} + */ + this._touchTimer; + + /** + * @private + * @type {module:zrender/core/GestureMgr} + */ + this._gestureMgr = new GestureMgr(); + + this._handlers = {}; + + initDomHandler(this); + + if (env.pointerEventsSupported) { // Only IE11+/Edge + // 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240), + // IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event + // at the same time. + // 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on + // screen, which do not occurs in pointer event. + // So we use pointer event to both detect touch gesture and mouse behavior. + mountHandlers(pointerHandlerNames, this); + + // FIXME + // Note: MS Gesture require CSS touch-action set. But touch-action is not reliable, + // which does not prevent defuault behavior occasionally (which may cause view port + // zoomed in but use can not zoom it back). And event.preventDefault() does not work. + // So we have to not to use MSGesture and not to support touchmove and pinch on MS + // touch screen. And we only support click behavior on MS touch screen now. + + // MS Gesture Event is only supported on IE11+/Edge and on Windows 8+. + // We dont support touch on IE on win7. + // See + // if (typeof MSGesture === 'function') { + // (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line + // dom.addEventListener('MSGestureChange', onMSGestureChange); + // } + } + else { + if (env.touchEventsSupported) { + mountHandlers(touchHandlerNames, this); + // Handler of 'mouseout' event is needed in touch mode, which will be mounted below. + // addEventListener(root, 'mouseout', this._mouseoutHandler); + } + + // 1. Considering some devices that both enable touch and mouse event (like on MS Surface + // and lenovo X240, @see #2350), we make mouse event be always listened, otherwise + // mouse event can not be handle in those devices. + // 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent + // mouseevent after touch event triggered, see `setTouchTimer`. + mountHandlers(mouseHandlerNames, this); + } + + function mountHandlers(handlerNames, instance) { + zrUtil.each(handlerNames, function (name) { + addEventListener(dom, eventNameFix(name), instance._handlers[name]); + }, instance); + } + } + + var handlerDomProxyProto = HandlerDomProxy.prototype; + handlerDomProxyProto.dispose = function () { + var handlerNames = mouseHandlerNames.concat(touchHandlerNames); + + for (var i = 0; i < handlerNames.length; i++) { + var name = handlerNames[i]; + removeEventListener(this.dom, eventNameFix(name), this._handlers[name]); + } + }; + + handlerDomProxyProto.setCursor = function (cursorStyle) { + this.dom.style.cursor = cursorStyle || 'default'; + }; + + zrUtil.mixin(HandlerDomProxy, Eventful); + + module.exports = HandlerDomProxy; + + +/***/ }, +/* 91 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * Only implements needed gestures for mobile. + */ + + + var eventUtil = __webpack_require__(88); + + var GestureMgr = function () { + + /** + * @private + * @type {Array.} + */ + this._track = []; + }; + + GestureMgr.prototype = { + + constructor: GestureMgr, + + recognize: function (event, target, root) { + this._doTrack(event, target, root); + return this._recognize(event); + }, + + clear: function () { + this._track.length = 0; + return this; + }, + + _doTrack: function (event, target, root) { + var touches = event.touches; + + if (!touches) { + return; + } + + var trackItem = { + points: [], + touches: [], + target: target, + event: event + }; + + for (var i = 0, len = touches.length; i < len; i++) { + var touch = touches[i]; + var pos = eventUtil.clientToLocal(root, touch, {}); + trackItem.points.push([pos.zrX, pos.zrY]); + trackItem.touches.push(touch); + } + + this._track.push(trackItem); + }, + + _recognize: function (event) { + for (var eventName in recognizers) { + if (recognizers.hasOwnProperty(eventName)) { + var gestureInfo = recognizers[eventName](this._track, event); + if (gestureInfo) { + return gestureInfo; + } + } + } + } + }; + + function dist(pointPair) { + var dx = pointPair[1][0] - pointPair[0][0]; + var dy = pointPair[1][1] - pointPair[0][1]; + + return Math.sqrt(dx * dx + dy * dy); + } + + function center(pointPair) { + return [ + (pointPair[0][0] + pointPair[1][0]) / 2, + (pointPair[0][1] + pointPair[1][1]) / 2 + ]; + } + + var recognizers = { + + pinch: function (track, event) { + var trackLen = track.length; + + if (!trackLen) { + return; + } + + var pinchEnd = (track[trackLen - 1] || {}).points; + var pinchPre = (track[trackLen - 2] || {}).points || pinchEnd; + + if (pinchPre + && pinchPre.length > 1 + && pinchEnd + && pinchEnd.length > 1 + ) { + var pinchScale = dist(pinchEnd) / dist(pinchPre); + !isFinite(pinchScale) && (pinchScale = 1); + + event.pinchScale = pinchScale; + + var pinchCenter = center(pinchEnd); + event.pinchX = pinchCenter[0]; + event.pinchY = pinchCenter[1]; + + return { + type: 'pinch', + target: track[0].target, + event: event + }; + } + } + + // Only pinch currently. + }; + + module.exports = GestureMgr; + + + +/***/ }, +/* 92 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * Default canvas painter + * @module zrender/Painter + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + * errorrik (errorrik@gmail.com) + * pissang (https://www.github.com/pissang) + */ + + + var config = __webpack_require__(34); + var util = __webpack_require__(4); + var log = __webpack_require__(33); + var BoundingRect = __webpack_require__(9); + var timsort = __webpack_require__(86); + + var Layer = __webpack_require__(93); + + var requestAnimationFrame = __webpack_require__(89); + + // PENDIGN + // Layer exceeds MAX_PROGRESSIVE_LAYER_NUMBER may have some problem when flush directly second time. + // + // Maximum progressive layer. When exceeding this number. All elements will be drawed in the last layer. + var MAX_PROGRESSIVE_LAYER_NUMBER = 5; + + function parseInt10(val) { + return parseInt(val, 10); + } + + function isLayerValid(layer) { + if (!layer) { + return false; + } + + if (layer.__builtin__) { + return true; + } + + if (typeof(layer.resize) !== 'function' + || typeof(layer.refresh) !== 'function' + ) { + return false; + } + + return true; + } + + function preProcessLayer(layer) { + layer.__unusedCount++; + } + + function postProcessLayer(layer) { + if (layer.__unusedCount == 1) { + layer.clear(); + } + } + + var tmpRect = new BoundingRect(0, 0, 0, 0); + var viewRect = new BoundingRect(0, 0, 0, 0); + function isDisplayableCulled(el, width, height) { + tmpRect.copy(el.getBoundingRect()); + if (el.transform) { + tmpRect.applyTransform(el.transform); + } + viewRect.width = width; + viewRect.height = height; + return !tmpRect.intersect(viewRect); + } + + function isClipPathChanged(clipPaths, prevClipPaths) { + if (clipPaths == prevClipPaths) { // Can both be null or undefined + return false; + } + + if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) { + return true; + } + for (var i = 0; i < clipPaths.length; i++) { + if (clipPaths[i] !== prevClipPaths[i]) { + return true; + } + } + } + + function doClip(clipPaths, ctx) { + for (var i = 0; i < clipPaths.length; i++) { + var clipPath = clipPaths[i]; + + clipPath.setTransform(ctx); + ctx.beginPath(); + clipPath.buildPath(ctx, clipPath.shape); + ctx.clip(); + // Transform back + clipPath.restoreTransform(ctx); + } + } + + function createRoot(width, height) { + var domRoot = document.createElement('div'); + + // domRoot.onselectstart = returnFalse; // 避免页面选中的尴尬 + domRoot.style.cssText = [ + 'position:relative', + 'overflow:hidden', + 'width:' + width + 'px', + 'height:' + height + 'px', + 'padding:0', + 'margin:0', + 'border-width:0' + ].join(';') + ';'; + + return domRoot; + } + + /** + * @alias module:zrender/Painter + * @constructor + * @param {HTMLElement} root 绘图容器 + * @param {module:zrender/Storage} storage + * @param {Ojbect} opts + */ + var Painter = function (root, storage, opts) { + // In node environment using node-canvas + var singleCanvas = !root.nodeName // In node ? + || root.nodeName.toUpperCase() === 'CANVAS'; + + this._opts = opts = util.extend({}, opts || {}); + + /** + * @type {number} + */ + this.dpr = opts.devicePixelRatio || config.devicePixelRatio; + /** + * @type {boolean} + * @private + */ + this._singleCanvas = singleCanvas; + /** + * 绘图容器 + * @type {HTMLElement} + */ + this.root = root; + + var rootStyle = root.style; + + if (rootStyle) { + rootStyle['-webkit-tap-highlight-color'] = 'transparent'; + rootStyle['-webkit-user-select'] = + rootStyle['user-select'] = + rootStyle['-webkit-touch-callout'] = 'none'; + + root.innerHTML = ''; + } + + /** + * @type {module:zrender/Storage} + */ + this.storage = storage; + + /** + * @type {Array.} + * @private + */ + var zlevelList = this._zlevelList = []; + + /** + * @type {Object.} + * @private + */ + var layers = this._layers = {}; + + /** + * @type {Object.} + * @type {private} + */ + this._layerConfig = {}; + + if (!singleCanvas) { + this._width = this._getSize(0); + this._height = this._getSize(1); + + var domRoot = this._domRoot = createRoot( + this._width, this._height + ); + root.appendChild(domRoot); + } + else { + if (opts.width != null) { + root.width = opts.width; + } + if (opts.height != null) { + root.height = opts.height; + } + // Use canvas width and height directly + var width = root.width; + var height = root.height; + this._width = width; + this._height = height; + + // Create layer if only one given canvas + // Device pixel ratio is fixed to 1 because given canvas has its specified width and height + var mainLayer = new Layer(root, this, 1); + mainLayer.initContext(); + // FIXME Use canvas width and height + // mainLayer.resize(width, height); + layers[0] = mainLayer; + zlevelList.push(0); + + this._domRoot = root; + } + + // Layers for progressive rendering + this._progressiveLayers = []; + + /** + * @type {module:zrender/Layer} + * @private + */ + this._hoverlayer; + + this._hoverElements = []; + }; + + Painter.prototype = { + + constructor: Painter, + + /** + * If painter use a single canvas + * @return {boolean} + */ + isSingleCanvas: function () { + return this._singleCanvas; + }, + /** + * @return {HTMLDivElement} + */ + getViewportRoot: function () { + return this._domRoot; + }, + + /** + * 刷新 + * @param {boolean} [paintAll=false] 强制绘制所有displayable + */ + refresh: function (paintAll) { + + var list = this.storage.getDisplayList(true); + + var zlevelList = this._zlevelList; + + this._paintList(list, paintAll); + + // Paint custum layers + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (!layer.__builtin__ && layer.refresh) { + layer.refresh(); + } + } + + this.refreshHover(); + + if (this._progressiveLayers.length) { + this._startProgessive(); + } + + return this; + }, + + addHover: function (el, hoverStyle) { + if (el.__hoverMir) { + return; + } + var elMirror = new el.constructor({ + style: el.style, + shape: el.shape + }); + elMirror.__from = el; + el.__hoverMir = elMirror; + elMirror.setStyle(hoverStyle); + this._hoverElements.push(elMirror); + }, + + removeHover: function (el) { + var elMirror = el.__hoverMir; + var hoverElements = this._hoverElements; + var idx = util.indexOf(hoverElements, elMirror); + if (idx >= 0) { + hoverElements.splice(idx, 1); + } + el.__hoverMir = null; + }, + + clearHover: function (el) { + var hoverElements = this._hoverElements; + for (var i = 0; i < hoverElements.length; i++) { + var from = hoverElements[i].__from; + if (from) { + from.__hoverMir = null; + } + } + hoverElements.length = 0; + }, + + refreshHover: function () { + var hoverElements = this._hoverElements; + var len = hoverElements.length; + var hoverLayer = this._hoverlayer; + hoverLayer && hoverLayer.clear(); + + if (!len) { + return; + } + timsort(hoverElements, this.storage.displayableSortFunc); + + // Use a extream large zlevel + // FIXME? + if (!hoverLayer) { + hoverLayer = this._hoverlayer = this.getLayer(1e5); + } + + var scope = {}; + hoverLayer.ctx.save(); + for (var i = 0; i < len;) { + var el = hoverElements[i]; + var originalEl = el.__from; + // Original el is removed + // PENDING + if (!(originalEl && originalEl.__zr)) { + hoverElements.splice(i, 1); + originalEl.__hoverMir = null; + len--; + continue; + } + i++; + + // Use transform + // FIXME style and shape ? + if (!originalEl.invisible) { + el.transform = originalEl.transform; + el.invTransform = originalEl.invTransform; + el.__clipPaths = originalEl.__clipPaths; + // el. + this._doPaintEl(el, hoverLayer, true, scope); + } + } + hoverLayer.ctx.restore(); + }, + + _startProgessive: function () { + var self = this; + + if (!self._furtherProgressive) { + return; + } + + // Use a token to stop progress steps triggered by + // previous zr.refresh calling. + var token = self._progressiveToken = +new Date(); + + self._progress++; + requestAnimationFrame(step); + + function step() { + // In case refreshed or disposed + if (token === self._progressiveToken && self.storage) { + + self._doPaintList(self.storage.getDisplayList()); + + if (self._furtherProgressive) { + self._progress++; + requestAnimationFrame(step); + } + else { + self._progressiveToken = -1; + } + } + } + }, + + _clearProgressive: function () { + this._progressiveToken = -1; + this._progress = 0; + util.each(this._progressiveLayers, function (layer) { + layer.__dirty && layer.clear(); + }); + }, + + _paintList: function (list, paintAll) { + + if (paintAll == null) { + paintAll = false; + } + + this._updateLayerStatus(list); + + this._clearProgressive(); + + this.eachBuiltinLayer(preProcessLayer); + + this._doPaintList(list, paintAll); + + this.eachBuiltinLayer(postProcessLayer); + }, + + _doPaintList: function (list, paintAll) { + var currentLayer; + var currentZLevel; + var ctx; + + // var invTransform = []; + var scope; + + var progressiveLayerIdx = 0; + var currentProgressiveLayer; + + var width = this._width; + var height = this._height; + var layerProgress; + var frame = this._progress; + function flushProgressiveLayer(layer) { + var dpr = ctx.dpr || 1; + ctx.save(); + ctx.globalAlpha = 1; + ctx.shadowBlur = 0; + // Avoid layer don't clear in next progressive frame + currentLayer.__dirty = true; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(layer.dom, 0, 0, width * dpr, height * dpr); + ctx.restore(); + } + + for (var i = 0, l = list.length; i < l; i++) { + var el = list[i]; + var elZLevel = this._singleCanvas ? 0 : el.zlevel; + + var elFrame = el.__frame; + + // Flush at current context + // PENDING + if (elFrame < 0 && currentProgressiveLayer) { + flushProgressiveLayer(currentProgressiveLayer); + currentProgressiveLayer = null; + } + + // Change draw layer + if (currentZLevel !== elZLevel) { + if (ctx) { + ctx.restore(); + } + + // Reset scope + scope = {}; + + // Only 0 zlevel if only has one canvas + currentZLevel = elZLevel; + currentLayer = this.getLayer(currentZLevel); + + if (!currentLayer.__builtin__) { + log( + 'ZLevel ' + currentZLevel + + ' has been used by unkown layer ' + currentLayer.id + ); + } + + ctx = currentLayer.ctx; + ctx.save(); + + // Reset the count + currentLayer.__unusedCount = 0; + + if (currentLayer.__dirty || paintAll) { + currentLayer.clear(); + } + } + + if (!(currentLayer.__dirty || paintAll)) { + continue; + } + + if (elFrame >= 0) { + // Progressive layer changed + if (!currentProgressiveLayer) { + currentProgressiveLayer = this._progressiveLayers[ + Math.min(progressiveLayerIdx++, MAX_PROGRESSIVE_LAYER_NUMBER - 1) + ]; + + currentProgressiveLayer.ctx.save(); + currentProgressiveLayer.renderScope = {}; + + if (currentProgressiveLayer + && (currentProgressiveLayer.__progress > currentProgressiveLayer.__maxProgress) + ) { + // flushProgressiveLayer(currentProgressiveLayer); + // Quick jump all progressive elements + // All progressive element are not dirty, jump over and flush directly + i = currentProgressiveLayer.__nextIdxNotProg - 1; + // currentProgressiveLayer = null; + continue; + } + + layerProgress = currentProgressiveLayer.__progress; + + if (!currentProgressiveLayer.__dirty) { + // Keep rendering + frame = layerProgress; + } + + currentProgressiveLayer.__progress = frame + 1; + } + + if (elFrame === frame) { + this._doPaintEl(el, currentProgressiveLayer, true, currentProgressiveLayer.renderScope); + } + } + else { + this._doPaintEl(el, currentLayer, paintAll, scope); + } + + el.__dirty = false; + } + + if (currentProgressiveLayer) { + flushProgressiveLayer(currentProgressiveLayer); + } + + // Restore the lastLayer ctx + ctx && ctx.restore(); + // If still has clipping state + // if (scope.prevElClipPaths) { + // ctx.restore(); + // } + + this._furtherProgressive = false; + util.each(this._progressiveLayers, function (layer) { + if (layer.__maxProgress >= layer.__progress) { + this._furtherProgressive = true; + } + }, this); + }, + + _doPaintEl: function (el, currentLayer, forcePaint, scope) { + var ctx = currentLayer.ctx; + var m = el.transform; + if ( + (currentLayer.__dirty || forcePaint) + // Ignore invisible element + && !el.invisible + // Ignore transparent element + && el.style.opacity !== 0 + // Ignore scale 0 element, in some environment like node-canvas + // Draw a scale 0 element can cause all following draw wrong + // And setTransform with scale 0 will cause set back transform failed. + && !(m && !m[0] && !m[3]) + // Ignore culled element + && !(el.culling && isDisplayableCulled(el, this._width, this._height)) + ) { + + var clipPaths = el.__clipPaths; + + // Optimize when clipping on group with several elements + if (scope.prevClipLayer !== currentLayer + || isClipPathChanged(clipPaths, scope.prevElClipPaths) + ) { + // If has previous clipping state, restore from it + if (scope.prevElClipPaths) { + scope.prevClipLayer.ctx.restore(); + scope.prevClipLayer = scope.prevElClipPaths = null; + + // Reset prevEl since context has been restored + scope.prevEl = null; + } + // New clipping state + if (clipPaths) { + ctx.save(); + doClip(clipPaths, ctx); + scope.prevClipLayer = currentLayer; + scope.prevElClipPaths = clipPaths; + } + } + el.beforeBrush && el.beforeBrush(ctx); + + el.brush(ctx, scope.prevEl || null); + scope.prevEl = el; + + el.afterBrush && el.afterBrush(ctx); + } + }, + + /** + * 获取 zlevel 所在层,如果不存在则会创建一个新的层 + * @param {number} zlevel + * @return {module:zrender/Layer} + */ + getLayer: function (zlevel) { + if (this._singleCanvas) { + return this._layers[0]; + } + + var layer = this._layers[zlevel]; + if (!layer) { + // Create a new layer + layer = new Layer('zr_' + zlevel, this, this.dpr); + layer.__builtin__ = true; + + if (this._layerConfig[zlevel]) { + util.merge(layer, this._layerConfig[zlevel], true); + } + + this.insertLayer(zlevel, layer); + + // Context is created after dom inserted to document + // Or excanvas will get 0px clientWidth and clientHeight + layer.initContext(); + } + + return layer; + }, + + insertLayer: function (zlevel, layer) { + + var layersMap = this._layers; + var zlevelList = this._zlevelList; + var len = zlevelList.length; + var prevLayer = null; + var i = -1; + var domRoot = this._domRoot; + + if (layersMap[zlevel]) { + log('ZLevel ' + zlevel + ' has been used already'); + return; + } + // Check if is a valid layer + if (!isLayerValid(layer)) { + log('Layer of zlevel ' + zlevel + ' is not valid'); + return; + } + + if (len > 0 && zlevel > zlevelList[0]) { + for (i = 0; i < len - 1; i++) { + if ( + zlevelList[i] < zlevel + && zlevelList[i + 1] > zlevel + ) { + break; + } + } + prevLayer = layersMap[zlevelList[i]]; + } + zlevelList.splice(i + 1, 0, zlevel); + + layersMap[zlevel] = layer; + + // Vitual layer will not directly show on the screen. + // (It can be a WebGL layer and assigned to a ZImage element) + // But it still under management of zrender. + if (!layer.virtual) { + if (prevLayer) { + var prevDom = prevLayer.dom; + if (prevDom.nextSibling) { + domRoot.insertBefore( + layer.dom, + prevDom.nextSibling + ); + } + else { + domRoot.appendChild(layer.dom); + } + } + else { + if (domRoot.firstChild) { + domRoot.insertBefore(layer.dom, domRoot.firstChild); + } + else { + domRoot.appendChild(layer.dom); + } + } + } + }, + + // Iterate each layer + eachLayer: function (cb, context) { + var zlevelList = this._zlevelList; + var z; + var i; + for (i = 0; i < zlevelList.length; i++) { + z = zlevelList[i]; + cb.call(context, this._layers[z], z); + } + }, + + // Iterate each buildin layer + eachBuiltinLayer: function (cb, context) { + var zlevelList = this._zlevelList; + var layer; + var z; + var i; + for (i = 0; i < zlevelList.length; i++) { + z = zlevelList[i]; + layer = this._layers[z]; + if (layer.__builtin__) { + cb.call(context, layer, z); + } + } + }, + + // Iterate each other layer except buildin layer + eachOtherLayer: function (cb, context) { + var zlevelList = this._zlevelList; + var layer; + var z; + var i; + for (i = 0; i < zlevelList.length; i++) { + z = zlevelList[i]; + layer = this._layers[z]; + if (!layer.__builtin__) { + cb.call(context, layer, z); + } + } + }, + + /** + * 获取所有已创建的层 + * @param {Array.} [prevLayer] + */ + getLayers: function () { + return this._layers; + }, + + _updateLayerStatus: function (list) { + + var layers = this._layers; + var progressiveLayers = this._progressiveLayers; + + var elCountsLastFrame = {}; + var progressiveElCountsLastFrame = {}; + + this.eachBuiltinLayer(function (layer, z) { + elCountsLastFrame[z] = layer.elCount; + layer.elCount = 0; + layer.__dirty = false; + }); + + util.each(progressiveLayers, function (layer, idx) { + progressiveElCountsLastFrame[idx] = layer.elCount; + layer.elCount = 0; + layer.__dirty = false; + }); + + var progressiveLayerCount = 0; + var currentProgressiveLayer; + var lastProgressiveKey; + var frameCount = 0; + for (var i = 0, l = list.length; i < l; i++) { + var el = list[i]; + var zlevel = this._singleCanvas ? 0 : el.zlevel; + var layer = layers[zlevel]; + var elProgress = el.progressive; + if (layer) { + layer.elCount++; + layer.__dirty = layer.__dirty || el.__dirty; + } + + /////// Update progressive + if (elProgress >= 0) { + // Fix wrong progressive sequence problem. + if (lastProgressiveKey !== elProgress) { + lastProgressiveKey = elProgress; + frameCount++; + } + var elFrame = el.__frame = frameCount - 1; + if (!currentProgressiveLayer) { + var idx = Math.min(progressiveLayerCount, MAX_PROGRESSIVE_LAYER_NUMBER - 1); + currentProgressiveLayer = progressiveLayers[idx]; + if (!currentProgressiveLayer) { + currentProgressiveLayer = progressiveLayers[idx] = new Layer( + 'progressive', this, this.dpr + ); + currentProgressiveLayer.initContext(); + } + currentProgressiveLayer.__maxProgress = 0; + } + currentProgressiveLayer.__dirty = currentProgressiveLayer.__dirty || el.__dirty; + currentProgressiveLayer.elCount++; + + currentProgressiveLayer.__maxProgress = Math.max( + currentProgressiveLayer.__maxProgress, elFrame + ); + + if (currentProgressiveLayer.__maxProgress >= currentProgressiveLayer.__progress) { + // Should keep rendering this layer because progressive rendering is not finished yet + layer.__dirty = true; + } + } + else { + el.__frame = -1; + + if (currentProgressiveLayer) { + currentProgressiveLayer.__nextIdxNotProg = i; + progressiveLayerCount++; + currentProgressiveLayer = null; + } + } + } + + if (currentProgressiveLayer) { + progressiveLayerCount++; + currentProgressiveLayer.__nextIdxNotProg = i; + } + + // 层中的元素数量有发生变化 + this.eachBuiltinLayer(function (layer, z) { + if (elCountsLastFrame[z] !== layer.elCount) { + layer.__dirty = true; + } + }); + + progressiveLayers.length = Math.min(progressiveLayerCount, MAX_PROGRESSIVE_LAYER_NUMBER); + util.each(progressiveLayers, function (layer, idx) { + if (progressiveElCountsLastFrame[idx] !== layer.elCount) { + el.__dirty = true; + } + if (layer.__dirty) { + layer.__progress = 0; + } + }); + }, + + /** + * 清除hover层外所有内容 + */ + clear: function () { + this.eachBuiltinLayer(this._clearLayer); + return this; + }, + + _clearLayer: function (layer) { + layer.clear(); + }, + + /** + * 修改指定zlevel的绘制参数 + * + * @param {string} zlevel + * @param {Object} config 配置对象 + * @param {string} [config.clearColor=0] 每次清空画布的颜色 + * @param {string} [config.motionBlur=false] 是否开启动态模糊 + * @param {number} [config.lastFrameAlpha=0.7] + * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显 + */ + configLayer: function (zlevel, config) { + if (config) { + var layerConfig = this._layerConfig; + if (!layerConfig[zlevel]) { + layerConfig[zlevel] = config; + } + else { + util.merge(layerConfig[zlevel], config, true); + } + + var layer = this._layers[zlevel]; + + if (layer) { + util.merge(layer, layerConfig[zlevel], true); + } + } + }, + + /** + * 删除指定层 + * @param {number} zlevel 层所在的zlevel + */ + delLayer: function (zlevel) { + var layers = this._layers; + var zlevelList = this._zlevelList; + var layer = layers[zlevel]; + if (!layer) { + return; + } + layer.dom.parentNode.removeChild(layer.dom); + delete layers[zlevel]; + + zlevelList.splice(util.indexOf(zlevelList, zlevel), 1); + }, + + /** + * 区域大小变化后重绘 + */ + resize: function (width, height) { + var domRoot = this._domRoot; + // FIXME Why ? + domRoot.style.display = 'none'; + + // Save input w/h + var opts = this._opts; + width != null && (opts.width = width); + height != null && (opts.height = height); + + width = this._getSize(0); + height = this._getSize(1); + + domRoot.style.display = ''; + + // 优化没有实际改变的resize + if (this._width != width || height != this._height) { + domRoot.style.width = width + 'px'; + domRoot.style.height = height + 'px'; + + for (var id in this._layers) { + if (this._layers.hasOwnProperty(id)) { + this._layers[id].resize(width, height); + } + } + util.each(this._progressiveLayers, function (layer) { + layer.resize(width, height); + }); + + this.refresh(true); + } + + this._width = width; + this._height = height; + + return this; + }, + + /** + * 清除单独的一个层 + * @param {number} zlevel + */ + clearLayer: function (zlevel) { + var layer = this._layers[zlevel]; + if (layer) { + layer.clear(); + } + }, + + /** + * 释放 + */ + dispose: function () { + this.root.innerHTML = ''; + + this.root = + this.storage = + + this._domRoot = + this._layers = null; + }, + + /** + * Get canvas which has all thing rendered + * @param {Object} opts + * @param {string} [opts.backgroundColor] + */ + getRenderedCanvas: function (opts) { + opts = opts || {}; + if (this._singleCanvas) { + return this._layers[0].dom; + } + + var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr); + imageLayer.initContext(); + + imageLayer.clearColor = opts.backgroundColor; + imageLayer.clear(); + + var displayList = this.storage.getDisplayList(true); + + var scope = {}; + var zlevel; + + var self = this; + function findAndDrawOtherLayer(smaller, larger) { + var zlevelList = self._zlevelList; + if (smaller == null) { + smaller = -Infinity; + } + var intermediateLayer; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = self._layers[z]; + if (!layer.__builtin__ && z > smaller && z < larger) { + intermediateLayer = layer; + break; + } + } + if (intermediateLayer && intermediateLayer.renderToCanvas) { + imageLayer.ctx.save(); + intermediateLayer.renderToCanvas(imageLayer.ctx); + imageLayer.ctx.restore(); + } + } + for (var i = 0; i < displayList.length; i++) { + var el = displayList[i]; + + if (el.zlevel !== zlevel) { + findAndDrawOtherLayer(zlevel, el.zlevel); + zlevel = el.zlevel; + } + this._doPaintEl(el, imageLayer, true, scope); + } + + findAndDrawOtherLayer(zlevel, Infinity); + + return imageLayer.dom; + }, + /** + * 获取绘图区域宽度 + */ + getWidth: function () { + return this._width; + }, + + /** + * 获取绘图区域高度 + */ + getHeight: function () { + return this._height; + }, + + _getSize: function (whIdx) { + var opts = this._opts; + var wh = ['width', 'height'][whIdx]; + var cwh = ['clientWidth', 'clientHeight'][whIdx]; + var plt = ['paddingLeft', 'paddingTop'][whIdx]; + var prb = ['paddingRight', 'paddingBottom'][whIdx]; + + if (opts[wh] != null && opts[wh] !== 'auto') { + return parseFloat(opts[wh]); + } + + var root = this.root; + var stl = document.defaultView.getComputedStyle(root); + + return ( + (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) + - (parseInt10(stl[plt]) || 0) + - (parseInt10(stl[prb]) || 0) + ) | 0; + }, + + pathToImage: function (path, dpr) { + dpr = dpr || this.dpr; + + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var rect = path.getBoundingRect(); + var style = path.style; + var shadowBlurSize = style.shadowBlur; + var shadowOffsetX = style.shadowOffsetX; + var shadowOffsetY = style.shadowOffsetY; + var lineWidth = style.hasStroke() ? style.lineWidth : 0; + + var leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize); + var rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize); + var topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize); + var bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize); + var width = rect.width + leftMargin + rightMargin; + var height = rect.height + topMargin + bottomMargin; + + canvas.width = width * dpr; + canvas.height = height * dpr; + + ctx.scale(dpr, dpr); + ctx.clearRect(0, 0, width, height); + ctx.dpr = dpr; + + var pathTransform = { + position: path.position, + rotation: path.rotation, + scale: path.scale + }; + path.position = [leftMargin - rect.x, topMargin - rect.y]; + path.rotation = 0; + path.scale = [1, 1]; + path.updateTransform(); + if (path) { + path.brush(ctx); + } + + var ImageShape = __webpack_require__(49); + var imgShape = new ImageShape({ + style: { + x: 0, + y: 0, + image: canvas + } + }); + + if (pathTransform.position != null) { + imgShape.position = path.position = pathTransform.position; + } + + if (pathTransform.rotation != null) { + imgShape.rotation = path.rotation = pathTransform.rotation; + } + + if (pathTransform.scale != null) { + imgShape.scale = path.scale = pathTransform.scale; + } + + return imgShape; + } + }; + + module.exports = Painter; + + + +/***/ }, +/* 93 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module zrender/Layer + * @author pissang(https://www.github.com/pissang) + */ + + + var util = __webpack_require__(4); + var config = __webpack_require__(34); + var Style = __webpack_require__(22); + var Pattern = __webpack_require__(46); + + function returnFalse() { + return false; + } + + /** + * 创建dom + * + * @inner + * @param {string} id dom id 待用 + * @param {string} type dom type,such as canvas, div etc. + * @param {Painter} painter painter instance + * @param {number} number + */ + function createDom(id, type, painter, dpr) { + var newDom = document.createElement(type); + var width = painter.getWidth(); + var height = painter.getHeight(); + + var newDomStyle = newDom.style; + // 没append呢,请原谅我这样写,清晰~ + newDomStyle.position = 'absolute'; + newDomStyle.left = 0; + newDomStyle.top = 0; + newDomStyle.width = width + 'px'; + newDomStyle.height = height + 'px'; + newDom.width = width * dpr; + newDom.height = height * dpr; + + // id不作为索引用,避免可能造成的重名,定义为私有属性 + newDom.setAttribute('data-zr-dom-id', id); + return newDom; + } + + /** + * @alias module:zrender/Layer + * @constructor + * @extends module:zrender/mixin/Transformable + * @param {string} id + * @param {module:zrender/Painter} painter + * @param {number} [dpr] + */ + var Layer = function(id, painter, dpr) { + var dom; + dpr = dpr || config.devicePixelRatio; + if (typeof id === 'string') { + dom = createDom(id, 'canvas', painter, dpr); + } + // Not using isDom because in node it will return false + else if (util.isObject(id)) { + dom = id; + id = dom.id; + } + this.id = id; + this.dom = dom; + + var domStyle = dom.style; + if (domStyle) { // Not in node + dom.onselectstart = returnFalse; // 避免页面选中的尴尬 + domStyle['-webkit-user-select'] = 'none'; + domStyle['user-select'] = 'none'; + domStyle['-webkit-touch-callout'] = 'none'; + domStyle['-webkit-tap-highlight-color'] = 'rgba(0,0,0,0)'; + domStyle['padding'] = 0; + domStyle['margin'] = 0; + domStyle['border-width'] = 0; + } + + this.domBack = null; + this.ctxBack = null; + + this.painter = painter; + + this.config = null; + + // Configs + /** + * 每次清空画布的颜色 + * @type {string} + * @default 0 + */ + this.clearColor = 0; + /** + * 是否开启动态模糊 + * @type {boolean} + * @default false + */ + this.motionBlur = false; + /** + * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显 + * @type {number} + * @default 0.7 + */ + this.lastFrameAlpha = 0.7; + + /** + * Layer dpr + * @type {number} + */ + this.dpr = dpr; + }; + + Layer.prototype = { + + constructor: Layer, + + elCount: 0, + + __dirty: true, + + initContext: function () { + this.ctx = this.dom.getContext('2d'); + + this.ctx.dpr = this.dpr; + }, + + createBackBuffer: function () { + var dpr = this.dpr; + + this.domBack = createDom('back-' + this.id, 'canvas', this.painter, dpr); + this.ctxBack = this.domBack.getContext('2d'); + + if (dpr != 1) { + this.ctxBack.scale(dpr, dpr); + } + }, + + /** + * @param {number} width + * @param {number} height + */ + resize: function (width, height) { + var dpr = this.dpr; + + var dom = this.dom; + var domStyle = dom.style; + var domBack = this.domBack; + + domStyle.width = width + 'px'; + domStyle.height = height + 'px'; + + dom.width = width * dpr; + dom.height = height * dpr; + + if (domBack) { + domBack.width = width * dpr; + domBack.height = height * dpr; + + if (dpr != 1) { + this.ctxBack.scale(dpr, dpr); + } + } + }, + + /** + * 清空该层画布 + * @param {boolean} clearAll Clear all with out motion blur + */ + clear: function (clearAll) { + var dom = this.dom; + var ctx = this.ctx; + var width = dom.width; + var height = dom.height; + + var clearColor = this.clearColor; + var haveMotionBLur = this.motionBlur && !clearAll; + var lastFrameAlpha = this.lastFrameAlpha; + + var dpr = this.dpr; + + if (haveMotionBLur) { + if (!this.domBack) { + this.createBackBuffer(); + } + + this.ctxBack.globalCompositeOperation = 'copy'; + this.ctxBack.drawImage( + dom, 0, 0, + width / dpr, + height / dpr + ); + } + + ctx.clearRect(0, 0, width, height); + if (clearColor) { + var clearColorGradientOrPattern; + // Gradient + if (clearColor.colorStops) { + // Cache canvas gradient + clearColorGradientOrPattern = clearColor.__canvasGradient || Style.getGradient(ctx, clearColor, { + x: 0, + y: 0, + width: width, + height: height + }); + + clearColor.__canvasGradient = clearColorGradientOrPattern; + } + // Pattern + else if (clearColor.image) { + clearColorGradientOrPattern = Pattern.prototype.getCanvasPattern.call(clearColor, ctx); + } + ctx.save(); + ctx.fillStyle = clearColorGradientOrPattern || clearColor; + ctx.fillRect(0, 0, width, height); + ctx.restore(); + } + + if (haveMotionBLur) { + var domBack = this.domBack; + ctx.save(); + ctx.globalAlpha = lastFrameAlpha; + ctx.drawImage(domBack, 0, 0, width, height); + ctx.restore(); + } + } + }; + + module.exports = Layer; + + +/***/ }, +/* 94 */ +/***/ function(module, exports, __webpack_require__) { + + + var Gradient = __webpack_require__(66); + module.exports = function (ecModel) { + function encodeColor(seriesModel) { + var colorAccessPath = (seriesModel.visualColorAccessPath || 'itemStyle.normal.color').split('.'); + var data = seriesModel.getData(); + var color = seriesModel.get(colorAccessPath) // Set in itemStyle + || seriesModel.getColorFromPalette(seriesModel.get('name')); // Default color + + // FIXME Set color function or use the platte color + data.setVisual('color', color); + + // Only visible series has each data be visual encoded + if (!ecModel.isSeriesFiltered(seriesModel)) { + if (typeof color === 'function' && !(color instanceof Gradient)) { + data.each(function (idx) { + data.setItemVisual( + idx, 'color', color(seriesModel.getDataParams(idx)) + ); + }); + } + + // itemStyle in each data item + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var color = itemModel.get(colorAccessPath, true); + if (color != null) { + data.setItemVisual(idx, 'color', color); + } + }); + } + } + ecModel.eachRawSeries(encodeColor); + }; + + +/***/ }, +/* 95 */ +/***/ function(module, exports, __webpack_require__) { + + // Compatitable with 2.0 + + + var zrUtil = __webpack_require__(4); + var compatStyle = __webpack_require__(96); + + function get(opt, path) { + path = path.split(','); + var obj = opt; + for (var i = 0; i < path.length; i++) { + obj = obj && obj[path[i]]; + if (obj == null) { + break; + } + } + return obj; + } + + function set(opt, path, val, overwrite) { + path = path.split(','); + var obj = opt; + var key; + for (var i = 0; i < path.length - 1; i++) { + key = path[i]; + if (obj[key] == null) { + obj[key] = {}; + } + obj = obj[key]; + } + if (overwrite || obj[path[i]] == null) { + obj[path[i]] = val; + } + } + + function compatLayoutProperties(option) { + each(LAYOUT_PROPERTIES, function (prop) { + if (prop[0] in option && !(prop[1] in option)) { + option[prop[1]] = option[prop[0]]; + } + }); + } + + var LAYOUT_PROPERTIES = [ + ['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom'] + ]; + + var COMPATITABLE_COMPONENTS = [ + 'grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline' + ]; + + var COMPATITABLE_SERIES = [ + 'bar', 'boxplot', 'candlestick', 'chord', 'effectScatter', + 'funnel', 'gauge', 'lines', 'graph', 'heatmap', 'line', 'map', 'parallel', + 'pie', 'radar', 'sankey', 'scatter', 'treemap' + ]; + + var each = zrUtil.each; + + module.exports = function (option) { + each(option.series, function (seriesOpt) { + if (!zrUtil.isObject(seriesOpt)) { + return; + } + + var seriesType = seriesOpt.type; + + compatStyle(seriesOpt); + + if (seriesType === 'pie' || seriesType === 'gauge') { + if (seriesOpt.clockWise != null) { + seriesOpt.clockwise = seriesOpt.clockWise; + } + } + if (seriesType === 'gauge') { + var pointerColor = get(seriesOpt, 'pointer.color'); + pointerColor != null + && set(seriesOpt, 'itemStyle.normal.color', pointerColor); + } + + for (var i = 0; i < COMPATITABLE_SERIES.length; i++) { + if (COMPATITABLE_SERIES[i] === seriesOpt.type) { + compatLayoutProperties(seriesOpt); + break; + } + } + }); + + // dataRange has changed to visualMap + if (option.dataRange) { + option.visualMap = option.dataRange; + } + + each(COMPATITABLE_COMPONENTS, function (componentName) { + var options = option[componentName]; + if (options) { + if (!zrUtil.isArray(options)) { + options = [options]; + } + each(options, function (option) { + compatLayoutProperties(option); + }); + } + }); + }; + + +/***/ }, +/* 96 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var POSSIBLE_STYLES = [ + 'areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle', + 'chordStyle', 'label', 'labelLine' + ]; + + function compatItemStyle(opt) { + var itemStyleOpt = opt && opt.itemStyle; + if (itemStyleOpt) { + zrUtil.each(POSSIBLE_STYLES, function (styleName) { + var normalItemStyleOpt = itemStyleOpt.normal; + var emphasisItemStyleOpt = itemStyleOpt.emphasis; + if (normalItemStyleOpt && normalItemStyleOpt[styleName]) { + opt[styleName] = opt[styleName] || {}; + if (!opt[styleName].normal) { + opt[styleName].normal = normalItemStyleOpt[styleName]; + } + else { + zrUtil.merge(opt[styleName].normal, normalItemStyleOpt[styleName]); + } + normalItemStyleOpt[styleName] = null; + } + if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) { + opt[styleName] = opt[styleName] || {}; + if (!opt[styleName].emphasis) { + opt[styleName].emphasis = emphasisItemStyleOpt[styleName]; + } + else { + zrUtil.merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]); + } + emphasisItemStyleOpt[styleName] = null; + } + }); + } + } + + module.exports = function (seriesOpt) { + if (!seriesOpt) { + return; + } + compatItemStyle(seriesOpt); + compatItemStyle(seriesOpt.markPoint); + compatItemStyle(seriesOpt.markLine); + var data = seriesOpt.data; + if (data) { + for (var i = 0; i < data.length; i++) { + compatItemStyle(data[i]); + } + // mark point data + var markPoint = seriesOpt.markPoint; + if (markPoint && markPoint.data) { + var mpData = markPoint.data; + for (var i = 0; i < mpData.length; i++) { + compatItemStyle(mpData[i]); + } + } + // mark line data + var markLine = seriesOpt.markLine; + if (markLine && markLine.data) { + var mlData = markLine.data; + for (var i = 0; i < mlData.length; i++) { + if (zrUtil.isArray(mlData[i])) { + compatItemStyle(mlData[i][0]); + compatItemStyle(mlData[i][1]); + } + else { + compatItemStyle(mlData[i]); + } + } + } + } + }; + + +/***/ }, +/* 97 */ +/***/ function(module, exports, __webpack_require__) { + + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + var PI = Math.PI; + /** + * @param {module:echarts/ExtensionAPI} api + * @param {Object} [opts] + * @param {string} [opts.text] + * @param {string} [opts.color] + * @param {string} [opts.textColor] + * @return {module:zrender/Element} + */ + module.exports = function (api, opts) { + opts = opts || {}; + zrUtil.defaults(opts, { + text: 'loading', + color: '#c23531', + textColor: '#000', + maskColor: 'rgba(255, 255, 255, 0.8)', + zlevel: 0 + }); + var mask = new graphic.Rect({ + style: { + fill: opts.maskColor + }, + zlevel: opts.zlevel, + z: 10000 + }); + var arc = new graphic.Arc({ + shape: { + startAngle: -PI / 2, + endAngle: -PI / 2 + 0.1, + r: 10 + }, + style: { + stroke: opts.color, + lineCap: 'round', + lineWidth: 5 + }, + zlevel: opts.zlevel, + z: 10001 + }); + var labelRect = new graphic.Rect({ + style: { + fill: 'none', + text: opts.text, + textPosition: 'right', + textDistance: 10, + textFill: opts.textColor + }, + zlevel: opts.zlevel, + z: 10001 + }); + + arc.animateShape(true) + .when(1000, { + endAngle: PI * 3 / 2 + }) + .start('circularInOut'); + arc.animateShape(true) + .when(1000, { + startAngle: PI * 3 / 2 + }) + .delay(300) + .start('circularInOut'); + + var group = new graphic.Group(); + group.add(arc); + group.add(labelRect); + group.add(mask); + // Inject resize + group.resize = function () { + var cx = api.getWidth() / 2; + var cy = api.getHeight() / 2; + arc.setShape({ + cx: cx, + cy: cy + }); + var r = arc.shape.r; + labelRect.setShape({ + x: cx - r, + y: cy - r, + width: r * 2, + height: r * 2 + }); + + mask.setShape({ + x: 0, + y: 0, + width: api.getWidth(), + height: api.getHeight() + }); + }; + group.resize(); + return group; + }; + + +/***/ }, +/* 98 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * List for data storage + * @module echarts/data/List + */ + + + var UNDEFINED = 'undefined'; + var globalObj = typeof window === 'undefined' ? global : window; + var Float64Array = typeof globalObj.Float64Array === UNDEFINED + ? Array : globalObj.Float64Array; + var Int32Array = typeof globalObj.Int32Array === UNDEFINED + ? Array : globalObj.Int32Array; + + var dataCtors = { + 'float': Float64Array, + 'int': Int32Array, + // Ordinal data type can be string or int + 'ordinal': Array, + 'number': Array, + 'time': Array + }; + + var Model = __webpack_require__(12); + var DataDiffer = __webpack_require__(99); + + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var isObject = zrUtil.isObject; + + var TRANSFERABLE_PROPERTIES = [ + 'stackedOn', 'hasItemOption', '_nameList', '_idList', '_rawData' + ]; + + function transferProperties(a, b) { + zrUtil.each(TRANSFERABLE_PROPERTIES.concat(b.__wrappedMethods || []), function (propName) { + if (b.hasOwnProperty(propName)) { + a[propName] = b[propName]; + } + }); + + a.__wrappedMethods = b.__wrappedMethods; + } + + function DefaultDataProvider(dataArray) { + this._array = dataArray || []; + } + + DefaultDataProvider.prototype.pure = false; + + DefaultDataProvider.prototype.count = function () { + return this._array.length; + }; + DefaultDataProvider.prototype.getItem = function (idx) { + return this._array[idx]; + }; + + /** + * @constructor + * @alias module:echarts/data/List + * + * @param {Array.} dimensions + * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...]. + * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius + * @param {module:echarts/model/Model} hostModel + */ + var List = function (dimensions, hostModel) { + + dimensions = dimensions || ['x', 'y']; + + var dimensionInfos = {}; + var dimensionNames = []; + for (var i = 0; i < dimensions.length; i++) { + var dimensionName; + var dimensionInfo = {}; + if (typeof dimensions[i] === 'string') { + dimensionName = dimensions[i]; + dimensionInfo = { + name: dimensionName, + coordDim: dimensionName, + coordDimIndex: 0, + stackable: false, + // Type can be 'float', 'int', 'number' + // Default is number, Precision of float may not enough + type: 'number' + }; + } + else { + dimensionInfo = dimensions[i]; + dimensionName = dimensionInfo.name; + dimensionInfo.type = dimensionInfo.type || 'number'; + if (!dimensionInfo.coordDim) { + dimensionInfo.coordDim = dimensionName; + dimensionInfo.coordDimIndex = 0; + } + } + dimensionInfo.otherDims = dimensionInfo.otherDims || {}; + dimensionNames.push(dimensionName); + dimensionInfos[dimensionName] = dimensionInfo; + } + + /** + * @readOnly + * @type {Array.} + */ + this.dimensions = dimensionNames; + + /** + * Infomation of each data dimension, like data type. + * @type {Object} + */ + this._dimensionInfos = dimensionInfos; + + /** + * @type {module:echarts/model/Model} + */ + this.hostModel = hostModel; + + /** + * @type {module:echarts/model/Model} + */ + this.dataType; + + /** + * Indices stores the indices of data subset after filtered. + * This data subset will be used in chart. + * @type {Array.} + * @readOnly + */ + this.indices = []; + + /** + * Data storage + * @type {Object.} + * @private + */ + this._storage = {}; + + /** + * @type {Array.} + */ + this._nameList = []; + /** + * @type {Array.} + */ + this._idList = []; + + /** + * Models of data option is stored sparse for optimizing memory cost + * @type {Array.} + * @private + */ + this._optionModels = []; + + /** + * @param {module:echarts/data/List} + */ + this.stackedOn = null; + + /** + * Global visual properties after visual coding + * @type {Object} + * @private + */ + this._visual = {}; + + /** + * Globel layout properties. + * @type {Object} + * @private + */ + this._layout = {}; + + /** + * Item visual properties after visual coding + * @type {Array.} + * @private + */ + this._itemVisuals = []; + + /** + * Item layout properties after layout + * @type {Array.} + * @private + */ + this._itemLayouts = []; + + /** + * Graphic elemnents + * @type {Array.} + * @private + */ + this._graphicEls = []; + + /** + * @type {Array.} + * @private + */ + this._rawData; + + /** + * @type {Object} + * @private + */ + this._extent; + }; + + var listProto = List.prototype; + + listProto.type = 'list'; + + /** + * If each data item has it's own option + * @type {boolean} + */ + listProto.hasItemOption = true; + + /** + * Get dimension name + * @param {string|number} dim + * Dimension can be concrete names like x, y, z, lng, lat, angle, radius + * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius' + * @return {string} Concrete dim name. + */ + listProto.getDimension = function (dim) { + if (!isNaN(dim)) { + dim = this.dimensions[dim] || dim; + } + return dim; + }; + + /** + * Get type and stackable info of particular dimension + * @param {string|number} dim + * Dimension can be concrete names like x, y, z, lng, lat, angle, radius + * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius' + */ + listProto.getDimensionInfo = function (dim) { + return zrUtil.clone(this._dimensionInfos[this.getDimension(dim)]); + }; + + /** + * Initialize from data + * @param {Array.} data + * @param {Array.} [nameList] + * @param {Function} [dimValueGetter] (dataItem, dimName, dataIndex, dimIndex) => number + */ + listProto.initData = function (data, nameList, dimValueGetter) { + data = data || []; + + var isDataArray = zrUtil.isArray(data); + if (isDataArray) { + data = new DefaultDataProvider(data); + } + if (true) { + if (!isDataArray && (typeof data.getItem != 'function' || typeof data.count != 'function')) { + throw new Error('Inavlid data provider.'); + } + } + + this._rawData = data; + + // Clear + var storage = this._storage = {}; + var indices = this.indices = []; + + var dimensions = this.dimensions; + var dimensionInfoMap = this._dimensionInfos; + + var size = data.count(); + + var idList = []; + var nameRepeatCount = {}; + var nameDimIdx; + + nameList = nameList || []; + + // Init storage + for (var i = 0; i < dimensions.length; i++) { + var dimInfo = dimensionInfoMap[dimensions[i]]; + dimInfo.otherDims.itemName === 0 && (nameDimIdx = i); + var DataCtor = dataCtors[dimInfo.type]; + storage[dimensions[i]] = new DataCtor(size); + } + + var self = this; + if (!dimValueGetter) { + self.hasItemOption = false; + } + // Default dim value getter + dimValueGetter = dimValueGetter || function (dataItem, dimName, dataIndex, dimIndex) { + var value = modelUtil.getDataItemValue(dataItem); + // If any dataItem is like { value: 10 } + if (modelUtil.isDataItemOption(dataItem)) { + self.hasItemOption = true; + } + return modelUtil.converDataValue( + (value instanceof Array) + ? value[dimIndex] + // If value is a single number or something else not array. + : value, + dimensionInfoMap[dimName] + ); + }; + + for (var i = 0; i < size; i++) { + // NOTICE: Try not to write things into dataItem + var dataItem = data.getItem(i); + // Each data item is value + // [1, 2] + // 2 + // Bar chart, line chart which uses category axis + // only gives the 'y' value. 'x' value is the indices of cateogry + // Use a tempValue to normalize the value to be a (x, y) value + + // Store the data by dimensions + for (var k = 0; k < dimensions.length; k++) { + var dim = dimensions[k]; + var dimStorage = storage[dim]; + // PENDING NULL is empty or zero + dimStorage[i] = dimValueGetter(dataItem, dim, i, k); + } + + indices.push(i); + } + + // Use the name in option and create id + for (var i = 0; i < size; i++) { + var dataItem = data.getItem(i); + if (!nameList[i] && dataItem) { + if (dataItem.name != null) { + nameList[i] = dataItem.name; + } + else if (nameDimIdx != null) { + nameList[i] = storage[dimensions[nameDimIdx]][i]; + } + } + var name = nameList[i] || ''; + // Try using the id in option + var id = dataItem && dataItem.id; + + if (!id && name) { + // Use name as id and add counter to avoid same name + nameRepeatCount[name] = nameRepeatCount[name] || 0; + id = name; + if (nameRepeatCount[name] > 0) { + id += '__ec__' + nameRepeatCount[name]; + } + nameRepeatCount[name]++; + } + id && (idList[i] = id); + } + + this._nameList = nameList; + this._idList = idList; + }; + + /** + * @return {number} + */ + listProto.count = function () { + return this.indices.length; + }; + + /** + * Get value. Return NaN if idx is out of range. + * @param {string} dim Dim must be concrete name. + * @param {number} idx + * @param {boolean} stack + * @return {number} + */ + listProto.get = function (dim, idx, stack) { + var storage = this._storage; + var dataIndex = this.indices[idx]; + + // If value not exists + if (dataIndex == null || !storage[dim]) { + return NaN; + } + + var value = storage[dim][dataIndex]; + // FIXME ordinal data type is not stackable + if (stack) { + var dimensionInfo = this._dimensionInfos[dim]; + if (dimensionInfo && dimensionInfo.stackable) { + var stackedOn = this.stackedOn; + while (stackedOn) { + // Get no stacked data of stacked on + var stackedValue = stackedOn.get(dim, idx); + // Considering positive stack, negative stack and empty data + if ((value >= 0 && stackedValue > 0) // Positive stack + || (value <= 0 && stackedValue < 0) // Negative stack + ) { + value += stackedValue; + } + stackedOn = stackedOn.stackedOn; + } + } + } + return value; + }; + + /** + * Get value for multi dimensions. + * @param {Array.} [dimensions] If ignored, using all dimensions. + * @param {number} idx + * @param {boolean} stack + * @return {number} + */ + listProto.getValues = function (dimensions, idx, stack) { + var values = []; + + if (!zrUtil.isArray(dimensions)) { + stack = idx; + idx = dimensions; + dimensions = this.dimensions; + } + + for (var i = 0, len = dimensions.length; i < len; i++) { + values.push(this.get(dimensions[i], idx, stack)); + } + + return values; + }; + + /** + * If value is NaN. Inlcuding '-' + * @param {string} dim + * @param {number} idx + * @return {number} + */ + listProto.hasValue = function (idx) { + var dimensions = this.dimensions; + var dimensionInfos = this._dimensionInfos; + for (var i = 0, len = dimensions.length; i < len; i++) { + if ( + // Ordinal type can be string or number + dimensionInfos[dimensions[i]].type !== 'ordinal' + && isNaN(this.get(dimensions[i], idx)) + ) { + return false; + } + } + return true; + }; + + /** + * Get extent of data in one dimension + * @param {string} dim + * @param {boolean} stack + * @param {Function} filter + */ + listProto.getDataExtent = function (dim, stack, filter) { + dim = this.getDimension(dim); + var dimData = this._storage[dim]; + var dimInfo = this.getDimensionInfo(dim); + stack = (dimInfo && dimInfo.stackable) && stack; + var dimExtent = (this._extent || (this._extent = {}))[dim + (!!stack)]; + var value; + if (dimExtent) { + return dimExtent; + } + // var dimInfo = this._dimensionInfos[dim]; + if (dimData) { + var min = Infinity; + var max = -Infinity; + // var isOrdinal = dimInfo.type === 'ordinal'; + for (var i = 0, len = this.count(); i < len; i++) { + value = this.get(dim, i, stack); + // FIXME + // if (isOrdinal && typeof value === 'string') { + // value = zrUtil.indexOf(dimData, value); + // } + if (!filter || filter(value, dim, i)) { + value < min && (min = value); + value > max && (max = value); + } + } + return (this._extent[dim + !!stack] = [min, max]); + } + else { + return [Infinity, -Infinity]; + } + }; + + /** + * Get sum of data in one dimension + * @param {string} dim + * @param {boolean} stack + */ + listProto.getSum = function (dim, stack) { + var dimData = this._storage[dim]; + var sum = 0; + if (dimData) { + for (var i = 0, len = this.count(); i < len; i++) { + var value = this.get(dim, i, stack); + if (!isNaN(value)) { + sum += value; + } + } + } + return sum; + }; + + /** + * Retreive the index with given value + * @param {number} idx + * @param {number} value + * @return {number} + */ + // FIXME Precision of float value + listProto.indexOf = function (dim, value) { + var storage = this._storage; + var dimData = storage[dim]; + var indices = this.indices; + + if (dimData) { + for (var i = 0, len = indices.length; i < len; i++) { + var rawIndex = indices[i]; + if (dimData[rawIndex] === value) { + return i; + } + } + } + return -1; + }; + + /** + * Retreive the index with given name + * @param {number} idx + * @param {number} name + * @return {number} + */ + listProto.indexOfName = function (name) { + var indices = this.indices; + var nameList = this._nameList; + + for (var i = 0, len = indices.length; i < len; i++) { + var rawIndex = indices[i]; + if (nameList[rawIndex] === name) { + return i; + } + } + + return -1; + }; + + /** + * Retreive the index with given raw data index + * @param {number} idx + * @param {number} name + * @return {number} + */ + listProto.indexOfRawIndex = function (rawIndex) { + // Indices are ascending + var indices = this.indices; + + // If rawIndex === dataIndex + var rawDataIndex = indices[rawIndex]; + if (rawDataIndex != null && rawDataIndex === rawIndex) { + return rawIndex; + } + + var left = 0; + var right = indices.length - 1; + while (left <= right) { + var mid = (left + right) / 2 | 0; + if (indices[mid] < rawIndex) { + left = mid + 1; + } + else if (indices[mid] > rawIndex) { + right = mid - 1; + } + else { + return mid; + } + } + return -1; + }; + + /** + * Retreive the index of nearest value + * @param {string} dim + * @param {number} value + * @param {boolean} stack If given value is after stacked + * @param {number} [maxDistance=Infinity] + * @return {Array.} Considere multiple points has the same value. + */ + listProto.indicesOfNearest = function (dim, value, stack, maxDistance) { + var storage = this._storage; + var dimData = storage[dim]; + var nearestIndices = []; + + if (!dimData) { + return nearestIndices; + } + + if (maxDistance == null) { + maxDistance = Infinity; + } + + var minDist = Number.MAX_VALUE; + var minDiff = -1; + for (var i = 0, len = this.count(); i < len; i++) { + var diff = value - this.get(dim, i, stack); + var dist = Math.abs(diff); + if (diff <= maxDistance && dist <= minDist) { + // For the case of two data are same on xAxis, which has sequence data. + // Show the nearest index + // https://github.com/ecomfe/echarts/issues/2869 + if (dist < minDist || (diff >= 0 && minDiff < 0)) { + minDist = dist; + minDiff = diff; + nearestIndices.length = 0; + } + nearestIndices.push(i); + } + } + return nearestIndices; + }; + + /** + * Get raw data index + * @param {number} idx + * @return {number} + */ + listProto.getRawIndex = function (idx) { + var rawIdx = this.indices[idx]; + return rawIdx == null ? -1 : rawIdx; + }; + + /** + * Get raw data item + * @param {number} idx + * @return {number} + */ + listProto.getRawDataItem = function (idx) { + return this._rawData.getItem(this.getRawIndex(idx)); + }; + + /** + * @param {number} idx + * @param {boolean} [notDefaultIdx=false] + * @return {string} + */ + listProto.getName = function (idx) { + return this._nameList[this.indices[idx]] || ''; + }; + + /** + * @param {number} idx + * @param {boolean} [notDefaultIdx=false] + * @return {string} + */ + listProto.getId = function (idx) { + return this._idList[this.indices[idx]] || (this.getRawIndex(idx) + ''); + }; + + + function normalizeDimensions(dimensions) { + if (!zrUtil.isArray(dimensions)) { + dimensions = [dimensions]; + } + return dimensions; + } + + /** + * Data iteration + * @param {string|Array.} + * @param {Function} cb + * @param {boolean} [stack=false] + * @param {*} [context=this] + * + * @example + * list.each('x', function (x, idx) {}); + * list.each(['x', 'y'], function (x, y, idx) {}); + * list.each(function (idx) {}) + */ + listProto.each = function (dims, cb, stack, context) { + if (typeof dims === 'function') { + context = stack; + stack = cb; + cb = dims; + dims = []; + } + + dims = zrUtil.map(normalizeDimensions(dims), this.getDimension, this); + + var value = []; + var dimSize = dims.length; + var indices = this.indices; + + context = context || this; + + for (var i = 0; i < indices.length; i++) { + // Simple optimization + switch (dimSize) { + case 0: + cb.call(context, i); + break; + case 1: + cb.call(context, this.get(dims[0], i, stack), i); + break; + case 2: + cb.call(context, this.get(dims[0], i, stack), this.get(dims[1], i, stack), i); + break; + default: + for (var k = 0; k < dimSize; k++) { + value[k] = this.get(dims[k], i, stack); + } + // Index + value[k] = i; + cb.apply(context, value); + } + } + }; + + /** + * Data filter + * @param {string|Array.} + * @param {Function} cb + * @param {boolean} [stack=false] + * @param {*} [context=this] + */ + listProto.filterSelf = function (dimensions, cb, stack, context) { + if (typeof dimensions === 'function') { + context = stack; + stack = cb; + cb = dimensions; + dimensions = []; + } + + dimensions = zrUtil.map( + normalizeDimensions(dimensions), this.getDimension, this + ); + + var newIndices = []; + var value = []; + var dimSize = dimensions.length; + var indices = this.indices; + + context = context || this; + + for (var i = 0; i < indices.length; i++) { + var keep; + // Simple optimization + if (!dimSize) { + keep = cb.call(context, i); + } + else if (dimSize === 1) { + keep = cb.call( + context, this.get(dimensions[0], i, stack), i + ); + } + else { + for (var k = 0; k < dimSize; k++) { + value[k] = this.get(dimensions[k], i, stack); + } + value[k] = i; + keep = cb.apply(context, value); + } + if (keep) { + newIndices.push(indices[i]); + } + } + + this.indices = newIndices; + + // Reset data extent + this._extent = {}; + + return this; + }; + + /** + * Data mapping to a plain array + * @param {string|Array.} [dimensions] + * @param {Function} cb + * @param {boolean} [stack=false] + * @param {*} [context=this] + * @return {Array} + */ + listProto.mapArray = function (dimensions, cb, stack, context) { + if (typeof dimensions === 'function') { + context = stack; + stack = cb; + cb = dimensions; + dimensions = []; + } + + var result = []; + this.each(dimensions, function () { + result.push(cb && cb.apply(this, arguments)); + }, stack, context); + return result; + }; + + function cloneListForMapAndSample(original, excludeDimensions) { + var allDimensions = original.dimensions; + var list = new List( + zrUtil.map(allDimensions, original.getDimensionInfo, original), + original.hostModel + ); + // FIXME If needs stackedOn, value may already been stacked + transferProperties(list, original); + + var storage = list._storage = {}; + var originalStorage = original._storage; + // Init storage + for (var i = 0; i < allDimensions.length; i++) { + var dim = allDimensions[i]; + var dimStore = originalStorage[dim]; + if (zrUtil.indexOf(excludeDimensions, dim) >= 0) { + storage[dim] = new dimStore.constructor( + originalStorage[dim].length + ); + } + else { + // Direct reference for other dimensions + storage[dim] = originalStorage[dim]; + } + } + return list; + } + + /** + * Data mapping to a new List with given dimensions + * @param {string|Array.} dimensions + * @param {Function} cb + * @param {boolean} [stack=false] + * @param {*} [context=this] + * @return {Array} + */ + listProto.map = function (dimensions, cb, stack, context) { + dimensions = zrUtil.map( + normalizeDimensions(dimensions), this.getDimension, this + ); + + var list = cloneListForMapAndSample(this, dimensions); + // Following properties are all immutable. + // So we can reference to the same value + var indices = list.indices = this.indices; + + var storage = list._storage; + + var tmpRetValue = []; + this.each(dimensions, function () { + var idx = arguments[arguments.length - 1]; + var retValue = cb && cb.apply(this, arguments); + if (retValue != null) { + // a number + if (typeof retValue === 'number') { + tmpRetValue[0] = retValue; + retValue = tmpRetValue; + } + for (var i = 0; i < retValue.length; i++) { + var dim = dimensions[i]; + var dimStore = storage[dim]; + var rawIdx = indices[idx]; + if (dimStore) { + dimStore[rawIdx] = retValue[i]; + } + } + } + }, stack, context); + + return list; + }; + + /** + * Large data down sampling on given dimension + * @param {string} dimension + * @param {number} rate + * @param {Function} sampleValue + * @param {Function} sampleIndex Sample index for name and id + */ + listProto.downSample = function (dimension, rate, sampleValue, sampleIndex) { + var list = cloneListForMapAndSample(this, [dimension]); + var storage = this._storage; + var targetStorage = list._storage; + + var originalIndices = this.indices; + var indices = list.indices = []; + + var frameValues = []; + var frameIndices = []; + var frameSize = Math.floor(1 / rate); + + var dimStore = targetStorage[dimension]; + var len = this.count(); + // Copy data from original data + for (var i = 0; i < storage[dimension].length; i++) { + targetStorage[dimension][i] = storage[dimension][i]; + } + for (var i = 0; i < len; i += frameSize) { + // Last frame + if (frameSize > len - i) { + frameSize = len - i; + frameValues.length = frameSize; + } + for (var k = 0; k < frameSize; k++) { + var idx = originalIndices[i + k]; + frameValues[k] = dimStore[idx]; + frameIndices[k] = idx; + } + var value = sampleValue(frameValues); + var idx = frameIndices[sampleIndex(frameValues, value) || 0]; + // Only write value on the filtered data + dimStore[idx] = value; + indices.push(idx); + } + + return list; + }; + + /** + * Get model of one data item. + * + * @param {number} idx + */ + // FIXME Model proxy ? + listProto.getItemModel = function (idx) { + var hostModel = this.hostModel; + idx = this.indices[idx]; + return new Model(this._rawData.getItem(idx), hostModel, hostModel && hostModel.ecModel); + }; + + /** + * Create a data differ + * @param {module:echarts/data/List} otherList + * @return {module:echarts/data/DataDiffer} + */ + listProto.diff = function (otherList) { + var idList = this._idList; + var otherIdList = otherList && otherList._idList; + var val; + // Use prefix to avoid index to be the same as otherIdList[idx], + // which will cause weird udpate animation. + var prefix = 'e\0\0'; + + return new DataDiffer( + otherList ? otherList.indices : [], + this.indices, + function (idx) { + return (val = otherIdList[idx]) != null ? val : prefix + idx; + }, + function (idx) { + return (val = idList[idx]) != null ? val : prefix + idx; + } + ); + }; + /** + * Get visual property. + * @param {string} key + */ + listProto.getVisual = function (key) { + var visual = this._visual; + return visual && visual[key]; + }; + + /** + * Set visual property + * @param {string|Object} key + * @param {*} [value] + * + * @example + * setVisual('color', color); + * setVisual({ + * 'color': color + * }); + */ + listProto.setVisual = function (key, val) { + if (isObject(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + this.setVisual(name, key[name]); + } + } + return; + } + this._visual = this._visual || {}; + this._visual[key] = val; + }; + + /** + * Set layout property. + * @param {string} key + * @param {*} [val] + */ + listProto.setLayout = function (key, val) { + if (isObject(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + this.setLayout(name, key[name]); + } + } + return; + } + this._layout[key] = val; + }; + + /** + * Get layout property. + * @param {string} key. + * @return {*} + */ + listProto.getLayout = function (key) { + return this._layout[key]; + }; + + /** + * Get layout of single data item + * @param {number} idx + */ + listProto.getItemLayout = function (idx) { + return this._itemLayouts[idx]; + }; + + /** + * Set layout of single data item + * @param {number} idx + * @param {Object} layout + * @param {boolean=} [merge=false] + */ + listProto.setItemLayout = function (idx, layout, merge) { + this._itemLayouts[idx] = merge + ? zrUtil.extend(this._itemLayouts[idx] || {}, layout) + : layout; + }; + + /** + * Clear all layout of single data item + */ + listProto.clearItemLayouts = function () { + this._itemLayouts.length = 0; + }; + + /** + * Get visual property of single data item + * @param {number} idx + * @param {string} key + * @param {boolean} [ignoreParent=false] + */ + listProto.getItemVisual = function (idx, key, ignoreParent) { + var itemVisual = this._itemVisuals[idx]; + var val = itemVisual && itemVisual[key]; + if (val == null && !ignoreParent) { + // Use global visual property + return this.getVisual(key); + } + return val; + }; + + /** + * Set visual property of single data item + * + * @param {number} idx + * @param {string|Object} key + * @param {*} [value] + * + * @example + * setItemVisual(0, 'color', color); + * setItemVisual(0, { + * 'color': color + * }); + */ + listProto.setItemVisual = function (idx, key, value) { + var itemVisual = this._itemVisuals[idx] || {}; + this._itemVisuals[idx] = itemVisual; + + if (isObject(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + itemVisual[name] = key[name]; + } + } + return; + } + itemVisual[key] = value; + }; + + /** + * Clear itemVisuals and list visual. + */ + listProto.clearAllVisual = function () { + this._visual = {}; + this._itemVisuals = []; + }; + + var setItemDataAndSeriesIndex = function (child) { + child.seriesIndex = this.seriesIndex; + child.dataIndex = this.dataIndex; + child.dataType = this.dataType; + }; + /** + * Set graphic element relative to data. It can be set as null + * @param {number} idx + * @param {module:zrender/Element} [el] + */ + listProto.setItemGraphicEl = function (idx, el) { + var hostModel = this.hostModel; + + if (el) { + // Add data index and series index for indexing the data by element + // Useful in tooltip + el.dataIndex = idx; + el.dataType = this.dataType; + el.seriesIndex = hostModel && hostModel.seriesIndex; + if (el.type === 'group') { + el.traverse(setItemDataAndSeriesIndex, el); + } + } + + this._graphicEls[idx] = el; + }; + + /** + * @param {number} idx + * @return {module:zrender/Element} + */ + listProto.getItemGraphicEl = function (idx) { + return this._graphicEls[idx]; + }; + + /** + * @param {Function} cb + * @param {*} context + */ + listProto.eachItemGraphicEl = function (cb, context) { + zrUtil.each(this._graphicEls, function (el, idx) { + if (el) { + cb && cb.call(context, el, idx); + } + }); + }; + + /** + * Shallow clone a new list except visual and layout properties, and graph elements. + * New list only change the indices. + */ + listProto.cloneShallow = function () { + var dimensionInfoList = zrUtil.map(this.dimensions, this.getDimensionInfo, this); + var list = new List(dimensionInfoList, this.hostModel); + + // FIXME + list._storage = this._storage; + + transferProperties(list, this); + + + // Clone will not change the data extent and indices + list.indices = this.indices.slice(); + + if (this._extent) { + list._extent = zrUtil.extend({}, this._extent); + } + + return list; + }; + + /** + * Wrap some method to add more feature + * @param {string} methodName + * @param {Function} injectFunction + */ + listProto.wrapMethod = function (methodName, injectFunction) { + var originalMethod = this[methodName]; + if (typeof originalMethod !== 'function') { + return; + } + this.__wrappedMethods = this.__wrappedMethods || []; + this.__wrappedMethods.push(methodName); + this[methodName] = function () { + var res = originalMethod.apply(this, arguments); + return injectFunction.apply(this, [res].concat(zrUtil.slice(arguments))); + }; + }; + + // Methods that create a new list based on this list should be listed here. + // Notice that those method should `RETURN` the new list. + listProto.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'map']; + // Methods that change indices of this list should be listed here. + listProto.CHANGABLE_METHODS = ['filterSelf']; + + module.exports = List; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 99 */ +/***/ function(module, exports) { + + 'use strict'; + + + function defaultKeyGetter(item) { + return item; + } + + function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter) { + this._old = oldArr; + this._new = newArr; + + this._oldKeyGetter = oldKeyGetter || defaultKeyGetter; + this._newKeyGetter = newKeyGetter || defaultKeyGetter; + } + + DataDiffer.prototype = { + + constructor: DataDiffer, + + /** + * Callback function when add a data + */ + add: function (func) { + this._add = func; + return this; + }, + + /** + * Callback function when update a data + */ + update: function (func) { + this._update = func; + return this; + }, + + /** + * Callback function when remove a data + */ + remove: function (func) { + this._remove = func; + return this; + }, + + execute: function () { + var oldArr = this._old; + var newArr = this._new; + var oldKeyGetter = this._oldKeyGetter; + var newKeyGetter = this._newKeyGetter; + + var oldDataIndexMap = {}; + var newDataIndexMap = {}; + var oldDataKeyArr = []; + var newDataKeyArr = []; + var i; + + initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, oldKeyGetter); + initIndexMap(newArr, newDataIndexMap, newDataKeyArr, newKeyGetter); + + // Travel by inverted order to make sure order consistency + // when duplicate keys exists (consider newDataIndex.pop() below). + // For performance consideration, these code below do not look neat. + for (i = 0; i < oldArr.length; i++) { + var key = oldDataKeyArr[i]; + var idx = newDataIndexMap[key]; + + // idx can never be empty array here. see 'set null' logic below. + if (idx != null) { + // Consider there is duplicate key (for example, use dataItem.name as key). + // We should make sure every item in newArr and oldArr can be visited. + var len = idx.length; + if (len) { + len === 1 && (newDataIndexMap[key] = null); + idx = idx.unshift(); + } + else { + newDataIndexMap[key] = null; + } + this._update && this._update(idx, i); + } + else { + this._remove && this._remove(i); + } + } + + for (var i = 0; i < newDataKeyArr.length; i++) { + var key = newDataKeyArr[i]; + if (newDataIndexMap.hasOwnProperty(key)) { + var idx = newDataIndexMap[key]; + if (idx == null) { + continue; + } + // idx can never be empty array here. see 'set null' logic above. + if (!idx.length) { + this._add && this._add(idx); + } + else { + for (var j = 0, len = idx.length; j < len; j++) { + this._add && this._add(idx[j]); + } + } + } + } + } + }; + + function initIndexMap(arr, map, keyArr, keyGetter) { + for (var i = 0; i < arr.length; i++) { + // Add prefix to avoid conflict with Object.prototype. + var key = '_ec_' + keyGetter(arr[i], i); + var existence = map[key]; + if (existence == null) { + keyArr.push(key); + map[key] = i; + } + else { + if (!existence.length) { + map[key] = existence = [existence]; + } + existence.push(i); + } + } + } + + module.exports = DataDiffer; + + +/***/ }, +/* 100 */ +/***/ function(module, exports, __webpack_require__) { + + + + var numberUtil = __webpack_require__(7); + var linearMap = numberUtil.linearMap; + var zrUtil = __webpack_require__(4); + var axisHelper = __webpack_require__(101); + + function fixExtentWithBands(extent, nTick) { + var size = extent[1] - extent[0]; + var len = nTick; + var margin = size / len / 2; + extent[0] += margin; + extent[1] -= margin; + } + + var normalizedExtent = [0, 1]; + /** + * @name module:echarts/coord/CartesianAxis + * @constructor + */ + var Axis = function (dim, scale, extent) { + + /** + * Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius' + * @type {string} + */ + this.dim = dim; + + /** + * Axis scale + * @type {module:echarts/coord/scale/*} + */ + this.scale = scale; + + /** + * @type {Array.} + * @private + */ + this._extent = extent || [0, 0]; + + /** + * @type {boolean} + */ + this.inverse = false; + + /** + * Usually true when axis has a ordinal scale + * @type {boolean} + */ + this.onBand = false; + + /** + * @private + * @type {number} + */ + this._labelInterval; + }; + + Axis.prototype = { + + constructor: Axis, + + /** + * If axis extent contain given coord + * @param {number} coord + * @return {boolean} + */ + contain: function (coord) { + var extent = this._extent; + var min = Math.min(extent[0], extent[1]); + var max = Math.max(extent[0], extent[1]); + return coord >= min && coord <= max; + }, + + /** + * If axis extent contain given data + * @param {number} data + * @return {boolean} + */ + containData: function (data) { + return this.contain(this.dataToCoord(data)); + }, + + /** + * Get coord extent. + * @return {Array.} + */ + getExtent: function () { + return this._extent.slice(); + }, + + /** + * Get precision used for formatting + * @param {Array.} [dataExtent] + * @return {number} + */ + getPixelPrecision: function (dataExtent) { + return numberUtil.getPixelPrecision( + dataExtent || this.scale.getExtent(), + this._extent + ); + }, + + /** + * Set coord extent + * @param {number} start + * @param {number} end + */ + setExtent: function (start, end) { + var extent = this._extent; + extent[0] = start; + extent[1] = end; + }, + + /** + * Convert data to coord. Data is the rank if it has a ordinal scale + * @param {number} data + * @param {boolean} clamp + * @return {number} + */ + dataToCoord: function (data, clamp) { + var extent = this._extent; + var scale = this.scale; + data = scale.normalize(data); + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + return linearMap(data, normalizedExtent, extent, clamp); + }, + + /** + * Convert coord to data. Data is the rank if it has a ordinal scale + * @param {number} coord + * @param {boolean} clamp + * @return {number} + */ + coordToData: function (coord, clamp) { + var extent = this._extent; + var scale = this.scale; + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + var t = linearMap(coord, extent, normalizedExtent, clamp); + + return this.scale.scale(t); + }, + + /** + * Convert pixel point to data in axis + * @param {Array.} point + * @param {boolean} clamp + * @return {number} data + */ + pointToData: function (point, clamp) { + // Should be implemented in derived class if necessary. + }, + + /** + * @return {Array.} + */ + getTicksCoords: function (alignWithLabel) { + if (this.onBand && !alignWithLabel) { + var bands = this.getBands(); + var coords = []; + for (var i = 0; i < bands.length; i++) { + coords.push(bands[i][0]); + } + if (bands[i - 1]) { + coords.push(bands[i - 1][1]); + } + return coords; + } + else { + return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this); + } + }, + + /** + * Coords of labels are on the ticks or on the middle of bands + * @return {Array.} + */ + getLabelsCoords: function () { + return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this); + }, + + /** + * Get bands. + * + * If axis has labels [1, 2, 3, 4]. Bands on the axis are + * |---1---|---2---|---3---|---4---|. + * + * @return {Array} + */ + // FIXME Situation when labels is on ticks + getBands: function () { + var extent = this.getExtent(); + var bands = []; + var len = this.scale.count(); + var start = extent[0]; + var end = extent[1]; + var span = end - start; + + for (var i = 0; i < len; i++) { + bands.push([ + span * i / len + start, + span * (i + 1) / len + start + ]); + } + return bands; + }, + + /** + * Get width of band + * @return {number} + */ + getBandWidth: function () { + var axisExtent = this._extent; + var dataExtent = this.scale.getExtent(); + + var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); + // Fix #2728, avoid NaN when only one data. + len === 0 && (len = 1); + + var size = Math.abs(axisExtent[1] - axisExtent[0]); + + return Math.abs(size) / len; + }, + + /** + * Get interval of the axis label. + * @return {number} + */ + getLabelInterval: function () { + var labelInterval = this._labelInterval; + if (!labelInterval) { + var axisModel = this.model; + var labelModel = axisModel.getModel('axisLabel'); + var interval = labelModel.get('interval'); + if (!(this.type === 'category' && interval === 'auto')) { + labelInterval = interval === 'auto' ? 0 : interval; + } + else if (this.isHorizontal){ + labelInterval = axisHelper.getAxisLabelInterval( + zrUtil.map(this.scale.getTicks(), this.dataToCoord, this), + axisModel.getFormattedLabels(), + labelModel.getModel('textStyle').getFont(), + this.isHorizontal() + ); + } + this._labelInterval = labelInterval; + } + return labelInterval; + } + + }; + + module.exports = Axis; + + +/***/ }, +/* 101 */ +/***/ function(module, exports, __webpack_require__) { + + + + var OrdinalScale = __webpack_require__(102); + var IntervalScale = __webpack_require__(104); + __webpack_require__(106); + __webpack_require__(107); + var Scale = __webpack_require__(103); + + var numberUtil = __webpack_require__(7); + var zrUtil = __webpack_require__(4); + var textContain = __webpack_require__(8); + var axisHelper = {}; + + /** + * Get axis scale extent before niced. + * Item of returned array can only be number (including Infinity and NaN). + */ + axisHelper.getScaleExtent = function (scale, model) { + var scaleType = scale.type; + + var min = model.getMin(); + var max = model.getMax(); + var fixMin = min != null; + var fixMax = max != null; + var originalExtent = scale.getExtent(); + + var axisDataLen; + var boundaryGap; + var span; + if (scaleType === 'ordinal') { + axisDataLen = (model.get('data') || []).length; + } + else { + boundaryGap = model.get('boundaryGap'); + if (!zrUtil.isArray(boundaryGap)) { + boundaryGap = [boundaryGap || 0, boundaryGap || 0]; + } + if (typeof boundaryGap[0] === 'boolean') { + if (true) { + console.warn('Boolean type for boundaryGap is only ' + + 'allowed for ordinal axis. Please use string in ' + + 'percentage instead, e.g., "20%". Currently, ' + + 'boundaryGap is set to be 0.'); + } + boundaryGap = [0, 0]; + } + boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], 1); + boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], 1); + span = (originalExtent[1] - originalExtent[0]) + || Math.abs(originalExtent[0]); + } + + // Notice: When min/max is not set (that is, when there are null/undefined, + // which is the most common case), these cases should be ensured: + // (1) For 'ordinal', show all axis.data. + // (2) For others: + // + `boundaryGap` is applied (if min/max set, boundaryGap is + // disabled). + // + If `needCrossZero`, min/max should be zero, otherwise, min/max should + // be the result that originalExtent enlarged by boundaryGap. + // (3) If no data, it should be ensured that `scale.setBlank` is set. + + // FIXME + // (1) When min/max is 'dataMin' or 'dataMax', should boundaryGap be able to used? + // (2) When `needCrossZero` and all data is positive/negative, should it be ensured + // that the results processed by boundaryGap are positive/negative? + + if (min == null) { + min = scaleType === 'ordinal' + ? (axisDataLen ? 0 : NaN) + : originalExtent[0] - boundaryGap[0] * span; + } + if (max == null) { + max = scaleType === 'ordinal' + ? (axisDataLen ? axisDataLen - 1 : NaN) + : originalExtent[1] + boundaryGap[1] * span; + } + + if (min === 'dataMin') { + min = originalExtent[0]; + } + if (max === 'dataMax') { + max = originalExtent[1]; + } + + (min == null || !isFinite(min)) && (min = NaN); + (max == null || !isFinite(max)) && (max = NaN); + + scale.setBlank(zrUtil.eqNaN(min) || zrUtil.eqNaN(max)); + + // Evaluate if axis needs cross zero + if (model.getNeedCrossZero()) { + // Axis is over zero and min is not set + if (min > 0 && max > 0 && !fixMin) { + min = 0; + } + // Axis is under zero and max is not set + if (min < 0 && max < 0 && !fixMax) { + max = 0; + } + } + + return [min, max]; + }; + + axisHelper.niceScaleExtent = function (scale, model) { + var extent = axisHelper.getScaleExtent(scale, model); + var fixMin = model.getMin() != null; + var fixMax = model.getMax() != null; + var splitNumber = model.get('splitNumber'); + + if (scale.type === 'log') { + scale.base = model.get('logBase'); + } + + scale.setExtent(extent[0], extent[1]); + scale.niceExtent({ + splitNumber: splitNumber, + fixMin: fixMin, + fixMax: fixMax, + minInterval: scale.type === 'interval' ? model.get('minInterval') : null + }); + + // If some one specified the min, max. And the default calculated interval + // is not good enough. He can specify the interval. It is often appeared + // in angle axis with angle 0 - 360. Interval calculated in interval scale is hard + // to be 60. + // FIXME + var interval = model.get('interval'); + if (interval != null) { + scale.setInterval && scale.setInterval(interval); + } + }; + + /** + * @param {module:echarts/model/Model} model + * @param {string} [axisType] Default retrieve from model.type + * @return {module:echarts/scale/*} + */ + axisHelper.createScaleByModel = function(model, axisType) { + axisType = axisType || model.get('type'); + if (axisType) { + switch (axisType) { + // Buildin scale + case 'category': + return new OrdinalScale( + model.getCategories(), [Infinity, -Infinity] + ); + case 'value': + return new IntervalScale(); + // Extended scale, like time and log + default: + return (Scale.getClass(axisType) || IntervalScale).create(model); + } + } + }; + + /** + * Check if the axis corss 0 + */ + axisHelper.ifAxisCrossZero = function (axis) { + var dataExtent = axis.scale.getExtent(); + var min = dataExtent[0]; + var max = dataExtent[1]; + return !((min > 0 && max > 0) || (min < 0 && max < 0)); + }; + + /** + * @param {Array.} tickCoords In axis self coordinate. + * @param {Array.} labels + * @param {string} font + * @param {boolean} isAxisHorizontal + * @return {number} + */ + axisHelper.getAxisLabelInterval = function (tickCoords, labels, font, isAxisHorizontal) { + // FIXME + // 不同角的axis和label,不只是horizontal和vertical. + + var textSpaceTakenRect; + var autoLabelInterval = 0; + var accumulatedLabelInterval = 0; + + var step = 1; + if (labels.length > 40) { + // Simple optimization for large amount of labels + step = Math.floor(labels.length / 40); + } + + for (var i = 0; i < tickCoords.length; i += step) { + var tickCoord = tickCoords[i]; + var rect = textContain.getBoundingRect( + labels[i], font, 'center', 'top' + ); + rect[isAxisHorizontal ? 'x' : 'y'] += tickCoord; + // FIXME Magic number 1.5 + rect[isAxisHorizontal ? 'width' : 'height'] *= 1.3; + if (!textSpaceTakenRect) { + textSpaceTakenRect = rect.clone(); + } + // There is no space for current label; + else if (textSpaceTakenRect.intersect(rect)) { + accumulatedLabelInterval++; + autoLabelInterval = Math.max(autoLabelInterval, accumulatedLabelInterval); + } + else { + textSpaceTakenRect.union(rect); + // Reset + accumulatedLabelInterval = 0; + } + } + if (autoLabelInterval === 0 && step > 1) { + return step; + } + return (autoLabelInterval + 1) * step - 1; + }; + + /** + * @param {Object} axis + * @param {Function} labelFormatter + * @return {Array.} + */ + axisHelper.getFormattedLabels = function (axis, labelFormatter) { + var scale = axis.scale; + var labels = scale.getTicksLabels(); + var ticks = scale.getTicks(); + if (typeof labelFormatter === 'string') { + labelFormatter = (function (tpl) { + return function (val) { + return tpl.replace('{value}', val != null ? val : ''); + }; + })(labelFormatter); + // Consider empty array + return zrUtil.map(labels, labelFormatter); + } + else if (typeof labelFormatter === 'function') { + return zrUtil.map(ticks, function (tick, idx) { + return labelFormatter( + axisHelper.getAxisRawValue(axis, tick), + idx + ); + }, this); + } + else { + return labels; + } + }; + + axisHelper.getAxisRawValue = function (axis, value) { + // In category axis with data zoom, tick is not the original + // index of axis.data. So tick should not be exposed to user + // in category axis. + return axis.type === 'category' ? axis.scale.getLabel(value) : value; + }; + + module.exports = axisHelper; + + +/***/ }, +/* 102 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Linear continuous scale + * @module echarts/coord/scale/Ordinal + * + * http://en.wikipedia.org/wiki/Level_of_measurement + */ + + // FIXME only one data + + + var zrUtil = __webpack_require__(4); + var Scale = __webpack_require__(103); + + var scaleProto = Scale.prototype; + + var OrdinalScale = Scale.extend({ + + type: 'ordinal', + + init: function (data, extent) { + this._data = data; + this._extent = extent || [0, data.length - 1]; + }, + + parse: function (val) { + return typeof val === 'string' + ? zrUtil.indexOf(this._data, val) + // val might be float. + : Math.round(val); + }, + + contain: function (rank) { + rank = this.parse(rank); + return scaleProto.contain.call(this, rank) + && this._data[rank] != null; + }, + + /** + * Normalize given rank or name to linear [0, 1] + * @param {number|string} [val] + * @return {number} + */ + normalize: function (val) { + return scaleProto.normalize.call(this, this.parse(val)); + }, + + scale: function (val) { + return Math.round(scaleProto.scale.call(this, val)); + }, + + /** + * @return {Array} + */ + getTicks: function () { + var ticks = []; + var extent = this._extent; + var rank = extent[0]; + + while (rank <= extent[1]) { + ticks.push(rank); + rank++; + } + + return ticks; + }, + + /** + * Get item on rank n + * @param {number} n + * @return {string} + */ + getLabel: function (n) { + return this._data[n]; + }, + + /** + * @return {number} + */ + count: function () { + return this._extent[1] - this._extent[0] + 1; + }, + + /** + * @override + */ + unionExtentFromData: function (data, dim) { + this.unionExtent(data.getDataExtent(dim, false)); + }, + + niceTicks: zrUtil.noop, + niceExtent: zrUtil.noop + }); + + /** + * @return {module:echarts/scale/Time} + */ + OrdinalScale.create = function () { + return new OrdinalScale(); + }; + + module.exports = OrdinalScale; + + +/***/ }, +/* 103 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * // Scale class management + * @module echarts/scale/Scale + */ + + + var clazzUtil = __webpack_require__(13); + + /** + * @param {Object} [setting] + */ + function Scale(setting) { + this._setting = setting || {}; + + /** + * Extent + * @type {Array.} + * @protected + */ + this._extent = [Infinity, -Infinity]; + + /** + * Step is calculated in adjustExtent + * @type {Array.} + * @protected + */ + this._interval = 0; + + this.init && this.init.apply(this, arguments); + } + + var scaleProto = Scale.prototype; + + /** + * Parse input val to valid inner number. + * @param {*} val + * @return {number} + */ + scaleProto.parse = function (val) { + // Notice: This would be a trap here, If the implementation + // of this method depends on extent, and this method is used + // before extent set (like in dataZoom), it would be wrong. + // Nevertheless, parse does not depend on extent generally. + return val; + }; + + scaleProto.getSetting = function (name) { + return this._setting[name]; + }; + + scaleProto.contain = function (val) { + var extent = this._extent; + return val >= extent[0] && val <= extent[1]; + }; + + /** + * Normalize value to linear [0, 1], return 0.5 if extent span is 0 + * @param {number} val + * @return {number} + */ + scaleProto.normalize = function (val) { + var extent = this._extent; + if (extent[1] === extent[0]) { + return 0.5; + } + return (val - extent[0]) / (extent[1] - extent[0]); + }; + + /** + * Scale normalized value + * @param {number} val + * @return {number} + */ + scaleProto.scale = function (val) { + var extent = this._extent; + return val * (extent[1] - extent[0]) + extent[0]; + }; + + /** + * Set extent from data + * @param {Array.} other + */ + scaleProto.unionExtent = function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); + // not setExtent because in log axis it may transformed to power + // this.setExtent(extent[0], extent[1]); + }; + + /** + * Set extent from data + * @param {module:echarts/data/List} data + * @param {string} dim + */ + scaleProto.unionExtentFromData = function (data, dim) { + this.unionExtent(data.getDataExtent(dim, true)); + }; + + /** + * Get extent + * @return {Array.} + */ + scaleProto.getExtent = function () { + return this._extent.slice(); + }; + + /** + * Set extent + * @param {number} start + * @param {number} end + */ + scaleProto.setExtent = function (start, end) { + var thisExtent = this._extent; + if (!isNaN(start)) { + thisExtent[0] = start; + } + if (!isNaN(end)) { + thisExtent[1] = end; + } + }; + + /** + * @return {Array.} + */ + scaleProto.getTicksLabels = function () { + var labels = []; + var ticks = this.getTicks(); + for (var i = 0; i < ticks.length; i++) { + labels.push(this.getLabel(ticks[i])); + } + return labels; + }; + + /** + * When axis extent depends on data and no data exists, + * axis ticks should not be drawn, which is named 'blank'. + */ + scaleProto.isBlank = function () { + return this._isBlank; + }, + + /** + * When axis extent depends on data and no data exists, + * axis ticks should not be drawn, which is named 'blank'. + */ + scaleProto.setBlank = function (isBlank) { + this._isBlank = isBlank; + }; + + + clazzUtil.enableClassExtend(Scale); + clazzUtil.enableClassManagement(Scale, { + registerWhenExtend: true + }); + + module.exports = Scale; + + +/***/ }, +/* 104 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Interval scale + * @module echarts/scale/Interval + */ + + + + var numberUtil = __webpack_require__(7); + var formatUtil = __webpack_require__(6); + var Scale = __webpack_require__(103); + var helper = __webpack_require__(105); + + var roundNumber = numberUtil.round; + + /** + * @alias module:echarts/coord/scale/Interval + * @constructor + */ + var IntervalScale = Scale.extend({ + + type: 'interval', + + _interval: 0, + + _intervalPrecision: 2, + + setExtent: function (start, end) { + var thisExtent = this._extent; + //start,end may be a Number like '25',so... + if (!isNaN(start)) { + thisExtent[0] = parseFloat(start); + } + if (!isNaN(end)) { + thisExtent[1] = parseFloat(end); + } + }, + + unionExtent: function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); + + // unionExtent may called by it's sub classes + IntervalScale.prototype.setExtent.call(this, extent[0], extent[1]); + }, + /** + * Get interval + */ + getInterval: function () { + return this._interval; + }, + + /** + * Set interval + */ + setInterval: function (interval) { + this._interval = interval; + // Dropped auto calculated niceExtent and use user setted extent + // We assume user wan't to set both interval, min, max to get a better result + this._niceExtent = this._extent.slice(); + + this._intervalPrecision = helper.getIntervalPrecision(interval); + }, + + /** + * @return {Array.} + */ + getTicks: function () { + return helper.intervalScaleGetTicks( + this._interval, this._extent, this._niceExtent, this._intervalPrecision + ); + }, + + /** + * @return {Array.} + */ + getTicksLabels: function () { + var labels = []; + var ticks = this.getTicks(); + for (var i = 0; i < ticks.length; i++) { + labels.push(this.getLabel(ticks[i])); + } + return labels; + }, + + /** + * @param {number} data + * @param {Object} [opt] + * @param {number|string} [opt.precision] If 'auto', use nice presision. + * @param {boolean} [opt.pad] returns 1.50 but not 1.5 if precision is 2. + * @return {string} + */ + getLabel: function (data, opt) { + if (data == null) { + return ''; + } + + var precision = opt && opt.precision; + + if (precision == null) { + precision = numberUtil.getPrecisionSafe(data) || 0; + } + else if (precision === 'auto') { + // Should be more precise then tick. + precision = this._intervalPrecision; + } + + // (1) If `precision` is set, 12.005 should be display as '12.00500'. + // (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'. + data = roundNumber(data, precision, true); + + return formatUtil.addCommas(data); + }, + + /** + * Update interval and extent of intervals for nice ticks + * + * @param {number} [splitNumber = 5] Desired number of ticks + * @param {number} [minInterval] + */ + niceTicks: function (splitNumber, minInterval) { + splitNumber = splitNumber || 5; + var extent = this._extent; + var span = extent[1] - extent[0]; + if (!isFinite(span)) { + return; + } + // User may set axis min 0 and data are all negative + // FIXME If it needs to reverse ? + if (span < 0) { + span = -span; + extent.reverse(); + } + + var result = helper.intervalScaleNiceTicks(extent, splitNumber, minInterval); + + this._intervalPrecision = result.intervalPrecision; + this._interval = result.interval; + this._niceExtent = result.niceTickExtent; + }, + + /** + * Nice extent. + * @param {Object} opt + * @param {number} [opt.splitNumber = 5] Given approx tick number + * @param {boolean} [opt.fixMin=false] + * @param {boolean} [opt.fixMax=false] + * @param {boolean} [opt.minInterval=false] + */ + niceExtent: function (opt) { + var extent = this._extent; + // If extent start and end are same, expand them + if (extent[0] === extent[1]) { + if (extent[0] !== 0) { + // Expand extent + var expandSize = extent[0]; + // In the fowllowing case + // Axis has been fixed max 100 + // Plus data are all 100 and axis extent are [100, 100]. + // Extend to the both side will cause expanded max is larger than fixed max. + // So only expand to the smaller side. + if (!opt.fixMax) { + extent[1] += expandSize / 2; + extent[0] -= expandSize / 2; + } + else { + extent[0] -= expandSize / 2; + } + } + else { + extent[1] = 1; + } + } + var span = extent[1] - extent[0]; + // If there are no data and extent are [Infinity, -Infinity] + if (!isFinite(span)) { + extent[0] = 0; + extent[1] = 1; + } + + this.niceTicks(opt.splitNumber, opt.minInterval); + + // var extent = this._extent; + var interval = this._interval; + + if (!opt.fixMin) { + extent[0] = roundNumber(Math.floor(extent[0] / interval) * interval); + } + if (!opt.fixMax) { + extent[1] = roundNumber(Math.ceil(extent[1] / interval) * interval); + } + } + }); + + /** + * @return {module:echarts/scale/Time} + */ + IntervalScale.create = function () { + return new IntervalScale(); + }; + + module.exports = IntervalScale; + + + +/***/ }, +/* 105 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * For testable. + */ + + + var numberUtil = __webpack_require__(7); + + var roundNumber = numberUtil.round; + + var helper = {}; + + /** + * @param {Array.} extent Both extent[0] and extent[1] should be valid number. + * Should be extent[0] < extent[1]. + * @param {number} splitNumber splitNumber should be >= 1. + * @param {number} [minInterval] + * @return {Object} {interval, intervalPrecision, niceTickExtent} + */ + helper.intervalScaleNiceTicks = function (extent, splitNumber, minInterval) { + var result = {}; + var span = extent[1] - extent[0]; + + var interval = result.interval = numberUtil.nice(span / splitNumber, true); + if (minInterval != null && interval < minInterval) { + interval = result.interval = minInterval; + } + // Tow more digital for tick. + var precision = result.intervalPrecision = helper.getIntervalPrecision(interval); + // Niced extent inside original extent + var niceTickExtent = result.niceTickExtent = [ + roundNumber(Math.ceil(extent[0] / interval) * interval, precision), + roundNumber(Math.floor(extent[1] / interval) * interval, precision) + ]; + + helper.fixExtent(niceTickExtent, extent); + + return result; + }; + + /** + * @param {number} interval + * @return {number} interval precision + */ + helper.getIntervalPrecision = function (interval) { + // Tow more digital for tick. + return numberUtil.getPrecisionSafe(interval) + 2; + }; + + function clamp(niceTickExtent, idx, extent) { + niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]); + } + + // In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent. + helper.fixExtent = function (niceTickExtent, extent) { + !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]); + !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]); + clamp(niceTickExtent, 0, extent); + clamp(niceTickExtent, 1, extent); + if (niceTickExtent[0] > niceTickExtent[1]) { + niceTickExtent[0] = niceTickExtent[1]; + } + }; + + helper.intervalScaleGetTicks = function (interval, extent, niceTickExtent, intervalPrecision) { + var ticks = []; + + // If interval is 0, return []; + if (!interval) { + return ticks; + } + + // Consider this case: using dataZoom toolbox, zoom and zoom. + var safeLimit = 10000; + + if (extent[0] < niceTickExtent[0]) { + ticks.push(extent[0]); + } + var tick = niceTickExtent[0]; + + while (tick <= niceTickExtent[1]) { + ticks.push(tick); + // Avoid rounding error + tick = roundNumber(tick + interval, intervalPrecision); + if (tick === ticks[ticks.length - 1]) { + // Consider out of safe float point, e.g., + // -3711126.9907707 + 2e-10 === -3711126.9907707 + break; + } + if (ticks.length > safeLimit) { + return []; + } + } + // Consider this case: the last item of ticks is smaller + // than niceTickExtent[1] and niceTickExtent[1] === extent[1]. + if (extent[1] > (ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1])) { + ticks.push(extent[1]); + } + + return ticks; + }; + + module.exports = helper; + + +/***/ }, +/* 106 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Interval scale + * @module echarts/coord/scale/Time + */ + + + + // [About UTC and local time zone]: + // In most cases, `number.parseDate` will treat input data string as local time + // (except time zone is specified in time string). And `format.formateTime` returns + // local time by default. option.useUTC is false by default. This design have + // concidered these common case: + // (1) Time that is persistent in server is in UTC, but it is needed to be diplayed + // in local time by default. + // (2) By default, the input data string (e.g., '2011-01-02') should be displayed + // as its original time, without any time difference. + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var formatUtil = __webpack_require__(6); + var scaleHelper = __webpack_require__(105); + + var IntervalScale = __webpack_require__(104); + + var intervalScaleProto = IntervalScale.prototype; + + var mathCeil = Math.ceil; + var mathFloor = Math.floor; + var ONE_SECOND = 1000; + var ONE_MINUTE = ONE_SECOND * 60; + var ONE_HOUR = ONE_MINUTE * 60; + var ONE_DAY = ONE_HOUR * 24; + + // FIXME 公用? + var bisect = function (a, x, lo, hi) { + while (lo < hi) { + var mid = lo + hi >>> 1; + if (a[mid][2] < x) { + lo = mid + 1; + } + else { + hi = mid; + } + } + return lo; + }; + + /** + * @alias module:echarts/coord/scale/Time + * @constructor + */ + var TimeScale = IntervalScale.extend({ + type: 'time', + + /** + * @override + */ + getLabel: function (val) { + var stepLvl = this._stepLvl; + + var date = new Date(val); + + return formatUtil.formatTime(stepLvl[0], date, this.getSetting('useUTC')); + }, + + /** + * @override + */ + niceExtent: function (opt) { + var extent = this._extent; + // If extent start and end are same, expand them + if (extent[0] === extent[1]) { + // Expand extent + extent[0] -= ONE_DAY; + extent[1] += ONE_DAY; + } + // If there are no data and extent are [Infinity, -Infinity] + if (extent[1] === -Infinity && extent[0] === Infinity) { + var d = new Date(); + extent[1] = new Date(d.getFullYear(), d.getMonth(), d.getDate()); + extent[0] = extent[1] - ONE_DAY; + } + + this.niceTicks(opt.splitNumber); + + // var extent = this._extent; + var interval = this._interval; + + if (!opt.fixMin) { + extent[0] = numberUtil.round(mathFloor(extent[0] / interval) * interval); + } + if (!opt.fixMax) { + extent[1] = numberUtil.round(mathCeil(extent[1] / interval) * interval); + } + }, + + /** + * @override + */ + niceTicks: function (approxTickNum) { + var timezoneOffset = this.getSetting('useUTC') + ? 0 : numberUtil.getTimezoneOffset() * 60 * 1000; + approxTickNum = approxTickNum || 10; + + var extent = this._extent; + var span = extent[1] - extent[0]; + var approxInterval = span / approxTickNum; + var scaleLevelsLen = scaleLevels.length; + var idx = bisect(scaleLevels, approxInterval, 0, scaleLevelsLen); + + var level = scaleLevels[Math.min(idx, scaleLevelsLen - 1)]; + var interval = level[2]; + // Same with interval scale if span is much larger than 1 year + if (level[0] === 'year') { + var yearSpan = span / interval; + + // From "Nice Numbers for Graph Labels" of Graphic Gems + // var niceYearSpan = numberUtil.nice(yearSpan, false); + var yearStep = numberUtil.nice(yearSpan / approxTickNum, true); + + interval *= yearStep; + } + + var niceExtent = [ + Math.round(mathCeil((extent[0] - timezoneOffset) / interval) * interval + timezoneOffset), + Math.round(mathFloor((extent[1] - timezoneOffset)/ interval) * interval + timezoneOffset) + ]; + + scaleHelper.fixExtent(niceExtent, extent); + + this._stepLvl = level; + // Interval will be used in getTicks + this._interval = interval; + this._niceExtent = niceExtent; + }, + + parse: function (val) { + // val might be float. + return +numberUtil.parseDate(val); + } + }); + + zrUtil.each(['contain', 'normalize'], function (methodName) { + TimeScale.prototype[methodName] = function (val) { + return intervalScaleProto[methodName].call(this, this.parse(val)); + }; + }); + + // Steps from d3 + var scaleLevels = [ + // Format step interval + ['hh:mm:ss', 1, ONE_SECOND], // 1s + ['hh:mm:ss', 5, ONE_SECOND * 5], // 5s + ['hh:mm:ss', 10, ONE_SECOND * 10], // 10s + ['hh:mm:ss', 15, ONE_SECOND * 15], // 15s + ['hh:mm:ss', 30, ONE_SECOND * 30], // 30s + ['hh:mm\nMM-dd',1, ONE_MINUTE], // 1m + ['hh:mm\nMM-dd',5, ONE_MINUTE * 5], // 5m + ['hh:mm\nMM-dd',10, ONE_MINUTE * 10], // 10m + ['hh:mm\nMM-dd',15, ONE_MINUTE * 15], // 15m + ['hh:mm\nMM-dd',30, ONE_MINUTE * 30], // 30m + ['hh:mm\nMM-dd',1, ONE_HOUR], // 1h + ['hh:mm\nMM-dd',2, ONE_HOUR * 2], // 2h + ['hh:mm\nMM-dd',6, ONE_HOUR * 6], // 6h + ['hh:mm\nMM-dd',12, ONE_HOUR * 12], // 12h + ['MM-dd\nyyyy', 1, ONE_DAY], // 1d + ['week', 7, ONE_DAY * 7], // 7d + ['month', 1, ONE_DAY * 31], // 1M + ['quarter', 3, ONE_DAY * 380 / 4], // 3M + ['half-year', 6, ONE_DAY * 380 / 2], // 6M + ['year', 1, ONE_DAY * 380] // 1Y + ]; + + /** + * @param {module:echarts/model/Model} + * @return {module:echarts/scale/Time} + */ + TimeScale.create = function (model) { + return new TimeScale({useUTC: model.ecModel.get('useUTC')}); + }; + + module.exports = TimeScale; + + +/***/ }, +/* 107 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Log scale + * @module echarts/scale/Log + */ + + + var zrUtil = __webpack_require__(4); + var Scale = __webpack_require__(103); + var numberUtil = __webpack_require__(7); + + // Use some method of IntervalScale + var IntervalScale = __webpack_require__(104); + + var scaleProto = Scale.prototype; + var intervalScaleProto = IntervalScale.prototype; + + var getPrecisionSafe = numberUtil.getPrecisionSafe; + var roundingErrorFix = numberUtil.round; + + var mathFloor = Math.floor; + var mathCeil = Math.ceil; + var mathPow = Math.pow; + + var mathLog = Math.log; + + var LogScale = Scale.extend({ + + type: 'log', + + base: 10, + + $constructor: function () { + Scale.apply(this, arguments); + this._originalScale = new IntervalScale(); + }, + + /** + * @return {Array.} + */ + getTicks: function () { + var originalScale = this._originalScale; + var extent = this._extent; + var originalExtent = originalScale.getExtent(); + + return zrUtil.map(intervalScaleProto.getTicks.call(this), function (val) { + var powVal = numberUtil.round(mathPow(this.base, val)); + + // Fix #4158 + powVal = (val === extent[0] && originalScale.__fixMin) + ? fixRoundingError(powVal, originalExtent[0]) + : powVal; + powVal = (val === extent[1] && originalScale.__fixMax) + ? fixRoundingError(powVal, originalExtent[1]) + : powVal; + + return powVal; + }, this); + }, + + /** + * @param {number} val + * @return {string} + */ + getLabel: intervalScaleProto.getLabel, + + /** + * @param {number} val + * @return {number} + */ + scale: function (val) { + val = scaleProto.scale.call(this, val); + return mathPow(this.base, val); + }, + + /** + * @param {number} start + * @param {number} end + */ + setExtent: function (start, end) { + var base = this.base; + start = mathLog(start) / mathLog(base); + end = mathLog(end) / mathLog(base); + intervalScaleProto.setExtent.call(this, start, end); + }, + + /** + * @return {number} end + */ + getExtent: function () { + var base = this.base; + var extent = scaleProto.getExtent.call(this); + extent[0] = mathPow(base, extent[0]); + extent[1] = mathPow(base, extent[1]); + + // Fix #4158 + var originalScale = this._originalScale; + var originalExtent = originalScale.getExtent(); + originalScale.__fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0])); + originalScale.__fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1])); + + return extent; + }, + + /** + * @param {Array.} extent + */ + unionExtent: function (extent) { + this._originalScale.unionExtent(extent); + + var base = this.base; + extent[0] = mathLog(extent[0]) / mathLog(base); + extent[1] = mathLog(extent[1]) / mathLog(base); + scaleProto.unionExtent.call(this, extent); + }, + + /** + * @override + */ + unionExtentFromData: function (data, dim) { + this.unionExtent(data.getDataExtent(dim, true, function (val) { + return val > 0; + })); + }, + + /** + * Update interval and extent of intervals for nice ticks + * @param {number} [approxTickNum = 10] Given approx tick number + */ + niceTicks: function (approxTickNum) { + approxTickNum = approxTickNum || 10; + var extent = this._extent; + var span = extent[1] - extent[0]; + if (span === Infinity || span <= 0) { + return; + } + + var interval = numberUtil.quantity(span); + var err = approxTickNum / span * interval; + + // Filter ticks to get closer to the desired count. + if (err <= 0.5) { + interval *= 10; + } + + // Interval should be integer + while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) { + interval *= 10; + } + + var niceExtent = [ + numberUtil.round(mathCeil(extent[0] / interval) * interval), + numberUtil.round(mathFloor(extent[1] / interval) * interval) + ]; + + this._interval = interval; + this._niceExtent = niceExtent; + }, + + /** + * Nice extent. + * @override + */ + niceExtent: function (opt) { + intervalScaleProto.niceExtent.call(this, opt); + + var originalScale = this._originalScale; + originalScale.__fixMin = opt.fixMin; + originalScale.__fixMax = opt.fixMax; + } + + }); + + zrUtil.each(['contain', 'normalize'], function (methodName) { + LogScale.prototype[methodName] = function (val) { + val = mathLog(val) / mathLog(this.base); + return scaleProto[methodName].call(this, val); + }; + }); + + LogScale.create = function () { + return new LogScale(); + }; + + function fixRoundingError(val, originalVal) { + return roundingErrorFix(val, getPrecisionSafe(originalVal)); + } + + module.exports = LogScale; + + +/***/ }, +/* 108 */ +/***/ function(module, exports, __webpack_require__) { + + + + var createListFromArray = __webpack_require__(109); + var symbolUtil = __webpack_require__(111); + var axisHelper = __webpack_require__(101); + var axisModelCommonMixin = __webpack_require__(112); + var Model = __webpack_require__(12); + var util = __webpack_require__(4); + + module.exports = { + /** + * Create a muti dimension List structure from seriesModel. + * @param {module:echarts/model/Model} seriesModel + * @return {module:echarts/data/List} list + */ + createList: function (seriesModel) { + var data = seriesModel.get('data'); + return createListFromArray(data, seriesModel, seriesModel.ecModel); + }, + + /** + * @see {module:echarts/data/helper/completeDimensions} + */ + completeDimensions: __webpack_require__(110), + + /** + * Create a symbol element with given symbol configuration: shape, x, y, width, height, color + * @see http://echarts.baidu.com/option.html#series-scatter.symbol + * @param {string} symbolDesc + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {string} color + */ + createSymbol: symbolUtil.createSymbol, + + /** + * Create scale + * @param {Array.} dataExtent + * @param {Object|module:echarts/Model} option + */ + createScale: function (dataExtent, option) { + var axisModel = option; + if (!(option instanceof Model)) { + axisModel = new Model(option); + util.mixin(axisModel, axisModelCommonMixin); + } + + var scale = axisHelper.createScaleByModel(axisModel); + scale.setExtent(dataExtent[0], dataExtent[1]); + + axisHelper.niceScaleExtent(scale, axisModel); + return scale; + }, + + /** + * Mixin common methods to axis model, + * + * Inlcude methods + * `getFormattedLabels() => Array.` + * `getCategories() => Array.` + * `getMin(origin: boolean) => number` + * `getMax(origin: boolean) => number` + * `getNeedCrossZero() => boolean` + * `setRange(start: number, end: number)` + * `resetRange()` + */ + mixinAxisModelCommonMethods: function (Model) { + util.mixin(Model, axisModelCommonMixin); + } + }; + + +/***/ }, +/* 109 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var List = __webpack_require__(98); + var completeDimensions = __webpack_require__(110); + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var CoordinateSystem = __webpack_require__(76); + var getDataItemValue = modelUtil.getDataItemValue; + var converDataValue = modelUtil.converDataValue; + + function firstDataNotNull(data) { + var i = 0; + while (i < data.length && data[i] == null) { + i++; + } + return data[i]; + } + function ifNeedCompleteOrdinalData(data) { + var sampleItem = firstDataNotNull(data); + return sampleItem != null + && !zrUtil.isArray(getDataItemValue(sampleItem)); + } + + /** + * Helper function to create a list from option data + */ + function createListFromArray(data, seriesModel, ecModel) { + // If data is undefined + data = data || []; + + if (true) { + if (!zrUtil.isArray(data)) { + throw new Error('Invalid data.'); + } + } + + var coordSysName = seriesModel.get('coordinateSystem'); + var creator = creators[coordSysName]; + var registeredCoordSys = CoordinateSystem.get(coordSysName); + var completeDimOpt = { + encodeDef: seriesModel.get('encode'), + dimsDef: seriesModel.get('dimensions') + }; + + // FIXME + var axesInfo = creator && creator(data, seriesModel, ecModel, completeDimOpt); + var dimensions = axesInfo && axesInfo.dimensions; + if (!dimensions) { + // Get dimensions from registered coordinate system + dimensions = (registeredCoordSys && ( + registeredCoordSys.getDimensionsInfo + ? registeredCoordSys.getDimensionsInfo() + : registeredCoordSys.dimensions.slice() + )) || ['x', 'y']; + dimensions = completeDimensions(dimensions, data, completeDimOpt); + } + + var categoryIndex = axesInfo ? axesInfo.categoryIndex : -1; + + var list = new List(dimensions, seriesModel); + + var nameList = createNameList(axesInfo, data); + + var categories = {}; + var dimValueGetter = (categoryIndex >= 0 && ifNeedCompleteOrdinalData(data)) + ? function (itemOpt, dimName, dataIndex, dimIndex) { + // If any dataItem is like { value: 10 } + if (modelUtil.isDataItemOption(itemOpt)) { + list.hasItemOption = true; + } + + // Use dataIndex as ordinal value in categoryAxis + return dimIndex === categoryIndex + ? dataIndex + : converDataValue(getDataItemValue(itemOpt), dimensions[dimIndex]); + } + : function (itemOpt, dimName, dataIndex, dimIndex) { + var value = getDataItemValue(itemOpt); + var val = converDataValue(value && value[dimIndex], dimensions[dimIndex]); + // If any dataItem is like { value: 10 } + if (modelUtil.isDataItemOption(itemOpt)) { + list.hasItemOption = true; + } + + var categoryAxesModels = axesInfo && axesInfo.categoryAxesModels; + if (categoryAxesModels && categoryAxesModels[dimName]) { + // If given value is a category string + if (typeof val === 'string') { + // Lazy get categories + categories[dimName] = categories[dimName] + || categoryAxesModels[dimName].getCategories(); + val = zrUtil.indexOf(categories[dimName], val); + if (val < 0 && !isNaN(val)) { + // In case some one write '1', '2' istead of 1, 2 + val = +val; + } + } + } + return val; + }; + + list.hasItemOption = false; + list.initData(data, nameList, dimValueGetter); + + return list; + } + + function isStackable(axisType) { + return axisType !== 'category' && axisType !== 'time'; + } + + function getDimTypeByAxis(axisType) { + return axisType === 'category' + ? 'ordinal' + : axisType === 'time' + ? 'time' + : 'float'; + } + + /** + * Creaters for each coord system. + */ + var creators = { + + cartesian2d: function (data, seriesModel, ecModel, completeDimOpt) { + + var axesModels = zrUtil.map(['xAxis', 'yAxis'], function (name) { + return ecModel.queryComponents({ + mainType: name, + index: seriesModel.get(name + 'Index'), + id: seriesModel.get(name + 'Id') + })[0]; + }); + var xAxisModel = axesModels[0]; + var yAxisModel = axesModels[1]; + + if (true) { + if (!xAxisModel) { + throw new Error('xAxis "' + zrUtil.retrieve( + seriesModel.get('xAxisIndex'), + seriesModel.get('xAxisId'), + 0 + ) + '" not found'); + } + if (!yAxisModel) { + throw new Error('yAxis "' + zrUtil.retrieve( + seriesModel.get('xAxisIndex'), + seriesModel.get('yAxisId'), + 0 + ) + '" not found'); + } + } + + var xAxisType = xAxisModel.get('type'); + var yAxisType = yAxisModel.get('type'); + + var dimensions = [ + { + name: 'x', + type: getDimTypeByAxis(xAxisType), + stackable: isStackable(xAxisType) + }, + { + name: 'y', + // If two category axes + type: getDimTypeByAxis(yAxisType), + stackable: isStackable(yAxisType) + } + ]; + + var isXAxisCateogry = xAxisType === 'category'; + var isYAxisCategory = yAxisType === 'category'; + + dimensions = completeDimensions(dimensions, data, completeDimOpt); + + var categoryAxesModels = {}; + if (isXAxisCateogry) { + categoryAxesModels.x = xAxisModel; + } + if (isYAxisCategory) { + categoryAxesModels.y = yAxisModel; + } + return { + dimensions: dimensions, + categoryIndex: isXAxisCateogry ? 0 : (isYAxisCategory ? 1 : -1), + categoryAxesModels: categoryAxesModels + }; + }, + + singleAxis: function (data, seriesModel, ecModel, completeDimOpt) { + + var singleAxisModel = ecModel.queryComponents({ + mainType: 'singleAxis', + index: seriesModel.get('singleAxisIndex'), + id: seriesModel.get('singleAxisId') + })[0]; + + if (true) { + if (!singleAxisModel) { + throw new Error('singleAxis should be specified.'); + } + } + + var singleAxisType = singleAxisModel.get('type'); + var isCategory = singleAxisType === 'category'; + + var dimensions = [{ + name: 'single', + type: getDimTypeByAxis(singleAxisType), + stackable: isStackable(singleAxisType) + }]; + + dimensions = completeDimensions(dimensions, data, completeDimOpt); + + var categoryAxesModels = {}; + if (isCategory) { + categoryAxesModels.single = singleAxisModel; + } + + return { + dimensions: dimensions, + categoryIndex: isCategory ? 0 : -1, + categoryAxesModels: categoryAxesModels + }; + }, + + polar: function (data, seriesModel, ecModel, completeDimOpt) { + var polarModel = ecModel.queryComponents({ + mainType: 'polar', + index: seriesModel.get('polarIndex'), + id: seriesModel.get('polarId') + })[0]; + + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + + if (true) { + if (!angleAxisModel) { + throw new Error('angleAxis option not found'); + } + if (!radiusAxisModel) { + throw new Error('radiusAxis option not found'); + } + } + + var radiusAxisType = radiusAxisModel.get('type'); + var angleAxisType = angleAxisModel.get('type'); + + var dimensions = [ + { + name: 'radius', + type: getDimTypeByAxis(radiusAxisType), + stackable: isStackable(radiusAxisType) + }, + { + name: 'angle', + type: getDimTypeByAxis(angleAxisType), + stackable: isStackable(angleAxisType) + } + ]; + var isAngleAxisCateogry = angleAxisType === 'category'; + var isRadiusAxisCateogry = radiusAxisType === 'category'; + + dimensions = completeDimensions(dimensions, data, completeDimOpt); + + var categoryAxesModels = {}; + if (isRadiusAxisCateogry) { + categoryAxesModels.radius = radiusAxisModel; + } + if (isAngleAxisCateogry) { + categoryAxesModels.angle = angleAxisModel; + } + return { + dimensions: dimensions, + categoryIndex: isAngleAxisCateogry ? 1 : (isRadiusAxisCateogry ? 0 : -1), + categoryAxesModels: categoryAxesModels + }; + }, + + geo: function (data, seriesModel, ecModel, completeDimOpt) { + // TODO Region + // 多个散点图系列在同一个地区的时候 + return { + dimensions: completeDimensions([ + {name: 'lng'}, + {name: 'lat'} + ], data, completeDimOpt) + }; + } + }; + + function createNameList(result, data) { + var nameList = []; + + var categoryDim = result && result.dimensions[result.categoryIndex]; + var categoryAxisModel; + if (categoryDim) { + categoryAxisModel = result.categoryAxesModels[categoryDim.name]; + } + + if (categoryAxisModel) { + // FIXME Two category axis + var categories = categoryAxisModel.getCategories(); + if (categories) { + var dataLen = data.length; + // Ordered data is given explicitly like + // [[3, 0.2], [1, 0.3], [2, 0.15]] + // or given scatter data, + // pick the category + if (zrUtil.isArray(data[0]) && data[0].length > 1) { + nameList = []; + for (var i = 0; i < dataLen; i++) { + nameList[i] = categories[data[i][result.categoryIndex || 0]]; + } + } + else { + nameList = categories.slice(0); + } + } + } + + return nameList; + } + + module.exports = createListFromArray; + + + +/***/ }, +/* 110 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Complete dimensions by data (guess dimension). + */ + + + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var each = zrUtil.each; + var isString = zrUtil.isString; + var defaults = zrUtil.defaults; + var normalizeToArray = modelUtil.normalizeToArray; + + var OTHER_DIMS = {tooltip: 1, label: 1, itemName: 1}; + + /** + * Complete the dimensions array, by user defined `dimension` and `encode`, + * and guessing from the data structure. + * If no 'value' dimension specified, the first no-named dimension will be + * named as 'value'. + * + * @param {Array.} sysDims Necessary dimensions, like ['x', 'y'], which + * provides not only dim template, but also default order. + * `name` of each item provides default coord name. + * [{dimsDef: []}, ...] can be specified to give names. + * @param {Array} data Data list. [[1, 2, 3], [2, 3, 4]]. + * @param {Object} [opt] + * @param {Array.} [opt.dimsDef] option.series.dimensions User defined dimensions + * For example: ['asdf', {name, type}, ...]. + * @param {Object} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3} + * @param {string} [opt.extraPrefix] Prefix of name when filling the left dimensions. + * @param {string} [opt.extraFromZero] If specified, extra dim names will be: + * extraPrefix + 0, extraPrefix + extraBaseIndex + 1 ... + * If not specified, extra dim names will be: + * extraPrefix, extraPrefix + 0, extraPrefix + 1 ... + * @param {number} [opt.dimCount] If not specified, guess by the first data item. + * @return {Array.} [{ + * name: string mandatory, + * coordDim: string mandatory, + * coordDimIndex: number mandatory, + * type: string optional, + * tooltipName: string optional, + * otherDims: { + * tooltip: number optional, + * label: number optional + * }, + * isExtraCoord: boolean true or undefined. + * other props ... + * }] + */ + function completeDimensions(sysDims, data, opt) { + data = data || []; + opt = opt || {}; + sysDims = (sysDims || []).slice(); + var dimsDef = (opt.dimsDef || []).slice(); + var encodeDef = zrUtil.createHashMap(opt.encodeDef); + var dataDimNameMap = zrUtil.createHashMap(); + var coordDimNameMap = zrUtil.createHashMap(); + // var valueCandidate; + var result = []; + + var dimCount = opt.dimCount; + if (dimCount == null) { + var value0 = retrieveValue(data[0]); + dimCount = Math.max( + zrUtil.isArray(value0) && value0.length || 1, + sysDims.length, + dimsDef.length + ); + each(sysDims, function (sysDimItem) { + var sysDimItemDimsDef = sysDimItem.dimsDef; + sysDimItemDimsDef && (dimCount = Math.max(dimCount, sysDimItemDimsDef.length)); + }); + } + + // Apply user defined dims (`name` and `type`) and init result. + for (var i = 0; i < dimCount; i++) { + var dimDefItem = isString(dimsDef[i]) ? {name: dimsDef[i]} : (dimsDef[i] || {}); + var userDimName = dimDefItem.name; + var resultItem = result[i] = {otherDims: {}}; + // Name will be applied later for avoiding duplication. + if (userDimName != null && dataDimNameMap.get(userDimName) == null) { + // Only if `series.dimensions` is defined in option, tooltipName + // will be set, and dimension will be diplayed vertically in + // tooltip by default. + resultItem.name = resultItem.tooltipName = userDimName; + dataDimNameMap.set(userDimName, i); + } + dimDefItem.type != null && (resultItem.type = dimDefItem.type); + } + + // Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`. + encodeDef.each(function (dataDims, coordDim) { + dataDims = encodeDef.set(coordDim, normalizeToArray(dataDims).slice()); + each(dataDims, function (resultDimIdx, coordDimIndex) { + // The input resultDimIdx can be dim name or index. + isString(resultDimIdx) && (resultDimIdx = dataDimNameMap.get(resultDimIdx)); + if (resultDimIdx != null && resultDimIdx < dimCount) { + dataDims[coordDimIndex] = resultDimIdx; + applyDim(result[resultDimIdx], coordDim, coordDimIndex); + } + }); + }); + + // Apply templetes and default order from `sysDims`. + var availDimIdx = 0; + each(sysDims, function (sysDimItem, sysDimIndex) { + var coordDim; + var sysDimItem; + var sysDimItemDimsDef; + var sysDimItemOtherDims; + if (isString(sysDimItem)) { + coordDim = sysDimItem; + sysDimItem = {}; + } + else { + coordDim = sysDimItem.name; + sysDimItem = zrUtil.clone(sysDimItem); + // `coordDimIndex` should not be set directly. + sysDimItemDimsDef = sysDimItem.dimsDef; + sysDimItemOtherDims = sysDimItem.otherDims; + sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex + = sysDimItem.dimsDef = sysDimItem.otherDims = null; + } + + var dataDims = normalizeToArray(encodeDef.get(coordDim)); + // dimensions provides default dim sequences. + if (!dataDims.length) { + for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) { + while (availDimIdx < result.length && result[availDimIdx].coordDim != null) { + availDimIdx++; + } + availDimIdx < result.length && dataDims.push(availDimIdx++); + } + } + // Apply templates. + each(dataDims, function (resultDimIdx, coordDimIndex) { + var resultItem = result[resultDimIdx]; + applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex); + if (resultItem.name == null && sysDimItemDimsDef) { + resultItem.name = resultItem.tooltipName = sysDimItemDimsDef[coordDimIndex]; + } + sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims); + }); + }); + + // Make sure the first extra dim is 'value'. + var extra = opt.extraPrefix || 'value'; + + // Set dim `name` and other `coordDim` and other props. + for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) { + var resultItem = result[resultDimIdx] = result[resultDimIdx] || {}; + var coordDim = resultItem.coordDim; + + coordDim == null && ( + resultItem.coordDim = genName(extra, coordDimNameMap, opt.extraFromZero), + resultItem.coordDimIndex = 0, + resultItem.isExtraCoord = true + ); + + resultItem.name == null && (resultItem.name = genName( + resultItem.coordDim, + dataDimNameMap + )); + + resultItem.type == null && guessOrdinal(data, resultDimIdx) + && (resultItem.type = 'ordinal'); + } + + return result; + + function applyDim(resultItem, coordDim, coordDimIndex) { + if (OTHER_DIMS[coordDim]) { + resultItem.otherDims[coordDim] = coordDimIndex; + } + else { + resultItem.coordDim = coordDim; + resultItem.coordDimIndex = coordDimIndex; + coordDimNameMap.set(coordDim, true); + } + } + + function genName(name, map, fromZero) { + if (fromZero || map.get(name) != null) { + var i = 0; + while (map.get(name + i) != null) { + i++; + } + name += i; + } + map.set(name, true); + return name; + } + } + + // The rule should not be complex, otherwise user might not + // be able to known where the data is wrong. + var guessOrdinal = completeDimensions.guessOrdinal = function (data, dimIndex) { + for (var i = 0, len = data.length; i < len; i++) { + var value = retrieveValue(data[i]); + + if (!zrUtil.isArray(value)) { + return false; + } + + var value = value[dimIndex]; + // Consider usage convenience, '1', '2' will be treated as "number". + if (value != null && isFinite(value)) { + return false; + } + else if (isString(value) && value !== '-') { + return true; + } + } + return false; + }; + + function retrieveValue(o) { + return zrUtil.isArray(o) ? o : zrUtil.isObject(o) ? o.value: o; + } + + module.exports = completeDimensions; + + + +/***/ }, +/* 111 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + // Symbol factory + + + var graphic = __webpack_require__(18); + var BoundingRect = __webpack_require__(9); + + /** + * Triangle shape + * @inner + */ + var Triangle = graphic.extendShape({ + type: 'triangle', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy + height); + path.lineTo(cx - width, cy + height); + path.closePath(); + } + }); + /** + * Diamond shape + * @inner + */ + var Diamond = graphic.extendShape({ + type: 'diamond', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy); + path.lineTo(cx, cy + height); + path.lineTo(cx - width, cy); + path.closePath(); + } + }); + + /** + * Pin shape + * @inner + */ + var Pin = graphic.extendShape({ + type: 'pin', + shape: { + // x, y on the cusp + x: 0, + y: 0, + width: 0, + height: 0 + }, + + buildPath: function (path, shape) { + var x = shape.x; + var y = shape.y; + var w = shape.width / 5 * 3; + // Height must be larger than width + var h = Math.max(w, shape.height); + var r = w / 2; + + // Dist on y with tangent point and circle center + var dy = r * r / (h - r); + var cy = y - h + r + dy; + var angle = Math.asin(dy / r); + // Dist on x with tangent point and circle center + var dx = Math.cos(angle) * r; + + var tanX = Math.sin(angle); + var tanY = Math.cos(angle); + + path.arc( + x, cy, r, + Math.PI - angle, + Math.PI * 2 + angle + ); + + var cpLen = r * 0.6; + var cpLen2 = r * 0.7; + path.bezierCurveTo( + x + dx - tanX * cpLen, cy + dy + tanY * cpLen, + x, y - cpLen2, + x, y + ); + path.bezierCurveTo( + x, y - cpLen2, + x - dx + tanX * cpLen, cy + dy + tanY * cpLen, + x - dx, cy + dy + ); + path.closePath(); + } + }); + + /** + * Arrow shape + * @inner + */ + var Arrow = graphic.extendShape({ + + type: 'arrow', + + shape: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + + buildPath: function (ctx, shape) { + var height = shape.height; + var width = shape.width; + var x = shape.x; + var y = shape.y; + var dx = width / 3 * 2; + ctx.moveTo(x, y); + ctx.lineTo(x + dx, y + height); + ctx.lineTo(x, y + height / 4 * 3); + ctx.lineTo(x - dx, y + height); + ctx.lineTo(x, y); + ctx.closePath(); + } + }); + + /** + * Map of path contructors + * @type {Object.} + */ + var symbolCtors = { + line: graphic.Line, + + rect: graphic.Rect, + + roundRect: graphic.Rect, + + square: graphic.Rect, + + circle: graphic.Circle, + + diamond: Diamond, + + pin: Pin, + + arrow: Arrow, + + triangle: Triangle + }; + + var symbolShapeMakers = { + + line: function (x, y, w, h, shape) { + // FIXME + shape.x1 = x; + shape.y1 = y + h / 2; + shape.x2 = x + w; + shape.y2 = y + h / 2; + }, + + rect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + }, + + roundRect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + shape.r = Math.min(w, h) / 4; + }, + + square: function (x, y, w, h, shape) { + var size = Math.min(w, h); + shape.x = x; + shape.y = y; + shape.width = size; + shape.height = size; + }, + + circle: function (x, y, w, h, shape) { + // Put circle in the center of square + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.r = Math.min(w, h) / 2; + }, + + diamond: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + }, + + pin: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + + arrow: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + + triangle: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + } + }; + + var symbolBuildProxies = {}; + for (var name in symbolCtors) { + if (symbolCtors.hasOwnProperty(name)) { + symbolBuildProxies[name] = new symbolCtors[name](); + } + } + + var Symbol = graphic.extendShape({ + + type: 'symbol', + + shape: { + symbolType: '', + x: 0, + y: 0, + width: 0, + height: 0 + }, + + beforeBrush: function () { + var style = this.style; + var shape = this.shape; + // FIXME + if (shape.symbolType === 'pin' && style.textPosition === 'inside') { + style.textPosition = ['50%', '40%']; + style.textAlign = 'center'; + style.textVerticalAlign = 'middle'; + } + }, + + buildPath: function (ctx, shape, inBundle) { + var symbolType = shape.symbolType; + var proxySymbol = symbolBuildProxies[symbolType]; + if (shape.symbolType !== 'none') { + if (!proxySymbol) { + // Default rect + symbolType = 'rect'; + proxySymbol = symbolBuildProxies[symbolType]; + } + symbolShapeMakers[symbolType]( + shape.x, shape.y, shape.width, shape.height, proxySymbol.shape + ); + proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle); + } + } + }); + + // Provide setColor helper method to avoid determine if set the fill or stroke outside + var symbolPathSetColor = function (color) { + if (this.type !== 'image') { + var symbolStyle = this.style; + var symbolShape = this.shape; + if (symbolShape && symbolShape.symbolType === 'line') { + symbolStyle.stroke = color; + } + else if (this.__isEmptyBrush) { + symbolStyle.stroke = color; + symbolStyle.fill = '#fff'; + } + else { + // FIXME 判断图形默认是填充还是描边,使用 onlyStroke ? + symbolStyle.fill && (symbolStyle.fill = color); + symbolStyle.stroke && (symbolStyle.stroke = color); + } + this.dirty(false); + } + }; + + var symbolUtil = { + /** + * Create a symbol element with given symbol configuration: shape, x, y, width, height, color + * @param {string} symbolType + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {string} color + */ + createSymbol: function (symbolType, x, y, w, h, color) { + // TODO Support image object, DynamicImage. + + var isEmpty = symbolType.indexOf('empty') === 0; + if (isEmpty) { + symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6); + } + var symbolPath; + + if (symbolType.indexOf('image://') === 0) { + symbolPath = new graphic.Image({ + style: { + image: symbolType.slice(8), + x: x, + y: y, + width: w, + height: h + } + }); + } + else if (symbolType.indexOf('path://') === 0) { + symbolPath = graphic.makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h)); + } + else { + symbolPath = new Symbol({ + shape: { + symbolType: symbolType, + x: x, + y: y, + width: w, + height: h + } + }); + } + + symbolPath.__isEmptyBrush = isEmpty; + + symbolPath.setColor = symbolPathSetColor; + + symbolPath.setColor(color); + + return symbolPath; + } + }; + + module.exports = symbolUtil; + + +/***/ }, +/* 112 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var axisHelper = __webpack_require__(101); + + function getName(obj) { + if (zrUtil.isObject(obj) && obj.value != null) { + return obj.value; + } + else { + return obj + ''; + } + } + + module.exports = { + + /** + * Format labels + * @return {Array.} + */ + getFormattedLabels: function () { + return axisHelper.getFormattedLabels( + this.axis, + this.get('axisLabel.formatter') + ); + }, + + /** + * Get categories + */ + getCategories: function () { + return this.get('type') === 'category' + && zrUtil.map(this.get('data'), getName); + }, + + /** + * @param {boolean} origin + * @return {number|string} min value or 'dataMin' or null/undefined (means auto) or NaN + */ + getMin: function (origin) { + var option = this.option; + var min = (!origin && option.rangeStart != null) + ? option.rangeStart : option.min; + + if (this.axis && min != null && min !== 'dataMin' && !zrUtil.eqNaN(min)) { + min = this.axis.scale.parse(min); + } + return min; + }, + + /** + * @param {boolean} origin + * @return {number|string} max value or 'dataMax' or null/undefined (means auto) or NaN + */ + getMax: function (origin) { + var option = this.option; + var max = (!origin && option.rangeEnd != null) + ? option.rangeEnd : option.max; + + if (this.axis && max != null && max !== 'dataMax' && !zrUtil.eqNaN(max)) { + max = this.axis.scale.parse(max); + } + return max; + }, + + /** + * @return {boolean} + */ + getNeedCrossZero: function () { + var option = this.option; + return (option.rangeStart != null || option.rangeEnd != null) + ? false : !option.scale; + }, + + /** + * Should be implemented by each axis model if necessary. + * @return {module:echarts/model/Component} coordinate system model + */ + getCoordSysModel: zrUtil.noop, + + /** + * @param {number} rangeStart Can only be finite number or null/undefined or NaN. + * @param {number} rangeEnd Can only be finite number or null/undefined or NaN. + */ + setRange: function (rangeStart, rangeEnd) { + this.option.rangeStart = rangeStart; + this.option.rangeEnd = rangeEnd; + }, + + /** + * Reset range + */ + resetRange: function () { + // rangeStart and rangeEnd is readonly. + this.option.rangeStart = this.option.rangeEnd = null; + } + }; + + +/***/ }, +/* 113 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var echarts = __webpack_require__(1); + var PRIORITY = echarts.PRIORITY; + + __webpack_require__(114); + __webpack_require__(115); + + echarts.registerVisual(zrUtil.curry( + __webpack_require__(121), 'line', 'circle', 'line' + )); + echarts.registerLayout(zrUtil.curry( + __webpack_require__(122), 'line' + )); + + // Down sample after filter + echarts.registerProcessor(PRIORITY.PROCESSOR.STATISTIC, zrUtil.curry( + __webpack_require__(123), 'line' + )); + + // In case developer forget to include grid component + __webpack_require__(124); + + +/***/ }, +/* 114 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var createListFromArray = __webpack_require__(109); + var SeriesModel = __webpack_require__(78); + + module.exports = SeriesModel.extend({ + + type: 'series.line', + + dependencies: ['grid', 'polar'], + + getInitialData: function (option, ecModel) { + if (true) { + var coordSys = option.coordinateSystem; + if (coordSys !== 'polar' && coordSys !== 'cartesian2d') { + throw new Error('Line not support coordinateSystem besides cartesian and polar'); + } + } + return createListFromArray(option.data, this, ecModel); + }, + + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + + hoverAnimation: true, + // stack: null + // xAxisIndex: 0, + // yAxisIndex: 0, + + // polarIndex: 0, + + // If clip the overflow value + clipOverflow: true, + // cursor: null, + + label: { + normal: { + position: 'top' + } + }, + // itemStyle: { + // normal: {}, + // emphasis: {} + // }, + lineStyle: { + normal: { + width: 2, + type: 'solid' + } + }, + // areaStyle: {}, + // false, 'start', 'end', 'middle' + step: false, + + // Disabled if step is true + smooth: false, + smoothMonotone: null, + // 拐点图形类型 + symbol: 'emptyCircle', + // 拐点图形大小 + symbolSize: 4, + // 拐点图形旋转控制 + symbolRotate: null, + + // 是否显示 symbol, 只有在 tooltip hover 的时候显示 + showSymbol: true, + // 标志图形默认只有主轴显示(随主轴标签间隔隐藏策略) + showAllSymbol: false, + + // 是否连接断点 + connectNulls: false, + + // 数据过滤,'average', 'max', 'min', 'sum' + sampling: 'none', + + animationEasing: 'linear', + + // Disable progressive + progressive: 0, + hoverLayerThreshold: Infinity + } + }); + + +/***/ }, +/* 115 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + // FIXME step not support polar + + + var zrUtil = __webpack_require__(4); + var SymbolDraw = __webpack_require__(116); + var Symbol = __webpack_require__(117); + var lineAnimationDiff = __webpack_require__(119); + var graphic = __webpack_require__(18); + var modelUtil = __webpack_require__(5); + var polyHelper = __webpack_require__(120); + var ChartView = __webpack_require__(80); + + function isPointsSame(points1, points2) { + if (points1.length !== points2.length) { + return; + } + for (var i = 0; i < points1.length; i++) { + var p1 = points1[i]; + var p2 = points2[i]; + if (p1[0] !== p2[0] || p1[1] !== p2[1]) { + return; + } + } + return true; + } + + function getSmooth(smooth) { + return typeof (smooth) === 'number' ? smooth : (smooth ? 0.3 : 0); + } + + function getAxisExtentWithGap(axis) { + var extent = axis.getGlobalExtent(); + if (axis.onBand) { + // Remove extra 1px to avoid line miter in clipped edge + var halfBandWidth = axis.getBandWidth() / 2 - 1; + var dir = extent[1] > extent[0] ? 1 : -1; + extent[0] += dir * halfBandWidth; + extent[1] -= dir * halfBandWidth; + } + return extent; + } + + function sign(val) { + return val >= 0 ? 1 : -1; + } + /** + * @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar} coordSys + * @param {module:echarts/data/List} data + * @param {Array.>} points + * @private + */ + function getStackedOnPoints(coordSys, data) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var valueStart = baseAxis.onZero + ? 0 : valueAxis.scale.getExtent()[0]; + + var valueDim = valueAxis.dim; + + var baseDataOffset = valueDim === 'x' || valueDim === 'radius' ? 1 : 0; + + return data.mapArray([valueDim], function (val, idx) { + var stackedOnSameSign; + var stackedOn = data.stackedOn; + // Find first stacked value with same sign + while (stackedOn && + sign(stackedOn.get(valueDim, idx)) === sign(val) + ) { + stackedOnSameSign = stackedOn; + break; + } + var stackedData = []; + stackedData[baseDataOffset] = data.get(baseAxis.dim, idx); + stackedData[1 - baseDataOffset] = stackedOnSameSign + ? stackedOnSameSign.get(valueDim, idx, true) : valueStart; + + return coordSys.dataToPoint(stackedData); + }, true); + } + + function createGridClipShape(cartesian, hasAnimation, seriesModel) { + var xExtent = getAxisExtentWithGap(cartesian.getAxis('x')); + var yExtent = getAxisExtentWithGap(cartesian.getAxis('y')); + var isHorizontal = cartesian.getBaseAxis().isHorizontal(); + + var x = Math.min(xExtent[0], xExtent[1]); + var y = Math.min(yExtent[0], yExtent[1]); + var width = Math.max(xExtent[0], xExtent[1]) - x; + var height = Math.max(yExtent[0], yExtent[1]) - y; + var lineWidth = seriesModel.get('lineStyle.normal.width') || 2; + // Expand clip shape to avoid clipping when line value exceeds axis + var expandSize = seriesModel.get('clipOverflow') ? lineWidth / 2 : Math.max(width, height); + if (isHorizontal) { + y -= expandSize; + height += expandSize * 2; + } + else { + x -= expandSize; + width += expandSize * 2; + } + + var clipPath = new graphic.Rect({ + shape: { + x: x, + y: y, + width: width, + height: height + } + }); + + if (hasAnimation) { + clipPath.shape[isHorizontal ? 'width' : 'height'] = 0; + graphic.initProps(clipPath, { + shape: { + width: width, + height: height + } + }, seriesModel); + } + + return clipPath; + } + + function createPolarClipShape(polar, hasAnimation, seriesModel) { + var angleAxis = polar.getAngleAxis(); + var radiusAxis = polar.getRadiusAxis(); + + var radiusExtent = radiusAxis.getExtent(); + var angleExtent = angleAxis.getExtent(); + + var RADIAN = Math.PI / 180; + + var clipPath = new graphic.Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: radiusExtent[0], + r: radiusExtent[1], + startAngle: -angleExtent[0] * RADIAN, + endAngle: -angleExtent[1] * RADIAN, + clockwise: angleAxis.inverse + } + }); + + if (hasAnimation) { + clipPath.shape.endAngle = -angleExtent[0] * RADIAN; + graphic.initProps(clipPath, { + shape: { + endAngle: -angleExtent[1] * RADIAN + } + }, seriesModel); + } + + return clipPath; + } + + function createClipShape(coordSys, hasAnimation, seriesModel) { + return coordSys.type === 'polar' + ? createPolarClipShape(coordSys, hasAnimation, seriesModel) + : createGridClipShape(coordSys, hasAnimation, seriesModel); + } + + function turnPointsIntoStep(points, coordSys, stepTurnAt) { + var baseAxis = coordSys.getBaseAxis(); + var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1; + + var stepPoints = []; + for (var i = 0; i < points.length - 1; i++) { + var nextPt = points[i + 1]; + var pt = points[i]; + stepPoints.push(pt); + + var stepPt = []; + switch (stepTurnAt) { + case 'end': + stepPt[baseIndex] = nextPt[baseIndex]; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + // default is start + stepPoints.push(stepPt); + break; + case 'middle': + // default is start + var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2; + var stepPt2 = []; + stepPt[baseIndex] = stepPt2[baseIndex] = middle; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + stepPt2[1 - baseIndex] = nextPt[1 - baseIndex]; + stepPoints.push(stepPt); + stepPoints.push(stepPt2); + break; + default: + stepPt[baseIndex] = pt[baseIndex]; + stepPt[1 - baseIndex] = nextPt[1 - baseIndex]; + // default is start + stepPoints.push(stepPt); + } + } + // Last points + points[i] && stepPoints.push(points[i]); + return stepPoints; + } + + function getVisualGradient(data, coordSys) { + var visualMetaList = data.getVisual('visualMeta'); + if (!visualMetaList || !visualMetaList.length || !data.count()) { + // When data.count() is 0, gradient range can not be calculated. + return; + } + + var visualMeta; + for (var i = visualMetaList.length - 1; i >= 0; i--) { + // Can only be x or y + if (visualMetaList[i].dimension < 2) { + visualMeta = visualMetaList[i]; + break; + } + } + if (!visualMeta || coordSys.type !== 'cartesian2d') { + if (true) { + console.warn('Visual map on line style only support x or y dimension.'); + } + return; + } + + // If the area to be rendered is bigger than area defined by LinearGradient, + // the canvas spec prescribes that the color of the first stop and the last + // stop should be used. But if two stops are added at offset 0, in effect + // browsers use the color of the second stop to render area outside + // LinearGradient. So we can only infinitesimally extend area defined in + // LinearGradient to render `outerColors`. + + var dimension = visualMeta.dimension; + var dimName = data.dimensions[dimension]; + var axis = coordSys.getAxis(dimName); + + // dataToCoor mapping may not be linear, but must be monotonic. + var colorStops = zrUtil.map(visualMeta.stops, function (stop) { + return { + coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)), + color: stop.color + }; + }); + var stopLen = colorStops.length; + var outerColors = visualMeta.outerColors.slice(); + + if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) { + colorStops.reverse(); + outerColors.reverse(); + } + + var tinyExtent = 10; // Arbitrary value: 10px + var minCoord = colorStops[0].coord - tinyExtent; + var maxCoord = colorStops[stopLen - 1].coord + tinyExtent; + var coordSpan = maxCoord - minCoord; + + if (coordSpan < 1e-3) { + return 'transparent'; + } + + zrUtil.each(colorStops, function (stop) { + stop.offset = (stop.coord - minCoord) / coordSpan; + }); + colorStops.push({ + offset: stopLen ? colorStops[stopLen - 1].offset : 0.5, + color: outerColors[1] || 'transparent' + }); + colorStops.unshift({ // notice colorStops.length have been changed. + offset: stopLen ? colorStops[0].offset : 0.5, + color: outerColors[0] || 'transparent' + }); + + // zrUtil.each(colorStops, function (colorStop) { + // // Make sure each offset has rounded px to avoid not sharp edge + // colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start); + // }); + + var gradient = new graphic.LinearGradient(0, 0, 0, 0, colorStops, true); + gradient[dimName] = minCoord; + gradient[dimName + '2'] = maxCoord; + + return gradient; + } + + module.exports = ChartView.extend({ + + type: 'line', + + init: function () { + var lineGroup = new graphic.Group(); + + var symbolDraw = new SymbolDraw(); + this.group.add(symbolDraw.group); + + this._symbolDraw = symbolDraw; + this._lineGroup = lineGroup; + }, + + render: function (seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var group = this.group; + var data = seriesModel.getData(); + var lineStyleModel = seriesModel.getModel('lineStyle.normal'); + var areaStyleModel = seriesModel.getModel('areaStyle.normal'); + + var points = data.mapArray(data.getItemLayout, true); + + var isCoordSysPolar = coordSys.type === 'polar'; + var prevCoordSys = this._coordSys; + + var symbolDraw = this._symbolDraw; + var polyline = this._polyline; + var polygon = this._polygon; + + var lineGroup = this._lineGroup; + + var hasAnimation = seriesModel.get('animation'); + + var isAreaChart = !areaStyleModel.isEmpty(); + var stackedOnPoints = getStackedOnPoints(coordSys, data); + + var showSymbol = seriesModel.get('showSymbol'); + + var isSymbolIgnore = showSymbol && !isCoordSysPolar && !seriesModel.get('showAllSymbol') + && this._getSymbolIgnoreFunc(data, coordSys); + + // Remove temporary symbols + var oldData = this._data; + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); + + // Remove previous created symbols if showSymbol changed to false + if (!showSymbol) { + symbolDraw.remove(); + } + + group.add(lineGroup); + + // FIXME step not support polar + var step = !isCoordSysPolar && seriesModel.get('step'); + // Initialization animation or coordinate system changed + if ( + !(polyline && prevCoordSys.type === coordSys.type && step === this._step) + ) { + showSymbol && symbolDraw.updateData(data, isSymbolIgnore); + + if (step) { + // TODO If stacked series is not step + points = turnPointsIntoStep(points, coordSys, step); + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step); + } + + polyline = this._newPolyline(points, coordSys, hasAnimation); + if (isAreaChart) { + polygon = this._newPolygon( + points, stackedOnPoints, + coordSys, hasAnimation + ); + } + lineGroup.setClipPath(createClipShape(coordSys, true, seriesModel)); + } + else { + if (isAreaChart && !polygon) { + // If areaStyle is added + polygon = this._newPolygon( + points, stackedOnPoints, + coordSys, hasAnimation + ); + } + else if (polygon && !isAreaChart) { + // If areaStyle is removed + lineGroup.remove(polygon); + polygon = this._polygon = null; + } + + // Update clipPath + lineGroup.setClipPath(createClipShape(coordSys, false, seriesModel)); + + // Always update, or it is wrong in the case turning on legend + // because points are not changed + showSymbol && symbolDraw.updateData(data, isSymbolIgnore); + + // Stop symbol animation and sync with line points + // FIXME performance? + data.eachItemGraphicEl(function (el) { + el.stopAnimation(true); + }); + + // In the case data zoom triggerred refreshing frequently + // Data may not change if line has a category axis. So it should animate nothing + if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) + || !isPointsSame(this._points, points) + ) { + if (hasAnimation) { + this._updateAnimation( + data, stackedOnPoints, coordSys, api, step + ); + } + else { + // Not do it in update with animation + if (step) { + // TODO If stacked series is not step + points = turnPointsIntoStep(points, coordSys, step); + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step); + } + + polyline.setShape({ + points: points + }); + polygon && polygon.setShape({ + points: points, + stackedOnPoints: stackedOnPoints + }); + } + } + } + + var visualColor = getVisualGradient(data, coordSys) || data.getVisual('color'); + + polyline.useStyle(zrUtil.defaults( + // Use color in lineStyle first + lineStyleModel.getLineStyle(), + { + fill: 'none', + stroke: visualColor, + lineJoin: 'bevel' + } + )); + + var smooth = seriesModel.get('smooth'); + smooth = getSmooth(seriesModel.get('smooth')); + polyline.setShape({ + smooth: smooth, + smoothMonotone: seriesModel.get('smoothMonotone'), + connectNulls: seriesModel.get('connectNulls') + }); + + if (polygon) { + var stackedOn = data.stackedOn; + var stackedOnSmooth = 0; + + polygon.useStyle(zrUtil.defaults( + areaStyleModel.getAreaStyle(), + { + fill: visualColor, + opacity: 0.7, + lineJoin: 'bevel' + } + )); + + if (stackedOn) { + var stackedOnSeries = stackedOn.hostModel; + stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth')); + } + + polygon.setShape({ + smooth: smooth, + stackedOnSmooth: stackedOnSmooth, + smoothMonotone: seriesModel.get('smoothMonotone'), + connectNulls: seriesModel.get('connectNulls') + }); + } + + this._data = data; + // Save the coordinate system for transition animation when data changed + this._coordSys = coordSys; + this._stackedOnPoints = stackedOnPoints; + this._points = points; + this._step = step; + }, + + dispose: function () {}, + + highlight: function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = modelUtil.queryDataIndex(data, payload); + + if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) { + var symbol = data.getItemGraphicEl(dataIndex); + if (!symbol) { + // Create a temporary symbol if it is not exists + var pt = data.getItemLayout(dataIndex); + if (!pt) { + // Null data + return; + } + symbol = new Symbol(data, dataIndex); + symbol.position = pt; + symbol.setZ( + seriesModel.get('zlevel'), + seriesModel.get('z') + ); + symbol.ignore = isNaN(pt[0]) || isNaN(pt[1]); + symbol.__temp = true; + data.setItemGraphicEl(dataIndex, symbol); + + // Stop scale animation + symbol.stopSymbolAnimation(true); + + this.group.add(symbol); + } + symbol.highlight(); + } + else { + // Highlight whole series + ChartView.prototype.highlight.call( + this, seriesModel, ecModel, api, payload + ); + } + }, + + downplay: function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = modelUtil.queryDataIndex(data, payload); + if (dataIndex != null && dataIndex >= 0) { + var symbol = data.getItemGraphicEl(dataIndex); + if (symbol) { + if (symbol.__temp) { + data.setItemGraphicEl(dataIndex, null); + this.group.remove(symbol); + } + else { + symbol.downplay(); + } + } + } + else { + // FIXME + // can not downplay completely. + // Downplay whole series + ChartView.prototype.downplay.call( + this, seriesModel, ecModel, api, payload + ); + } + }, + + /** + * @param {module:zrender/container/Group} group + * @param {Array.>} points + * @private + */ + _newPolyline: function (points) { + var polyline = this._polyline; + // Remove previous created polyline + if (polyline) { + this._lineGroup.remove(polyline); + } + + polyline = new polyHelper.Polyline({ + shape: { + points: points + }, + silent: true, + z2: 10 + }); + + this._lineGroup.add(polyline); + + this._polyline = polyline; + + return polyline; + }, + + /** + * @param {module:zrender/container/Group} group + * @param {Array.>} stackedOnPoints + * @param {Array.>} points + * @private + */ + _newPolygon: function (points, stackedOnPoints) { + var polygon = this._polygon; + // Remove previous created polygon + if (polygon) { + this._lineGroup.remove(polygon); + } + + polygon = new polyHelper.Polygon({ + shape: { + points: points, + stackedOnPoints: stackedOnPoints + }, + silent: true + }); + + this._lineGroup.add(polygon); + + this._polygon = polygon; + return polygon; + }, + /** + * @private + */ + _getSymbolIgnoreFunc: function (data, coordSys) { + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + // `getLabelInterval` is provided by echarts/component/axis + if (categoryAxis && categoryAxis.isLabelIgnored) { + return zrUtil.bind(categoryAxis.isLabelIgnored, categoryAxis); + } + }, + + /** + * @private + */ + // FIXME Two value axis + _updateAnimation: function (data, stackedOnPoints, coordSys, api, step) { + var polyline = this._polyline; + var polygon = this._polygon; + var seriesModel = data.hostModel; + + var diff = lineAnimationDiff( + this._data, data, + this._stackedOnPoints, stackedOnPoints, + this._coordSys, coordSys + ); + + var current = diff.current; + var stackedOnCurrent = diff.stackedOnCurrent; + var next = diff.next; + var stackedOnNext = diff.stackedOnNext; + if (step) { + // TODO If stacked series is not step + current = turnPointsIntoStep(diff.current, coordSys, step); + stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step); + next = turnPointsIntoStep(diff.next, coordSys, step); + stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step); + } + // `diff.current` is subset of `current` (which should be ensured by + // turnPointsIntoStep), so points in `__points` can be updated when + // points in `current` are update during animation. + polyline.shape.__points = diff.current; + polyline.shape.points = current; + + graphic.updateProps(polyline, { + shape: { + points: next + } + }, seriesModel); + + if (polygon) { + polygon.setShape({ + points: current, + stackedOnPoints: stackedOnCurrent + }); + graphic.updateProps(polygon, { + shape: { + points: next, + stackedOnPoints: stackedOnNext + } + }, seriesModel); + } + + var updatedDataInfo = []; + var diffStatus = diff.status; + + for (var i = 0; i < diffStatus.length; i++) { + var cmd = diffStatus[i].cmd; + if (cmd === '=') { + var el = data.getItemGraphicEl(diffStatus[i].idx1); + if (el) { + updatedDataInfo.push({ + el: el, + ptIdx: i // Index of points + }); + } + } + } + + if (polyline.animators && polyline.animators.length) { + polyline.animators[0].during(function () { + for (var i = 0; i < updatedDataInfo.length; i++) { + var el = updatedDataInfo[i].el; + el.attr('position', polyline.shape.__points[updatedDataInfo[i].ptIdx]); + } + }); + } + }, + + remove: function (ecModel) { + var group = this.group; + var oldData = this._data; + this._lineGroup.removeAll(); + this._symbolDraw.remove(true); + // Remove temporary created elements when highlighting + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); + + this._polyline = + this._polygon = + this._coordSys = + this._points = + this._stackedOnPoints = + this._data = null; + } + }); + + +/***/ }, +/* 116 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/chart/helper/SymbolDraw + */ + + + var graphic = __webpack_require__(18); + var Symbol = __webpack_require__(117); + + /** + * @constructor + * @alias module:echarts/chart/helper/SymbolDraw + * @param {module:zrender/graphic/Group} [symbolCtor] + */ + function SymbolDraw(symbolCtor) { + this.group = new graphic.Group(); + + this._symbolCtor = symbolCtor || Symbol; + } + + var symbolDrawProto = SymbolDraw.prototype; + + function symbolNeedsDraw(data, idx, isIgnore) { + var point = data.getItemLayout(idx); + // Is an object + // if (point && point.hasOwnProperty('point')) { + // point = point.point; + // } + return point && !isNaN(point[0]) && !isNaN(point[1]) && !(isIgnore && isIgnore(idx)) + && data.getItemVisual(idx, 'symbol') !== 'none'; + } + /** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + * @param {Array.} [isIgnore] + */ + symbolDrawProto.updateData = function (data, isIgnore) { + var group = this.group; + var seriesModel = data.hostModel; + var oldData = this._data; + + var SymbolCtor = this._symbolCtor; + + var seriesScope = { + itemStyle: seriesModel.getModel('itemStyle.normal').getItemStyle(['color']), + hoverItemStyle: seriesModel.getModel('itemStyle.emphasis').getItemStyle(), + symbolRotate: seriesModel.get('symbolRotate'), + symbolOffset: seriesModel.get('symbolOffset'), + hoverAnimation: seriesModel.get('hoverAnimation'), + + labelModel: seriesModel.getModel('label.normal'), + hoverLabelModel: seriesModel.getModel('label.emphasis'), + cursorStyle: seriesModel.get('cursor') + }; + + data.diff(oldData) + .add(function (newIdx) { + var point = data.getItemLayout(newIdx); + if (symbolNeedsDraw(data, newIdx, isIgnore)) { + var symbolEl = new SymbolCtor(data, newIdx, seriesScope); + symbolEl.attr('position', point); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }) + .update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + var point = data.getItemLayout(newIdx); + if (!symbolNeedsDraw(data, newIdx, isIgnore)) { + group.remove(symbolEl); + return; + } + if (!symbolEl) { + symbolEl = new SymbolCtor(data, newIdx); + symbolEl.attr('position', point); + } + else { + symbolEl.updateData(data, newIdx, seriesScope); + graphic.updateProps(symbolEl, { + position: point + }, seriesModel); + } + + // Add back + group.add(symbolEl); + + data.setItemGraphicEl(newIdx, symbolEl); + }) + .remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && el.fadeOut(function () { + group.remove(el); + }); + }) + .execute(); + + this._data = data; + }; + + symbolDrawProto.updateLayout = function () { + var data = this._data; + if (data) { + // Not use animation + data.eachItemGraphicEl(function (el, idx) { + var point = data.getItemLayout(idx); + el.attr('position', point); + }); + } + }; + + symbolDrawProto.remove = function (enableAnimation) { + var group = this.group; + var data = this._data; + if (data) { + if (enableAnimation) { + data.eachItemGraphicEl(function (el) { + el.fadeOut(function () { + group.remove(el); + }); + }); + } + else { + group.removeAll(); + } + } + }; + + module.exports = SymbolDraw; + + +/***/ }, +/* 117 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/chart/helper/Symbol + */ + + + var zrUtil = __webpack_require__(4); + var symbolUtil = __webpack_require__(111); + var graphic = __webpack_require__(18); + var numberUtil = __webpack_require__(7); + var labelHelper = __webpack_require__(118); + + function getSymbolSize(data, idx) { + var symbolSize = data.getItemVisual(idx, 'symbolSize'); + return symbolSize instanceof Array + ? symbolSize.slice() + : [+symbolSize, +symbolSize]; + } + + function getScale(symbolSize) { + return [symbolSize[0] / 2, symbolSize[1] / 2]; + } + + /** + * @constructor + * @alias {module:echarts/chart/helper/Symbol} + * @param {module:echarts/data/List} data + * @param {number} idx + * @extends {module:zrender/graphic/Group} + */ + function Symbol(data, idx, seriesScope) { + graphic.Group.call(this); + + this.updateData(data, idx, seriesScope); + } + + var symbolProto = Symbol.prototype; + + function driftSymbol(dx, dy) { + this.parent.drift(dx, dy); + } + + symbolProto._createSymbol = function (symbolType, data, idx, symbolSize) { + // Remove paths created before + this.removeAll(); + + var seriesModel = data.hostModel; + var color = data.getItemVisual(idx, 'color'); + + // var symbolPath = symbolUtil.createSymbol( + // symbolType, -0.5, -0.5, 1, 1, color + // ); + // If width/height are set too small (e.g., set to 1) on ios10 + // and macOS Sierra, a circle stroke become a rect, no matter what + // the scale is set. So we set width/height as 2. See #4150. + var symbolPath = symbolUtil.createSymbol( + symbolType, -1, -1, 2, 2, color + ); + + symbolPath.attr({ + z2: 100, + culling: true, + scale: [0, 0] + }); + // Rewrite drift method + symbolPath.drift = driftSymbol; + + graphic.initProps(symbolPath, { + scale: getScale(symbolSize) + }, seriesModel, idx); + this._symbolType = symbolType; + + this.add(symbolPath); + }; + + /** + * Stop animation + * @param {boolean} toLastFrame + */ + symbolProto.stopSymbolAnimation = function (toLastFrame) { + this.childAt(0).stopAnimation(toLastFrame); + }; + + /** + * Get symbol path element + */ + symbolProto.getSymbolPath = function () { + return this.childAt(0); + }; + + /** + * Get scale(aka, current symbol size). + * Including the change caused by animation + */ + symbolProto.getScale = function () { + return this.childAt(0).scale; + }; + + /** + * Highlight symbol + */ + symbolProto.highlight = function () { + this.childAt(0).trigger('emphasis'); + }; + + /** + * Downplay symbol + */ + symbolProto.downplay = function () { + this.childAt(0).trigger('normal'); + }; + + /** + * @param {number} zlevel + * @param {number} z + */ + symbolProto.setZ = function (zlevel, z) { + var symbolPath = this.childAt(0); + symbolPath.zlevel = zlevel; + symbolPath.z = z; + }; + + symbolProto.setDraggable = function (draggable) { + var symbolPath = this.childAt(0); + symbolPath.draggable = draggable; + symbolPath.cursor = draggable ? 'move' : 'pointer'; + }; + + /** + * Update symbol properties + * @param {module:echarts/data/List} data + * @param {number} idx + */ + symbolProto.updateData = function (data, idx, seriesScope) { + this.silent = false; + + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + var seriesModel = data.hostModel; + var symbolSize = getSymbolSize(data, idx); + + if (symbolType !== this._symbolType) { + this._createSymbol(symbolType, data, idx, symbolSize); + } + else { + var symbolPath = this.childAt(0); + symbolPath.silent = false; + graphic.updateProps(symbolPath, { + scale: getScale(symbolSize) + }, seriesModel, idx); + } + this._updateCommon(data, idx, symbolSize, seriesScope); + this._seriesModel = seriesModel; + }; + + // Update common properties + var normalStyleAccessPath = ['itemStyle', 'normal']; + var emphasisStyleAccessPath = ['itemStyle', 'emphasis']; + var normalLabelAccessPath = ['label', 'normal']; + var emphasisLabelAccessPath = ['label', 'emphasis']; + + symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) { + var symbolPath = this.childAt(0); + var seriesModel = data.hostModel; + var color = data.getItemVisual(idx, 'color'); + + // Reset style + if (symbolPath.type !== 'image') { + symbolPath.useStyle({ + strokeNoScale: true + }); + } + + seriesScope = seriesScope || null; + + var itemStyle = seriesScope && seriesScope.itemStyle; + var hoverItemStyle = seriesScope && seriesScope.hoverItemStyle; + var symbolRotate = seriesScope && seriesScope.symbolRotate; + var symbolOffset = seriesScope && seriesScope.symbolOffset; + var labelModel = seriesScope && seriesScope.labelModel; + var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel; + var hoverAnimation = seriesScope && seriesScope.hoverAnimation; + var cursorStyle = seriesScope && seriesScope.cursorStyle; + + if (!seriesScope || data.hasItemOption) { + var itemModel = data.getItemModel(idx); + + // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + itemStyle = itemModel.getModel(normalStyleAccessPath).getItemStyle(['color']); + hoverItemStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle(); + + symbolRotate = itemModel.getShallow('symbolRotate'); + symbolOffset = itemModel.getShallow('symbolOffset'); + + labelModel = itemModel.getModel(normalLabelAccessPath); + hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath); + hoverAnimation = itemModel.getShallow('hoverAnimation'); + cursorStyle = itemModel.getShallow('cursor'); + } + else { + hoverItemStyle = zrUtil.extend({}, hoverItemStyle); + } + + var elStyle = symbolPath.style; + + symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0); + + if (symbolOffset) { + symbolPath.attr('position', [ + numberUtil.parsePercent(symbolOffset[0], symbolSize[0]), + numberUtil.parsePercent(symbolOffset[1], symbolSize[1]) + ]); + } + + cursorStyle && symbolPath.attr('cursor', cursorStyle); + + // PENDING setColor before setStyle!!! + symbolPath.setColor(color); + + symbolPath.setStyle(itemStyle); + + var opacity = data.getItemVisual(idx, 'opacity'); + if (opacity != null) { + elStyle.opacity = opacity; + } + + var valueDim = labelHelper.findLabelValueDim(data); + labelHelper.setTextToStyle( + data, idx, valueDim, elStyle, seriesModel, labelModel, color + ); + labelHelper.setTextToStyle( + data, idx, valueDim, hoverItemStyle, seriesModel, hoverLabelModel, color + ); + + symbolPath.off('mouseover') + .off('mouseout') + .off('emphasis') + .off('normal'); + + symbolPath.hoverStyle = hoverItemStyle; + + graphic.setHoverStyle(symbolPath); + + var scale = getScale(symbolSize); + + if (hoverAnimation && seriesModel.isAnimationEnabled()) { + var onEmphasis = function() { + var ratio = scale[1] / scale[0]; + this.animateTo({ + scale: [ + Math.max(scale[0] * 1.1, scale[0] + 3), + Math.max(scale[1] * 1.1, scale[1] + 3 * ratio) + ] + }, 400, 'elasticOut'); + }; + var onNormal = function() { + this.animateTo({ + scale: scale + }, 400, 'elasticOut'); + }; + symbolPath.on('mouseover', onEmphasis) + .on('mouseout', onNormal) + .on('emphasis', onEmphasis) + .on('normal', onNormal); + } + }; + + symbolProto.fadeOut = function (cb) { + var symbolPath = this.childAt(0); + // Avoid mistaken hover when fading out + this.silent = symbolPath.silent = true; + // Not show text when animating + symbolPath.style.text = ''; + graphic.updateProps(symbolPath, { + scale: [0, 0] + }, this._seriesModel, this.dataIndex, cb); + }; + + zrUtil.inherits(Symbol, graphic.Group); + + module.exports = Symbol; + + +/***/ }, +/* 118 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/chart/helper/Symbol + */ + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + + var helper = {}; + + helper.findLabelValueDim = function (data) { + var valueDim; + var labelDims = modelUtil.otherDimToDataDim(data, 'label'); + + if (labelDims.length) { + valueDim = labelDims[0]; + } + else { + // Get last value dim + var dimensions = data.dimensions.slice(); + var dataType; + while (dimensions.length && ( + valueDim = dimensions.pop(), + dataType = data.getDimensionInfo(valueDim).type, + dataType === 'ordinal' || dataType === 'time' + )) {} // jshint ignore:line + } + + return valueDim; + }; + + helper.setTextToStyle = function ( + data, dataIndex, valueDim, elStyle, seriesModel, labelModel, color + ) { + if (valueDim != null && labelModel.getShallow('show')) { + graphic.setText(elStyle, labelModel, color); + elStyle.text = zrUtil.retrieve( + seriesModel.getFormattedLabel(dataIndex, 'normal'), + data.get(valueDim, dataIndex) + ); + } + else { + elStyle.text = ''; + } + }; + + module.exports = helper; + + +/***/ }, +/* 119 */ +/***/ function(module, exports) { + + + + // var arrayDiff = require('zrender/lib/core/arrayDiff'); + // 'zrender/core/arrayDiff' has been used before, but it did + // not do well in performance when roam with fixed dataZoom window. + + function sign(val) { + return val >= 0 ? 1 : -1; + } + + function getStackedOnPoint(coordSys, data, idx) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var valueStart = baseAxis.onZero + ? 0 : valueAxis.scale.getExtent()[0]; + + var valueDim = valueAxis.dim; + var baseDataOffset = valueDim === 'x' || valueDim === 'radius' ? 1 : 0; + + var stackedOnSameSign; + var stackedOn = data.stackedOn; + var val = data.get(valueDim, idx); + // Find first stacked value with same sign + while (stackedOn && + sign(stackedOn.get(valueDim, idx)) === sign(val) + ) { + stackedOnSameSign = stackedOn; + break; + } + var stackedData = []; + stackedData[baseDataOffset] = data.get(baseAxis.dim, idx); + stackedData[1 - baseDataOffset] = stackedOnSameSign + ? stackedOnSameSign.get(valueDim, idx, true) : valueStart; + + return coordSys.dataToPoint(stackedData); + } + + // function convertToIntId(newIdList, oldIdList) { + // // Generate int id instead of string id. + // // Compare string maybe slow in score function of arrDiff + + // // Assume id in idList are all unique + // var idIndicesMap = {}; + // var idx = 0; + // for (var i = 0; i < newIdList.length; i++) { + // idIndicesMap[newIdList[i]] = idx; + // newIdList[i] = idx++; + // } + // for (var i = 0; i < oldIdList.length; i++) { + // var oldId = oldIdList[i]; + // // Same with newIdList + // if (idIndicesMap[oldId]) { + // oldIdList[i] = idIndicesMap[oldId]; + // } + // else { + // oldIdList[i] = idx++; + // } + // } + // } + + function diffData(oldData, newData) { + var diffResult = []; + + newData.diff(oldData) + .add(function (idx) { + diffResult.push({cmd: '+', idx: idx}); + }) + .update(function (newIdx, oldIdx) { + diffResult.push({cmd: '=', idx: oldIdx, idx1: newIdx}); + }) + .remove(function (idx) { + diffResult.push({cmd: '-', idx: idx}); + }) + .execute(); + + return diffResult; + } + + module.exports = function ( + oldData, newData, + oldStackedOnPoints, newStackedOnPoints, + oldCoordSys, newCoordSys + ) { + var diff = diffData(oldData, newData); + + // var newIdList = newData.mapArray(newData.getId); + // var oldIdList = oldData.mapArray(oldData.getId); + + // convertToIntId(newIdList, oldIdList); + + // // FIXME One data ? + // diff = arrayDiff(oldIdList, newIdList); + + var currPoints = []; + var nextPoints = []; + // Points for stacking base line + var currStackedPoints = []; + var nextStackedPoints = []; + + var status = []; + var sortedIndices = []; + var rawIndices = []; + var dims = newCoordSys.dimensions; + for (var i = 0; i < diff.length; i++) { + var diffItem = diff[i]; + var pointAdded = true; + + // FIXME, animation is not so perfect when dataZoom window moves fast + // Which is in case remvoing or add more than one data in the tail or head + switch (diffItem.cmd) { + case '=': + var currentPt = oldData.getItemLayout(diffItem.idx); + var nextPt = newData.getItemLayout(diffItem.idx1); + // If previous data is NaN, use next point directly + if (isNaN(currentPt[0]) || isNaN(currentPt[1])) { + currentPt = nextPt.slice(); + } + currPoints.push(currentPt); + nextPoints.push(nextPt); + + currStackedPoints.push(oldStackedOnPoints[diffItem.idx]); + nextStackedPoints.push(newStackedOnPoints[diffItem.idx1]); + + rawIndices.push(newData.getRawIndex(diffItem.idx1)); + break; + case '+': + var idx = diffItem.idx; + currPoints.push( + oldCoordSys.dataToPoint([ + newData.get(dims[0], idx, true), newData.get(dims[1], idx, true) + ]) + ); + + nextPoints.push(newData.getItemLayout(idx).slice()); + + currStackedPoints.push( + getStackedOnPoint(oldCoordSys, newData, idx) + ); + nextStackedPoints.push(newStackedOnPoints[idx]); + + rawIndices.push(newData.getRawIndex(idx)); + break; + case '-': + var idx = diffItem.idx; + var rawIndex = oldData.getRawIndex(idx); + // Data is replaced. In the case of dynamic data queue + // FIXME FIXME FIXME + if (rawIndex !== idx) { + currPoints.push(oldData.getItemLayout(idx)); + nextPoints.push(newCoordSys.dataToPoint([ + oldData.get(dims[0], idx, true), oldData.get(dims[1], idx, true) + ])); + + currStackedPoints.push(oldStackedOnPoints[idx]); + nextStackedPoints.push( + getStackedOnPoint( + newCoordSys, oldData, idx + ) + ); + + rawIndices.push(rawIndex); + } + else { + pointAdded = false; + } + } + + // Original indices + if (pointAdded) { + status.push(diffItem); + sortedIndices.push(sortedIndices.length); + } + } + + // Diff result may be crossed if all items are changed + // Sort by data index + sortedIndices.sort(function (a, b) { + return rawIndices[a] - rawIndices[b]; + }); + + var sortedCurrPoints = []; + var sortedNextPoints = []; + + var sortedCurrStackedPoints = []; + var sortedNextStackedPoints = []; + + var sortedStatus = []; + for (var i = 0; i < sortedIndices.length; i++) { + var idx = sortedIndices[i]; + sortedCurrPoints[i] = currPoints[idx]; + sortedNextPoints[i] = nextPoints[idx]; + + sortedCurrStackedPoints[i] = currStackedPoints[idx]; + sortedNextStackedPoints[i] = nextStackedPoints[idx]; + + sortedStatus[i] = status[idx]; + } + + return { + current: sortedCurrPoints, + next: sortedNextPoints, + + stackedOnCurrent: sortedCurrStackedPoints, + stackedOnNext: sortedNextStackedPoints, + + status: sortedStatus + }; + }; + + +/***/ }, +/* 120 */ +/***/ function(module, exports, __webpack_require__) { + + // Poly path support NaN point + + + var Path = __webpack_require__(20); + var vec2 = __webpack_require__(10); + + var vec2Min = vec2.min; + var vec2Max = vec2.max; + + var scaleAndAdd = vec2.scaleAndAdd; + var v2Copy = vec2.copy; + + // Temporary variable + var v = []; + var cp0 = []; + var cp1 = []; + + function isPointNull(p) { + return isNaN(p[0]) || isNaN(p[1]); + } + + function drawSegment( + ctx, points, start, segLen, allLen, + dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls + ) { + var prevIdx = 0; + var idx = start; + for (var k = 0; k < segLen; k++) { + var p = points[idx]; + if (idx >= allLen || idx < 0) { + break; + } + if (isPointNull(p)) { + if (connectNulls) { + idx += dir; + continue; + } + break; + } + + if (idx === start) { + ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]); + v2Copy(cp0, p); + } + else { + if (smooth > 0) { + var nextIdx = idx + dir; + var nextP = points[nextIdx]; + if (connectNulls) { + // Find next point not null + while (nextP && isPointNull(points[nextIdx])) { + nextIdx += dir; + nextP = points[nextIdx]; + } + } + + var ratioNextSeg = 0.5; + var prevP = points[prevIdx]; + var nextP = points[nextIdx]; + // Last point + if (!nextP || isPointNull(nextP)) { + v2Copy(cp1, p); + } + else { + // If next data is null in not connect case + if (isPointNull(nextP) && !connectNulls) { + nextP = p; + } + + vec2.sub(v, nextP, prevP); + + var lenPrevSeg; + var lenNextSeg; + if (smoothMonotone === 'x' || smoothMonotone === 'y') { + var dim = smoothMonotone === 'x' ? 0 : 1; + lenPrevSeg = Math.abs(p[dim] - prevP[dim]); + lenNextSeg = Math.abs(p[dim] - nextP[dim]); + } + else { + lenPrevSeg = vec2.dist(p, prevP); + lenNextSeg = vec2.dist(p, nextP); + } + + // Use ratio of seg length + ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg); + + scaleAndAdd(cp1, p, v, -smooth * (1 - ratioNextSeg)); + } + // Smooth constraint + vec2Min(cp0, cp0, smoothMax); + vec2Max(cp0, cp0, smoothMin); + vec2Min(cp1, cp1, smoothMax); + vec2Max(cp1, cp1, smoothMin); + + ctx.bezierCurveTo( + cp0[0], cp0[1], + cp1[0], cp1[1], + p[0], p[1] + ); + // cp0 of next segment + scaleAndAdd(cp0, p, v, smooth * ratioNextSeg); + } + else { + ctx.lineTo(p[0], p[1]); + } + } + + prevIdx = idx; + idx += dir; + } + + return k; + } + + function getBoundingBox(points, smoothConstraint) { + var ptMin = [Infinity, Infinity]; + var ptMax = [-Infinity, -Infinity]; + if (smoothConstraint) { + for (var i = 0; i < points.length; i++) { + var pt = points[i]; + if (pt[0] < ptMin[0]) { ptMin[0] = pt[0]; } + if (pt[1] < ptMin[1]) { ptMin[1] = pt[1]; } + if (pt[0] > ptMax[0]) { ptMax[0] = pt[0]; } + if (pt[1] > ptMax[1]) { ptMax[1] = pt[1]; } + } + } + return { + min: smoothConstraint ? ptMin : ptMax, + max: smoothConstraint ? ptMax : ptMin + }; + } + + module.exports = { + + Polyline: Path.extend({ + + type: 'ec-polyline', + + shape: { + points: [], + + smooth: 0, + + smoothConstraint: true, + + smoothMonotone: null, + + connectNulls: false + }, + + style: { + fill: null, + + stroke: '#000' + }, + + buildPath: function (ctx, shape) { + var points = shape.points; + + var i = 0; + var len = points.length; + + var result = getBoundingBox(points, shape.smoothConstraint); + + if (shape.connectNulls) { + // Must remove first and last null values avoid draw error in polygon + for (; len > 0; len--) { + if (!isPointNull(points[len - 1])) { + break; + } + } + for (; i < len; i++) { + if (!isPointNull(points[i])) { + break; + } + } + } + while (i < len) { + i += drawSegment( + ctx, points, i, len, len, + 1, result.min, result.max, shape.smooth, + shape.smoothMonotone, shape.connectNulls + ) + 1; + } + } + }), + + Polygon: Path.extend({ + + type: 'ec-polygon', + + shape: { + points: [], + + // Offset between stacked base points and points + stackedOnPoints: [], + + smooth: 0, + + stackedOnSmooth: 0, + + smoothConstraint: true, + + smoothMonotone: null, + + connectNulls: false + }, + + buildPath: function (ctx, shape) { + var points = shape.points; + var stackedOnPoints = shape.stackedOnPoints; + + var i = 0; + var len = points.length; + var smoothMonotone = shape.smoothMonotone; + var bbox = getBoundingBox(points, shape.smoothConstraint); + var stackedOnBBox = getBoundingBox(stackedOnPoints, shape.smoothConstraint); + + if (shape.connectNulls) { + // Must remove first and last null values avoid draw error in polygon + for (; len > 0; len--) { + if (!isPointNull(points[len - 1])) { + break; + } + } + for (; i < len; i++) { + if (!isPointNull(points[i])) { + break; + } + } + } + while (i < len) { + var k = drawSegment( + ctx, points, i, len, len, + 1, bbox.min, bbox.max, shape.smooth, + smoothMonotone, shape.connectNulls + ); + drawSegment( + ctx, stackedOnPoints, i + k - 1, k, len, + -1, stackedOnBBox.min, stackedOnBBox.max, shape.stackedOnSmooth, + smoothMonotone, shape.connectNulls + ); + i += k + 1; + + ctx.closePath(); + } + } + }) + }; + + +/***/ }, +/* 121 */ +/***/ function(module, exports) { + + + + module.exports = function (seriesType, defaultSymbolType, legendSymbol, ecModel, api) { + + // Encoding visual for all series include which is filtered for legend drawing + ecModel.eachRawSeriesByType(seriesType, function (seriesModel) { + var data = seriesModel.getData(); + + var symbolType = seriesModel.get('symbol') || defaultSymbolType; + var symbolSize = seriesModel.get('symbolSize'); + + data.setVisual({ + legendSymbol: legendSymbol || symbolType, + symbol: symbolType, + symbolSize: symbolSize + }); + + // Only visible series has each data be visual encoded + if (!ecModel.isSeriesFiltered(seriesModel)) { + if (typeof symbolSize === 'function') { + data.each(function (idx) { + var rawValue = seriesModel.getRawValue(idx); + // FIXME + var params = seriesModel.getDataParams(idx); + data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params)); + }); + } + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var itemSymbolType = itemModel.getShallow('symbol', true); + var itemSymbolSize = itemModel.getShallow('symbolSize', true); + // If has item symbol + if (itemSymbolType != null) { + data.setItemVisual(idx, 'symbol', itemSymbolType); + } + if (itemSymbolSize != null) { + // PENDING Transform symbolSize ? + data.setItemVisual(idx, 'symbolSize', itemSymbolSize); + } + }); + } + }); + }; + + +/***/ }, +/* 122 */ +/***/ function(module, exports) { + + + + module.exports = function (seriesType, ecModel) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + + if (!coordSys) { + return; + } + + var dims = []; + var coordDims = coordSys.dimensions; + for (var i = 0; i < coordDims.length; i++) { + dims.push(seriesModel.coordDimToDataDim(coordSys.dimensions[i])[0]); + } + + if (dims.length === 1) { + data.each(dims[0], function (x, idx) { + // Also {Array.}, not undefined to avoid if...else... statement + data.setItemLayout(idx, isNaN(x) ? [NaN, NaN] : coordSys.dataToPoint(x)); + }); + } + else if (dims.length === 2) { + data.each(dims, function (x, y, idx) { + // Also {Array.}, not undefined to avoid if...else... statement + data.setItemLayout( + idx, (isNaN(x) || isNaN(y)) ? [NaN, NaN] : coordSys.dataToPoint([x, y]) + ); + }, true); + } + }); + }; + + + +/***/ }, +/* 123 */ +/***/ function(module, exports) { + + + var samplers = { + average: function (frame) { + var sum = 0; + var count = 0; + for (var i = 0; i < frame.length; i++) { + if (!isNaN(frame[i])) { + sum += frame[i]; + count++; + } + } + // Return NaN if count is 0 + return count === 0 ? NaN : sum / count; + }, + sum: function (frame) { + var sum = 0; + for (var i = 0; i < frame.length; i++) { + // Ignore NaN + sum += frame[i] || 0; + } + return sum; + }, + max: function (frame) { + var max = -Infinity; + for (var i = 0; i < frame.length; i++) { + frame[i] > max && (max = frame[i]); + } + return max; + }, + min: function (frame) { + var min = Infinity; + for (var i = 0; i < frame.length; i++) { + frame[i] < min && (min = frame[i]); + } + return min; + }, + // TODO + // Median + nearest: function (frame) { + return frame[0]; + } + }; + + var indexSampler = function (frame, value) { + return Math.round(frame.length / 2); + }; + module.exports = function (seriesType, ecModel, api) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var data = seriesModel.getData(); + var sampling = seriesModel.get('sampling'); + var coordSys = seriesModel.coordinateSystem; + // Only cartesian2d support down sampling + if (coordSys.type === 'cartesian2d' && sampling) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var extent = baseAxis.getExtent(); + // Coordinste system has been resized + var size = extent[1] - extent[0]; + var rate = Math.round(data.count() / size); + if (rate > 1) { + var sampler; + if (typeof sampling === 'string') { + sampler = samplers[sampling]; + } + else if (typeof sampling === 'function') { + sampler = sampling; + } + if (sampler) { + data = data.downSample( + valueAxis.dim, 1 / rate, sampler, indexSampler + ); + seriesModel.setData(data); + } + } + } + }, this); + }; + + +/***/ }, +/* 124 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + var echarts = __webpack_require__(1); + + __webpack_require__(125); + + __webpack_require__(133); + + // Grid view + echarts.extendComponentView({ + + type: 'grid', + + render: function (gridModel, ecModel) { + this.group.removeAll(); + if (gridModel.get('show')) { + this.group.add(new graphic.Rect({ + shape: gridModel.coordinateSystem.getRect(), + style: zrUtil.defaults({ + fill: gridModel.get('backgroundColor') + }, gridModel.getItemStyle()), + silent: true, + z2: -1 + })); + } + } + + }); + + echarts.registerPreprocessor(function (option) { + // Only create grid when need + if (option.xAxis && option.yAxis && !option.grid) { + option.grid = {}; + } + }); + + +/***/ }, +/* 125 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Grid is a region which contains at most 4 cartesian systems + * + * TODO Default cartesian + */ + var factory = exports; + + var layout = __webpack_require__(71); + var axisHelper = __webpack_require__(101); + + var zrUtil = __webpack_require__(4); + var Cartesian2D = __webpack_require__(126); + var Axis2D = __webpack_require__(128); + + var each = zrUtil.each; + + var ifAxisCrossZero = axisHelper.ifAxisCrossZero; + var niceScaleExtent = axisHelper.niceScaleExtent; + + // 依赖 GridModel, AxisModel 做预处理 + __webpack_require__(129); + + /** + * Check if the axis is used in the specified grid + * @inner + */ + function isAxisUsedInTheGrid(axisModel, gridModel, ecModel) { + return axisModel.getCoordSysModel() === gridModel; + } + + function getLabelUnionRect(axis) { + var axisModel = axis.model; + var labels = axisModel.getFormattedLabels(); + var textStyleModel = axisModel.getModel('axisLabel.textStyle'); + var rect; + var step = 1; + var labelCount = labels.length; + if (labelCount > 40) { + // Simple optimization for large amount of labels + step = Math.ceil(labelCount / 40); + } + for (var i = 0; i < labelCount; i += step) { + if (!axis.isLabelIgnored(i)) { + var singleRect = textStyleModel.getTextRect(labels[i]); + // FIXME consider label rotate + rect ? rect.union(singleRect) : (rect = singleRect); + } + } + return rect; + } + + function Grid(gridModel, ecModel, api) { + /** + * @type {Object.} + * @private + */ + this._coordsMap = {}; + + /** + * @type {Array.} + * @private + */ + this._coordsList = []; + + /** + * @type {Object.} + * @private + */ + this._axesMap = {}; + + /** + * @type {Array.} + * @private + */ + this._axesList = []; + + this._initCartesian(gridModel, ecModel, api); + + this.model = gridModel; + } + + var gridProto = Grid.prototype; + + gridProto.type = 'grid'; + + gridProto.axisPointerEnabled = true; + + gridProto.getRect = function () { + return this._rect; + }; + + gridProto.update = function (ecModel, api) { + + var axesMap = this._axesMap; + + this._updateScale(ecModel, this.model); + + function ifAxisCanNotOnZero(otherAxisDim) { + var axes = axesMap[otherAxisDim]; + for (var idx in axes) { + if (axes.hasOwnProperty(idx)) { + var axis = axes[idx]; + if (axis && ( + axis.type === 'category' || axis.type === 'time' || !ifAxisCrossZero(axis) + )) { + return true; + } + } + } + return false; + } + + each(axesMap.x, function (xAxis) { + niceScaleExtent(xAxis.scale, xAxis.model); + }); + each(axesMap.y, function (yAxis) { + niceScaleExtent(yAxis.scale, yAxis.model); + }); + // Fix configuration + each(axesMap.x, function (xAxis) { + // onZero can not be enabled in these two situations + // 1. When any other axis is a category axis + // 2. When any other axis not across 0 point + if (ifAxisCanNotOnZero('y')) { + xAxis.onZero = false; + } + }); + each(axesMap.y, function (yAxis) { + if (ifAxisCanNotOnZero('x')) { + yAxis.onZero = false; + } + }); + + // Resize again if containLabel is enabled + // FIXME It may cause getting wrong grid size in data processing stage + this.resize(this.model, api); + }; + + /** + * Resize the grid + * @param {module:echarts/coord/cartesian/GridModel} gridModel + * @param {module:echarts/ExtensionAPI} api + */ + gridProto.resize = function (gridModel, api, ignoreContainLabel) { + + var gridRect = layout.getLayoutRect( + gridModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + + this._rect = gridRect; + + var axesList = this._axesList; + + adjustAxes(); + + // Minus label size + if (!ignoreContainLabel && gridModel.get('containLabel')) { + each(axesList, function (axis) { + if (!axis.model.get('axisLabel.inside')) { + var labelUnionRect = getLabelUnionRect(axis); + if (labelUnionRect) { + var dim = axis.isHorizontal() ? 'height' : 'width'; + var margin = axis.model.get('axisLabel.margin'); + gridRect[dim] -= labelUnionRect[dim] + margin; + if (axis.position === 'top') { + gridRect.y += labelUnionRect.height + margin; + } + else if (axis.position === 'left') { + gridRect.x += labelUnionRect.width + margin; + } + } + } + }); + + adjustAxes(); + } + + function adjustAxes() { + each(axesList, function (axis) { + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(extent[idx], extent[1 - idx]); + updateAxisTransfrom(axis, isHorizontal ? gridRect.x : gridRect.y); + }); + } + }; + + /** + * @param {string} axisType + * @param {ndumber} [axisIndex] + */ + gridProto.getAxis = function (axisType, axisIndex) { + var axesMapOnDim = this._axesMap[axisType]; + if (axesMapOnDim != null) { + if (axisIndex == null) { + // Find first axis + for (var name in axesMapOnDim) { + if (axesMapOnDim.hasOwnProperty(name)) { + return axesMapOnDim[name]; + } + } + } + return axesMapOnDim[axisIndex]; + } + }; + + /** + * @return {Array.} + */ + gridProto.getAxes = function () { + return this._axesList.slice(); + }; + + /** + * Usage: + * grid.getCartesian(xAxisIndex, yAxisIndex); + * grid.getCartesian(xAxisIndex); + * grid.getCartesian(null, yAxisIndex); + * grid.getCartesian({xAxisIndex: ..., yAxisIndex: ...}); + * + * @param {number|Object} [xAxisIndex] + * @param {number} [yAxisIndex] + */ + gridProto.getCartesian = function (xAxisIndex, yAxisIndex) { + if (xAxisIndex != null && yAxisIndex != null) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + return this._coordsMap[key]; + } + + if (zrUtil.isObject(xAxisIndex)) { + yAxisIndex = xAxisIndex.yAxisIndex; + xAxisIndex = xAxisIndex.xAxisIndex; + } + // When only xAxisIndex or yAxisIndex given, find its first cartesian. + for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) { + if (coordList[i].getAxis('x').index === xAxisIndex + || coordList[i].getAxis('y').index === yAxisIndex + ) { + return coordList[i]; + } + } + }; + + gridProto.getCartesians = function () { + return this._coordsList.slice(); + }; + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + gridProto.convertToPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(ecModel, finder); + + return target.cartesian + ? target.cartesian.dataToPoint(value) + : target.axis + ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) + : null; + }; + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + gridProto.convertFromPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(ecModel, finder); + + return target.cartesian + ? target.cartesian.pointToData(value) + : target.axis + ? target.axis.coordToData(target.axis.toLocalCoord(value)) + : null; + }; + + /** + * @inner + */ + gridProto._findConvertTarget = function (ecModel, finder) { + var seriesModel = finder.seriesModel; + var xAxisModel = finder.xAxisModel + || (seriesModel && seriesModel.getReferringComponents('xAxis')[0]); + var yAxisModel = finder.yAxisModel + || (seriesModel && seriesModel.getReferringComponents('yAxis')[0]); + var gridModel = finder.gridModel; + var coordsList = this._coordsList; + var cartesian; + var axis; + + if (seriesModel) { + cartesian = seriesModel.coordinateSystem; + zrUtil.indexOf(coordsList, cartesian) < 0 && (cartesian = null); + } + else if (xAxisModel && yAxisModel) { + cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + } + else if (xAxisModel) { + axis = this.getAxis('x', xAxisModel.componentIndex); + } + else if (yAxisModel) { + axis = this.getAxis('y', yAxisModel.componentIndex); + } + // Lowest priority. + else if (gridModel) { + var grid = gridModel.coordinateSystem; + if (grid === this) { + cartesian = this._coordsList[0]; + } + } + + return {cartesian: cartesian, axis: axis}; + }; + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + gridProto.containPoint = function (point) { + var coord = this._coordsList[0]; + if (coord) { + return coord.containPoint(point); + } + }; + + /** + * Initialize cartesian coordinate systems + * @private + */ + gridProto._initCartesian = function (gridModel, ecModel, api) { + var axisPositionUsed = { + left: false, + right: false, + top: false, + bottom: false + }; + + var axesMap = { + x: {}, + y: {} + }; + var axesCount = { + x: 0, + y: 0 + }; + + /// Create axis + ecModel.eachComponent('xAxis', createAxisCreator('x'), this); + ecModel.eachComponent('yAxis', createAxisCreator('y'), this); + + if (!axesCount.x || !axesCount.y) { + // Roll back when there no either x or y axis + this._axesMap = {}; + this._axesList = []; + return; + } + + this._axesMap = axesMap; + + /// Create cartesian2d + each(axesMap.x, function (xAxis, xAxisIndex) { + each(axesMap.y, function (yAxis, yAxisIndex) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + var cartesian = new Cartesian2D(key); + + cartesian.grid = this; + cartesian.model = gridModel; + + this._coordsMap[key] = cartesian; + this._coordsList.push(cartesian); + + cartesian.addAxis(xAxis); + cartesian.addAxis(yAxis); + }, this); + }, this); + + function createAxisCreator(axisType) { + return function (axisModel, idx) { + if (!isAxisUsedInTheGrid(axisModel, gridModel, ecModel)) { + return; + } + + var axisPosition = axisModel.get('position'); + if (axisType === 'x') { + // Fix position + if (axisPosition !== 'top' && axisPosition !== 'bottom') { + // Default bottom of X + axisPosition = 'bottom'; + if (axisPositionUsed[axisPosition]) { + axisPosition = axisPosition === 'top' ? 'bottom' : 'top'; + } + } + } + else { + // Fix position + if (axisPosition !== 'left' && axisPosition !== 'right') { + // Default left of Y + axisPosition = 'left'; + if (axisPositionUsed[axisPosition]) { + axisPosition = axisPosition === 'left' ? 'right' : 'left'; + } + } + } + axisPositionUsed[axisPosition] = true; + + var axis = new Axis2D( + axisType, axisHelper.createScaleByModel(axisModel), + [0, 0], + axisModel.get('type'), + axisPosition + ); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + + axis.onZero = axisModel.get('axisLine.onZero'); + + // Inject axis into axisModel + axisModel.axis = axis; + + // Inject axisModel into axis + axis.model = axisModel; + + // Inject grid info axis + axis.grid = this; + + // Index of axis, can be used as key + axis.index = idx; + + this._axesList.push(axis); + + axesMap[axisType][idx] = axis; + axesCount[axisType]++; + }; + } + }; + + /** + * Update cartesian properties from series + * @param {module:echarts/model/Option} option + * @private + */ + gridProto._updateScale = function (ecModel, gridModel) { + // Reset scale + zrUtil.each(this._axesList, function (axis) { + axis.scale.setExtent(Infinity, -Infinity); + }); + ecModel.eachSeries(function (seriesModel) { + if (isCartesian2D(seriesModel)) { + var axesModels = findAxesModels(seriesModel, ecModel); + var xAxisModel = axesModels[0]; + var yAxisModel = axesModels[1]; + + if (!isAxisUsedInTheGrid(xAxisModel, gridModel, ecModel) + || !isAxisUsedInTheGrid(yAxisModel, gridModel, ecModel) + ) { + return; + } + + var cartesian = this.getCartesian( + xAxisModel.componentIndex, yAxisModel.componentIndex + ); + var data = seriesModel.getData(); + var xAxis = cartesian.getAxis('x'); + var yAxis = cartesian.getAxis('y'); + + if (data.type === 'list') { + unionExtent(data, xAxis, seriesModel); + unionExtent(data, yAxis, seriesModel); + } + } + }, this); + + function unionExtent(data, axis, seriesModel) { + each(seriesModel.coordDimToDataDim(axis.dim), function (dim) { + axis.scale.unionExtentFromData(data, dim); + }); + } + }; + + /** + * @param {string} [dim] 'x' or 'y' or 'auto' or null/undefined + * @return {Object} {baseAxes: [], otherAxes: []} + */ + gridProto.getTooltipAxes = function (dim) { + var baseAxes = []; + var otherAxes = []; + + each(this.getCartesians(), function (cartesian) { + var baseAxis = (dim != null && dim !== 'auto') + ? cartesian.getAxis(dim) : cartesian.getBaseAxis(); + var otherAxis = cartesian.getOtherAxis(baseAxis); + zrUtil.indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis); + zrUtil.indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis); + }); + + return {baseAxes: baseAxes, otherAxes: otherAxes}; + }; + + /** + * @inner + */ + function updateAxisTransfrom(axis, coordBase) { + var axisExtent = axis.getExtent(); + var axisExtentSum = axisExtent[0] + axisExtent[1]; + + // Fast transform + axis.toGlobalCoord = axis.dim === 'x' + ? function (coord) { + return coord + coordBase; + } + : function (coord) { + return axisExtentSum - coord + coordBase; + }; + axis.toLocalCoord = axis.dim === 'x' + ? function (coord) { + return coord - coordBase; + } + : function (coord) { + return axisExtentSum - coord + coordBase; + }; + } + + var axesTypes = ['xAxis', 'yAxis']; + /** + * @inner + */ + function findAxesModels(seriesModel, ecModel) { + return zrUtil.map(axesTypes, function (axisType) { + var axisModel = seriesModel.getReferringComponents(axisType)[0]; + + if (true) { + if (!axisModel) { + throw new Error(axisType + ' "' + zrUtil.retrieve( + seriesModel.get(axisType + 'Index'), + seriesModel.get(axisType + 'Id'), + 0 + ) + '" not found'); + } + } + return axisModel; + }); + } + + /** + * @inner + */ + function isCartesian2D(seriesModel) { + return seriesModel.get('coordinateSystem') === 'cartesian2d'; + } + + Grid.create = function (ecModel, api) { + var grids = []; + ecModel.eachComponent('grid', function (gridModel, idx) { + var grid = new Grid(gridModel, ecModel, api); + grid.name = 'grid_' + idx; + // dataSampling requires axis extent, so resize + // should be performed in create stage. + grid.resize(gridModel, api, true); + + gridModel.coordinateSystem = grid; + + grids.push(grid); + }); + + // Inject the coordinateSystems into seriesModel + ecModel.eachSeries(function (seriesModel) { + if (!isCartesian2D(seriesModel)) { + return; + } + + var axesModels = findAxesModels(seriesModel, ecModel); + var xAxisModel = axesModels[0]; + var yAxisModel = axesModels[1]; + + var gridModel = xAxisModel.getCoordSysModel(); + + if (true) { + if (!gridModel) { + throw new Error( + 'Grid "' + zrUtil.retrieve( + xAxisModel.get('gridIndex'), + xAxisModel.get('gridId'), + 0 + ) + '" not found' + ); + } + if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) { + throw new Error('xAxis and yAxis must use the same grid'); + } + } + + var grid = gridModel.coordinateSystem; + + seriesModel.coordinateSystem = grid.getCartesian( + xAxisModel.componentIndex, yAxisModel.componentIndex + ); + }); + + return grids; + }; + + // For deciding which dimensions to use when creating list data + Grid.dimensions = Grid.prototype.dimensions = Cartesian2D.prototype.dimensions; + + __webpack_require__(76).register('cartesian2d', Grid); + + module.exports = Grid; + + +/***/ }, +/* 126 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var Cartesian = __webpack_require__(127); + + function Cartesian2D(name) { + + Cartesian.call(this, name); + } + + Cartesian2D.prototype = { + + constructor: Cartesian2D, + + type: 'cartesian2d', + + /** + * @type {Array.} + * @readOnly + */ + dimensions: ['x', 'y'], + + /** + * Base axis will be used on stacking. + * + * @return {module:echarts/coord/cartesian/Axis2D} + */ + getBaseAxis: function () { + return this.getAxesByScale('ordinal')[0] + || this.getAxesByScale('time')[0] + || this.getAxis('x'); + }, + + /** + * If contain point + * @param {Array.} point + * @return {boolean} + */ + containPoint: function (point) { + var axisX = this.getAxis('x'); + var axisY = this.getAxis('y'); + return axisX.contain(axisX.toLocalCoord(point[0])) + && axisY.contain(axisY.toLocalCoord(point[1])); + }, + + /** + * If contain data + * @param {Array.} data + * @return {boolean} + */ + containData: function (data) { + return this.getAxis('x').containData(data[0]) + && this.getAxis('y').containData(data[1]); + }, + + /** + * Convert series data to an array of points + * @param {module:echarts/data/List} data + * @param {boolean} stack + * @return {Array} + * Return array of points. For example: + * `[[10, 10], [20, 20], [30, 30]]` + */ + dataToPoints: function (data, stack) { + return data.mapArray(['x', 'y'], function (x, y) { + return this.dataToPoint([x, y]); + }, stack, this); + }, + + /** + * @param {Array.} data + * @param {boolean} [clamp=false] + * @return {Array.} + */ + dataToPoint: function (data, clamp) { + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + return [ + xAxis.toGlobalCoord(xAxis.dataToCoord(data[0], clamp)), + yAxis.toGlobalCoord(yAxis.dataToCoord(data[1], clamp)) + ]; + }, + + /** + * @param {Array.} point + * @param {boolean} [clamp=false] + * @return {Array.} + */ + pointToData: function (point, clamp) { + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + return [ + xAxis.coordToData(xAxis.toLocalCoord(point[0]), clamp), + yAxis.coordToData(yAxis.toLocalCoord(point[1]), clamp) + ]; + }, + + /** + * Get other axis + * @param {module:echarts/coord/cartesian/Axis2D} axis + */ + getOtherAxis: function (axis) { + return this.getAxis(axis.dim === 'x' ? 'y' : 'x'); + } + + }; + + zrUtil.inherits(Cartesian2D, Cartesian); + + module.exports = Cartesian2D; + + +/***/ }, +/* 127 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * Cartesian coordinate system + * @module echarts/coord/Cartesian + * + */ + + + var zrUtil = __webpack_require__(4); + + function dimAxisMapper(dim) { + return this._axes[dim]; + } + + /** + * @alias module:echarts/coord/Cartesian + * @constructor + */ + var Cartesian = function (name) { + this._axes = {}; + + this._dimList = []; + + /** + * @type {string} + */ + this.name = name || ''; + }; + + Cartesian.prototype = { + + constructor: Cartesian, + + type: 'cartesian', + + /** + * Get axis + * @param {number|string} dim + * @return {module:echarts/coord/Cartesian~Axis} + */ + getAxis: function (dim) { + return this._axes[dim]; + }, + + /** + * Get axes list + * @return {Array.} + */ + getAxes: function () { + return zrUtil.map(this._dimList, dimAxisMapper, this); + }, + + /** + * Get axes list by given scale type + */ + getAxesByScale: function (scaleType) { + scaleType = scaleType.toLowerCase(); + return zrUtil.filter( + this.getAxes(), + function (axis) { + return axis.scale.type === scaleType; + } + ); + }, + + /** + * Add axis + * @param {module:echarts/coord/Cartesian.Axis} + */ + addAxis: function (axis) { + var dim = axis.dim; + + this._axes[dim] = axis; + + this._dimList.push(dim); + }, + + /** + * Convert data to coord in nd space + * @param {Array.|Object.} val + * @return {Array.|Object.} + */ + dataToCoord: function (val) { + return this._dataCoordConvert(val, 'dataToCoord'); + }, + + /** + * Convert coord in nd space to data + * @param {Array.|Object.} val + * @return {Array.|Object.} + */ + coordToData: function (val) { + return this._dataCoordConvert(val, 'coordToData'); + }, + + _dataCoordConvert: function (input, method) { + var dimList = this._dimList; + + var output = input instanceof Array ? [] : {}; + + for (var i = 0; i < dimList.length; i++) { + var dim = dimList[i]; + var axis = this._axes[dim]; + + output[dim] = axis[method](input[dim]); + } + + return output; + } + }; + + module.exports = Cartesian; + + +/***/ }, +/* 128 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var Axis = __webpack_require__(100); + + /** + * Extend axis 2d + * @constructor module:echarts/coord/cartesian/Axis2D + * @extends {module:echarts/coord/cartesian/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + * @param {string} position + */ + var Axis2D = function (dim, scale, coordExtent, axisType, position) { + Axis.call(this, dim, scale, coordExtent); + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * Axis position + * - 'top' + * - 'bottom' + * - 'left' + * - 'right' + */ + this.position = position || 'bottom'; + }; + + Axis2D.prototype = { + + constructor: Axis2D, + + /** + * Index of axis, can be used as key + */ + index: 0, + /** + * If axis is on the zero position of the other axis + * @type {boolean} + */ + onZero: false, + + /** + * Axis model + * @param {module:echarts/coord/cartesian/AxisModel} + */ + model: null, + + isHorizontal: function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + }, + + /** + * Each item cooresponds to this.getExtent(), which + * means globalExtent[0] may greater than globalExtent[1], + * unless `asc` is input. + * + * @param {boolean} [asc] + * @return {Array.} + */ + getGlobalExtent: function (asc) { + var ret = this.getExtent(); + ret[0] = this.toGlobalCoord(ret[0]); + ret[1] = this.toGlobalCoord(ret[1]); + asc && ret[0] > ret[1] && ret.reverse(); + return ret; + }, + + getOtherAxis: function () { + this.grid.getOtherAxis(); + }, + + /** + * If label is ignored. + * Automatically used when axis is category and label can not be all shown + * @param {number} idx + * @return {boolean} + */ + isLabelIgnored: function (idx) { + if (this.type === 'category') { + var labelInterval = this.getLabelInterval(); + return ((typeof labelInterval === 'function') + && !labelInterval(idx, this.scale.getLabel(idx))) + || idx % (labelInterval + 1); + } + }, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp); + }, + + /** + * Transform global coord to local coord, + * i.e. var localCoord = axis.toLocalCoord(80); + * designate by module:echarts/coord/cartesian/Grid. + * @type {Function} + */ + toLocalCoord: null, + + /** + * Transform global coord to local coord, + * i.e. var globalCoord = axis.toLocalCoord(40); + * designate by module:echarts/coord/cartesian/Grid. + * @type {Function} + */ + toGlobalCoord: null + + }; + zrUtil.inherits(Axis2D, Axis); + + module.exports = Axis2D; + + +/***/ }, +/* 129 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + // Grid 是在有直角坐标系的时候必须要存在的 + // 所以这里也要被 Cartesian2D 依赖 + + + __webpack_require__(130); + + var ComponentModel = __webpack_require__(69); + + module.exports = ComponentModel.extend({ + + type: 'grid', + + dependencies: ['xAxis', 'yAxis'], + + layoutMode: 'box', + + /** + * @type {module:echarts/coord/cartesian/Grid} + */ + coordinateSystem: null, + + defaultOption: { + show: false, + zlevel: 0, + z: 0, + left: '10%', + top: 60, + right: '10%', + bottom: 60, + // If grid size contain label + containLabel: false, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 1, + borderColor: '#ccc' + } + }); + + +/***/ }, +/* 130 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var ComponentModel = __webpack_require__(69); + var zrUtil = __webpack_require__(4); + var axisModelCreator = __webpack_require__(131); + + var AxisModel = ComponentModel.extend({ + + type: 'cartesian2dAxis', + + /** + * @type {module:echarts/coord/cartesian/Axis2D} + */ + axis: null, + + /** + * @override + */ + init: function () { + AxisModel.superApply(this, 'init', arguments); + this.resetRange(); + }, + + /** + * @override + */ + mergeOption: function () { + AxisModel.superApply(this, 'mergeOption', arguments); + this.resetRange(); + }, + + /** + * @override + */ + restoreData: function () { + AxisModel.superApply(this, 'restoreData', arguments); + this.resetRange(); + }, + + /** + * @override + * @return {module:echarts/model/Component} + */ + getCoordSysModel: function () { + return this.ecModel.queryComponents({ + mainType: 'grid', + index: this.option.gridIndex, + id: this.option.gridId + })[0]; + } + + }); + + function getAxisType(axisDim, option) { + // Default axis with data is category axis + return option.type || (option.data ? 'category' : 'value'); + } + + zrUtil.merge(AxisModel.prototype, __webpack_require__(112)); + + var extraOption = { + // gridIndex: 0, + // gridId: '', + + // Offset is for multiple axis on the same position + offset: 0 + }; + + axisModelCreator('x', AxisModel, getAxisType, extraOption); + axisModelCreator('y', AxisModel, getAxisType, extraOption); + + module.exports = AxisModel; + + +/***/ }, +/* 131 */ +/***/ function(module, exports, __webpack_require__) { + + + + var axisDefault = __webpack_require__(132); + var zrUtil = __webpack_require__(4); + var ComponentModel = __webpack_require__(69); + var layout = __webpack_require__(71); + + // FIXME axisType is fixed ? + var AXIS_TYPES = ['value', 'category', 'time', 'log']; + + /** + * Generate sub axis model class + * @param {string} axisName 'x' 'y' 'radius' 'angle' 'parallel' + * @param {module:echarts/model/Component} BaseAxisModelClass + * @param {Function} axisTypeDefaulter + * @param {Object} [extraDefaultOption] + */ + module.exports = function (axisName, BaseAxisModelClass, axisTypeDefaulter, extraDefaultOption) { + + zrUtil.each(AXIS_TYPES, function (axisType) { + + BaseAxisModelClass.extend({ + + type: axisName + 'Axis.' + axisType, + + mergeDefaultAndTheme: function (option, ecModel) { + var layoutMode = this.layoutMode; + var inputPositionParams = layoutMode + ? layout.getLayoutParams(option) : {}; + + var themeModel = ecModel.getTheme(); + zrUtil.merge(option, themeModel.get(axisType + 'Axis')); + zrUtil.merge(option, this.getDefaultOption()); + + option.type = axisTypeDefaulter(axisName, option); + + if (layoutMode) { + layout.mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }, + + defaultOption: zrUtil.mergeAll( + [ + {}, + axisDefault[axisType + 'Axis'], + extraDefaultOption + ], + true + ) + }); + }); + + ComponentModel.registerSubTypeDefaulter( + axisName + 'Axis', + zrUtil.curry(axisTypeDefaulter, axisName) + ); + }; + + +/***/ }, +/* 132 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var defaultOption = { + show: true, + zlevel: 0, // 一级层叠 + z: 0, // 二级层叠 + // 反向坐标轴 + inverse: false, + + // 坐标轴名字,默认为空 + name: '', + // 坐标轴名字位置,支持'start' | 'middle' | 'end' + nameLocation: 'end', + // 坐标轴名字旋转,degree。 + nameRotate: null, // Adapt to axis rotate, when nameLocation is 'middle'. + nameTruncate: { + maxWidth: null, + ellipsis: '...', + placeholder: '.' + }, + // 坐标轴文字样式,默认取全局样式 + nameTextStyle: {}, + // 文字与轴线距离 + nameGap: 15, + + silent: false, // Default false to support tooltip. + triggerEvent: false, // Default false to avoid legacy user event listener fail. + + tooltip: { + show: false + }, + + axisPointer: {}, + + // 坐标轴线 + axisLine: { + // 默认显示,属性show控制显示与否 + show: true, + onZero: true, + // 属性lineStyle控制线条样式 + lineStyle: { + color: '#333', + width: 1, + type: 'solid' + } + }, + // 坐标轴小标记 + axisTick: { + // 属性show控制显示与否,默认显示 + show: true, + // 控制小标记是否在grid里 + inside: false, + // 属性length控制线长 + length: 5, + // 属性lineStyle控制线条样式 + lineStyle: { + width: 1 + } + }, + // 坐标轴文本标签,详见axis.axisLabel + axisLabel: { + show: true, + // 控制文本标签是否在grid里 + inside: false, + rotate: 0, + showMinLabel: null, // true | false | null (auto) + showMaxLabel: null, // true | false | null (auto) + margin: 8, + // formatter: null, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + textStyle: { + fontSize: 12 + } + }, + // 分隔线 + splitLine: { + // 默认显示,属性show控制显示与否 + show: true, + // 属性lineStyle(详见lineStyle)控制线条样式 + lineStyle: { + color: ['#ccc'], + width: 1, + type: 'solid' + } + }, + // 分隔区域 + splitArea: { + // 默认不显示,属性show控制显示与否 + show: false, + // 属性areaStyle(详见areaStyle)控制区域样式 + areaStyle: { + color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)'] + } + } + }; + + var categoryAxis = zrUtil.merge({ + // 类目起始和结束两端空白策略 + boundaryGap: true, + // splitArea: { + // show: false + // }, + splitLine: { + show: false + }, + // 坐标轴小标记 + axisTick: { + // If tick is align with label when boundaryGap is true + alignWithLabel: false, + interval: 'auto' + }, + // 坐标轴文本标签,详见axis.axisLabel + axisLabel: { + interval: 'auto' + } + }, defaultOption); + + var valueAxis = zrUtil.merge({ + // 数值起始和结束两端空白策略 + boundaryGap: [0, 0], + // 最小值, 设置成 'dataMin' 则从数据中计算最小值 + // min: null, + // 最大值,设置成 'dataMax' 则从数据中计算最大值 + // max: null, + // Readonly prop, specifies start value of the range when using data zoom. + // rangeStart: null + // Readonly prop, specifies end value of the range when using data zoom. + // rangeEnd: null + // 脱离0值比例,放大聚焦到最终_min,_max区间 + // scale: false, + // 分割段数,默认为5 + splitNumber: 5 + // Minimum interval + // minInterval: null + }, defaultOption); + + // FIXME + var timeAxis = zrUtil.defaults({ + scale: true, + min: 'dataMin', + max: 'dataMax' + }, valueAxis); + + var logAxis = zrUtil.defaults({ + scale: true, + logBase: 10 + }, valueAxis); + + module.exports = { + categoryAxis: categoryAxis, + valueAxis: valueAxis, + timeAxis: timeAxis, + logAxis: logAxis + }; + + +/***/ }, +/* 133 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + // TODO boundaryGap + + + __webpack_require__(130); + + __webpack_require__(134); + + +/***/ }, +/* 134 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var AxisBuilder = __webpack_require__(135); + var AxisView = __webpack_require__(136); + var cartesianAxisHelper = __webpack_require__(138); + var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick; + var getInterval = AxisBuilder.getInterval; + + var axisBuilderAttrs = [ + 'axisLine', 'axisLabel', 'axisTick', 'axisName' + ]; + var selfBuilderAttrs = [ + 'splitArea', 'splitLine' + ]; + + // function getAlignWithLabel(model, axisModel) { + // var alignWithLabel = model.get('alignWithLabel'); + // if (alignWithLabel === 'auto') { + // alignWithLabel = axisModel.get('axisTick.alignWithLabel'); + // } + // return alignWithLabel; + // } + + var CartesianAxisView = AxisView.extend({ + + type: 'cartesianAxis', + + axisPointerClass: 'CartesianAxisPointer', + + /** + * @override + */ + render: function (axisModel, ecModel, api, payload) { + + this.group.removeAll(); + + var oldAxisGroup = this._axisGroup; + this._axisGroup = new graphic.Group(); + + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var gridModel = axisModel.getCoordSysModel(); + + var layout = cartesianAxisHelper.layout(gridModel, axisModel); + + var axisBuilder = new AxisBuilder(axisModel, layout); + + zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + zrUtil.each(selfBuilderAttrs, function (name) { + if (axisModel.get(name + '.show')) { + this['_' + name](axisModel, gridModel, layout.labelInterval); + } + }, this); + + graphic.groupTransition(oldAxisGroup, this._axisGroup, axisModel); + + CartesianAxisView.superCall(this, 'render', axisModel, ecModel, api, payload); + }, + + /** + * @param {module:echarts/coord/cartesian/AxisModel} axisModel + * @param {module:echarts/coord/cartesian/GridModel} gridModel + * @param {number|Function} labelInterval + * @private + */ + _splitLine: function (axisModel, gridModel, labelInterval) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + + var lineInterval = getInterval(splitLineModel, labelInterval); + + lineColors = zrUtil.isArray(lineColors) ? lineColors : [lineColors]; + + var gridRect = gridModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + + var lineCount = 0; + + var ticksCoords = axis.getTicksCoords( + // splitLineModel.get('alignWithLabel') + ); + var ticks = axis.scale.getTicks(); + + var p1 = []; + var p2 = []; + // Simple optimization + // Batching the lines if color are the same + var lineStyle = lineStyleModel.getLineStyle(); + for (var i = 0; i < ticksCoords.length; i++) { + if (ifIgnoreOnTick(axis, i, lineInterval)) { + continue; + } + + var tickCoord = axis.toGlobalCoord(ticksCoords[i]); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } + else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + var colorIndex = (lineCount++) % lineColors.length; + this._axisGroup.add(new graphic.Line(graphic.subPixelOptimizeLine({ + anid: 'line_' + ticks[i], + + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: zrUtil.defaults({ + stroke: lineColors[colorIndex] + }, lineStyle), + silent: true + }))); + } + }, + + /** + * @param {module:echarts/coord/cartesian/AxisModel} axisModel + * @param {module:echarts/coord/cartesian/GridModel} gridModel + * @param {number|Function} labelInterval + * @private + */ + _splitArea: function (axisModel, gridModel, labelInterval) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitAreaModel = axisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + + var gridRect = gridModel.coordinateSystem.getRect(); + + var ticksCoords = axis.getTicksCoords( + // splitAreaModel.get('alignWithLabel') + ); + var ticks = axis.scale.getTicks(); + + var prevX = axis.toGlobalCoord(ticksCoords[0]); + var prevY = axis.toGlobalCoord(ticksCoords[0]); + + var count = 0; + + var areaInterval = getInterval(splitAreaModel, labelInterval); + + var areaStyle = areaStyleModel.getAreaStyle(); + areaColors = zrUtil.isArray(areaColors) ? areaColors : [areaColors]; + + for (var i = 1; i < ticksCoords.length; i++) { + if (ifIgnoreOnTick(axis, i, areaInterval)) { + continue; + } + + var tickCoord = axis.toGlobalCoord(ticksCoords[i]); + + var x; + var y; + var width; + var height; + if (axis.isHorizontal()) { + x = prevX; + y = gridRect.y; + width = tickCoord - x; + height = gridRect.height; + } + else { + x = gridRect.x; + y = prevY; + width = gridRect.width; + height = tickCoord - y; + } + + var colorIndex = (count++) % areaColors.length; + this._axisGroup.add(new graphic.Rect({ + anid: 'area_' + ticks[i], + + shape: { + x: x, + y: y, + width: width, + height: height + }, + style: zrUtil.defaults({ + fill: areaColors[colorIndex] + }, areaStyle), + silent: true + })); + + prevX = x + width; + prevY = y + height; + } + } + }); + + CartesianAxisView.extend({ + type: 'xAxis' + }); + CartesianAxisView.extend({ + type: 'yAxis' + }); + + + +/***/ }, +/* 135 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var formatUtil = __webpack_require__(6); + var graphic = __webpack_require__(18); + var Model = __webpack_require__(12); + var numberUtil = __webpack_require__(7); + var remRadian = numberUtil.remRadian; + var isRadianAroundZero = numberUtil.isRadianAroundZero; + var vec2 = __webpack_require__(10); + var matrix = __webpack_require__(11); + var v2ApplyTransform = vec2.applyTransform; + var retrieve = zrUtil.retrieve; + + var PI = Math.PI; + + function makeAxisEventDataBase(axisModel) { + var eventData = { + componentType: axisModel.mainType + }; + eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex; + return eventData; + } + + /** + * A final axis is translated and rotated from a "standard axis". + * So opt.position and opt.rotation is required. + * + * A standard axis is and axis from [0, 0] to [0, axisExtent[1]], + * for example: (0, 0) ------------> (0, 50) + * + * nameDirection or tickDirection or labelDirection is 1 means tick + * or label is below the standard axis, whereas is -1 means above + * the standard axis. labelOffset means offset between label and axis, + * which is useful when 'onZero', where axisLabel is in the grid and + * label in outside grid. + * + * Tips: like always, + * positive rotation represents anticlockwise, and negative rotation + * represents clockwise. + * The direction of position coordinate is the same as the direction + * of screen coordinate. + * + * Do not need to consider axis 'inverse', which is auto processed by + * axis extent. + * + * @param {module:zrender/container/Group} group + * @param {Object} axisModel + * @param {Object} opt Standard axis parameters. + * @param {Array.} opt.position [x, y] + * @param {number} opt.rotation by radian + * @param {number} [opt.nameDirection=1] 1 or -1 Used when nameLocation is 'middle'. + * @param {number} [opt.tickDirection=1] 1 or -1 + * @param {number} [opt.labelDirection=1] 1 or -1 + * @param {number} [opt.labelOffset=0] Usefull when onZero. + * @param {string} [opt.axisLabelShow] default get from axisModel. + * @param {string} [opt.axisName] default get from axisModel. + * @param {number} [opt.axisNameAvailableWidth] + * @param {number} [opt.labelRotate] by degree, default get from axisModel. + * @param {number} [opt.labelInterval] Default label interval when label + * interval from model is null or 'auto'. + * @param {number} [opt.strokeContainThreshold] Default label interval when label + * @param {number} [opt.nameTruncateMaxWidth] + */ + var AxisBuilder = function (axisModel, opt) { + + /** + * @readOnly + */ + this.opt = opt; + + /** + * @readOnly + */ + this.axisModel = axisModel; + + // Default value + zrUtil.defaults( + opt, + { + labelOffset: 0, + nameDirection: 1, + tickDirection: 1, + labelDirection: 1, + silent: true + } + ); + + /** + * @readOnly + */ + this.group = new graphic.Group(); + + // FIXME Not use a seperate text group? + var dumbGroup = new graphic.Group({ + position: opt.position.slice(), + rotation: opt.rotation + }); + + // this.group.add(dumbGroup); + // this._dumbGroup = dumbGroup; + + dumbGroup.updateTransform(); + this._transform = dumbGroup.transform; + + this._dumbGroup = dumbGroup; + }; + + AxisBuilder.prototype = { + + constructor: AxisBuilder, + + hasBuilder: function (name) { + return !!builders[name]; + }, + + add: function (name) { + builders[name].call(this); + }, + + getGroup: function () { + return this.group; + } + + }; + + var builders = { + + /** + * @private + */ + axisLine: function () { + var opt = this.opt; + var axisModel = this.axisModel; + + if (!axisModel.get('axisLine.show')) { + return; + } + + var extent = this.axisModel.axis.getExtent(); + + var matrix = this._transform; + var pt1 = [extent[0], 0]; + var pt2 = [extent[1], 0]; + if (matrix) { + v2ApplyTransform(pt1, pt1, matrix); + v2ApplyTransform(pt2, pt2, matrix); + } + + this.group.add(new graphic.Line(graphic.subPixelOptimizeLine({ + + // Id for animation + anid: 'line', + + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: zrUtil.extend( + {lineCap: 'round'}, + axisModel.getModel('axisLine.lineStyle').getLineStyle() + ), + strokeContainThreshold: opt.strokeContainThreshold || 5, + silent: true, + z2: 1 + }))); + }, + + /** + * @private + */ + axisTick: function () { + var axisModel = this.axisModel; + var axis = axisModel.axis; + + if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) { + return; + } + + var tickModel = axisModel.getModel('axisTick'); + var opt = this.opt; + + var lineStyleModel = tickModel.getModel('lineStyle'); + var tickLen = tickModel.get('length'); + + var tickInterval = getInterval(tickModel, opt.labelInterval); + var ticksCoords = axis.getTicksCoords(tickModel.get('alignWithLabel')); + var ticks = axis.scale.getTicks(); + + var pt1 = []; + var pt2 = []; + var matrix = this._transform; + + for (var i = 0; i < ticksCoords.length; i++) { + // Only ordinal scale support tick interval + if (ifIgnoreOnTick(axis, i, tickInterval)) { + continue; + } + + var tickCoord = ticksCoords[i]; + + pt1[0] = tickCoord; + pt1[1] = 0; + pt2[0] = tickCoord; + pt2[1] = opt.tickDirection * tickLen; + + if (matrix) { + v2ApplyTransform(pt1, pt1, matrix); + v2ApplyTransform(pt2, pt2, matrix); + } + // Tick line, Not use group transform to have better line draw + this.group.add(new graphic.Line(graphic.subPixelOptimizeLine({ + + // Id for animation + anid: 'tick_' + ticks[i], + + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: zrUtil.defaults( + lineStyleModel.getLineStyle(), + { + stroke: axisModel.get('axisLine.lineStyle.color') + } + ), + z2: 2, + silent: true + }))); + } + }, + + /** + * @param {module:echarts/coord/cartesian/AxisModel} axisModel + * @param {module:echarts/coord/cartesian/GridModel} gridModel + * @private + */ + axisLabel: function () { + var opt = this.opt; + var axisModel = this.axisModel; + var axis = axisModel.axis; + var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show')); + + if (!show || axis.scale.isBlank()) { + return; + } + + var labelModel = axisModel.getModel('axisLabel'); + var textStyleModel = labelModel.getModel('textStyle'); + var labelMargin = labelModel.get('margin'); + var ticks = axis.scale.getTicks(); + var labels = axisModel.getFormattedLabels(); + + // Special label rotate. + var labelRotation = ( + retrieve(opt.labelRotate, labelModel.get('rotate')) || 0 + ) * PI / 180; + + var labelLayout = innerTextLayout(opt.rotation, labelRotation, opt.labelDirection); + var categoryData = axisModel.get('data'); + + var textEls = []; + var silent = isSilent(axisModel); + var triggerEvent = axisModel.get('triggerEvent'); + + zrUtil.each(ticks, function (tickVal, index) { + if (ifIgnoreOnTick(axis, index, opt.labelInterval)) { + return; + } + + var itemTextStyleModel = textStyleModel; + if (categoryData && categoryData[tickVal] && categoryData[tickVal].textStyle) { + itemTextStyleModel = new Model( + categoryData[tickVal].textStyle, textStyleModel, axisModel.ecModel + ); + } + var textColor = itemTextStyleModel.getTextColor() + || axisModel.get('axisLine.lineStyle.color'); + + var tickCoord = axis.dataToCoord(tickVal); + var pos = [ + tickCoord, + opt.labelOffset + opt.labelDirection * labelMargin + ]; + var labelStr = axis.scale.getLabel(tickVal); + + var textEl = new graphic.Text({ + + // Id for animation + anid: 'label_' + tickVal, + + style: { + text: labels[index], + textAlign: itemTextStyleModel.get('align', true) || labelLayout.textAlign, + textVerticalAlign: itemTextStyleModel.get('baseline', true) || labelLayout.textVerticalAlign, + textFont: itemTextStyleModel.getFont(), + fill: typeof textColor === 'function' + ? textColor( + // (1) In category axis with data zoom, tick is not the original + // index of axis.data. So tick should not be exposed to user + // in category axis. + // (2) Compatible with previous version, which always returns labelStr. + // But in interval scale labelStr is like '223,445', which maked + // user repalce ','. So we modify it to return original val but remain + // it as 'string' to avoid error in replacing. + axis.type === 'category' ? labelStr : axis.type === 'value' ? tickVal + '' : tickVal, + index + ) + : textColor + }, + position: pos, + rotation: labelLayout.rotation, + silent: silent, + z2: 10 + }); + + // Pack data for mouse event + if (triggerEvent) { + textEl.eventData = makeAxisEventDataBase(axisModel); + textEl.eventData.targetType = 'axisLabel'; + textEl.eventData.value = labelStr; + } + + // FIXME + this._dumbGroup.add(textEl); + textEl.updateTransform(); + + textEls.push(textEl); + this.group.add(textEl); + + textEl.decomposeTransform(); + + }, this); + + fixMinMaxLabelShow(axisModel, textEls); + }, + + /** + * @private + */ + axisName: function () { + var opt = this.opt; + var axisModel = this.axisModel; + var name = retrieve(opt.axisName, axisModel.get('name')); + + if (!name) { + return; + } + + var nameLocation = axisModel.get('nameLocation'); + var nameDirection = opt.nameDirection; + var textStyleModel = axisModel.getModel('nameTextStyle'); + var gap = axisModel.get('nameGap') || 0; + + var extent = this.axisModel.axis.getExtent(); + var gapSignal = extent[0] > extent[1] ? -1 : 1; + var pos = [ + nameLocation === 'start' + ? extent[0] - gapSignal * gap + : nameLocation === 'end' + ? extent[1] + gapSignal * gap + : (extent[0] + extent[1]) / 2, // 'middle' + // Reuse labelOffset. + nameLocation === 'middle' ? opt.labelOffset + nameDirection * gap : 0 + ]; + + var labelLayout; + + var nameRotation = axisModel.get('nameRotate'); + if (nameRotation != null) { + nameRotation = nameRotation * PI / 180; // To radian. + } + + var axisNameAvailableWidth; + + if (nameLocation === 'middle') { + labelLayout = innerTextLayout( + opt.rotation, + nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis. + nameDirection + ); + } + else { + labelLayout = endTextLayout( + opt, nameLocation, nameRotation || 0, extent + ); + + axisNameAvailableWidth = opt.axisNameAvailableWidth; + if (axisNameAvailableWidth != null) { + axisNameAvailableWidth = Math.abs( + axisNameAvailableWidth / Math.sin(labelLayout.rotation) + ); + !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null); + } + } + + var textFont = textStyleModel.getFont(); + + var truncateOpt = axisModel.get('nameTruncate', true) || {}; + var ellipsis = truncateOpt.ellipsis; + var maxWidth = retrieve( + opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth + ); + var truncatedText = (ellipsis != null && maxWidth != null) + ? formatUtil.truncateText( + name, maxWidth, textFont, ellipsis, + {minChar: 2, placeholder: truncateOpt.placeholder} + ) + : name; + + var tooltipOpt = axisModel.get('tooltip', true); + + var mainType = axisModel.mainType; + var formatterParams = { + componentType: mainType, + name: name, + $vars: ['name'] + }; + formatterParams[mainType + 'Index'] = axisModel.componentIndex; + + var textEl = new graphic.Text({ + + // Id for animation + anid: 'name', + + __fullText: name, + __truncatedText: truncatedText, + + style: { + text: truncatedText, + textFont: textFont, + fill: textStyleModel.getTextColor() + || axisModel.get('axisLine.lineStyle.color'), + textAlign: labelLayout.textAlign, + textVerticalAlign: labelLayout.textVerticalAlign + }, + position: pos, + rotation: labelLayout.rotation, + silent: isSilent(axisModel), + z2: 1, + tooltip: (tooltipOpt && tooltipOpt.show) + ? zrUtil.extend({ + content: name, + formatter: function () { + return name; + }, + formatterParams: formatterParams + }, tooltipOpt) + : null + }); + + if (axisModel.get('triggerEvent')) { + textEl.eventData = makeAxisEventDataBase(axisModel); + textEl.eventData.targetType = 'axisName'; + textEl.eventData.name = name; + } + + // FIXME + this._dumbGroup.add(textEl); + textEl.updateTransform(); + + this.group.add(textEl); + + textEl.decomposeTransform(); + } + + }; + + /** + * @public + * @static + * @param {Object} opt + * @param {number} axisRotation in radian + * @param {number} textRotation in radian + * @param {number} direction + * @return {Object} { + * rotation, // according to axis + * textAlign, + * textVerticalAlign + * } + */ + var innerTextLayout = AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) { + var rotationDiff = remRadian(textRotation - axisRotation); + var textAlign; + var textVerticalAlign; + + if (isRadianAroundZero(rotationDiff)) { // Label is parallel with axis line. + textVerticalAlign = direction > 0 ? 'top' : 'bottom'; + textAlign = 'center'; + } + else if (isRadianAroundZero(rotationDiff - PI)) { // Label is inverse parallel with axis line. + textVerticalAlign = direction > 0 ? 'bottom' : 'top'; + textAlign = 'center'; + } + else { + textVerticalAlign = 'middle'; + + if (rotationDiff > 0 && rotationDiff < PI) { + textAlign = direction > 0 ? 'right' : 'left'; + } + else { + textAlign = direction > 0 ? 'left' : 'right'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; + }; + + function endTextLayout(opt, textPosition, textRotate, extent) { + var rotationDiff = remRadian(textRotate - opt.rotation); + var textAlign; + var textVerticalAlign; + var inverse = extent[0] > extent[1]; + var onLeft = (textPosition === 'start' && !inverse) + || (textPosition !== 'start' && inverse); + + if (isRadianAroundZero(rotationDiff - PI / 2)) { + textVerticalAlign = onLeft ? 'bottom' : 'top'; + textAlign = 'center'; + } + else if (isRadianAroundZero(rotationDiff - PI * 1.5)) { + textVerticalAlign = onLeft ? 'top' : 'bottom'; + textAlign = 'center'; + } + else { + textVerticalAlign = 'middle'; + if (rotationDiff < PI * 1.5 && rotationDiff > PI / 2) { + textAlign = onLeft ? 'left' : 'right'; + } + else { + textAlign = onLeft ? 'right' : 'left'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; + } + + function isSilent(axisModel) { + var tooltipOpt = axisModel.get('tooltip'); + return axisModel.get('silent') + // Consider mouse cursor, add these restrictions. + || !( + axisModel.get('triggerEvent') || (tooltipOpt && tooltipOpt.show) + ); + } + + function fixMinMaxLabelShow(axisModel, textEls) { + // If min or max are user set, we need to check + // If the tick on min(max) are overlap on their neighbour tick + // If they are overlapped, we need to hide the min(max) tick label + var showMinLabel = axisModel.get('axisLabel.showMinLabel'); + var showMaxLabel = axisModel.get('axisLabel.showMaxLabel'); + var firstLabel = textEls[0]; + var nextLabel = textEls[1]; + var lastLabel = textEls[textEls.length - 1]; + var prevLabel = textEls[textEls.length - 2]; + + if (showMinLabel === false) { + firstLabel.ignore = true; + } + else if (axisModel.getMin() != null && isTwoLabelOverlapped(firstLabel, nextLabel)) { + showMinLabel ? (nextLabel.ignore = true) : (firstLabel.ignore = true); + } + + if (showMaxLabel === false) { + lastLabel.ignore = true; + } + else if (axisModel.getMax() != null && isTwoLabelOverlapped(prevLabel, lastLabel)) { + showMaxLabel ? (prevLabel.ignore = true) : (lastLabel.ignore = true); + } + } + + function isTwoLabelOverlapped(current, next, labelLayout) { + // current and next has the same rotation. + var firstRect = current && current.getBoundingRect().clone(); + var nextRect = next && next.getBoundingRect().clone(); + + if (!firstRect || !nextRect) { + return; + } + + // When checking intersect of two rotated labels, we use mRotationBack + // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`. + var mRotationBack = matrix.identity([]); + matrix.rotate(mRotationBack, mRotationBack, -current.rotation); + + firstRect.applyTransform(matrix.mul([], mRotationBack, current.getLocalTransform())); + nextRect.applyTransform(matrix.mul([], mRotationBack, next.getLocalTransform())); + + return firstRect.intersect(nextRect); + } + + + /** + * @static + */ + var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick = function (axis, i, interval) { + var rawTick; + var scale = axis.scale; + return scale.type === 'ordinal' + && ( + typeof interval === 'function' + ? ( + rawTick = scale.getTicks()[i], + !interval(rawTick, scale.getLabel(rawTick)) + ) + : i % (interval + 1) + ); + }; + + /** + * @static + */ + var getInterval = AxisBuilder.getInterval = function (model, labelInterval) { + var interval = model.get('interval'); + if (interval == null || interval == 'auto') { + interval = labelInterval; + } + return interval; + }; + + module.exports = AxisBuilder; + + + +/***/ }, +/* 136 */ +/***/ function(module, exports, __webpack_require__) { + + + + var axisPointerModelHelper = __webpack_require__(137); + + /** + * Base class of AxisView. + */ + var AxisView = __webpack_require__(1).extendComponentView({ + + type: 'axis', + + /** + * @private + */ + _axisPointer: null, + + /** + * @protected + * @type {string} + */ + axisPointerClass: null, + + /** + * @override + */ + render: function (axisModel, ecModel, api, payload) { + // FIXME + // This process should proformed after coordinate systems updated + // (axis scale updated), and should be performed each time update. + // So put it here temporarily, although it is not appropriate to + // put a model-writing procedure in `view`. + this.axisPointerClass && axisPointerModelHelper.fixValue(axisModel); + + AxisView.superApply(this, 'render', arguments); + + updateAxisPointer(this, axisModel, ecModel, api, payload, true); + }, + + /** + * Action handler. + * @public + * @param {module:echarts/coord/cartesian/AxisModel} axisModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + updateAxisPointer: function (axisModel, ecModel, api, payload, force) { + updateAxisPointer(this, axisModel, ecModel, api, payload, false); + }, + + /** + * @override + */ + remove: function (ecModel, api) { + var axisPointer = this._axisPointer; + axisPointer && axisPointer.remove(api); + AxisView.superApply(this, 'remove', arguments); + }, + + /** + * @override + */ + dispose: function (ecModel, api) { + disposeAxisPointer(this, api); + AxisView.superApply(this, 'dispose', arguments); + } + + }); + + function updateAxisPointer(axisView, axisModel, ecModel, api, payload, forceRender) { + var Clazz = AxisView.getAxisPointerClass(axisView.axisPointerClass); + if (!Clazz) { + return; + } + var axisPointerModel = axisPointerModelHelper.getAxisPointerModel(axisModel); + axisPointerModel + ? (axisView._axisPointer || (axisView._axisPointer = new Clazz())) + .render(axisModel, axisPointerModel, api, forceRender) + : disposeAxisPointer(axisView, api); + } + + function disposeAxisPointer(axisView, ecModel, api) { + var axisPointer = axisView._axisPointer; + axisPointer && axisPointer.dispose(ecModel, api); + axisView._axisPointer = null; + } + + var axisPointerClazz = []; + + AxisView.registerAxisPointerClass = function (type, clazz) { + if (true) { + if (axisPointerClazz[type]) { + throw new Error('axisPointer ' + type + ' exists'); + } + } + axisPointerClazz[type] = clazz; + }; + + AxisView.getAxisPointerClass = function (type) { + return type && axisPointerClazz[type]; + }; + + module.exports = AxisView; + + +/***/ }, +/* 137 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var Model = __webpack_require__(12); + var each = zrUtil.each; + var curry = zrUtil.curry; + + var helper = {}; + + // Build axisPointerModel, mergin tooltip.axisPointer model for each axis. + // allAxesInfo should be updated when setOption performed. + helper.collect = function (ecModel, api) { + var result = { + /** + * key: makeKey(axis.model) + * value: { + * axis, + * coordSys, + * axisPointerModel, + * triggerTooltip, + * involveSeries, + * snap, + * seriesModels, + * seriesDataCount + * } + */ + axesInfo: {}, + seriesInvolved: false, + /** + * key: makeKey(coordSys.model) + * value: Object: key makeKey(axis.model), value: axisInfo + */ + coordSysAxesInfo: {}, + coordSysMap: {} + }; + + collectAxesInfo(result, ecModel, api); + + // Check seriesInvolved for performance, in case too many series in some chart. + result.seriesInvolved && collectSeriesInfo(result, ecModel); + + return result; + }; + + function collectAxesInfo(result, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var globalAxisPointerModel = ecModel.getComponent('axisPointer'); + // links can only be set on global. + var linksOption = globalAxisPointerModel.get('link', true) || []; + var linkGroups = []; + + // Collect axes info. + each(api.getCoordinateSystems(), function (coordSys) { + // Some coordinate system do not support axes, like geo. + if (!coordSys.axisPointerEnabled) { + return; + } + + var coordSysKey = makeKey(coordSys.model); + var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {}; + result.coordSysMap[coordSysKey] = coordSys; + + // Set tooltip (like 'cross') is a convienent way to show axisPointer + // for user. So we enable seting tooltip on coordSys model. + var coordSysModel = coordSys.model; + var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel); + + each(coordSys.getAxes(), curry(saveTooltipAxisInfo, false, null)); + + // If axis tooltip used, choose tooltip axis for each coordSys. + // Notice this case: coordSys is `grid` but not `cartesian2D` here. + if (coordSys.getTooltipAxes + && globalTooltipModel + // If tooltip.showContent is set as false, tooltip will not + // show but axisPointer will show as normal. + && baseTooltipModel.get('show') + ) { + // Compatible with previous logic. But series.tooltip.trigger: 'axis' + // or series.data[n].tooltip.trigger: 'axis' are not support any more. + var triggerAxis = baseTooltipModel.get('trigger') === 'axis'; + var cross = baseTooltipModel.get('axisPointer.type') === 'cross'; + var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get('axisPointer.axis')); + if (triggerAxis || cross) { + each(tooltipAxes.baseAxes, curry( + saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis + )); + } + if (cross) { + each(tooltipAxes.otherAxes, curry(saveTooltipAxisInfo, 'cross', false)); + } + } + + // fromTooltip: true | false | 'cross' + // triggerTooltip: true | false | null + function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) { + var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel); + + var axisPointerShow = axisPointerModel.get('show'); + if (!axisPointerShow || ( + axisPointerShow === 'auto' + && !fromTooltip + && !isHandleTrigger(axisPointerModel) + )) { + return; + } + + if (triggerTooltip == null) { + triggerTooltip = axisPointerModel.get('triggerTooltip'); + } + + axisPointerModel = fromTooltip + ? makeAxisPointerModel( + axis, baseTooltipModel, globalAxisPointerModel, ecModel, + fromTooltip, triggerTooltip + ) + : axisPointerModel; + + var snap = axisPointerModel.get('snap'); + var key = makeKey(axis.model); + var involveSeries = triggerTooltip || snap || axis.type === 'category'; + + // If result.axesInfo[key] exist, override it (tooltip has higher priority). + var axisInfo = result.axesInfo[key] = { + key: key, + axis: axis, + coordSys: coordSys, + axisPointerModel: axisPointerModel, + triggerTooltip: triggerTooltip, + involveSeries: involveSeries, + snap: snap, + useHandle: isHandleTrigger(axisPointerModel), + seriesModels: [] + }; + axesInfoInCoordSys[key] = axisInfo; + result.seriesInvolved |= involveSeries; + + var groupIndex = getLinkGroupIndex(linksOption, axis); + if (groupIndex != null) { + var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = {axesInfo: {}}); + linkGroup.axesInfo[key] = axisInfo; + linkGroup.mapper = linksOption[groupIndex].mapper; + axisInfo.linkGroup = linkGroup; + } + } + }); + } + + function makeAxisPointerModel( + axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip + ) { + var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer'); + var volatileOption = {}; + + each( + [ + 'type', 'snap', 'lineStyle', 'shadowStyle', 'label', + 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z' + ], + function (field) { + volatileOption[field] = zrUtil.clone(tooltipAxisPointerModel.get(field)); + } + ); + + // category axis do not auto snap, otherwise some tick that do not + // has value can not be hovered. value/time/log axis default snap if + // triggered from tooltip and trigger tooltip. + volatileOption.snap = axis.type !== 'category' && !!triggerTooltip; + + // Compatibel with previous behavior, tooltip axis do not show label by default. + // Only these properties can be overrided from tooltip to axisPointer. + if (tooltipAxisPointerModel.get('type') === 'cross') { + volatileOption.type = 'line'; + } + var labelOption = volatileOption.label || (volatileOption.label = {}); + // Follow the convention, do not show label when triggered by tooltip by default. + labelOption.show == null && (labelOption.show = false); + + if (fromTooltip === 'cross') { + // When 'cross', both axes show labels. + labelOption.show = true; + // If triggerTooltip, this is a base axis, which should better not use cross style + // (cross style is dashed by default) + if (!triggerTooltip) { + var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle'); + crossStyle && zrUtil.defaults( + labelOption.textStyle || (labelOption.textStyle = {}), + crossStyle.textStyle + ); + } + } + + return axis.model.getModel( + 'axisPointer', + new Model(volatileOption, globalAxisPointerModel, ecModel) + ); + } + + function collectSeriesInfo(result, ecModel) { + // Prepare data for axis trigger + ecModel.eachSeries(function (seriesModel) { + + // Notice this case: this coordSys is `cartesian2D` but not `grid`. + var coordSys = seriesModel.coordinateSystem; + var seriesTooltipTrigger = seriesModel.get('tooltip.trigger', true); + var seriesTooltipShow = seriesModel.get('tooltip.show', true); + if (!coordSys + || seriesTooltipTrigger === 'none' + || seriesTooltipTrigger === false + || seriesTooltipTrigger === 'item' + || seriesTooltipShow === false + || seriesModel.get('axisPointer.show', true) === false + ) { + return; + } + + each(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) { + var axis = axisInfo.axis; + if (coordSys.getAxis(axis.dim) === axis) { + axisInfo.seriesModels.push(seriesModel); + axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0); + axisInfo.seriesDataCount += seriesModel.getData().count(); + } + }); + + }, this); + } + + /** + * For example: + * { + * axisPointer: { + * links: [{ + * xAxisIndex: [2, 4], + * yAxisIndex: 'all' + * }, { + * xAxisId: ['a5', 'a7'], + * xAxisName: 'xxx' + * }] + * } + * } + */ + function getLinkGroupIndex(linksOption, axis) { + var axisModel = axis.model; + var dim = axis.dim; + for (var i = 0; i < linksOption.length; i++) { + var linkOption = linksOption[i] || {}; + if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) + || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) + || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name) + ) { + return i; + } + } + } + + function checkPropInLink(linkPropValue, axisPropValue) { + return linkPropValue === 'all' + || (zrUtil.isArray(linkPropValue) && zrUtil.indexOf(linkPropValue, axisPropValue) >= 0) + || linkPropValue === axisPropValue; + } + + helper.fixValue = function (axisModel) { + var axisInfo = helper.getAxisInfo(axisModel); + if (!axisInfo) { + return; + } + + var axisPointerModel = axisInfo.axisPointerModel; + var scale = axisInfo.axis.scale; + var option = axisPointerModel.option; + var status = axisPointerModel.get('status'); + var value = axisPointerModel.get('value'); + + // Parse init value for category and time axis. + if (value != null) { + value = scale.parse(value); + } + + var useHandle = isHandleTrigger(axisPointerModel); + // If `handle` used, `axisPointer` will always be displayed, so value + // and status should be initialized. + if (status == null) { + option.status = useHandle ? 'show' : 'hide'; + } + + var extent = scale.getExtent().slice(); + extent[0] > extent[1] && extent.reverse(); + + if (// Pick a value on axis when initializing. + value == null + // If both `handle` and `dataZoom` are used, value may be out of axis extent, + // where we should re-pick a value to keep `handle` displaying normally. + || value > extent[1] + ) { + // Make handle displayed on the end of the axis when init, which looks better. + value = extent[1]; + } + if (value < extent[0]) { + value = extent[0]; + } + + option.value = value; + + if (useHandle) { + option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show'; + } + }; + + helper.getAxisInfo = function (axisModel) { + var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo; + return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)]; + }; + + helper.getAxisPointerModel = function (axisModel) { + var axisInfo = helper.getAxisInfo(axisModel); + return axisInfo && axisInfo.axisPointerModel; + }; + + function isHandleTrigger(axisPointerModel) { + return !!axisPointerModel.get('handle.show'); + } + + /** + * @param {module:echarts/model/Model} model + * @return {string} unique key + */ + var makeKey = helper.makeKey = function (model) { + return model.type + '||' + model.id; + }; + + module.exports = helper; + + + +/***/ }, +/* 138 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var helper = {}; + + /** + * @param {Object} opt {labelInside} + * @return {Object} { + * position, rotation, labelDirection, labelOffset, + * tickDirection, labelRotate, labelInterval, z2 + * } + */ + helper.layout = function (gridModel, axisModel, opt) { + opt = opt || {}; + var grid = gridModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + + var rawAxisPosition = axis.position; + var axisPosition = axis.onZero ? 'onZero' : rawAxisPosition; + var axisDim = axis.dim; + + // [left, right, top, bottom] + var rect = grid.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + + var axisOffset = axisModel.get('offset') || 0; + + var posMap = { + x: { top: rectBound[2] - axisOffset, bottom: rectBound[3] + axisOffset }, + y: { left: rectBound[0] - axisOffset, right: rectBound[1] + axisOffset } + }; + + posMap.x.onZero = Math.max(Math.min(getZero('y'), posMap.x.bottom), posMap.x.top); + posMap.y.onZero = Math.max(Math.min(getZero('x'), posMap.y.right), posMap.y.left); + + function getZero(dim, val) { + var theAxis = grid.getAxis(dim); + return theAxis.toGlobalCoord(theAxis.dataToCoord(0)); + } + + // Axis position + layout.position = [ + axisDim === 'y' ? posMap.y[axisPosition] : rectBound[0], + axisDim === 'x' ? posMap.x[axisPosition] : rectBound[3] + ]; + + // Axis rotation + layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1); + + // Tick and label direction, x y is axisDim + var dirMap = {top: -1, bottom: 1, left: -1, right: 1}; + + layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition]; + layout.labelOffset = axis.onZero ? posMap[axisDim][rawAxisPosition] - posMap[axisDim].onZero : 0; + + if (axisModel.get('axisTick.inside')) { + layout.tickDirection = -layout.tickDirection; + } + if (zrUtil.retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) { + layout.labelDirection = -layout.labelDirection; + } + + // Special label rotation + var labelRotate = axisModel.get('axisLabel.rotate'); + layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate; + + // label interval when auto mode. + layout.labelInterval = axis.getLabelInterval(); + + // Over splitLine and splitArea + layout.z2 = 1; + + return layout; + }; + + module.exports = helper; + + + +/***/ }, +/* 139 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + __webpack_require__(125); + + __webpack_require__(140); + __webpack_require__(142); + + var barLayoutGrid = __webpack_require__(145); + var echarts = __webpack_require__(1); + + echarts.registerLayout(zrUtil.curry(barLayoutGrid, 'bar')); + + // Visual coding for legend + echarts.registerVisual(function (ecModel) { + ecModel.eachSeriesByType('bar', function (seriesModel) { + var data = seriesModel.getData(); + data.setVisual('legendSymbol', 'roundRect'); + }); + }); + + // In case developer forget to include grid component + __webpack_require__(124); + + +/***/ }, +/* 140 */ +/***/ function(module, exports, __webpack_require__) { + + + + module.exports = __webpack_require__(141).extend({ + + type: 'series.bar', + + dependencies: ['grid', 'polar'], + + brushSelector: 'rect' + }); + + +/***/ }, +/* 141 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var SeriesModel = __webpack_require__(78); + var createListFromArray = __webpack_require__(109); + + module.exports = SeriesModel.extend({ + + type: 'series.__base_bar__', + + getInitialData: function (option, ecModel) { + return createListFromArray(option.data, this, ecModel); + }, + + getMarkerPosition: function (value) { + var coordSys = this.coordinateSystem; + if (coordSys) { + // PENDING if clamp ? + var pt = coordSys.dataToPoint(value, true); + var data = this.getData(); + var offset = data.getLayout('offset'); + var size = data.getLayout('size'); + var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1; + pt[offsetIndex] += offset + size / 2; + return pt; + } + return [NaN, NaN]; + }, + + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + // stack: null + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // 最小高度改为0 + barMinHeight: 0, + // 最小角度为0,仅对极坐标系下的柱状图有效 + barMinAngle: 0, + // cursor: null, + + // barMaxWidth: null, + // 默认自适应 + // barWidth: null, + // 柱间距离,默认为柱形宽度的30%,可设固定值 + // barGap: '30%', + // 类目间柱形距离,默认为类目间距的20%,可设固定值 + // barCategoryGap: '20%', + // label: { + // normal: { + // show: false + // } + // }, + itemStyle: { + normal: { + // color: '各异' + }, + emphasis: {} + } + } + }); + + +/***/ }, +/* 142 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var helper = __webpack_require__(143); + + var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'normal', 'barBorderWidth']; + + // FIXME + // Just for compatible with ec2. + zrUtil.extend(__webpack_require__(12).prototype, __webpack_require__(144)); + + var BarView = __webpack_require__(1).extendChartView({ + + type: 'bar', + + render: function (seriesModel, ecModel, api) { + var coordinateSystemType = seriesModel.get('coordinateSystem'); + + if (coordinateSystemType === 'cartesian2d' + || coordinateSystemType === 'polar' + ) { + this._render(seriesModel, ecModel, api); + } + else if (true) { + console.warn('Only cartesian2d and polar supported for bar.'); + } + + return this.group; + }, + + dispose: zrUtil.noop, + + _render: function (seriesModel, ecModel, api) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + + var coord = seriesModel.coordinateSystem; + var baseAxis = coord.getBaseAxis(); + var isHorizontalOrRadial; + + if (coord.type === 'cartesian2d') { + isHorizontalOrRadial = baseAxis.isHorizontal(); + } + else if (coord.type === 'polar') { + isHorizontalOrRadial = baseAxis.dim === 'angle'; + } + + var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null; + + data.diff(oldData) + .add(function (dataIndex) { + if (!data.hasValue(dataIndex)) { + return; + } + + var itemModel = data.getItemModel(dataIndex); + var layout = getLayout[coord.type](data, dataIndex, itemModel); + var el = elementCreator[coord.type]( + data, dataIndex, itemModel, layout, isHorizontalOrRadial, animationModel + ); + data.setItemGraphicEl(dataIndex, el); + group.add(el); + + updateStyle( + el, data, dataIndex, itemModel, layout, + seriesModel, isHorizontalOrRadial, coord.type === 'polar' + ); + }) + .update(function (newIndex, oldIndex) { + var el = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex)) { + group.remove(el); + return; + } + + var itemModel = data.getItemModel(newIndex); + var layout = getLayout[coord.type](data, newIndex, itemModel); + + if (el) { + graphic.updateProps(el, {shape: layout}, animationModel, newIndex); + } + else { + el = elementCreator[coord.type]( + data, newIndex, itemModel, layout, isHorizontalOrRadial, animationModel, true + ); + } + + data.setItemGraphicEl(newIndex, el); + // Add back + group.add(el); + + updateStyle( + el, data, newIndex, itemModel, layout, + seriesModel, isHorizontalOrRadial, coord.type === 'polar' + ); + }) + .remove(function (dataIndex) { + var el = oldData.getItemGraphicEl(dataIndex); + if (coord.type === 'cartesian2d') { + el && removeRect(dataIndex, animationModel, el); + } + else { + el && removeSector(dataIndex, animationModel, el); + } + }) + .execute(); + + this._data = data; + }, + + remove: function (ecModel, api) { + var group = this.group; + var data = this._data; + if (ecModel.get('animation')) { + if (data) { + data.eachItemGraphicEl(function (el) { + if (el.type === 'sector') { + removeSector(el.dataIndex, ecModel, el); + } + else { + removeRect(el.dataIndex, ecModel, el); + } + }); + } + } + else { + group.removeAll(); + } + } + }); + + var elementCreator = { + + cartesian2d: function ( + data, dataIndex, itemModel, layout, isHorizontal, + animationModel, isUpdate + ) { + var rect = new graphic.Rect({shape: zrUtil.extend({}, layout)}); + + // Animation + if (animationModel) { + var rectShape = rect.shape; + var animateProperty = isHorizontal ? 'height' : 'width'; + var animateTarget = {}; + rectShape[animateProperty] = 0; + animateTarget[animateProperty] = layout[animateProperty]; + graphic[isUpdate ? 'updateProps' : 'initProps'](rect, { + shape: animateTarget + }, animationModel, dataIndex); + } + + return rect; + }, + + polar: function ( + data, dataIndex, itemModel, layout, isRadial, + animationModel, isUpdate + ) { + var sector = new graphic.Sector({shape: zrUtil.extend({}, layout)}); + + // Animation + if (animationModel) { + var sectorShape = sector.shape; + var animateProperty = isRadial ? 'r' : 'endAngle'; + var animateTarget = {}; + sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle; + animateTarget[animateProperty] = layout[animateProperty]; + graphic[isUpdate ? 'updateProps' : 'initProps'](sector, { + shape: animateTarget + }, animationModel, dataIndex); + } + + return sector; + } + }; + + function removeRect(dataIndex, animationModel, el) { + // Not show text when animating + el.style.text = ''; + graphic.updateProps(el, { + shape: { + width: 0 + } + }, animationModel, dataIndex, function () { + el.parent && el.parent.remove(el); + }); + } + + function removeSector(dataIndex, animationModel, el) { + // Not show text when animating + el.style.text = ''; + graphic.updateProps(el, { + shape: { + r: el.shape.r0 + } + }, animationModel, dataIndex, function () { + el.parent && el.parent.remove(el); + }); + } + + var getLayout = { + cartesian2d: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + var fixedLineWidth = getLineWidth(itemModel, layout); + + // fix layout with lineWidth + var signX = layout.width > 0 ? 1 : -1; + var signY = layout.height > 0 ? 1 : -1; + return { + x: layout.x + signX * fixedLineWidth / 2, + y: layout.y + signY * fixedLineWidth / 2, + width: layout.width - signX * fixedLineWidth, + height: layout.height - signY * fixedLineWidth + }; + }, + + polar: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + return { + cx: layout.cx, + cy: layout.cy, + r0: layout.r0, + r: layout.r, + startAngle: layout.startAngle, + endAngle: layout.endAngle + }; + } + }; + + function updateStyle( + el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar + ) { + var color = data.getItemVisual(dataIndex, 'color'); + var opacity = data.getItemVisual(dataIndex, 'opacity'); + var itemStyleModel = itemModel.getModel('itemStyle.normal'); + var hoverStyle = itemModel.getModel('itemStyle.emphasis').getBarItemStyle(); + + if (!isPolar) { + el.setShape('r', itemStyleModel.get('barBorderRadius') || 0); + } + + el.useStyle(zrUtil.defaults( + { + fill: color, + opacity: opacity + }, + itemStyleModel.getBarItemStyle() + )); + + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && el.attr('cursor', cursorStyle); + + var labelPositionOutside = isHorizontal + ? (layout.height > 0 ? 'bottom' : 'top') + : (layout.width > 0 ? 'left' : 'right'); + + if (!isPolar) { + helper.setLabel( + el.style, hoverStyle, itemModel, color, + seriesModel, dataIndex, labelPositionOutside + ); + } + + graphic.setHoverStyle(el, hoverStyle); + } + + // In case width or height are too small. + function getLineWidth(itemModel, rawLayout) { + var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; + return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height)); + } + + module.exports = BarView; + + +/***/ }, +/* 143 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + + var helper = {}; + + helper.setLabel = function ( + normalStyle, hoverStyle, itemModel, color, seriesModel, dataIndex, labelPositionOutside + ) { + var labelModel = itemModel.getModel('label.normal'); + var hoverLabelModel = itemModel.getModel('label.emphasis'); + + if (labelModel.get('show')) { + setLabel( + normalStyle, labelModel, color, + zrUtil.retrieve( + seriesModel.getFormattedLabel(dataIndex, 'normal'), + seriesModel.getRawValue(dataIndex) + ), + labelPositionOutside + ); + } + else { + normalStyle.text = ''; + } + + if (hoverLabelModel.get('show')) { + setLabel( + hoverStyle, hoverLabelModel, color, + zrUtil.retrieve( + seriesModel.getFormattedLabel(dataIndex, 'emphasis'), + seriesModel.getRawValue(dataIndex) + ), + labelPositionOutside + ); + } + else { + hoverStyle.text = ''; + } + }; + + function setLabel(style, model, color, labelText, labelPositionOutside) { + graphic.setText(style, model, color); + style.text = labelText; + if (style.textPosition === 'outside') { + style.textPosition = labelPositionOutside; + } + } + + module.exports = helper; + + +/***/ }, +/* 144 */ +/***/ function(module, exports, __webpack_require__) { + + + + + var getBarItemStyle = __webpack_require__(15)( + [ + ['fill', 'color'], + ['stroke', 'borderColor'], + ['lineWidth', 'borderWidth'], + // Compatitable with 2 + ['stroke', 'barBorderColor'], + ['lineWidth', 'barBorderWidth'], + ['opacity'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['shadowColor'] + ] + ); + module.exports = { + getBarItemStyle: function (excludes) { + var style = getBarItemStyle.call(this, excludes); + if (this.getBorderLineDash) { + var lineDash = this.getBorderLineDash(); + lineDash && (style.lineDash = lineDash); + } + return style; + } + }; + + +/***/ }, +/* 145 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var parsePercent = numberUtil.parsePercent; + + var STACK_PREFIX = '__ec_stack_'; + + function getSeriesStackId(seriesModel) { + return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex; + } + + function getAxisKey(axis) { + return axis.dim + axis.index; + } + + /** + * @param {Object} opt + * @param {module:echarts/coord/Axis} opt.axis Only support category axis currently. + * @param {number} opt.count Positive interger. + * @param {number} [opt.barWidth] + * @param {number} [opt.barMaxWidth] + * @param {number} [opt.barGap] + * @param {number} [opt.barCategoryGap] + * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined. + */ + function getLayoutOnAxis(opt, api) { + var params = []; + var baseAxis = opt.axis; + var axisKey = 'axis0'; + + if (baseAxis.type !== 'category') { + return; + } + var bandWidth = baseAxis.getBandWidth(); + + for (var i = 0; i < opt.count || 0; i++) { + params.push(zrUtil.defaults({ + bandWidth: bandWidth, + axisKey: axisKey, + stackId: STACK_PREFIX + i + }, opt)); + } + var widthAndOffsets = doCalBarWidthAndOffset(params, api); + + var result = []; + for (var i = 0; i < opt.count; i++) { + var item = widthAndOffsets[axisKey][STACK_PREFIX + i]; + item.offsetCenter = item.offset + item.width / 2; + result.push(item); + } + + return result; + } + + function calBarWidthAndOffset(barSeries, api) { + var seriesInfoList = zrUtil.map(barSeries, function (seriesModel) { + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var axisExtent = baseAxis.getExtent(); + var bandWidth = baseAxis.type === 'category' + ? baseAxis.getBandWidth() + : (Math.abs(axisExtent[1] - axisExtent[0]) / data.count()); + + var barWidth = parsePercent( + seriesModel.get('barWidth'), bandWidth + ); + var barMaxWidth = parsePercent( + seriesModel.get('barMaxWidth'), bandWidth + ); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + + return { + bandWidth: bandWidth, + barWidth: barWidth, + barMaxWidth: barMaxWidth, + barGap: barGap, + barCategoryGap: barCategoryGap, + axisKey: getAxisKey(baseAxis), + stackId: getSeriesStackId(seriesModel) + }; + }); + + return doCalBarWidthAndOffset(seriesInfoList, api); + } + + function doCalBarWidthAndOffset(seriesInfoList, api) { + // Columns info on each category axis. Key is cartesian name + var columnsMap = {}; + + zrUtil.each(seriesInfoList, function (seriesInfo, idx) { + var axisKey = seriesInfo.axisKey; + var bandWidth = seriesInfo.bandWidth; + var columnsOnAxis = columnsMap[axisKey] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: '20%', + gap: '30%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[axisKey] = columnsOnAxis; + + var stackId = seriesInfo.stackId; + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; + + // Caution: In a single coordinate system, these barGrid attributes + // will be shared by series. Consider that they have default values, + // only the attributes set on the last series will work. + // Do not change this fact unless there will be a break change. + + // TODO + var barWidth = seriesInfo.barWidth; + if (barWidth && !stacks[stackId].width) { + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + stacks[stackId].width = barWidth; + columnsOnAxis.remainedWidth -= barWidth; + } + + var barMaxWidth = seriesInfo.barMaxWidth; + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + var barGap = seriesInfo.barGap; + (barGap != null) && (columnsOnAxis.gap = barGap); + var barCategoryGap = seriesInfo.barCategoryGap; + (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap); + }); + + var result = {}; + + zrUtil.each(columnsMap, function (columnsOnAxis, coordSysName) { + + result[coordSysName] = {}; + + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGap = parsePercent(columnsOnAxis.categoryGap, bandWidth); + var barGapPercent = parsePercent(columnsOnAxis.gap, 1); + + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + // Find if any auto calculated bar exceeded maxBarWidth + zrUtil.each(stacks, function (column, stack) { + var maxWidth = column.maxWidth; + if (maxWidth && maxWidth < autoWidth) { + maxWidth = Math.min(maxWidth, remainedWidth); + if (column.width) { + maxWidth = Math.min(maxWidth, column.width); + } + remainedWidth -= maxWidth; + column.width = maxWidth; + autoWidthCount--; + } + }); + + // Recalculate width again + autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + var widthSum = 0; + var lastColumn; + zrUtil.each(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + zrUtil.each(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + offset: offset, + width: column.width + }; + + offset += column.width * (1 + barGapPercent); + }); + }); + + return result; + } + + /** + * @param {string} seriesType + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + function barLayoutGrid(seriesType, ecModel, api) { + + var barWidthAndOffset = calBarWidthAndOffset( + zrUtil.filter( + ecModel.getSeriesByType(seriesType), + function (seriesModel) { + return !ecModel.isSeriesFiltered(seriesModel) + && seriesModel.coordinateSystem + && seriesModel.coordinateSystem.type === 'cartesian2d'; + } + ) + ); + + var lastStackCoords = {}; + var lastStackCoordsOrigin = {}; + + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + + // Check series coordinate, do layout for cartesian2d only + if (seriesModel.coordinateSystem.type !== 'cartesian2d') { + return; + } + + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + + var stackId = getSeriesStackId(seriesModel); + var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + var valueAxis = cartesian.getOtherAxis(baseAxis); + + var barMinHeight = seriesModel.get('barMinHeight') || 0; + + var valueAxisStart = baseAxis.onZero + ? valueAxis.toGlobalCoord(valueAxis.dataToCoord(0)) + : valueAxis.getGlobalExtent()[0]; + + var coords = cartesian.dataToPoints(data, true); + lastStackCoords[stackId] = lastStackCoords[stackId] || []; + lastStackCoordsOrigin[stackId] = lastStackCoordsOrigin[stackId] || []; // Fix #4243 + + data.setLayout({ + offset: columnOffset, + size: columnWidth + }); + + data.each(valueAxis.dim, function (value, idx) { + if (isNaN(value)) { + return; + } + + if (!lastStackCoords[stackId][idx]) { + lastStackCoords[stackId][idx] = { + p: valueAxisStart, // Positive stack + n: valueAxisStart // Negative stack + }; + lastStackCoordsOrigin[stackId][idx] = { + p: valueAxisStart, // Positive stack + n: valueAxisStart // Negative stack + }; + } + var sign = value >= 0 ? 'p' : 'n'; + var coord = coords[idx]; + var lastCoord = lastStackCoords[stackId][idx][sign]; + var lastCoordOrigin = lastStackCoordsOrigin[stackId][idx][sign]; + var x; + var y; + var width; + var height; + + if (valueAxis.isHorizontal()) { + x = lastCoord; + y = coord[1] + columnOffset; + width = coord[0] - lastCoordOrigin; + height = columnWidth; + + lastStackCoordsOrigin[stackId][idx][sign] += width; + if (Math.abs(width) < barMinHeight) { + width = (width < 0 ? -1 : 1) * barMinHeight; + } + lastStackCoords[stackId][idx][sign] += width; + } + else { + x = coord[0] + columnOffset; + y = lastCoord; + width = columnWidth; + height = coord[1] - lastCoordOrigin; + + lastStackCoordsOrigin[stackId][idx][sign] += height; + if (Math.abs(height) < barMinHeight) { + // Include zero to has a positive bar + height = (height <= 0 ? -1 : 1) * barMinHeight; + } + lastStackCoords[stackId][idx][sign] += height; + } + + data.setItemLayout(idx, { + x: x, + y: y, + width: width, + height: height + }); + }, true); + + }, this); + } + + barLayoutGrid.getLayoutOnAxis = getLayoutOnAxis; + + module.exports = barLayoutGrid; + + +/***/ }, +/* 146 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var echarts = __webpack_require__(1); + + __webpack_require__(147); + __webpack_require__(149); + + __webpack_require__(150)('pie', [{ + type: 'pieToggleSelect', + event: 'pieselectchanged', + method: 'toggleSelected' + }, { + type: 'pieSelect', + event: 'pieselected', + method: 'select' + }, { + type: 'pieUnSelect', + event: 'pieunselected', + method: 'unSelect' + }]); + + echarts.registerVisual(zrUtil.curry(__webpack_require__(151), 'pie')); + + echarts.registerLayout(zrUtil.curry( + __webpack_require__(152), 'pie' + )); + + echarts.registerProcessor(zrUtil.curry(__webpack_require__(154), 'pie')); + + +/***/ }, +/* 147 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var List = __webpack_require__(98); + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var numberUtil = __webpack_require__(7); + var completeDimensions = __webpack_require__(110); + + var dataSelectableMixin = __webpack_require__(148); + + var PieSeries = __webpack_require__(1).extendSeriesModel({ + + type: 'series.pie', + + // Overwrite + init: function (option) { + PieSeries.superApply(this, 'init', arguments); + + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + + this.updateSelectedMap(option.data); + + this._defaultLabelLine(option); + }, + + // Overwrite + mergeOption: function (newOption) { + PieSeries.superCall(this, 'mergeOption', newOption); + this.updateSelectedMap(this.option.data); + }, + + getInitialData: function (option, ecModel) { + var dimensions = completeDimensions(['value'], option.data); + var list = new List(dimensions, this); + list.initData(option.data); + return list; + }, + + // Overwrite + getDataParams: function (dataIndex) { + var data = this.getData(); + var params = PieSeries.superCall(this, 'getDataParams', dataIndex); + // FIXME toFixed? + + var valueList = []; + data.each('value', function (value) { + valueList.push(value); + }); + + params.percent = numberUtil.getPercentWithPrecision( + valueList, + dataIndex, + data.hostModel.get('percentPrecision') + ); + + params.$vars.push('percent'); + return params; + }, + + _defaultLabelLine: function (option) { + // Extend labelLine emphasis + modelUtil.defaultEmphasis(option.labelLine, ['show']); + + var labelLineNormalOpt = option.labelLine.normal; + var labelLineEmphasisOpt = option.labelLine.emphasis; + // Not show label line if `label.normal.show = false` + labelLineNormalOpt.show = labelLineNormalOpt.show + && option.label.normal.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show + && option.label.emphasis.show; + }, + + defaultOption: { + zlevel: 0, + z: 2, + legendHoverLink: true, + + hoverAnimation: true, + // 默认全局居中 + center: ['50%', '50%'], + radius: [0, '75%'], + // 默认顺时针 + clockwise: true, + startAngle: 90, + // 最小角度改为0 + minAngle: 0, + // 选中是扇区偏移量 + selectedOffset: 10, + + // If use strategy to avoid label overlapping + avoidLabelOverlap: true, + // 选择模式,默认关闭,可选single,multiple + // selectedMode: false, + // 南丁格尔玫瑰图模式,'radius'(半径) | 'area'(面积) + // roseType: null, + + percentPrecision: 2, + + // If still show when all data zero. + stillShowZeroSum: true, + + // cursor: null, + + label: { + normal: { + // If rotate around circle + rotate: false, + show: true, + // 'outer', 'inside', 'center' + position: 'outer' + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + // textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE + // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数 + }, + emphasis: {} + }, + // Enabled when label.normal.position is 'outer' + labelLine: { + normal: { + show: true, + // 引导线两段中的第一段长度 + length: 15, + // 引导线两段中的第二段长度 + length2: 15, + smooth: false, + lineStyle: { + // color: 各异, + width: 1, + type: 'solid' + } + } + }, + itemStyle: { + normal: { + borderWidth: 1 + }, + emphasis: {} + }, + + // Animation type canbe expansion, scale + animationType: 'expansion', + + animationEasing: 'cubicOut', + + data: [] + } + }); + + zrUtil.mixin(PieSeries, dataSelectableMixin); + + module.exports = PieSeries; + + +/***/ }, +/* 148 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Data selectable mixin for chart series. + * To eanble data select, option of series must have `selectedMode`. + * And each data item will use `selected` to toggle itself selected status + * + * @module echarts/chart/helper/DataSelectable + */ + + + var zrUtil = __webpack_require__(4); + + module.exports = { + + updateSelectedMap: function (targetList) { + this._selectTargetMap = zrUtil.reduce(targetList || [], function (targetMap, target) { + targetMap.set(target.name, target); + return targetMap; + }, zrUtil.createHashMap()); + }, + /** + * @param {string} name + */ + // PENGING If selectedMode is null ? + select: function (name) { + var targetMap = this._selectTargetMap; + var target = targetMap.get(name); + var selectedMode = this.get('selectedMode'); + if (selectedMode === 'single') { + targetMap.each(function (target) { + target.selected = false; + }); + } + target && (target.selected = true); + }, + + /** + * @param {string} name + */ + unSelect: function (name) { + var target = this._selectTargetMap.get(name); + // var selectedMode = this.get('selectedMode'); + // selectedMode !== 'single' && target && (target.selected = false); + target && (target.selected = false); + }, + + /** + * @param {string} name + */ + toggleSelected: function (name) { + var target = this._selectTargetMap.get(name); + if (target != null) { + this[target.selected ? 'unSelect' : 'select'](name); + return target.selected; + } + }, + + /** + * @param {string} name + */ + isSelected: function (name) { + var target = this._selectTargetMap.get(name); + return target && target.selected; + } + }; + + +/***/ }, +/* 149 */ +/***/ function(module, exports, __webpack_require__) { + + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + + /** + * @param {module:echarts/model/Series} seriesModel + * @param {boolean} hasAnimation + * @inner + */ + function updateDataSelected(uid, seriesModel, hasAnimation, api) { + var data = seriesModel.getData(); + var dataIndex = this.dataIndex; + var name = data.getName(dataIndex); + var selectedOffset = seriesModel.get('selectedOffset'); + + api.dispatchAction({ + type: 'pieToggleSelect', + from: uid, + name: name, + seriesId: seriesModel.id + }); + + data.each(function (idx) { + toggleItemSelected( + data.getItemGraphicEl(idx), + data.getItemLayout(idx), + seriesModel.isSelected(data.getName(idx)), + selectedOffset, + hasAnimation + ); + }); + } + + /** + * @param {module:zrender/graphic/Sector} el + * @param {Object} layout + * @param {boolean} isSelected + * @param {number} selectedOffset + * @param {boolean} hasAnimation + * @inner + */ + function toggleItemSelected(el, layout, isSelected, selectedOffset, hasAnimation) { + var midAngle = (layout.startAngle + layout.endAngle) / 2; + + var dx = Math.cos(midAngle); + var dy = Math.sin(midAngle); + + var offset = isSelected ? selectedOffset : 0; + var position = [dx * offset, dy * offset]; + + hasAnimation + // animateTo will stop revious animation like update transition + ? el.animate() + .when(200, { + position: position + }) + .start('bounceOut') + : el.attr('position', position); + } + + /** + * Piece of pie including Sector, Label, LabelLine + * @constructor + * @extends {module:zrender/graphic/Group} + */ + function PiePiece(data, idx) { + + graphic.Group.call(this); + + var sector = new graphic.Sector({ + z2: 2 + }); + var polyline = new graphic.Polyline(); + var text = new graphic.Text(); + this.add(sector); + this.add(polyline); + this.add(text); + + this.updateData(data, idx, true); + + // Hover to change label and labelLine + function onEmphasis() { + polyline.ignore = polyline.hoverIgnore; + text.ignore = text.hoverIgnore; + } + function onNormal() { + polyline.ignore = polyline.normalIgnore; + text.ignore = text.normalIgnore; + } + this.on('emphasis', onEmphasis) + .on('normal', onNormal) + .on('mouseover', onEmphasis) + .on('mouseout', onNormal); + } + + var piePieceProto = PiePiece.prototype; + + function getLabelStyle(data, idx, state, labelModel, labelPosition) { + var textStyleModel = labelModel.getModel('textStyle'); + var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner'; + return { + fill: textStyleModel.getTextColor() + || (isLabelInside ? '#fff' : data.getItemVisual(idx, 'color')), + opacity: data.getItemVisual(idx, 'opacity'), + textFont: textStyleModel.getFont(), + text: zrUtil.retrieve( + data.hostModel.getFormattedLabel(idx, state), data.getName(idx) + ) + }; + } + + piePieceProto.updateData = function (data, idx, firstCreate) { + + var sector = this.childAt(0); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var sectorShape = zrUtil.extend({}, layout); + sectorShape.label = null; + + if (firstCreate) { + sector.setShape(sectorShape); + + var animationType = seriesModel.getShallow('animationType'); + if (animationType === 'scale') { + sector.shape.r = layout.r0; + graphic.initProps(sector, { + shape: { + r: layout.r + } + }, seriesModel, idx); + } + // Expansion + else { + sector.shape.endAngle = layout.startAngle; + graphic.updateProps(sector, { + shape: { + endAngle: layout.endAngle + } + }, seriesModel, idx); + } + + } + else { + graphic.updateProps(sector, { + shape: sectorShape + }, seriesModel, idx); + } + + // Update common style + var itemStyleModel = itemModel.getModel('itemStyle'); + var visualColor = data.getItemVisual(idx, 'color'); + + sector.useStyle( + zrUtil.defaults( + { + lineJoin: 'bevel', + fill: visualColor + }, + itemStyleModel.getModel('normal').getItemStyle() + ) + ); + sector.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle(); + + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && sector.attr('cursor', cursorStyle); + + // Toggle selected + toggleItemSelected( + this, + data.getItemLayout(idx), + itemModel.get('selected'), + seriesModel.get('selectedOffset'), + seriesModel.get('animation') + ); + + function onEmphasis() { + // Sector may has animation of updating data. Force to move to the last frame + // Or it may stopped on the wrong shape + sector.stopAnimation(true); + sector.animateTo({ + shape: { + r: layout.r + 10 + } + }, 300, 'elasticOut'); + } + function onNormal() { + sector.stopAnimation(true); + sector.animateTo({ + shape: { + r: layout.r + } + }, 300, 'elasticOut'); + } + sector.off('mouseover').off('mouseout').off('emphasis').off('normal'); + if (itemModel.get('hoverAnimation') && seriesModel.isAnimationEnabled()) { + sector + .on('mouseover', onEmphasis) + .on('mouseout', onNormal) + .on('emphasis', onEmphasis) + .on('normal', onNormal); + } + + this._updateLabel(data, idx); + + graphic.setHoverStyle(this); + }; + + piePieceProto._updateLabel = function (data, idx) { + + var labelLine = this.childAt(1); + var labelText = this.childAt(2); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var labelLayout = layout.label; + var visualColor = data.getItemVisual(idx, 'color'); + + graphic.updateProps(labelLine, { + shape: { + points: labelLayout.linePoints || [ + [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y] + ] + } + }, seriesModel, idx); + + graphic.updateProps(labelText, { + style: { + x: labelLayout.x, + y: labelLayout.y + } + }, seriesModel, idx); + labelText.attr({ + style: { + textVerticalAlign: labelLayout.verticalAlign, + textAlign: labelLayout.textAlign, + textFont: labelLayout.font + }, + rotation: labelLayout.rotation, + origin: [labelLayout.x, labelLayout.y], + z2: 10 + }); + + var labelModel = itemModel.getModel('label.normal'); + var labelHoverModel = itemModel.getModel('label.emphasis'); + var labelLineModel = itemModel.getModel('labelLine.normal'); + var labelLineHoverModel = itemModel.getModel('labelLine.emphasis'); + var labelPosition = labelModel.get('position') || labelHoverModel.get('position'); + + labelText.setStyle(getLabelStyle(data, idx, 'normal', labelModel, labelPosition)); + + labelText.ignore = labelText.normalIgnore = !labelModel.get('show'); + labelText.hoverIgnore = !labelHoverModel.get('show'); + + labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show'); + labelLine.hoverIgnore = !labelLineHoverModel.get('show'); + + // Default use item visual color + labelLine.setStyle({ + stroke: visualColor, + opacity: data.getItemVisual(idx, 'opacity') + }); + labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle()); + + labelText.hoverStyle = getLabelStyle(data, idx, 'emphasis', labelHoverModel, labelPosition); + labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle(); + + var smooth = labelLineModel.get('smooth'); + if (smooth && smooth === true) { + smooth = 0.4; + } + labelLine.setShape({ + smooth: smooth + }); + }; + + zrUtil.inherits(PiePiece, graphic.Group); + + + // Pie view + var Pie = __webpack_require__(80).extend({ + + type: 'pie', + + init: function () { + var sectorGroup = new graphic.Group(); + this._sectorGroup = sectorGroup; + }, + + render: function (seriesModel, ecModel, api, payload) { + if (payload && (payload.from === this.uid)) { + return; + } + + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + + var hasAnimation = ecModel.get('animation'); + var isFirstRender = !oldData; + var animationType = seriesModel.get('animationType'); + + var onSectorClick = zrUtil.curry( + updateDataSelected, this.uid, seriesModel, hasAnimation, api + ); + + var selectedMode = seriesModel.get('selectedMode'); + + data.diff(oldData) + .add(function (idx) { + var piePiece = new PiePiece(data, idx); + // Default expansion animation + if (isFirstRender && animationType !== 'scale') { + piePiece.eachChild(function (child) { + child.stopAnimation(true); + }); + } + + selectedMode && piePiece.on('click', onSectorClick); + + data.setItemGraphicEl(idx, piePiece); + + group.add(piePiece); + }) + .update(function (newIdx, oldIdx) { + var piePiece = oldData.getItemGraphicEl(oldIdx); + + piePiece.updateData(data, newIdx); + + piePiece.off('click'); + selectedMode && piePiece.on('click', onSectorClick); + group.add(piePiece); + data.setItemGraphicEl(newIdx, piePiece); + }) + .remove(function (idx) { + var piePiece = oldData.getItemGraphicEl(idx); + group.remove(piePiece); + }) + .execute(); + + if ( + hasAnimation && isFirstRender && data.count() > 0 + // Default expansion animation + && animationType !== 'scale' + ) { + var shape = data.getItemLayout(0); + var r = Math.max(api.getWidth(), api.getHeight()) / 2; + + var removeClipPath = zrUtil.bind(group.removeClipPath, group); + group.setClipPath(this._createClipPath( + shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel + )); + } + + this._data = data; + }, + + dispose: function () {}, + + _createClipPath: function ( + cx, cy, r, startAngle, clockwise, cb, seriesModel + ) { + var clipPath = new graphic.Sector({ + shape: { + cx: cx, + cy: cy, + r0: 0, + r: r, + startAngle: startAngle, + endAngle: startAngle, + clockwise: clockwise + } + }); + + graphic.initProps(clipPath, { + shape: { + endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2 + } + }, seriesModel, cb); + + return clipPath; + }, + + /** + * @implement + */ + containPoint: function (point, seriesModel) { + var data = seriesModel.getData(); + var itemLayout = data.getItemLayout(0); + if (itemLayout) { + var dx = point[0] - itemLayout.cx; + var dy = point[1] - itemLayout.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + return radius <= itemLayout.r && radius >= itemLayout.r0; + } + } + + }); + + module.exports = Pie; + + +/***/ }, +/* 150 */ +/***/ function(module, exports, __webpack_require__) { + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + module.exports = function (seriesType, actionInfos) { + zrUtil.each(actionInfos, function (actionInfo) { + actionInfo.update = 'updateView'; + /** + * @payload + * @property {string} seriesName + * @property {string} name + */ + echarts.registerAction(actionInfo, function (payload, ecModel) { + var selected = {}; + ecModel.eachComponent( + {mainType: 'series', subType: seriesType, query: payload}, + function (seriesModel) { + if (seriesModel[actionInfo.method]) { + seriesModel[actionInfo.method](payload.name); + } + var data = seriesModel.getData(); + // Create selected map + data.each(function (idx) { + var name = data.getName(idx); + selected[name] = seriesModel.isSelected(name) || false; + }); + } + ); + return { + name: payload.name, + selected: selected + }; + }); + }); + }; + + +/***/ }, +/* 151 */ +/***/ function(module, exports) { + + // Pick color from palette for each data item. + // Applicable for charts that require applying color palette + // in data level (like pie, funnel, chord). + + + module.exports = function (seriesType, ecModel) { + // Pie and funnel may use diferrent scope + var paletteScope = {}; + ecModel.eachRawSeriesByType(seriesType, function (seriesModel) { + var dataAll = seriesModel.getRawData(); + var idxMap = {}; + if (!ecModel.isSeriesFiltered(seriesModel)) { + var data = seriesModel.getData(); + data.each(function (idx) { + var rawIdx = data.getRawIndex(idx); + idxMap[rawIdx] = idx; + }); + dataAll.each(function (rawIdx) { + var filteredIdx = idxMap[rawIdx]; + + // If series.itemStyle.normal.color is a function. itemVisual may be encoded + var singleDataColor = filteredIdx != null + && data.getItemVisual(filteredIdx, 'color', true); + + if (!singleDataColor) { + // FIXME Performance + var itemModel = dataAll.getItemModel(rawIdx); + var color = itemModel.get('itemStyle.normal.color') + || seriesModel.getColorFromPalette(dataAll.getName(rawIdx), paletteScope); + // Legend may use the visual info in data before processed + dataAll.setItemVisual(rawIdx, 'color', color); + + // Data is not filtered + if (filteredIdx != null) { + data.setItemVisual(filteredIdx, 'color', color); + } + } + else { + // Set data all color for legend + dataAll.setItemVisual(rawIdx, 'color', singleDataColor); + } + }); + } + }); + }; + + +/***/ }, +/* 152 */ +/***/ function(module, exports, __webpack_require__) { + + + + var numberUtil = __webpack_require__(7); + var parsePercent = numberUtil.parsePercent; + var labelLayout = __webpack_require__(153); + var zrUtil = __webpack_require__(4); + + var PI2 = Math.PI * 2; + var RADIAN = Math.PI / 180; + + module.exports = function (seriesType, ecModel, api, payload) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var center = seriesModel.get('center'); + var radius = seriesModel.get('radius'); + + if (!zrUtil.isArray(radius)) { + radius = [0, radius]; + } + if (!zrUtil.isArray(center)) { + center = [center, center]; + } + + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent(center[0], width); + var cy = parsePercent(center[1], height); + var r0 = parsePercent(radius[0], size / 2); + var r = parsePercent(radius[1], size / 2); + + var data = seriesModel.getData(); + + var startAngle = -seriesModel.get('startAngle') * RADIAN; + + var minAngle = seriesModel.get('minAngle') * RADIAN; + + var validDataCount = 0; + data.each('value', function (value) { + !isNaN(value) && validDataCount++; + }); + + var sum = data.getSum('value'); + // Sum may be 0 + var unitRadian = Math.PI / (sum || validDataCount) * 2; + + var clockwise = seriesModel.get('clockwise'); + + var roseType = seriesModel.get('roseType'); + var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); + + // [0...max] + var extent = data.getDataExtent('value'); + extent[0] = 0; + + // In the case some sector angle is smaller than minAngle + var restAngle = PI2; + var valueSumLargerThanMinAngle = 0; + + var currentAngle = startAngle; + var dir = clockwise ? 1 : -1; + + data.each('value', function (value, idx) { + var angle; + if (isNaN(value)) { + data.setItemLayout(idx, { + angle: NaN, + startAngle: NaN, + endAngle: NaN, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType + ? NaN + : r + }); + return; + } + + // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样? + if (roseType !== 'area') { + angle = (sum === 0 && stillShowZeroSum) + ? unitRadian : (value * unitRadian); + } + else { + angle = PI2 / validDataCount; + } + + if (angle < minAngle) { + angle = minAngle; + restAngle -= minAngle; + } + else { + valueSumLargerThanMinAngle += value; + } + + var endAngle = currentAngle + dir * angle; + data.setItemLayout(idx, { + angle: angle, + startAngle: currentAngle, + endAngle: endAngle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType + ? numberUtil.linearMap(value, extent, [r0, r]) + : r + }); + + currentAngle = endAngle; + }, true); + + // Some sector is constrained by minAngle + // Rest sectors needs recalculate angle + if (restAngle < PI2 && validDataCount) { + // Average the angle if rest angle is not enough after all angles is + // Constrained by minAngle + if (restAngle <= 1e-3) { + var angle = PI2 / validDataCount; + data.each('value', function (value, idx) { + if (!isNaN(value)) { + var layout = data.getItemLayout(idx); + layout.angle = angle; + layout.startAngle = startAngle + dir * idx * angle; + layout.endAngle = startAngle + dir * (idx + 1) * angle; + } + }); + } + else { + unitRadian = restAngle / valueSumLargerThanMinAngle; + currentAngle = startAngle; + data.each('value', function (value, idx) { + if (!isNaN(value)) { + var layout = data.getItemLayout(idx); + var angle = layout.angle === minAngle + ? minAngle : value * unitRadian; + layout.startAngle = currentAngle; + layout.endAngle = currentAngle + dir * angle; + currentAngle += dir * angle; + } + }); + } + } + + labelLayout(seriesModel, r, width, height); + }); + }; + + +/***/ }, +/* 153 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + // FIXME emphasis label position is not same with normal label position + + + var textContain = __webpack_require__(8); + + function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) { + list.sort(function (a, b) { + return a.y - b.y; + }); + + // 压 + function shiftDown(start, end, delta, dir) { + for (var j = start; j < end; j++) { + list[j].y += delta; + if (j > start + && j + 1 < end + && list[j + 1].y > list[j].y + list[j].height + ) { + shiftUp(j, delta / 2); + return; + } + } + + shiftUp(end - 1, delta / 2); + } + + // 弹 + function shiftUp(end, delta) { + for (var j = end; j >= 0; j--) { + list[j].y -= delta; + if (j > 0 + && list[j].y > list[j - 1].y + list[j - 1].height + ) { + break; + } + } + } + + function changeX(list, isDownList, cx, cy, r, dir) { + var lastDeltaX = dir > 0 + ? isDownList // 右侧 + ? Number.MAX_VALUE // 下 + : 0 // 上 + : isDownList // 左侧 + ? Number.MAX_VALUE // 下 + : 0; // 上 + + for (var i = 0, l = list.length; i < l; i++) { + // Not change x for center label + if (list[i].position === 'center') { + continue; + } + var deltaY = Math.abs(list[i].y - cy); + var length = list[i].len; + var length2 = list[i].len2; + var deltaX = (deltaY < r + length) + ? Math.sqrt( + (r + length + length2) * (r + length + length2) + - deltaY * deltaY + ) + : Math.abs(list[i].x - cx); + if (isDownList && deltaX >= lastDeltaX) { + // 右下,左下 + deltaX = lastDeltaX - 10; + } + if (!isDownList && deltaX <= lastDeltaX) { + // 右上,左上 + deltaX = lastDeltaX + 10; + } + + list[i].x = cx + deltaX * dir; + lastDeltaX = deltaX; + } + } + + var lastY = 0; + var delta; + var len = list.length; + var upList = []; + var downList = []; + for (var i = 0; i < len; i++) { + delta = list[i].y - lastY; + if (delta < 0) { + shiftDown(i, len, -delta, dir); + } + lastY = list[i].y + list[i].height; + } + if (viewHeight - lastY < 0) { + shiftUp(len - 1, lastY - viewHeight); + } + for (var i = 0; i < len; i++) { + if (list[i].y >= cy) { + downList.push(list[i]); + } + else { + upList.push(list[i]); + } + } + changeX(upList, false, cx, cy, r, dir); + changeX(downList, true, cx, cy, r, dir); + } + + function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) { + var leftList = []; + var rightList = []; + for (var i = 0; i < labelLayoutList.length; i++) { + if (labelLayoutList[i].x < cx) { + leftList.push(labelLayoutList[i]); + } + else { + rightList.push(labelLayoutList[i]); + } + } + + adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight); + adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight); + + for (var i = 0; i < labelLayoutList.length; i++) { + var linePoints = labelLayoutList[i].linePoints; + if (linePoints) { + var dist = linePoints[1][0] - linePoints[2][0]; + if (labelLayoutList[i].x < cx) { + linePoints[2][0] = labelLayoutList[i].x + 3; + } + else { + linePoints[2][0] = labelLayoutList[i].x - 3; + } + linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y; + linePoints[1][0] = linePoints[2][0] + dist; + } + } + } + + module.exports = function (seriesModel, r, viewWidth, viewHeight) { + var data = seriesModel.getData(); + var labelLayoutList = []; + var cx; + var cy; + var hasLabelRotate = false; + + data.each(function (idx) { + var layout = data.getItemLayout(idx); + + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label.normal'); + // Use position in normal or emphasis + var labelPosition = labelModel.get('position') || itemModel.get('label.emphasis.position'); + + var labelLineModel = itemModel.getModel('labelLine.normal'); + var labelLineLen = labelLineModel.get('length'); + var labelLineLen2 = labelLineModel.get('length2'); + + var midAngle = (layout.startAngle + layout.endAngle) / 2; + var dx = Math.cos(midAngle); + var dy = Math.sin(midAngle); + + var textX; + var textY; + var linePoints; + var textAlign; + + cx = layout.cx; + cy = layout.cy; + + var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner'; + if (labelPosition === 'center') { + textX = layout.cx; + textY = layout.cy; + textAlign = 'center'; + } + else { + var x1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dx : layout.r * dx) + cx; + var y1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dy : layout.r * dy) + cy; + + textX = x1 + dx * 3; + textY = y1 + dy * 3; + + if (!isLabelInside) { + // For roseType + var x2 = x1 + dx * (labelLineLen + r - layout.r); + var y2 = y1 + dy * (labelLineLen + r - layout.r); + var x3 = x2 + ((dx < 0 ? -1 : 1) * labelLineLen2); + var y3 = y2; + + textX = x3 + (dx < 0 ? -5 : 5); + textY = y3; + linePoints = [[x1, y1], [x2, y2], [x3, y3]]; + } + + textAlign = isLabelInside ? 'center' : (dx > 0 ? 'left' : 'right'); + } + var font = labelModel.getModel('textStyle').getFont(); + + var labelRotate = labelModel.get('rotate') + ? (dx < 0 ? -midAngle + Math.PI : -midAngle) : 0; + var text = seriesModel.getFormattedLabel(idx, 'normal') + || data.getName(idx); + var textRect = textContain.getBoundingRect( + text, font, textAlign, 'top' + ); + hasLabelRotate = !!labelRotate; + layout.label = { + x: textX, + y: textY, + position: labelPosition, + height: textRect.height, + len: labelLineLen, + len2: labelLineLen2, + linePoints: linePoints, + textAlign: textAlign, + verticalAlign: 'middle', + font: font, + rotation: labelRotate + }; + + // Not layout the inside label + if (!isLabelInside) { + labelLayoutList.push(layout.label); + } + }); + if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) { + avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight); + } + }; + + +/***/ }, +/* 154 */ +/***/ function(module, exports) { + + + module.exports = function (seriesType, ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + if (!legendModels || !legendModels.length) { + return; + } + ecModel.eachSeriesByType(seriesType, function (series) { + var data = series.getData(); + data.filterSelf(function (idx) { + var name = data.getName(idx); + // If in any legend component the status is not selected. + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(name)) { + return false; + } + } + return true; + }, this); + }, this); + }; + + +/***/ }, +/* 155 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var echarts = __webpack_require__(1); + + __webpack_require__(156); + __webpack_require__(157); + + echarts.registerVisual(zrUtil.curry( + __webpack_require__(121), 'scatter', 'circle', null + )); + echarts.registerLayout(zrUtil.curry( + __webpack_require__(122), 'scatter' + )); + + // In case developer forget to include grid component + __webpack_require__(124); + + +/***/ }, +/* 156 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var createListFromArray = __webpack_require__(109); + var SeriesModel = __webpack_require__(78); + + module.exports = SeriesModel.extend({ + + type: 'series.scatter', + + dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'], + + getInitialData: function (option, ecModel) { + return createListFromArray(option.data, this, ecModel); + }, + + brushSelector: 'point', + + defaultOption: { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true, + + hoverAnimation: true, + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Polar coordinate system + // polarIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + // symbol: null, // 图形类型 + symbolSize: 10, // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2 + // symbolRotate: null, // 图形旋转控制 + + large: false, + // Available when large is true + largeThreshold: 2000, + // cursor: null, + + // label: { + // normal: { + // show: false + // distance: 5, + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为 + // 'inside'|'left'|'right'|'top'|'bottom' + // textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE + // } + // }, + itemStyle: { + normal: { + opacity: 0.8 + // color: 各异 + } + } + } + + }); + + +/***/ }, +/* 157 */ +/***/ function(module, exports, __webpack_require__) { + + + + var SymbolDraw = __webpack_require__(116); + var LargeSymbolDraw = __webpack_require__(158); + + __webpack_require__(1).extendChartView({ + + type: 'scatter', + + init: function () { + this._normalSymbolDraw = new SymbolDraw(); + this._largeSymbolDraw = new LargeSymbolDraw(); + }, + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var largeSymbolDraw = this._largeSymbolDraw; + var normalSymbolDraw = this._normalSymbolDraw; + var group = this.group; + + var symbolDraw = seriesModel.get('large') && data.count() > seriesModel.get('largeThreshold') + ? largeSymbolDraw : normalSymbolDraw; + + this._symbolDraw = symbolDraw; + symbolDraw.updateData(data); + group.add(symbolDraw.group); + + group.remove( + symbolDraw === largeSymbolDraw + ? normalSymbolDraw.group : largeSymbolDraw.group + ); + }, + + updateLayout: function (seriesModel) { + this._symbolDraw.updateLayout(seriesModel); + }, + + remove: function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(api, true); + }, + + dispose: function () {} + }); + + +/***/ }, +/* 158 */ +/***/ function(module, exports, __webpack_require__) { + + // TODO Batch by color + + + + var graphic = __webpack_require__(18); + var symbolUtil = __webpack_require__(111); + + var LargeSymbolPath = graphic.extendShape({ + + shape: { + points: null, + sizes: null + }, + + symbolProxy: null, + + buildPath: function (path, shape) { + var points = shape.points; + var sizes = shape.sizes; + + var symbolProxy = this.symbolProxy; + var symbolProxyShape = symbolProxy.shape; + for (var i = 0; i < points.length; i++) { + var pt = points[i]; + + if (isNaN(pt[0]) || isNaN(pt[1])) { + continue; + } + + var size = sizes[i]; + if (size[0] < 4) { + // Optimize for small symbol + path.rect( + pt[0] - size[0] / 2, pt[1] - size[1] / 2, + size[0], size[1] + ); + } + else { + symbolProxyShape.x = pt[0] - size[0] / 2; + symbolProxyShape.y = pt[1] - size[1] / 2; + symbolProxyShape.width = size[0]; + symbolProxyShape.height = size[1]; + + symbolProxy.buildPath(path, symbolProxyShape, true); + } + } + }, + + findDataIndex: function (x, y) { + var shape = this.shape; + var points = shape.points; + var sizes = shape.sizes; + + // Not consider transform + // Treat each element as a rect + // top down traverse + for (var i = points.length - 1; i >= 0; i--) { + var pt = points[i]; + var size = sizes[i]; + var x0 = pt[0] - size[0] / 2; + var y0 = pt[1] - size[1] / 2; + if (x >= x0 && y >= y0 && x <= x0 + size[0] && y <= y0 + size[1]) { + // i is dataIndex + return i; + } + } + + return -1; + } + }); + + function LargeSymbolDraw() { + this.group = new graphic.Group(); + + this._symbolEl = new LargeSymbolPath({ + // rectHover: true, + // cursor: 'default' + }); + } + + var largeSymbolProto = LargeSymbolDraw.prototype; + + /** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + */ + largeSymbolProto.updateData = function (data) { + this.group.removeAll(); + + var symbolEl = this._symbolEl; + + var seriesModel = data.hostModel; + + symbolEl.setShape({ + points: data.mapArray(data.getItemLayout), + sizes: data.mapArray( + function (idx) { + var size = data.getItemVisual(idx, 'symbolSize'); + if (!(size instanceof Array)) { + size = [size, size]; + } + return size; + } + ) + }); + + // Create symbolProxy to build path for each data + symbolEl.symbolProxy = symbolUtil.createSymbol( + data.getVisual('symbol'), 0, 0, 0, 0 + ); + // Use symbolProxy setColor method + symbolEl.setColor = symbolEl.symbolProxy.setColor; + + symbolEl.useStyle( + seriesModel.getModel('itemStyle.normal').getItemStyle(['color']) + ); + + var visualColor = data.getVisual('color'); + if (visualColor) { + symbolEl.setColor(visualColor); + } + + // Enable tooltip + // PENDING May have performance issue when path is extremely large + symbolEl.seriesIndex = seriesModel.seriesIndex; + symbolEl.on('mousemove', function (e) { + symbolEl.dataIndex = null; + var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY); + if (dataIndex >= 0) { + // Provide dataIndex for tooltip + symbolEl.dataIndex = dataIndex; + } + }); + + // Add back + this.group.add(symbolEl); + }; + + largeSymbolProto.updateLayout = function (seriesModel) { + var data = seriesModel.getData(); + this._symbolEl.setShape({ + points: data.mapArray(data.getItemLayout) + }); + }; + + largeSymbolProto.remove = function () { + this.group.removeAll(); + }; + + module.exports = LargeSymbolDraw; + + +/***/ }, +/* 159 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var echarts = __webpack_require__(1); + + // Must use radar component + __webpack_require__(160); + + __webpack_require__(165); + __webpack_require__(166); + + echarts.registerVisual(zrUtil.curry(__webpack_require__(151), 'radar')); + echarts.registerVisual(zrUtil.curry( + __webpack_require__(121), 'radar', 'circle', null + )); + echarts.registerLayout(__webpack_require__(167)); + + echarts.registerProcessor( + zrUtil.curry(__webpack_require__(154), 'radar') + ); + + echarts.registerPreprocessor(__webpack_require__(168)); + + +/***/ }, +/* 160 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(161); + __webpack_require__(163); + + __webpack_require__(164); + + +/***/ }, +/* 161 */ +/***/ function(module, exports, __webpack_require__) { + + // TODO clockwise + + + var zrUtil = __webpack_require__(4); + var IndicatorAxis = __webpack_require__(162); + var IntervalScale = __webpack_require__(104); + var numberUtil = __webpack_require__(7); + var axisHelper = __webpack_require__(101); + + function Radar(radarModel, ecModel, api) { + + this._model = radarModel; + /** + * Radar dimensions + * @type {Array.} + */ + this.dimensions = []; + + this._indicatorAxes = zrUtil.map(radarModel.getIndicatorModels(), function (indicatorModel, idx) { + var dim = 'indicator_' + idx; + var indicatorAxis = new IndicatorAxis(dim, new IntervalScale()); + indicatorAxis.name = indicatorModel.get('name'); + // Inject model and axis + indicatorAxis.model = indicatorModel; + indicatorModel.axis = indicatorAxis; + this.dimensions.push(dim); + return indicatorAxis; + }, this); + + this.resize(radarModel, api); + + /** + * @type {number} + * @readOnly + */ + this.cx; + /** + * @type {number} + * @readOnly + */ + this.cy; + /** + * @type {number} + * @readOnly + */ + this.r; + /** + * @type {number} + * @readOnly + */ + this.startAngle; + } + + Radar.prototype.getIndicatorAxes = function () { + return this._indicatorAxes; + }; + + Radar.prototype.dataToPoint = function (value, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + + return this.coordToPoint(indicatorAxis.dataToCoord(value), indicatorIndex); + }; + + Radar.prototype.coordToPoint = function (coord, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + var angle = indicatorAxis.angle; + var x = this.cx + coord * Math.cos(angle); + var y = this.cy - coord * Math.sin(angle); + return [x, y]; + }; + + Radar.prototype.pointToData = function (pt) { + var dx = pt[0] - this.cx; + var dy = pt[1] - this.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + + var radian = Math.atan2(-dy, dx); + + // Find the closest angle + // FIXME index can calculated directly + var minRadianDiff = Infinity; + var closestAxis; + var closestAxisIdx = -1; + for (var i = 0; i < this._indicatorAxes.length; i++) { + var indicatorAxis = this._indicatorAxes[i]; + var diff = Math.abs(radian - indicatorAxis.angle); + if (diff < minRadianDiff) { + closestAxis = indicatorAxis; + closestAxisIdx = i; + minRadianDiff = diff; + } + } + + return [closestAxisIdx, +(closestAxis && closestAxis.coodToData(radius))]; + }; + + Radar.prototype.resize = function (radarModel, api) { + var center = radarModel.get('center'); + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + var viewSize = Math.min(viewWidth, viewHeight) / 2; + this.cx = numberUtil.parsePercent(center[0], viewWidth); + this.cy = numberUtil.parsePercent(center[1], viewHeight); + + this.startAngle = radarModel.get('startAngle') * Math.PI / 180; + + this.r = numberUtil.parsePercent(radarModel.get('radius'), viewSize); + + zrUtil.each(this._indicatorAxes, function (indicatorAxis, idx) { + indicatorAxis.setExtent(0, this.r); + var angle = (this.startAngle + idx * Math.PI * 2 / this._indicatorAxes.length); + // Normalize to [-PI, PI] + angle = Math.atan2(Math.sin(angle), Math.cos(angle)); + indicatorAxis.angle = angle; + }, this); + }; + + Radar.prototype.update = function (ecModel, api) { + var indicatorAxes = this._indicatorAxes; + var radarModel = this._model; + zrUtil.each(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.setExtent(Infinity, -Infinity); + }); + ecModel.eachSeriesByType('radar', function (radarSeries, idx) { + if (radarSeries.get('coordinateSystem') !== 'radar' + || ecModel.getComponent('radar', radarSeries.get('radarIndex')) !== radarModel + ) { + return; + } + var data = radarSeries.getData(); + zrUtil.each(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.unionExtentFromData(data, indicatorAxis.dim); + }); + }, this); + + var splitNumber = radarModel.get('splitNumber'); + + function increaseInterval(interval) { + var exp10 = Math.pow(10, Math.floor(Math.log(interval) / Math.LN10)); + // Increase interval + var f = interval / exp10; + if (f === 2) { + f = 5; + } + else { // f is 2 or 5 + f *= 2; + } + return f * exp10; + } + // Force all the axis fixing the maxSplitNumber. + zrUtil.each(indicatorAxes, function (indicatorAxis, idx) { + var rawExtent = axisHelper.getScaleExtent(indicatorAxis.scale, indicatorAxis.model); + axisHelper.niceScaleExtent(indicatorAxis.scale, indicatorAxis.model); + + var axisModel = indicatorAxis.model; + var scale = indicatorAxis.scale; + var fixedMin = axisModel.getMin(); + var fixedMax = axisModel.getMax(); + var interval = scale.getInterval(); + + if (fixedMin != null && fixedMax != null) { + // User set min, max, divide to get new interval + scale.setExtent(+fixedMin, +fixedMax); + scale.setInterval( + (fixedMax - fixedMin) / splitNumber + ); + } + else if (fixedMin != null) { + var max; + // User set min, expand extent on the other side + do { + max = fixedMin + interval * splitNumber; + scale.setExtent(+fixedMin, max); + // Interval must been set after extent + // FIXME + scale.setInterval(interval); + + interval = increaseInterval(interval); + } while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])); + } + else if (fixedMax != null) { + var min; + // User set min, expand extent on the other side + do { + min = fixedMax - interval * splitNumber; + scale.setExtent(min, +fixedMax); + scale.setInterval(interval); + interval = increaseInterval(interval); + } while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])); + } + else { + var nicedSplitNumber = scale.getTicks().length - 1; + if (nicedSplitNumber > splitNumber) { + interval = increaseInterval(interval); + } + // PENDING + var center = Math.round((rawExtent[0] + rawExtent[1]) / 2 / interval) * interval; + var halfSplitNumber = Math.round(splitNumber / 2); + scale.setExtent( + numberUtil.round(center - halfSplitNumber * interval), + numberUtil.round(center + (splitNumber - halfSplitNumber) * interval) + ); + scale.setInterval(interval); + } + }); + }; + + /** + * Radar dimensions is based on the data + * @type {Array} + */ + Radar.dimensions = []; + + Radar.create = function (ecModel, api) { + var radarList = []; + ecModel.eachComponent('radar', function (radarModel) { + var radar = new Radar(radarModel, ecModel, api); + radarList.push(radar); + radarModel.coordinateSystem = radar; + }); + ecModel.eachSeriesByType('radar', function (radarSeries) { + if (radarSeries.get('coordinateSystem') === 'radar') { + // Inject coordinate system + radarSeries.coordinateSystem = radarList[radarSeries.get('radarIndex') || 0]; + } + }); + return radarList; + }; + + __webpack_require__(76).register('radar', Radar); + module.exports = Radar; + + +/***/ }, +/* 162 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var Axis = __webpack_require__(100); + + function IndicatorAxis(dim, scale, radiusExtent) { + Axis.call(this, dim, scale, radiusExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = 'value'; + + this.angle = 0; + + /** + * Indicator name + * @type {string} + */ + this.name = ''; + /** + * @type {module:echarts/model/Model} + */ + this.model; + } + + zrUtil.inherits(IndicatorAxis, Axis); + + module.exports = IndicatorAxis; + + +/***/ }, +/* 163 */ +/***/ function(module, exports, __webpack_require__) { + + + + + var axisDefault = __webpack_require__(132); + var valueAxisDefault = axisDefault.valueAxis; + var Model = __webpack_require__(12); + var zrUtil = __webpack_require__(4); + + var axisModelCommonMixin = __webpack_require__(112); + + function defaultsShow(opt, show) { + return zrUtil.defaults({ + show: show + }, opt); + } + + var RadarModel = __webpack_require__(1).extendComponentModel({ + + type: 'radar', + + optionUpdated: function () { + var boundaryGap = this.get('boundaryGap'); + var splitNumber = this.get('splitNumber'); + var scale = this.get('scale'); + var axisLine = this.get('axisLine'); + var axisTick = this.get('axisTick'); + var axisLabel = this.get('axisLabel'); + var nameTextStyle = this.get('name.textStyle'); + var showName = this.get('name.show'); + var nameFormatter = this.get('name.formatter'); + var nameGap = this.get('nameGap'); + var triggerEvent = this.get('triggerEvent'); + + var indicatorModels = zrUtil.map(this.get('indicator') || [], function (indicatorOpt) { + // PENDING + if (indicatorOpt.max != null && indicatorOpt.max > 0 && !indicatorOpt.min) { + indicatorOpt.min = 0; + } + else if (indicatorOpt.min != null && indicatorOpt.min < 0 && !indicatorOpt.max) { + indicatorOpt.max = 0; + } + // Use same configuration + indicatorOpt = zrUtil.merge(zrUtil.clone(indicatorOpt), { + boundaryGap: boundaryGap, + splitNumber: splitNumber, + scale: scale, + axisLine: axisLine, + axisTick: axisTick, + axisLabel: axisLabel, + // Competitable with 2 and use text + name: indicatorOpt.text, + nameLocation: 'end', + nameGap: nameGap, + // min: 0, + nameTextStyle: nameTextStyle, + triggerEvent: triggerEvent + }, false); + if (!showName) { + indicatorOpt.name = ''; + } + if (typeof nameFormatter === 'string') { + var indName = indicatorOpt.name; + indicatorOpt.name = nameFormatter.replace('{value}', indName != null ? indName : ''); + } + else if (typeof nameFormatter === 'function') { + indicatorOpt.name = nameFormatter( + indicatorOpt.name, indicatorOpt + ); + } + var model = zrUtil.extend( + new Model(indicatorOpt, null, this.ecModel), + axisModelCommonMixin + ); + + // For triggerEvent. + model.mainType = 'radar'; + model.componentIndex = this.componentIndex; + + return model; + }, this); + + this.getIndicatorModels = function () { + return indicatorModels; + }; + }, + + defaultOption: { + + zlevel: 0, + + z: 0, + + center: ['50%', '50%'], + + radius: '75%', + + startAngle: 90, + + name: { + show: true + // formatter: null + // textStyle: {} + }, + + boundaryGap: [0, 0], + + splitNumber: 5, + + nameGap: 15, + + scale: false, + + // Polygon or circle + shape: 'polygon', + + axisLine: zrUtil.merge( + { + lineStyle: { + color: '#bbb' + } + }, + valueAxisDefault.axisLine + ), + axisLabel: defaultsShow(valueAxisDefault.axisLabel, false), + axisTick: defaultsShow(valueAxisDefault.axisTick, false), + splitLine: defaultsShow(valueAxisDefault.splitLine, true), + splitArea: defaultsShow(valueAxisDefault.splitArea, true), + + // {text, min, max} + indicator: [] + } + }); + + module.exports = RadarModel; + + +/***/ }, +/* 164 */ +/***/ function(module, exports, __webpack_require__) { + + + + var AxisBuilder = __webpack_require__(135); + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + + var axisBuilderAttrs = [ + 'axisLine', 'axisLabel', 'axisTick', 'axisName' + ]; + + module.exports = __webpack_require__(1).extendComponentView({ + + type: 'radar', + + render: function (radarModel, ecModel, api) { + var group = this.group; + group.removeAll(); + + this._buildAxes(radarModel); + this._buildSplitLineAndArea(radarModel); + }, + + _buildAxes: function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + var axisBuilders = zrUtil.map(indicatorAxes, function (indicatorAxis) { + var axisBuilder = new AxisBuilder(indicatorAxis.model, { + position: [radar.cx, radar.cy], + rotation: indicatorAxis.angle, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1 + }); + return axisBuilder; + }); + + zrUtil.each(axisBuilders, function (axisBuilder) { + zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder); + this.group.add(axisBuilder.getGroup()); + }, this); + }, + + _buildSplitLineAndArea: function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + if (!indicatorAxes.length) { + return; + } + var shape = radarModel.get('shape'); + var splitLineModel = radarModel.getModel('splitLine'); + var splitAreaModel = radarModel.getModel('splitArea'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + + var showSplitLine = splitLineModel.get('show'); + var showSplitArea = splitAreaModel.get('show'); + var splitLineColors = lineStyleModel.get('color'); + var splitAreaColors = areaStyleModel.get('color'); + + splitLineColors = zrUtil.isArray(splitLineColors) ? splitLineColors : [splitLineColors]; + splitAreaColors = zrUtil.isArray(splitAreaColors) ? splitAreaColors : [splitAreaColors]; + + var splitLines = []; + var splitAreas = []; + + function getColorIndex(areaOrLine, areaOrLineColorList, idx) { + var colorIndex = idx % areaOrLineColorList.length; + areaOrLine[colorIndex] = areaOrLine[colorIndex] || []; + return colorIndex; + } + + if (shape === 'circle') { + var ticksRadius = indicatorAxes[0].getTicksCoords(); + var cx = radar.cx; + var cy = radar.cy; + for (var i = 0; i < ticksRadius.length; i++) { + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColors, i); + splitLines[colorIndex].push(new graphic.Circle({ + shape: { + cx: cx, + cy: cy, + r: ticksRadius[i] + } + })); + } + if (showSplitArea && i < ticksRadius.length - 1) { + var colorIndex = getColorIndex(splitAreas, splitAreaColors, i); + splitAreas[colorIndex].push(new graphic.Ring({ + shape: { + cx: cx, + cy: cy, + r0: ticksRadius[i], + r: ticksRadius[i + 1] + } + })); + } + } + } + // Polyyon + else { + var realSplitNumber; + var axesTicksPoints = zrUtil.map(indicatorAxes, function (indicatorAxis, idx) { + var ticksCoords = indicatorAxis.getTicksCoords(); + realSplitNumber = realSplitNumber == null + ? ticksCoords.length - 1 + : Math.min(ticksCoords.length - 1, realSplitNumber); + return zrUtil.map(ticksCoords, function (tickCoord) { + return radar.coordToPoint(tickCoord, idx); + }); + }); + + var prevPoints = []; + for (var i = 0; i <= realSplitNumber; i++) { + var points = []; + for (var j = 0; j < indicatorAxes.length; j++) { + points.push(axesTicksPoints[j][i]); + } + // Close + if (points[0]) { + points.push(points[0].slice()); + } + else { + if (true) { + console.error('Can\'t draw value axis ' + i); + } + } + + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColors, i); + splitLines[colorIndex].push(new graphic.Polyline({ + shape: { + points: points + } + })); + } + if (showSplitArea && prevPoints) { + var colorIndex = getColorIndex(splitAreas, splitAreaColors, i - 1); + splitAreas[colorIndex].push(new graphic.Polygon({ + shape: { + points: points.concat(prevPoints) + } + })); + } + prevPoints = points.slice().reverse(); + } + } + + var lineStyle = lineStyleModel.getLineStyle(); + var areaStyle = areaStyleModel.getAreaStyle(); + // Add splitArea before splitLine + zrUtil.each(splitAreas, function (splitAreas, idx) { + this.group.add(graphic.mergePath( + splitAreas, { + style: zrUtil.defaults({ + stroke: 'none', + fill: splitAreaColors[idx % splitAreaColors.length] + }, areaStyle), + silent: true + } + )); + }, this); + + zrUtil.each(splitLines, function (splitLines, idx) { + this.group.add(graphic.mergePath( + splitLines, { + style: zrUtil.defaults({ + fill: 'none', + stroke: splitLineColors[idx % splitLineColors.length] + }, lineStyle), + silent: true + } + )); + }, this); + + } + }); + + +/***/ }, +/* 165 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var SeriesModel = __webpack_require__(78); + var List = __webpack_require__(98); + var completeDimensions = __webpack_require__(110); + var zrUtil = __webpack_require__(4); + var encodeHTML = __webpack_require__(6).encodeHTML; + + var RadarSeries = SeriesModel.extend({ + + type: 'series.radar', + + dependencies: ['radar'], + + + // Overwrite + init: function (option) { + RadarSeries.superApply(this, 'init', arguments); + + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + }, + + getInitialData: function (option, ecModel) { + var data = option.data || []; + var dimensions = completeDimensions( + [], data, {extraPrefix: 'indicator_', extraFromZero: true} + ); + var list = new List(dimensions, this); + list.initData(data); + return list; + }, + + formatTooltip: function (dataIndex) { + var value = this.getRawValue(dataIndex); + var coordSys = this.coordinateSystem; + var indicatorAxes = coordSys.getIndicatorAxes(); + var name = this.getData().getName(dataIndex); + return encodeHTML(name === '' ? this.name : name) + '
' + + zrUtil.map(indicatorAxes, function (axis, idx) { + return encodeHTML(axis.name + ' : ' + value[idx]); + }).join('
'); + }, + + defaultOption: { + zlevel: 0, + z: 2, + coordinateSystem: 'radar', + legendHoverLink: true, + radarIndex: 0, + lineStyle: { + normal: { + width: 2, + type: 'solid' + } + }, + label: { + normal: { + position: 'top' + } + }, + // areaStyle: { + // }, + // itemStyle: {} + symbol: 'emptyCircle', + symbolSize: 4 + // symbolRotate: null + } + }); + + module.exports = RadarSeries; + + +/***/ }, +/* 166 */ +/***/ function(module, exports, __webpack_require__) { + + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + var symbolUtil = __webpack_require__(111); + + function normalizeSymbolSize(symbolSize) { + if (!zrUtil.isArray(symbolSize)) { + symbolSize = [+symbolSize, +symbolSize]; + } + return symbolSize; + } + module.exports = __webpack_require__(1).extendChartView({ + type: 'radar', + + render: function (seriesModel, ecModel, api) { + var polar = seriesModel.coordinateSystem; + var group = this.group; + + var data = seriesModel.getData(); + var oldData = this._data; + + function createSymbol(data, idx) { + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + var color = data.getItemVisual(idx, 'color'); + if (symbolType === 'none') { + return; + } + var symbolPath = symbolUtil.createSymbol( + symbolType, -0.5, -0.5, 1, 1, color + ); + symbolPath.attr({ + style: { + strokeNoScale: true + }, + z2: 100, + scale: normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize')) + }); + return symbolPath; + } + + function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) { + // Simply rerender all + symbolGroup.removeAll(); + for (var i = 0; i < newPoints.length - 1; i++) { + var symbolPath = createSymbol(data, idx); + if (symbolPath) { + symbolPath.__dimIdx = i; + if (oldPoints[i]) { + symbolPath.attr('position', oldPoints[i]); + graphic[isInit ? 'initProps' : 'updateProps']( + symbolPath, { + position: newPoints[i] + }, seriesModel, idx + ); + } + else { + symbolPath.attr('position', newPoints[i]); + } + symbolGroup.add(symbolPath); + } + } + } + + function getInitialPoints(points) { + return zrUtil.map(points, function (pt) { + return [polar.cx, polar.cy]; + }); + } + data.diff(oldData) + .add(function (idx) { + var points = data.getItemLayout(idx); + if (!points) { + return; + } + var polygon = new graphic.Polygon(); + var polyline = new graphic.Polyline(); + var target = { + shape: { + points: points + } + }; + polygon.shape.points = getInitialPoints(points); + polyline.shape.points = getInitialPoints(points); + graphic.initProps(polygon, target, seriesModel, idx); + graphic.initProps(polyline, target, seriesModel, idx); + + var itemGroup = new graphic.Group(); + var symbolGroup = new graphic.Group(); + itemGroup.add(polyline); + itemGroup.add(polygon); + itemGroup.add(symbolGroup); + + updateSymbols( + polyline.shape.points, points, symbolGroup, data, idx, true + ); + + data.setItemGraphicEl(idx, itemGroup); + }) + .update(function (newIdx, oldIdx) { + var itemGroup = oldData.getItemGraphicEl(oldIdx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); + var target = { + shape: { + points: data.getItemLayout(newIdx) + } + }; + if (!target.shape.points) { + return; + } + updateSymbols( + polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false + ); + + graphic.updateProps(polyline, target, seriesModel); + graphic.updateProps(polygon, target, seriesModel); + + data.setItemGraphicEl(newIdx, itemGroup); + }) + .remove(function (idx) { + group.remove(oldData.getItemGraphicEl(idx)); + }) + .execute(); + + data.eachItemGraphicEl(function (itemGroup, idx) { + var itemModel = data.getItemModel(idx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); + var color = data.getItemVisual(idx, 'color'); + + group.add(itemGroup); + + polyline.useStyle( + zrUtil.defaults( + itemModel.getModel('lineStyle.normal').getLineStyle(), + { + fill: 'none', + stroke: color + } + ) + ); + polyline.hoverStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle(); + + var areaStyleModel = itemModel.getModel('areaStyle.normal'); + var hoverAreaStyleModel = itemModel.getModel('areaStyle.emphasis'); + var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty(); + var hoverPolygonIgnore = hoverAreaStyleModel.isEmpty() && hoverAreaStyleModel.parentModel.isEmpty(); + + hoverPolygonIgnore = hoverPolygonIgnore && polygonIgnore; + polygon.ignore = polygonIgnore; + + polygon.useStyle( + zrUtil.defaults( + areaStyleModel.getAreaStyle(), + { + fill: color, + opacity: 0.7 + } + ) + ); + polygon.hoverStyle = hoverAreaStyleModel.getAreaStyle(); + + var itemStyle = itemModel.getModel('itemStyle.normal').getItemStyle(['color']); + var itemHoverStyle = itemModel.getModel('itemStyle.emphasis').getItemStyle(); + var labelModel = itemModel.getModel('label.normal'); + var labelHoverModel = itemModel.getModel('label.emphasis'); + symbolGroup.eachChild(function (symbolPath) { + symbolPath.setStyle(itemStyle); + symbolPath.hoverStyle = zrUtil.clone(itemHoverStyle); + + var defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx); + graphic.setText(symbolPath.style, labelModel, color); + symbolPath.setStyle({ + text: labelModel.get('show') ? zrUtil.retrieve( + seriesModel.getFormattedLabel( + idx, 'normal', null, symbolPath.__dimIdx + ), + defaultText + ) : '' + }); + + graphic.setText(symbolPath.hoverStyle, labelHoverModel, color); + symbolPath.hoverStyle.text = labelHoverModel.get('show') ? zrUtil.retrieve( + seriesModel.getFormattedLabel( + idx, 'emphasis', null, symbolPath.__dimIdx + ), + defaultText + ) : ''; + }); + + function onEmphasis() { + polygon.attr('ignore', hoverPolygonIgnore); + } + + function onNormal() { + polygon.attr('ignore', polygonIgnore); + } + + itemGroup.off('mouseover').off('mouseout').off('normal').off('emphasis'); + itemGroup.on('emphasis', onEmphasis) + .on('mouseover', onEmphasis) + .on('normal', onNormal) + .on('mouseout', onNormal); + + graphic.setHoverStyle(itemGroup); + }); + + this._data = data; + }, + + remove: function () { + this.group.removeAll(); + this._data = null; + }, + + dispose: function () {} + }); + + +/***/ }, +/* 167 */ +/***/ function(module, exports) { + + + + module.exports = function (ecModel) { + ecModel.eachSeriesByType('radar', function (seriesModel) { + var data = seriesModel.getData(); + var points = []; + var coordSys = seriesModel.coordinateSystem; + if (!coordSys) { + return; + } + + function pointsConverter(val, idx) { + points[idx] = points[idx] || []; + points[idx][i] = coordSys.dataToPoint(val, i); + } + for (var i = 0; i < coordSys.getIndicatorAxes().length; i++) { + var dim = data.dimensions[i]; + data.each(dim, pointsConverter); + } + + data.each(function (idx) { + // Close polygon + points[idx][0] && points[idx].push(points[idx][0].slice()); + data.setItemLayout(idx, points[idx]); + }); + }); + }; + + +/***/ }, +/* 168 */ +/***/ function(module, exports, __webpack_require__) { + + // Backward compat for radar chart in 2 + + + var zrUtil = __webpack_require__(4); + + module.exports = function (option) { + var polarOptArr = option.polar; + if (polarOptArr) { + if (!zrUtil.isArray(polarOptArr)) { + polarOptArr = [polarOptArr]; + } + var polarNotRadar = []; + zrUtil.each(polarOptArr, function (polarOpt, idx) { + if (polarOpt.indicator) { + if (polarOpt.type && !polarOpt.shape) { + polarOpt.shape = polarOpt.type; + } + option.radar = option.radar || []; + if (!zrUtil.isArray(option.radar)) { + option.radar = [option.radar]; + } + option.radar.push(polarOpt); + } + else { + polarNotRadar.push(polarOpt); + } + }); + option.polar = polarNotRadar; + } + zrUtil.each(option.series, function (seriesOpt) { + if (seriesOpt.type === 'radar' && seriesOpt.polarIndex) { + seriesOpt.radarIndex = seriesOpt.polarIndex; + } + }); + }; + + +/***/ }, +/* 169 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + var PRIORITY = echarts.PRIORITY; + + __webpack_require__(170); + + __webpack_require__(181); + + __webpack_require__(187); + + __webpack_require__(171); + + echarts.registerLayout(__webpack_require__(189)); + + echarts.registerVisual(__webpack_require__(190)); + + echarts.registerProcessor(PRIORITY.PROCESSOR.STATISTIC, __webpack_require__(191)); + + echarts.registerPreprocessor(__webpack_require__(192)); + + __webpack_require__(150)('map', [{ + type: 'mapToggleSelect', + event: 'mapselectchanged', + method: 'toggleSelected' + }, { + type: 'mapSelect', + event: 'mapselected', + method: 'select' + }, { + type: 'mapUnSelect', + event: 'mapunselected', + method: 'unSelect' + }]); + + +/***/ }, +/* 170 */ +/***/ function(module, exports, __webpack_require__) { + + + + var List = __webpack_require__(98); + var SeriesModel = __webpack_require__(78); + var zrUtil = __webpack_require__(4); + var completeDimensions = __webpack_require__(110); + + var formatUtil = __webpack_require__(6); + var encodeHTML = formatUtil.encodeHTML; + var addCommas = formatUtil.addCommas; + + var dataSelectableMixin = __webpack_require__(148); + + var geoCreator = __webpack_require__(171); + + var MapSeries = SeriesModel.extend({ + + type: 'series.map', + + dependencies: ['geo'], + + layoutMode: 'box', + + /** + * Only first map series of same mapType will drawMap + * @type {boolean} + */ + needsDrawMap: false, + + /** + * Group of all map series with same mapType + * @type {boolean} + */ + seriesGroup: [], + + init: function (option) { + + option = this._fillOption(option, this.getMapType()); + this.option = option; + + MapSeries.superApply(this, 'init', arguments); + + this.updateSelectedMap(option.data); + }, + + getInitialData: function (option) { + var dimensions = completeDimensions(['value'], option.data || []); + + var list = new List(dimensions, this); + + list.initData(option.data); + + return list; + }, + + mergeOption: function (newOption) { + if (newOption.data) { + newOption = this._fillOption(newOption, this.getMapType()); + } + + MapSeries.superCall(this, 'mergeOption', newOption); + + this.updateSelectedMap(this.option.data); + }, + + /** + * If no host geo model, return null, which means using a + * inner exclusive geo model. + */ + getHostGeoModel: function () { + var geoIndex = this.option.geoIndex; + return geoIndex != null + ? this.dependentModels.geo[geoIndex] + : null; + }, + + getMapType: function () { + return (this.getHostGeoModel() || this).option.map; + }, + + _fillOption: function (option, mapName) { + // Shallow clone + option = zrUtil.extend({}, option); + + option.data = geoCreator.getFilledRegions(option.data, mapName); + + return option; + }, + + getRawValue: function (dataIndex) { + // Use value stored in data instead because it is calculated from multiple series + // FIXME Provide all value of multiple series ? + return this.getData().get('value', dataIndex); + }, + + /** + * Get model of region + * @param {string} name + * @return {module:echarts/model/Model} + */ + getRegionModel: function (regionName) { + var data = this.getData(); + return data.getItemModel(data.indexOfName(regionName)); + }, + + /** + * Map tooltip formatter + * + * @param {number} dataIndex + */ + formatTooltip: function (dataIndex) { + // FIXME orignalData and data is a bit confusing + var data = this.getData(); + var formattedValue = addCommas(this.getRawValue(dataIndex)); + var name = data.getName(dataIndex); + + var seriesGroup = this.seriesGroup; + var seriesNames = []; + for (var i = 0; i < seriesGroup.length; i++) { + var otherIndex = seriesGroup[i].originalData.indexOfName(name); + if (!isNaN(seriesGroup[i].originalData.get('value', otherIndex))) { + seriesNames.push( + encodeHTML(seriesGroup[i].name) + ); + } + } + + return seriesNames.join(', ') + '
' + + encodeHTML(name + ' : ' + formattedValue); + }, + + /** + * @implement + */ + getTooltipPosition: function (dataIndex) { + if (dataIndex != null) { + var name = this.getData().getName(dataIndex); + var geo = this.coordinateSystem; + var region = geo.getRegion(name); + + return region && geo.dataToPoint(region.center); + } + }, + + setZoom: function (zoom) { + this.option.zoom = zoom; + }, + + setCenter: function (center) { + this.option.center = center; + }, + + defaultOption: { + // 一级层叠 + zlevel: 0, + // 二级层叠 + z: 2, + + coordinateSystem: 'geo', + + // map should be explicitly specified since ec3. + map: '', + + // If `geoIndex` is not specified, a exclusive geo will be + // created. Otherwise use the specified geo component, and + // `map` and `mapType` are ignored. + // geoIndex: 0, + + // 'center' | 'left' | 'right' | 'x%' | {number} + left: 'center', + // 'center' | 'top' | 'bottom' | 'x%' | {number} + top: 'center', + // right + // bottom + // width: + // height + + // Aspect is width / height. Inited to be geoJson bbox aspect + // This parameter is used for scale this aspect + aspectScale: 0.75, + + ///// Layout with center and size + // If you wan't to put map in a fixed size box with right aspect ratio + // This two properties may more conveninet + // layoutCenter: [50%, 50%] + // layoutSize: 100 + + + // 数值合并方式,默认加和,可选为: + // 'sum' | 'average' | 'max' | 'min' + // mapValueCalculation: 'sum', + // 地图数值计算结果小数精度 + // mapValuePrecision: 0, + + + // 显示图例颜色标识(系列标识的小圆点),图例开启时有效 + showLegendSymbol: true, + // 选择模式,默认关闭,可选single,multiple + // selectedMode: false, + dataRangeHoverLink: true, + // 是否开启缩放及漫游模式 + // roam: false, + + // Define left-top, right-bottom coords to control view + // For example, [ [180, 90], [-180, -90] ], + // higher priority than center and zoom + boundingCoords: null, + + // Default on center of map + center: null, + + zoom: 1, + + scaleLimit: null, + + label: { + normal: { + show: false, + textStyle: { + color: '#000' + } + }, + emphasis: { + show: true, + textStyle: { + color: 'rgb(100,0,0)' + } + } + }, + // scaleLimit: null, + itemStyle: { + normal: { + // color: 各异, + borderWidth: 0.5, + borderColor: '#444', + areaColor: '#eee' + }, + // 也是选中样式 + emphasis: { + areaColor: 'rgba(255,215,0,0.8)' + } + } + } + + }); + + zrUtil.mixin(MapSeries, dataSelectableMixin); + + module.exports = MapSeries; + + +/***/ }, +/* 171 */ +/***/ function(module, exports, __webpack_require__) { + + + + var Geo = __webpack_require__(172); + + var layout = __webpack_require__(71); + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + + var mapDataStores = {}; + + /** + * Resize method bound to the geo + * @param {module:echarts/coord/geo/GeoModel|module:echarts/chart/map/MapModel} geoModel + * @param {module:echarts/ExtensionAPI} api + */ + function resizeGeo (geoModel, api) { + + var boundingCoords = geoModel.get('boundingCoords'); + if (boundingCoords != null) { + var leftTop = boundingCoords[0]; + var rightBottom = boundingCoords[1]; + if (isNaN(leftTop[0]) || isNaN(leftTop[1]) || isNaN(rightBottom[0]) || isNaN(rightBottom[1])) { + if (true) { + console.error('Invalid boundingCoords'); + } + } + else { + this.setBoundingRect(leftTop[0], leftTop[1], rightBottom[0] - leftTop[0], rightBottom[1] - leftTop[1]); + } + } + + var rect = this.getBoundingRect(); + + var boxLayoutOption; + + var center = geoModel.get('layoutCenter'); + var size = geoModel.get('layoutSize'); + + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + + var aspectScale = geoModel.get('aspectScale') || 0.75; + var aspect = rect.width / rect.height * aspectScale; + + var useCenterAndSize = false; + + if (center && size) { + center = [ + numberUtil.parsePercent(center[0], viewWidth), + numberUtil.parsePercent(center[1], viewHeight) + ]; + size = numberUtil.parsePercent(size, Math.min(viewWidth, viewHeight)); + + if (!isNaN(center[0]) && !isNaN(center[1]) && !isNaN(size)) { + useCenterAndSize = true; + } + else { + if (true) { + console.warn('Given layoutCenter or layoutSize data are invalid. Use left/top/width/height instead.'); + } + } + } + + var viewRect; + if (useCenterAndSize) { + var viewRect = {}; + if (aspect > 1) { + // Width is same with size + viewRect.width = size; + viewRect.height = size / aspect; + } + else { + viewRect.height = size; + viewRect.width = size * aspect; + } + viewRect.y = center[1] - viewRect.height / 2; + viewRect.x = center[0] - viewRect.width / 2; + } + else { + // Use left/top/width/height + boxLayoutOption = geoModel.getBoxLayoutParams(); + + // 0.75 rate + boxLayoutOption.aspect = aspect; + + viewRect = layout.getLayoutRect(boxLayoutOption, { + width: viewWidth, + height: viewHeight + }); + } + + this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height); + + this.setCenter(geoModel.get('center')); + this.setZoom(geoModel.get('zoom')); + } + + /** + * @param {module:echarts/coord/Geo} geo + * @param {module:echarts/model/Model} model + * @inner + */ + function setGeoCoords(geo, model) { + zrUtil.each(model.get('geoCoord'), function (geoCoord, name) { + geo.addGeoCoord(name, geoCoord); + }); + } + + if (true) { + var mapNotExistsError = function (name) { + //console.error('Map ' + name + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html'); + }; + } + + var geoCreator = { + + // For deciding which dimensions to use when creating list data + dimensions: Geo.prototype.dimensions, + + create: function (ecModel, api) { + var geoList = []; + + // FIXME Create each time may be slow + ecModel.eachComponent('geo', function (geoModel, idx) { + var name = geoModel.get('map'); + var mapData = mapDataStores[name]; + if (true) { + if (!mapData) { + mapNotExistsError(name); + } + } + var geo = new Geo( + name + idx, name, + mapData && mapData.geoJson, mapData && mapData.specialAreas, + geoModel.get('nameMap') + ); + geo.zoomLimit = geoModel.get('scaleLimit'); + geoList.push(geo); + + setGeoCoords(geo, geoModel); + + geoModel.coordinateSystem = geo; + geo.model = geoModel; + + // Inject resize method + geo.resize = resizeGeo; + + geo.resize(geoModel, api); + }); + + ecModel.eachSeries(function (seriesModel) { + var coordSys = seriesModel.get('coordinateSystem'); + if (coordSys === 'geo') { + var geoIndex = seriesModel.get('geoIndex') || 0; + seriesModel.coordinateSystem = geoList[geoIndex]; + } + }); + + // If has map series + var mapModelGroupBySeries = {}; + + ecModel.eachSeriesByType('map', function (seriesModel) { + if (!seriesModel.getHostGeoModel()) { + var mapType = seriesModel.getMapType(); + mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || []; + mapModelGroupBySeries[mapType].push(seriesModel); + } + }); + + zrUtil.each(mapModelGroupBySeries, function (mapSeries, mapType) { + var mapData = mapDataStores[mapType]; + if (true) { + if (!mapData) { + mapNotExistsError(mapSeries[0].get('map')); + } + } + + var nameMapList = zrUtil.map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('nameMap'); + }); + var geo = new Geo( + mapType, mapType, + mapData && mapData.geoJson, mapData && mapData.specialAreas, + zrUtil.mergeAll(nameMapList) + ); + geo.zoomLimit = zrUtil.retrieve.apply(null, zrUtil.map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('scaleLimit'); + })); + geoList.push(geo); + + // Inject resize method + geo.resize = resizeGeo; + + geo.resize(mapSeries[0], api); + + zrUtil.each(mapSeries, function (singleMapSeries) { + singleMapSeries.coordinateSystem = geo; + + setGeoCoords(geo, singleMapSeries); + }); + }); + + return geoList; + }, + + /** + * @param {string} mapName + * @param {Object|string} geoJson + * @param {Object} [specialAreas] + * + * @example + * $.get('USA.json', function (geoJson) { + * echarts.registerMap('USA', geoJson); + * // Or + * echarts.registerMap('USA', { + * geoJson: geoJson, + * specialAreas: {} + * }) + * }); + */ + registerMap: function (mapName, geoJson, specialAreas) { + if (geoJson.geoJson && !geoJson.features) { + specialAreas = geoJson.specialAreas; + geoJson = geoJson.geoJson; + } + if (typeof geoJson === 'string') { + geoJson = (typeof JSON !== 'undefined' && JSON.parse) + ? JSON.parse(geoJson) : (new Function('return (' + geoJson + ');'))(); + } + mapDataStores[mapName] = { + geoJson: geoJson, + specialAreas: specialAreas + }; + }, + + /** + * @param {string} mapName + * @return {Object} + */ + getMap: function (mapName) { + return mapDataStores[mapName]; + }, + + /** + * Fill given regions array + * @param {Array.} originRegionArr + * @param {string} mapName + * @return {Array} + */ + getFilledRegions: function (originRegionArr, mapName) { + // Not use the original + var regionsArr = (originRegionArr || []).slice(); + + var map = geoCreator.getMap(mapName); + var geoJson = map && map.geoJson; + if (!geoJson) { + if (true) { + mapNotExistsError(mapName); + } + return originRegionArr; + } + + var dataNameMap = zrUtil.createHashMap(); + var features = geoJson.features; + for (var i = 0; i < regionsArr.length; i++) { + dataNameMap.set(regionsArr[i].name, regionsArr[i]); + } + + for (var i = 0; i < features.length; i++) { + var name = features[i].properties.name; + if (!dataNameMap.get(name)) { + regionsArr.push({ + name: name + }); + } + } + return regionsArr; + } + }; + + // Inject methods into echarts + var echarts = __webpack_require__(1); + + echarts.registerMap = geoCreator.registerMap; + + echarts.getMap = geoCreator.getMap; + + echarts.parseGeoJSON = __webpack_require__(173); + + // TODO + echarts.loadMap = function () {}; + + echarts.registerCoordinateSystem('geo', geoCreator); + + module.exports = geoCreator; + + +/***/ }, +/* 172 */ +/***/ function(module, exports, __webpack_require__) { + + + + var parseGeoJson = __webpack_require__(173); + + var zrUtil = __webpack_require__(4); + + var BoundingRect = __webpack_require__(9); + + var View = __webpack_require__(176); + + + // Geo fix functions + var geoFixFuncs = [ + __webpack_require__(177), + __webpack_require__(178), + __webpack_require__(179), + __webpack_require__(180) + ]; + + /** + * [Geo description] + * @param {string} name Geo name + * @param {string} map Map type + * @param {Object} geoJson + * @param {Object} [specialAreas] + * Specify the positioned areas by left, top, width, height + * @param {Object.} [nameMap] + * Specify name alias + */ + function Geo(name, map, geoJson, specialAreas, nameMap) { + + View.call(this, name); + + /** + * Map type + * @type {string} + */ + this.map = map; + + this._nameCoordMap = zrUtil.createHashMap(); + + this.loadGeoJson(geoJson, specialAreas, nameMap); + } + + Geo.prototype = { + + constructor: Geo, + + type: 'geo', + + /** + * @param {Array.} + * @readOnly + */ + dimensions: ['lng', 'lat'], + + /** + * If contain given lng,lat coord + * @param {Array.} + * @readOnly + */ + containCoord: function (coord) { + var regions = this.regions; + for (var i = 0; i < regions.length; i++) { + if (regions[i].contain(coord)) { + return true; + } + } + return false; + }, + /** + * @param {Object} geoJson + * @param {Object} [specialAreas] + * Specify the positioned areas by left, top, width, height + * @param {Object.} [nameMap] + * Specify name alias + */ + loadGeoJson: function (geoJson, specialAreas, nameMap) { + // https://jsperf.com/try-catch-performance-overhead + try { + this.regions = geoJson ? parseGeoJson(geoJson) : []; + } + catch (e) { + throw 'Invalid geoJson format\n' + e.message; + } + specialAreas = specialAreas || {}; + nameMap = nameMap || {}; + var regions = this.regions; + var regionsMap = zrUtil.createHashMap(); + for (var i = 0; i < regions.length; i++) { + var regionName = regions[i].name; + // Try use the alias in nameMap + regionName = nameMap.hasOwnProperty(regionName) ? nameMap[regionName] : regionName; + regions[i].name = regionName; + + regionsMap.set(regionName, regions[i]); + // Add geoJson + this.addGeoCoord(regionName, regions[i].center); + + // Some area like Alaska in USA map needs to be tansformed + // to look better + var specialArea = specialAreas[regionName]; + if (specialArea) { + regions[i].transformTo( + specialArea.left, specialArea.top, specialArea.width, specialArea.height + ); + } + } + + this._regionsMap = regionsMap; + + this._rect = null; + + zrUtil.each(geoFixFuncs, function (fixFunc) { + fixFunc(this); + }, this); + }, + + // Overwrite + transformTo: function (x, y, width, height) { + var rect = this.getBoundingRect(); + + rect = rect.clone(); + // Longitute is inverted + rect.y = -rect.y - rect.height; + + var viewTransform = this._viewTransform; + + viewTransform.transform = rect.calculateTransform( + new BoundingRect(x, y, width, height) + ); + + viewTransform.decomposeTransform(); + + var scale = viewTransform.scale; + scale[1] = -scale[1]; + + viewTransform.updateTransform(); + + this._updateTransform(); + }, + + /** + * @param {string} name + * @return {module:echarts/coord/geo/Region} + */ + getRegion: function (name) { + return this._regionsMap.get(name); + }, + + getRegionByCoord: function (coord) { + var regions = this.regions; + for (var i = 0; i < regions.length; i++) { + if (regions[i].contain(coord)) { + return regions[i]; + } + } + }, + + /** + * Add geoCoord for indexing by name + * @param {string} name + * @param {Array.} geoCoord + */ + addGeoCoord: function (name, geoCoord) { + this._nameCoordMap.set(name, geoCoord); + }, + + /** + * Get geoCoord by name + * @param {string} name + * @return {Array.} + */ + getGeoCoord: function (name) { + return this._nameCoordMap.get(name); + }, + + // Overwrite + getBoundingRect: function () { + if (this._rect) { + return this._rect; + } + var rect; + + var regions = this.regions; + for (var i = 0; i < regions.length; i++) { + var regionRect = regions[i].getBoundingRect(); + rect = rect || regionRect.clone(); + rect.union(regionRect); + } + // FIXME Always return new ? + return (this._rect = rect || new BoundingRect(0, 0, 0, 0)); + }, + + /** + * Convert series data to a list of points + * @param {module:echarts/data/List} data + * @param {boolean} stack + * @return {Array} + * Return list of points. For example: + * `[[10, 10], [20, 20], [30, 30]]` + */ + dataToPoints: function (data) { + var item = []; + return data.mapArray(['lng', 'lat'], function (lon, lat) { + item[0] = lon; + item[1] = lat; + return this.dataToPoint(item); + }, this); + }, + + /** + * @param {string|Array.} data + * @return {Array.} + */ + dataToPoint: function (data) { + if (typeof data === 'string') { + // Map area name to geoCoord + data = this.getGeoCoord(data); + } + if (data) { + return View.prototype.dataToPoint.call(this, data); + } + }, + + /** + * @inheritDoc + */ + convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'), + + /** + * @inheritDoc + */ + convertFromPixel: zrUtil.curry(doConvert, 'pointToData') + + }; + + zrUtil.mixin(Geo, View); + + function doConvert(methodName, ecModel, finder, value) { + var geoModel = finder.geoModel; + var seriesModel = finder.seriesModel; + + var coordSys = geoModel + ? geoModel.coordinateSystem + : seriesModel + ? ( + seriesModel.coordinateSystem // For map. + || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem + ) + : null; + + return coordSys === this ? coordSys[methodName](value) : null; + } + + module.exports = Geo; + + +/***/ }, +/* 173 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Parse and decode geo json + * @module echarts/coord/geo/parseGeoJson + */ + + + var zrUtil = __webpack_require__(4); + + var Region = __webpack_require__(174); + + function decode(json) { + if (!json.UTF8Encoding) { + return json; + } + var encodeScale = json.UTF8Scale; + if (encodeScale == null) { + encodeScale = 1024; + } + + var features = json.features; + + for (var f = 0; f < features.length; f++) { + var feature = features[f]; + var geometry = feature.geometry; + var coordinates = geometry.coordinates; + var encodeOffsets = geometry.encodeOffsets; + + for (var c = 0; c < coordinates.length; c++) { + var coordinate = coordinates[c]; + + if (geometry.type === 'Polygon') { + coordinates[c] = decodePolygon( + coordinate, + encodeOffsets[c], + encodeScale + ); + } + else if (geometry.type === 'MultiPolygon') { + for (var c2 = 0; c2 < coordinate.length; c2++) { + var polygon = coordinate[c2]; + coordinate[c2] = decodePolygon( + polygon, + encodeOffsets[c][c2], + encodeScale + ); + } + } + } + } + // Has been decoded + json.UTF8Encoding = false; + return json; + } + + function decodePolygon(coordinate, encodeOffsets, encodeScale) { + var result = []; + var prevX = encodeOffsets[0]; + var prevY = encodeOffsets[1]; + + for (var i = 0; i < coordinate.length; i += 2) { + var x = coordinate.charCodeAt(i) - 64; + var y = coordinate.charCodeAt(i + 1) - 64; + // ZigZag decoding + x = (x >> 1) ^ (-(x & 1)); + y = (y >> 1) ^ (-(y & 1)); + // Delta deocding + x += prevX; + y += prevY; + + prevX = x; + prevY = y; + // Dequantize + result.push([x / encodeScale, y / encodeScale]); + } + + return result; + } + + /** + * @alias module:echarts/coord/geo/parseGeoJson + * @param {Object} geoJson + * @return {module:zrender/container/Group} + */ + module.exports = function (geoJson) { + + decode(geoJson); + + return zrUtil.map(zrUtil.filter(geoJson.features, function (featureObj) { + // Output of mapshaper may have geometry null + return featureObj.geometry + && featureObj.properties + && featureObj.geometry.coordinates.length > 0; + }), function (featureObj) { + var properties = featureObj.properties; + var geo = featureObj.geometry; + + var coordinates = geo.coordinates; + + var geometries = []; + if (geo.type === 'Polygon') { + geometries.push({ + type: 'polygon', + // According to the GeoJSON specification. + // First must be exterior, and the rest are all interior(holes). + exterior: coordinates[0], + interiors: coordinates.slice(1) + }); + } + if (geo.type === 'MultiPolygon') { + zrUtil.each(coordinates, function (item) { + if (item[0]) { + geometries.push({ + type: 'polygon', + exterior: item[0], + interiors: item.slice(1) + }); + } + }); + } + + var region = new Region( + properties.name, + geometries, + properties.cp + ); + region.properties = properties; + return region; + }); + }; + + +/***/ }, +/* 174 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/coord/geo/Region + */ + + + var polygonContain = __webpack_require__(175); + + var BoundingRect = __webpack_require__(9); + + var bbox = __webpack_require__(38); + var vec2 = __webpack_require__(10); + + /** + * @param {string} name + * @param {Array} geometries + * @param {Array.} cp + */ + function Region(name, geometries, cp) { + + /** + * @type {string} + * @readOnly + */ + this.name = name; + + /** + * @type {Array.} + * @readOnly + */ + this.geometries = geometries; + + if (!cp) { + var rect = this.getBoundingRect(); + cp = [ + rect.x + rect.width / 2, + rect.y + rect.height / 2 + ]; + } + else { + cp = [cp[0], cp[1]]; + } + /** + * @type {Array.} + */ + this.center = cp; + } + + Region.prototype = { + + constructor: Region, + + properties: null, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getBoundingRect: function () { + var rect = this._rect; + if (rect) { + return rect; + } + + var MAX_NUMBER = Number.MAX_VALUE; + var min = [MAX_NUMBER, MAX_NUMBER]; + var max = [-MAX_NUMBER, -MAX_NUMBER]; + var min2 = []; + var max2 = []; + var geometries = this.geometries; + for (var i = 0; i < geometries.length; i++) { + // Only support polygon + if (geometries[i].type !== 'polygon') { + continue; + } + // Doesn't consider hole + var exterior = geometries[i].exterior; + bbox.fromPoints(exterior, min2, max2); + vec2.min(min, min, min2); + vec2.max(max, max, max2); + } + // No data + if (i === 0) { + min[0] = min[1] = max[0] = max[1] = 0; + } + + return (this._rect = new BoundingRect( + min[0], min[1], max[0] - min[0], max[1] - min[1] + )); + }, + + /** + * @param {} coord + * @return {boolean} + */ + contain: function (coord) { + var rect = this.getBoundingRect(); + var geometries = this.geometries; + if (!rect.contain(coord[0], coord[1])) { + return false; + } + loopGeo: for (var i = 0, len = geometries.length; i < len; i++) { + // Only support polygon. + if (geometries[i].type !== 'polygon') { + continue; + } + var exterior = geometries[i].exterior; + var interiors = geometries[i].interiors; + if (polygonContain.contain(exterior, coord[0], coord[1])) { + // Not in the region if point is in the hole. + for (var k = 0; k < (interiors ? interiors.length : 0); k++) { + if (polygonContain.contain(interiors[k])) { + continue loopGeo; + } + } + return true; + } + } + return false; + }, + + transformTo: function (x, y, width, height) { + var rect = this.getBoundingRect(); + var aspect = rect.width / rect.height; + if (!width) { + width = aspect * height; + } + else if (!height) { + height = width / aspect ; + } + var target = new BoundingRect(x, y, width, height); + var transform = rect.calculateTransform(target); + var geometries = this.geometries; + for (var i = 0; i < geometries.length; i++) { + // Only support polygon. + if (geometries[i].type !== 'polygon') { + continue; + } + var exterior = geometries[i].exterior; + var interiors = geometries[i].interiors; + for (var p = 0; p < exterior.length; p++) { + vec2.applyTransform(exterior[p], exterior[p], transform); + } + for (var h = 0; h < (interiors ? interiors.length : 0); h++) { + for (var p = 0; p < interiors[h].length; p++) { + vec2.applyTransform(interiors[h][p], interiors[h][p], transform); + } + } + } + rect = this._rect; + rect.copy(target); + // Update center + this.center = [ + rect.x + rect.width / 2, + rect.y + rect.height / 2 + ]; + } + }; + + module.exports = Region; + + +/***/ }, +/* 175 */ +/***/ function(module, exports, __webpack_require__) { + + + + var windingLine = __webpack_require__(45); + + var EPSILON = 1e-8; + + function isAroundEqual(a, b) { + return Math.abs(a - b) < EPSILON; + } + + function contain(points, x, y) { + var w = 0; + var p = points[0]; + + if (!p) { + return false; + } + + for (var i = 1; i < points.length; i++) { + var p2 = points[i]; + w += windingLine(p[0], p[1], p2[0], p2[1], x, y); + p = p2; + } + + // Close polygon + var p0 = points[0]; + if (!isAroundEqual(p[0], p0[0]) || !isAroundEqual(p[1], p0[1])) { + w += windingLine(p[0], p[1], p0[0], p0[1], x, y); + } + + return w !== 0; + } + + + module.exports = { + contain: contain + }; + + +/***/ }, +/* 176 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Simple view coordinate system + * Mapping given x, y to transformd view x, y + */ + + + var vector = __webpack_require__(10); + var matrix = __webpack_require__(11); + + var Transformable = __webpack_require__(26); + var zrUtil = __webpack_require__(4); + + var BoundingRect = __webpack_require__(9); + + var v2ApplyTransform = vector.applyTransform; + + // Dummy transform node + function TransformDummy() { + Transformable.call(this); + } + zrUtil.mixin(TransformDummy, Transformable); + + function View(name) { + /** + * @type {string} + */ + this.name = name; + + /** + * @type {Object} + */ + this.zoomLimit; + + Transformable.call(this); + + this._roamTransform = new TransformDummy(); + + this._viewTransform = new TransformDummy(); + + this._center; + this._zoom; + } + + View.prototype = { + + constructor: View, + + type: 'view', + + /** + * @param {Array.} + * @readOnly + */ + dimensions: ['x', 'y'], + + /** + * Set bounding rect + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + */ + + // PENDING to getRect + setBoundingRect: function (x, y, width, height) { + this._rect = new BoundingRect(x, y, width, height); + return this._rect; + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + // PENDING to getRect + getBoundingRect: function () { + return this._rect; + }, + + /** + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + */ + setViewRect: function (x, y, width, height) { + this.transformTo(x, y, width, height); + this._viewRect = new BoundingRect(x, y, width, height); + }, + + /** + * Transformed to particular position and size + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + */ + transformTo: function (x, y, width, height) { + var rect = this.getBoundingRect(); + var viewTransform = this._viewTransform; + + viewTransform.transform = rect.calculateTransform( + new BoundingRect(x, y, width, height) + ); + + viewTransform.decomposeTransform(); + + this._updateTransform(); + }, + + /** + * Set center of view + * @param {Array.} [centerCoord] + */ + setCenter: function (centerCoord) { + if (!centerCoord) { + return; + } + this._center = centerCoord; + + this._updateCenterAndZoom(); + }, + + /** + * @param {number} zoom + */ + setZoom: function (zoom) { + zoom = zoom || 1; + + var zoomLimit = this.zoomLimit; + if (zoomLimit) { + if (zoomLimit.max != null) { + zoom = Math.min(zoomLimit.max, zoom); + } + if (zoomLimit.min != null) { + zoom = Math.max(zoomLimit.min, zoom); + } + } + this._zoom = zoom; + + this._updateCenterAndZoom(); + }, + + /** + * Get default center without roam + */ + getDefaultCenter: function () { + // Rect before any transform + var rawRect = this.getBoundingRect(); + var cx = rawRect.x + rawRect.width / 2; + var cy = rawRect.y + rawRect.height / 2; + + return [cx, cy]; + }, + + getCenter: function () { + return this._center || this.getDefaultCenter(); + }, + + getZoom: function () { + return this._zoom || 1; + }, + + /** + * @return {Array.} data + * @return {Array.} + */ + dataToPoint: function (data) { + var transform = this.transform; + return transform + ? v2ApplyTransform([], data, transform) + : [data[0], data[1]]; + }, + + /** + * Convert a (x, y) point to (lon, lat) data + * @param {Array.} point + * @return {Array.} + */ + pointToData: function (point) { + var invTransform = this.invTransform; + return invTransform + ? v2ApplyTransform([], point, invTransform) + : [point[0], point[1]]; + }, + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'), + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + convertFromPixel: zrUtil.curry(doConvert, 'pointToData'), + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + containPoint: function (point) { + return this.getViewRectAfterRoam().contain(point[0], point[1]); + } + + /** + * @return {number} + */ + // getScalarScale: function () { + // // Use determinant square root of transform to mutiply scalar + // var m = this.transform; + // var det = Math.sqrt(Math.abs(m[0] * m[3] - m[2] * m[1])); + // return det; + // } + }; + + zrUtil.mixin(View, Transformable); + + function doConvert(methodName, ecModel, finder, value) { + var seriesModel = finder.seriesModel; + var coordSys = seriesModel ? seriesModel.coordinateSystem : null; // e.g., graph. + return coordSys === this ? coordSys[methodName](value) : null; + } + + module.exports = View; + + +/***/ }, +/* 177 */ +/***/ function(module, exports, __webpack_require__) { + + // Fix for 南海诸岛 + + + var Region = __webpack_require__(174); + var zrUtil = __webpack_require__(4); + + var geoCoord = [126, 25]; + + var points = [ + [[0,3.5],[7,11.2],[15,11.9],[30,7],[42,0.7],[52,0.7], + [56,7.7],[59,0.7],[64,0.7],[64,0],[5,0],[0,3.5]], + [[13,16.1],[19,14.7],[16,21.7],[11,23.1],[13,16.1]], + [[12,32.2],[14,38.5],[15,38.5],[13,32.2],[12,32.2]], + [[16,47.6],[12,53.2],[13,53.2],[18,47.6],[16,47.6]], + [[6,64.4],[8,70],[9,70],[8,64.4],[6,64.4]], + [[23,82.6],[29,79.8],[30,79.8],[25,82.6],[23,82.6]], + [[37,70.7],[43,62.3],[44,62.3],[39,70.7],[37,70.7]], + [[48,51.1],[51,45.5],[53,45.5],[50,51.1],[48,51.1]], + [[51,35],[51,28.7],[53,28.7],[53,35],[51,35]], + [[52,22.4],[55,17.5],[56,17.5],[53,22.4],[52,22.4]], + [[58,12.6],[62,7],[63,7],[60,12.6],[58,12.6]], + [[0,3.5],[0,93.1],[64,93.1],[64,0],[63,0],[63,92.4], + [1,92.4],[1,3.5],[0,3.5]] + ]; + for (var i = 0; i < points.length; i++) { + for (var k = 0; k < points[i].length; k++) { + points[i][k][0] /= 10.5; + points[i][k][1] /= -10.5 / 0.75; + + points[i][k][0] += geoCoord[0]; + points[i][k][1] += geoCoord[1]; + } + } + module.exports = function (geo) { + if (geo.map === 'china') { + geo.regions.push(new Region( + '南海诸岛', + zrUtil.map(points, function (exterior) { + return { + type: 'polygon', + exterior: exterior + }; + }), geoCoord + )); + } + }; + + +/***/ }, +/* 178 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var coordsOffsetMap = { + '南海诸岛' : [32, 80], + // 全国 + '广东': [0, -10], + '香港': [10, 5], + '澳门': [-10, 10], + //'北京': [-10, 0], + '天津': [5, 5] + }; + + module.exports = function (geo) { + zrUtil.each(geo.regions, function (region) { + var coordFix = coordsOffsetMap[region.name]; + if (coordFix) { + var cp = region.center; + cp[0] += coordFix[0] / 10.5; + cp[1] += -coordFix[1] / (10.5 / 0.75); + } + }); + }; + + +/***/ }, +/* 179 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var geoCoordMap = { + 'Russia': [100, 60], + 'United States': [-99, 38], + 'United States of America': [-99, 38] + }; + + module.exports = function (geo) { + zrUtil.each(geo.regions, function (region) { + var geoCoord = geoCoordMap[region.name]; + if (geoCoord) { + var cp = region.center; + cp[0] = geoCoord[0]; + cp[1] = geoCoord[1]; + } + }); + }; + + +/***/ }, +/* 180 */ +/***/ function(module, exports, __webpack_require__) { + + // Fix for 钓鱼岛 + + + var Region = __webpack_require__(174); + var zrUtil = __webpack_require__(4); + + var geoCoord = [126, 25]; + + var points = [ + [ + [123.45165252685547, 25.73527164402261], + [123.49731445312499, 25.73527164402261], + [123.49731445312499, 25.750734064600884], + [123.45165252685547, 25.750734064600884], + [123.45165252685547, 25.73527164402261] + ] + ]; + module.exports = function (geo) { + if (geo.map === 'china') { + for (var i = 0, len = geo.regions.length; i < len; ++i) { + if (geo.regions[i].name === '台湾') { + geo.regions[i].geometries.push({ + type: 'polygon', + exterior: points[0] + }); + } + } + } + }; + + + +/***/ }, +/* 181 */ +/***/ function(module, exports, __webpack_require__) { + + + + // var zrUtil = require('zrender/lib/core/util'); + var graphic = __webpack_require__(18); + + var MapDraw = __webpack_require__(182); + + __webpack_require__(1).extendChartView({ + + type: 'map', + + render: function (mapModel, ecModel, api, payload) { + // Not render if it is an toggleSelect action from self + if (payload && payload.type === 'mapToggleSelect' + && payload.from === this.uid + ) { + return; + } + + var group = this.group; + group.removeAll(); + + if (mapModel.getHostGeoModel()) { + return; + } + + // Not update map if it is an roam action from self + if (!(payload && payload.type === 'geoRoam' + && payload.componentType === 'series' + && payload.seriesId === mapModel.id + ) + ) { + if (mapModel.needsDrawMap) { + var mapDraw = this._mapDraw || new MapDraw(api, true); + group.add(mapDraw.group); + + mapDraw.draw(mapModel, ecModel, api, this, payload); + + this._mapDraw = mapDraw; + } + else { + // Remove drawed map + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + } + } + else { + var mapDraw = this._mapDraw; + mapDraw && group.add(mapDraw.group); + } + + mapModel.get('showLegendSymbol') && ecModel.getComponent('legend') + && this._renderSymbols(mapModel, ecModel, api); + }, + + remove: function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + this.group.removeAll(); + }, + + dispose: function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + }, + + _renderSymbols: function (mapModel, ecModel, api) { + var originalData = mapModel.originalData; + var group = this.group; + + originalData.each('value', function (value, idx) { + if (isNaN(value)) { + return; + } + + var layout = originalData.getItemLayout(idx); + + if (!layout || !layout.point) { + // Not exists in map + return; + } + + var point = layout.point; + var offset = layout.offset; + + var circle = new graphic.Circle({ + style: { + // Because the special of map draw. + // Which needs statistic of multiple series and draw on one map. + // And each series also need a symbol with legend color + // + // Layout and visual are put one the different data + fill: mapModel.getData().getVisual('color') + }, + shape: { + cx: point[0] + offset * 9, + cy: point[1], + r: 3 + }, + silent: true, + z2: 10 + }); + + // First data on the same region + if (!offset) { + var fullData = mapModel.mainSeries.getData(); + var name = originalData.getName(idx); + var labelText = name; + var fullIndex = fullData.indexOfName(name); + + var itemModel = originalData.getItemModel(idx); + var labelModel = itemModel.getModel('label.normal'); + var hoverLabelModel = itemModel.getModel('label.emphasis'); + + var textStyleModel = labelModel.getModel('textStyle'); + var hoverTextStyleModel = hoverLabelModel.getModel('textStyle'); + + var polygonGroups = fullData.getItemGraphicEl(fullIndex); + circle.setStyle({ + textPosition: 'bottom' + }); + + var onEmphasis = function () { + circle.setStyle({ + text: hoverLabelModel.get('show') ? labelText : '', + textFill: hoverTextStyleModel.getTextColor(), + textFont: hoverTextStyleModel.getFont() + }); + }; + + var onNormal = function () { + circle.setStyle({ + text: labelModel.get('show') ? labelText : '', + textFill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont() + }); + }; + + polygonGroups.on('mouseover', onEmphasis) + .on('mouseout', onNormal) + .on('emphasis', onEmphasis) + .on('normal', onNormal); + + onNormal(); + } + + group.add(circle); + }); + } + }); + + +/***/ }, +/* 182 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/component/helper/MapDraw + */ + + + var RoamController = __webpack_require__(183); + var roamHelper = __webpack_require__(185); + var cursorHelper = __webpack_require__(186); + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + + function getFixedItemStyle(model, scale) { + var itemStyle = model.getItemStyle(); + var areaColor = model.get('areaColor'); + + // If user want the color not to be changed when hover, + // they should both set areaColor and color to be null. + if (areaColor != null) { + itemStyle.fill = areaColor; + } + + return itemStyle; + } + + function updateMapSelectHandler(mapDraw, mapOrGeoModel, group, api, fromView) { + group.off('click'); + group.off('mousedown'); + + if (mapOrGeoModel.get('selectedMode')) { + + group.on('mousedown', function () { + mapDraw._mouseDownFlag = true; + }); + + group.on('click', function (e) { + if (!mapDraw._mouseDownFlag) { + return; + } + mapDraw._mouseDownFlag = false; + + var el = e.target; + while (!el.__regions) { + el = el.parent; + } + if (!el) { + return; + } + + var action = { + type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect', + batch: zrUtil.map(el.__regions, function (region) { + return { + name: region.name, + from: fromView.uid + }; + }) + }; + action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id; + + api.dispatchAction(action); + + updateMapSelected(mapOrGeoModel, group); + }); + } + } + + function updateMapSelected(mapOrGeoModel, group) { + // FIXME + group.eachChild(function (otherRegionEl) { + zrUtil.each(otherRegionEl.__regions, function (region) { + otherRegionEl.trigger(mapOrGeoModel.isSelected(region.name) ? 'emphasis' : 'normal'); + }); + }); + } + + /** + * @alias module:echarts/component/helper/MapDraw + * @param {module:echarts/ExtensionAPI} api + * @param {boolean} updateGroup + */ + function MapDraw(api, updateGroup) { + + var group = new graphic.Group(); + + /** + * @type {module:echarts/component/helper/RoamController} + * @private + */ + this._controller = new RoamController(api.getZr()); + + /** + * @type {Object} {target, zoom, zoomLimit} + * @private + */ + this._controllerHost = {target: updateGroup ? group : null}; + + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = group; + + /** + * @type {boolean} + * @private + */ + this._updateGroup = updateGroup; + + /** + * This flag is used to make sure that only one among + * `pan`, `zoom`, `click` can occurs, otherwise 'selected' + * action may be triggered when `pan`, which is unexpected. + * @type {booelan} + */ + this._mouseDownFlag; + } + + MapDraw.prototype = { + + constructor: MapDraw, + + draw: function (mapOrGeoModel, ecModel, api, fromView, payload) { + + var isGeo = mapOrGeoModel.mainType === 'geo'; + + // map series has data, geo model that controlled by map series + // has no data, otherwise data exists. + var data = mapOrGeoModel.getData && mapOrGeoModel.getData(); + isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries) { + if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) { + data = mapSeries.getData(); + } + }); + + var geo = mapOrGeoModel.coordinateSystem; + + var group = this.group; + + var scale = geo.scale; + var groupNewProp = { + position: geo.position, + scale: scale + }; + + // No animation when first draw or in action + if (!group.childAt(0) || payload) { + group.attr(groupNewProp); + } + else { + graphic.updateProps(group, groupNewProp, mapOrGeoModel); + } + + group.removeAll(); + + var itemStyleAccessPath = ['itemStyle', 'normal']; + var hoverItemStyleAccessPath = ['itemStyle', 'emphasis']; + var labelAccessPath = ['label', 'normal']; + var hoverLabelAccessPath = ['label', 'emphasis']; + var nameMap = zrUtil.createHashMap(); + + zrUtil.each(geo.regions, function (region) { + + // Consider in GeoJson properties.name may be duplicated, for example, + // there is multiple region named "United Kindom" or "France" (so many + // colonies). And it is not appropriate to merge them in geo, which + // will make them share the same label and bring trouble in label + // location calculation. + var regionGroup = nameMap.get(region.name) + || nameMap.set(region.name, new graphic.Group()); + + var compoundPath = new graphic.CompoundPath({ + shape: { + paths: [] + } + }); + regionGroup.add(compoundPath); + + var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel; + + var itemStyleModel = regionModel.getModel(itemStyleAccessPath); + var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath); + var itemStyle = getFixedItemStyle(itemStyleModel, scale); + var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel, scale); + + var labelModel = regionModel.getModel(labelAccessPath); + var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath); + + var dataIdx; + // Use the itemStyle in data if has data + if (data) { + dataIdx = data.indexOfName(region.name); + // Only visual color of each item will be used. It can be encoded by dataRange + // But visual color of series is used in symbol drawing + // + // Visual color for each series is for the symbol draw + var visualColor = data.getItemVisual(dataIdx, 'color', true); + if (visualColor) { + itemStyle.fill = visualColor; + } + } + + var textStyleModel = labelModel.getModel('textStyle'); + var hoverTextStyleModel = hoverLabelModel.getModel('textStyle'); + + zrUtil.each(region.geometries, function (geometry) { + if (geometry.type !== 'polygon') { + return; + } + compoundPath.shape.paths.push(new graphic.Polygon({ + shape: { + points: geometry.exterior + } + })); + + for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); i++) { + compoundPath.shape.paths.push(new graphic.Polygon({ + shape: { + points: geometry.interiors[i] + } + })); + } + }); + + compoundPath.setStyle(itemStyle); + compoundPath.style.strokeNoScale = true; + compoundPath.culling = true; + // Label + var showLabel = labelModel.get('show'); + var hoverShowLabel = hoverLabelModel.get('show'); + + var isDataNaN = data && isNaN(data.get('value', dataIdx)); + var itemLayout = data && data.getItemLayout(dataIdx); + // In the following cases label will be drawn + // 1. In map series and data value is NaN + // 2. In geo component + // 4. Region has no series legendSymbol, which will be add a showLabel flag in mapSymbolLayout + if ( + (isGeo || isDataNaN && (showLabel || hoverShowLabel)) + || (itemLayout && itemLayout.showLabel) + ) { + var query = data ? dataIdx : region.name; + var formattedStr = mapOrGeoModel.getFormattedLabel(query, 'normal'); + var hoverFormattedStr = mapOrGeoModel.getFormattedLabel(query, 'emphasis'); + var text = new graphic.Text({ + style: { + text: showLabel ? (formattedStr || region.name) : '', + fill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont(), + textAlign: 'center', + textVerticalAlign: 'middle' + }, + hoverStyle: { + text: hoverShowLabel ? (hoverFormattedStr || region.name) : '', + fill: hoverTextStyleModel.getTextColor(), + textFont: hoverTextStyleModel.getFont() + }, + position: region.center.slice(), + scale: [1 / scale[0], 1 / scale[1]], + z2: 10, + silent: true + }); + + regionGroup.add(text); + } + + // setItemGraphicEl, setHoverStyle after all polygons and labels + // are added to the rigionGroup + if (data) { + data.setItemGraphicEl(dataIdx, regionGroup); + } + else { + var regionModel = mapOrGeoModel.getRegionModel(region.name); + // Package custom mouse event for geo component + compoundPath.eventData = { + componentType: 'geo', + geoIndex: mapOrGeoModel.componentIndex, + name: region.name, + region: (regionModel && regionModel.option) || {} + }; + } + + var groupRegions = regionGroup.__regions || (regionGroup.__regions = []); + groupRegions.push(region); + + graphic.setHoverStyle( + regionGroup, + hoverItemStyle, + {hoverSilentOnTouch: !!mapOrGeoModel.get('selectedMode')} + ); + + group.add(regionGroup); + }); + + this._updateController(mapOrGeoModel, ecModel, api); + + updateMapSelectHandler(this, mapOrGeoModel, group, api, fromView); + + updateMapSelected(mapOrGeoModel, group); + }, + + remove: function () { + this.group.removeAll(); + this._controller.dispose(); + this._controllerHost = {}; + }, + + _updateController: function (mapOrGeoModel, ecModel, api) { + var geo = mapOrGeoModel.coordinateSystem; + var controller = this._controller; + var controllerHost = this._controllerHost; + + controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit'); + controllerHost.zoom = geo.getZoom(); + + // roamType is will be set default true if it is null + controller.enable(mapOrGeoModel.get('roam') || false); + var mainType = mapOrGeoModel.mainType; + + function makeActionBase() { + var action = { + type: 'geoRoam', + componentType: mainType + }; + action[mainType + 'Id'] = mapOrGeoModel.id; + return action; + } + + controller.off('pan').on('pan', function (dx, dy) { + this._mouseDownFlag = false; + + roamHelper.updateViewOnPan(controllerHost, dx, dy); + + api.dispatchAction(zrUtil.extend(makeActionBase(), { + dx: dx, + dy: dy + })); + }, this); + + controller.off('zoom').on('zoom', function (zoom, mouseX, mouseY) { + this._mouseDownFlag = false; + + roamHelper.updateViewOnZoom(controllerHost, zoom, mouseX, mouseY); + + api.dispatchAction(zrUtil.extend(makeActionBase(), { + zoom: zoom, + originX: mouseX, + originY: mouseY + })); + + if (this._updateGroup) { + var group = this.group; + var scale = group.scale; + group.traverse(function (el) { + if (el.type === 'text') { + el.attr('scale', [1 / scale[0], 1 / scale[1]]); + } + }); + } + }, this); + + controller.setPointerChecker(function (e, x, y) { + return geo.getViewRectAfterRoam().contain(x, y) + && !cursorHelper.onIrrelevantElement(e, api, mapOrGeoModel); + }); + } + }; + + module.exports = MapDraw; + + +/***/ }, +/* 183 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/component/helper/RoamController + */ + + + var Eventful = __webpack_require__(25); + var zrUtil = __webpack_require__(4); + var eventTool = __webpack_require__(88); + var interactionMutex = __webpack_require__(184); + + /** + * @alias module:echarts/component/helper/RoamController + * @constructor + * @mixin {module:zrender/mixin/Eventful} + * + * @param {module:zrender/zrender~ZRender} zr + */ + function RoamController(zr) { + + /** + * @type {Function} + */ + this.pointerChecker; + + /** + * @type {module:zrender} + */ + this._zr = zr; + + /** + * @type {Object} + */ + this._opt = {}; + + // Avoid two roamController bind the same handler + var bind = zrUtil.bind; + var mousedownHandler = bind(mousedown, this); + var mousemoveHandler = bind(mousemove, this); + var mouseupHandler = bind(mouseup, this); + var mousewheelHandler = bind(mousewheel, this); + var pinchHandler = bind(pinch, this); + + Eventful.call(this); + + /** + * @param {Function} pointerChecker + * input: x, y + * output: boolean + */ + this.setPointerChecker = function (pointerChecker) { + this.pointerChecker = pointerChecker; + }; + + /** + * Notice: only enable needed types. For example, if 'zoom' + * is not needed, 'zoom' should not be enabled, otherwise + * default mousewheel behaviour (scroll page) will be disabled. + * + * @param {boolean|string} [controlType=true] Specify the control type, + * which can be null/undefined or true/false + * or 'pan/move' or 'zoom'/'scale' + * @param {Object} [opt] + * @param {Object} [opt.zoomOnMouseWheel=true] + * @param {Object} [opt.moveOnMouseMove=true] + * @param {Object} [opt.preventDefaultMouseMove=true] When pan. + */ + this.enable = function (controlType, opt) { + + // Disable previous first + this.disable(); + + this._opt = zrUtil.defaults(zrUtil.clone(opt) || {}, { + zoomOnMouseWheel: true, + moveOnMouseMove: true, + preventDefaultMouseMove: true + }); + + if (controlType == null) { + controlType = true; + } + + if (controlType === true || (controlType === 'move' || controlType === 'pan')) { + zr.on('mousedown', mousedownHandler); + zr.on('mousemove', mousemoveHandler); + zr.on('mouseup', mouseupHandler); + } + if (controlType === true || (controlType === 'scale' || controlType === 'zoom')) { + zr.on('mousewheel', mousewheelHandler); + zr.on('pinch', pinchHandler); + } + }; + + this.disable = function () { + zr.off('mousedown', mousedownHandler); + zr.off('mousemove', mousemoveHandler); + zr.off('mouseup', mouseupHandler); + zr.off('mousewheel', mousewheelHandler); + zr.off('pinch', pinchHandler); + }; + + this.dispose = this.disable; + + this.isDragging = function () { + return this._dragging; + }; + + this.isPinching = function () { + return this._pinching; + }; + } + + zrUtil.mixin(RoamController, Eventful); + + + function mousedown(e) { + if (e.target && e.target.draggable) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + + // Only check on mosedown, but not mousemove. + // Mouse can be out of target when mouse moving. + if (this.pointerChecker && this.pointerChecker(e, x, y)) { + this._x = x; + this._y = y; + this._dragging = true; + } + } + + function mousemove(e) { + if (!checkKeyBinding(this, 'moveOnMouseMove', e) || !this._dragging) { + return; + } + + if (e.gestureEvent === 'pinch') { + return; + } + + if (interactionMutex.isTaken(this._zr, 'globalPan')) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + + var oldX = this._x; + var oldY = this._y; + + var dx = x - oldX; + var dy = y - oldY; + + this._x = x; + this._y = y; + + this._opt.preventDefaultMouseMove && eventTool.stop(e.event); + + this.trigger('pan', dx, dy, oldX, oldY, x, y); + } + + function mouseup(e) { + this._dragging = false; + } + + function mousewheel(e) { + // wheelDelta maybe -0 in chrome mac. + if (!checkKeyBinding(this, 'zoomOnMouseWheel', e) || e.wheelDelta === 0) { + return; + } + + // Convenience: + // Mac and VM Windows on Mac: scroll up: zoom out. + // Windows: scroll up: zoom in. + var zoomDelta = e.wheelDelta > 0 ? 1.1 : 1 / 1.1; + zoom.call(this, e, zoomDelta, e.offsetX, e.offsetY); + } + + function pinch(e) { + if (interactionMutex.isTaken(this._zr, 'globalPan')) { + return; + } + var zoomDelta = e.pinchScale > 1 ? 1.1 : 1 / 1.1; + zoom.call(this, e, zoomDelta, e.pinchX, e.pinchY); + } + + function zoom(e, zoomDelta, zoomX, zoomY) { + if (this.pointerChecker && this.pointerChecker(e, zoomX, zoomY)) { + // When mouse is out of roamController rect, + // default befavoius should not be be disabled, otherwise + // page sliding is disabled, contrary to expectation. + eventTool.stop(e.event); + + this.trigger('zoom', zoomDelta, zoomX, zoomY); + } + } + + function checkKeyBinding(roamController, prop, e) { + var setting = roamController._opt[prop]; + return setting + && (!zrUtil.isString(setting) || e.event[setting + 'Key']); + } + + module.exports = RoamController; + + +/***/ }, +/* 184 */ +/***/ function(module, exports, __webpack_require__) { + + + + var ATTR = '\0_ec_interaction_mutex'; + + var interactionMutex = { + + take: function (zr, resourceKey, userKey) { + var store = getStore(zr); + store[resourceKey] = userKey; + }, + + release: function (zr, resourceKey, userKey) { + var store = getStore(zr); + var uKey = store[resourceKey]; + + if (uKey === userKey) { + store[resourceKey] = null; + } + }, + + isTaken: function (zr, resourceKey) { + return !!getStore(zr)[resourceKey]; + } + }; + + function getStore(zr) { + return zr[ATTR] || (zr[ATTR] = {}); + } + + /** + * payload: { + * type: 'takeGlobalCursor', + * key: 'dataZoomSelect', or 'brush', or ..., + * If no userKey, release global cursor. + * } + */ + __webpack_require__(1).registerAction( + {type: 'takeGlobalCursor', event: 'globalCursorTaken', update: 'update'}, + function () {} + ); + + module.exports = interactionMutex; + + +/***/ }, +/* 185 */ +/***/ function(module, exports) { + + + + var helper = {}; + + /** + * For geo and graph. + * + * @param {Object} controllerHost + * @param {module:zrender/Element} controllerHost.target + */ + helper.updateViewOnPan = function (controllerHost, dx, dy) { + var target = controllerHost.target; + var pos = target.position; + pos[0] += dx; + pos[1] += dy; + target.dirty(); + }; + + /** + * For geo and graph. + * + * @param {Object} controllerHost + * @param {module:zrender/Element} controllerHost.target + * @param {number} controllerHost.zoom + * @param {number} controllerHost.zoomLimit like: {min: 1, max: 2} + */ + helper.updateViewOnZoom = function (controllerHost, zoomDelta, zoomX, zoomY) { + var target = controllerHost.target; + var zoomLimit = controllerHost.zoomLimit; + var pos = target.position; + var scale = target.scale; + + var newZoom = controllerHost.zoom = controllerHost.zoom || 1; + newZoom *= zoomDelta; + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + newZoom = Math.max( + Math.min(zoomMax, newZoom), + zoomMin + ); + } + var zoomScale = newZoom / controllerHost.zoom; + controllerHost.zoom = newZoom; + // Keep the mouse center when scaling + pos[0] -= (zoomX - pos[0]) * (zoomScale - 1); + pos[1] -= (zoomY - pos[1]) * (zoomScale - 1); + scale[0] *= zoomScale; + scale[1] *= zoomScale; + + target.dirty(); + }; + + module.exports = helper; + + +/***/ }, +/* 186 */ +/***/ function(module, exports) { + + + + var helper = {}; + + var IRRELEVANT_EXCLUDES = {'axisPointer': 1, 'tooltip': 1, 'brush': 1}; + + /** + * Avoid that: mouse click on a elements that is over geo or graph, + * but roam is triggered. + */ + helper.onIrrelevantElement = function (e, api, targetCoordSysModel) { + var model = api.getComponentByElement(e.topTarget); + // If model is axisModel, it works only if it is injected with coordinateSystem. + var coordSys = model && model.coordinateSystem; + return model + && model !== targetCoordSysModel + && !IRRELEVANT_EXCLUDES[model.mainType] + && (coordSys && coordSys.model !== targetCoordSysModel); + }; + + module.exports = helper; + + +/***/ }, +/* 187 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var roamHelper = __webpack_require__(188); + + var echarts = __webpack_require__(1); + + /** + * @payload + * @property {string} [componentType=series] + * @property {number} [dx] + * @property {number} [dy] + * @property {number} [zoom] + * @property {number} [originX] + * @property {number} [originY] + */ + echarts.registerAction({ + type: 'geoRoam', + event: 'geoRoam', + update: 'updateLayout' + }, function (payload, ecModel) { + var componentType = payload.componentType || 'series'; + + ecModel.eachComponent( + { mainType: componentType, query: payload }, + function (componentModel) { + var geo = componentModel.coordinateSystem; + if (geo.type !== 'geo') { + return; + } + + var res = roamHelper.updateCenterAndZoom( + geo, payload, componentModel.get('scaleLimit') + ); + + componentModel.setCenter + && componentModel.setCenter(res.center); + + componentModel.setZoom + && componentModel.setZoom(res.zoom); + + // All map series with same `map` use the same geo coordinate system + // So the center and zoom must be in sync. Include the series not selected by legend + if (componentType === 'series') { + zrUtil.each(componentModel.seriesGroup, function (seriesModel) { + seriesModel.setCenter(res.center); + seriesModel.setZoom(res.zoom); + }); + } + } + ); + }); + + +/***/ }, +/* 188 */ +/***/ function(module, exports) { + + + + var roamHelper = {}; + + /** + * @param {module:echarts/coord/View} view + * @param {Object} payload + * @param {Object} [zoomLimit] + */ + roamHelper.updateCenterAndZoom = function ( + view, payload, zoomLimit + ) { + var previousZoom = view.getZoom(); + var center = view.getCenter(); + var zoom = payload.zoom; + + var point = view.dataToPoint(center); + + if (payload.dx != null && payload.dy != null) { + point[0] -= payload.dx; + point[1] -= payload.dy; + + var center = view.pointToData(point); + view.setCenter(center); + } + if (zoom != null) { + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + zoom = Math.max( + Math.min(previousZoom * zoom, zoomMax), + zoomMin + ) / previousZoom; + } + + // Zoom on given point(originX, originY) + view.scale[0] *= zoom; + view.scale[1] *= zoom; + var position = view.position; + var fixX = (payload.originX - position[0]) * (zoom - 1); + var fixY = (payload.originY - position[1]) * (zoom - 1); + + position[0] -= fixX; + position[1] -= fixY; + + view.updateTransform(); + // Get the new center + var center = view.pointToData(point); + view.setCenter(center); + view.setZoom(zoom * previousZoom); + } + + return { + center: view.getCenter(), + zoom: view.getZoom() + }; + }; + + module.exports = roamHelper; + + +/***/ }, +/* 189 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + module.exports = function (ecModel) { + + var processedMapType = {}; + + ecModel.eachSeriesByType('map', function (mapSeries) { + var mapType = mapSeries.getMapType(); + if (mapSeries.getHostGeoModel() || processedMapType[mapType]) { + return; + } + + var mapSymbolOffsets = {}; + + zrUtil.each(mapSeries.seriesGroup, function (subMapSeries) { + var geo = subMapSeries.coordinateSystem; + var data = subMapSeries.originalData; + if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) { + data.each('value', function (value, idx) { + var name = data.getName(idx); + var region = geo.getRegion(name); + + // If input series.data is [11, 22, '-'/null/undefined, 44], + // it will be filled with NaN: [11, 22, NaN, 44] and NaN will + // not be drawn. So here must validate if value is NaN. + if (!region || isNaN(value)) { + return; + } + + var offset = mapSymbolOffsets[name] || 0; + + var point = geo.dataToPoint(region.center); + + mapSymbolOffsets[name] = offset + 1; + + data.setItemLayout(idx, { + point: point, + offset: offset + }); + }); + } + }); + + // Show label of those region not has legendSymbol(which is offset 0) + var data = mapSeries.getData(); + data.each(function (idx) { + var name = data.getName(idx); + var layout = data.getItemLayout(idx) || {}; + layout.showLabel = !mapSymbolOffsets[name]; + data.setItemLayout(idx, layout); + }); + + processedMapType[mapType] = true; + }); + }; + + +/***/ }, +/* 190 */ +/***/ function(module, exports) { + + + module.exports = function (ecModel) { + ecModel.eachSeriesByType('map', function (seriesModel) { + var colorList = seriesModel.get('color'); + var itemStyleModel = seriesModel.getModel('itemStyle.normal'); + + var areaColor = itemStyleModel.get('areaColor'); + var color = itemStyleModel.get('color') + || colorList[seriesModel.seriesIndex % colorList.length]; + + seriesModel.getData().setVisual({ + 'areaColor': areaColor, + 'color': color + }); + }); + }; + + +/***/ }, +/* 191 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + // FIXME 公用? + /** + * @param {Array.} datas + * @param {string} statisticType 'average' 'sum' + * @inner + */ + function dataStatistics(datas, statisticType) { + var dataNameMap = {}; + var dims = ['value']; + + zrUtil.each(datas, function (data) { + data.each(dims, function (value, idx) { + // Add prefix to avoid conflict with Object.prototype. + var mapKey = 'ec-' + data.getName(idx); + dataNameMap[mapKey] = dataNameMap[mapKey] || []; + if (!isNaN(value)) { + dataNameMap[mapKey].push(value); + } + }); + }); + + return datas[0].map(dims, function (value, idx) { + var mapKey = 'ec-' + datas[0].getName(idx); + var sum = 0; + var min = Infinity; + var max = -Infinity; + var len = dataNameMap[mapKey].length; + for (var i = 0; i < len; i++) { + min = Math.min(min, dataNameMap[mapKey][i]); + max = Math.max(max, dataNameMap[mapKey][i]); + sum += dataNameMap[mapKey][i]; + } + var result; + if (statisticType === 'min') { + result = min; + } + else if (statisticType === 'max') { + result = max; + } + else if (statisticType === 'average') { + result = sum / len; + } + else { + result = sum; + } + return len === 0 ? NaN : result; + }); + } + + module.exports = function (ecModel) { + var seriesGroups = {}; + ecModel.eachSeriesByType('map', function (seriesModel) { + var hostGeoModel = seriesModel.getHostGeoModel(); + var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType(); + (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel); + }); + + zrUtil.each(seriesGroups, function (seriesList, key) { + var data = dataStatistics( + zrUtil.map(seriesList, function (seriesModel) { + return seriesModel.getData(); + }), + seriesList[0].get('mapValueCalculation') + ); + + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].originalData = seriesList[i].getData(); + } + + // FIXME Put where? + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].seriesGroup = seriesList; + seriesList[i].needsDrawMap = i === 0 && !seriesList[i].getHostGeoModel(); + + seriesList[i].setData(data.cloneShallow()); + seriesList[i].mainSeries = seriesList[0]; + } + }); + }; + + +/***/ }, +/* 192 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + module.exports = function (option) { + // Save geoCoord + var mapSeries = []; + zrUtil.each(option.series, function (seriesOpt) { + if (seriesOpt.type === 'map') { + mapSeries.push(seriesOpt); + } + }); + + zrUtil.each(mapSeries, function (seriesOpt) { + seriesOpt.map = seriesOpt.map || seriesOpt.mapType; + // Put x, y, width, height, x2, y2 in the top level + zrUtil.defaults(seriesOpt, seriesOpt.mapLocation); + }); + }; + + +/***/ }, +/* 193 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + + __webpack_require__(194); + __webpack_require__(198); + __webpack_require__(201); + + echarts.registerVisual(__webpack_require__(202)); + + echarts.registerLayout(__webpack_require__(204)); + + +/***/ }, +/* 194 */ +/***/ function(module, exports, __webpack_require__) { + + + + var SeriesModel = __webpack_require__(78); + var Tree = __webpack_require__(195); + var zrUtil = __webpack_require__(4); + var Model = __webpack_require__(12); + var formatUtil = __webpack_require__(6); + var helper = __webpack_require__(197); + var encodeHTML = formatUtil.encodeHTML; + var addCommas = formatUtil.addCommas; + + + module.exports = SeriesModel.extend({ + + type: 'series.treemap', + + layoutMode: 'box', + + dependencies: ['grid', 'polar'], + + /** + * @type {module:echarts/data/Tree~Node} + */ + _viewRoot: null, + + defaultOption: { + // Disable progressive rendering + progressive: 0, + hoverLayerThreshold: Infinity, + // center: ['50%', '50%'], // not supported in ec3. + // size: ['80%', '80%'], // deprecated, compatible with ec2. + left: 'center', + top: 'middle', + right: null, + bottom: null, + width: '80%', + height: '80%', + sort: true, // Can be null or false or true + // (order by desc default, asc not supported yet (strange effect)) + clipWindow: 'origin', // Size of clipped window when zooming. 'origin' or 'fullscreen' + squareRatio: 0.5 * (1 + Math.sqrt(5)), // golden ratio + leafDepth: null, // Nodes on depth from root are regarded as leaves. + // Count from zero (zero represents only view root). + drillDownIcon: '▶', // Use html character temporarily because it is complicated + // to align specialized icon. ▷▶❒❐▼✚ + + zoomToNodeRatio: 0.32 * 0.32, // Be effective when using zoomToNode. Specify the proportion of the + // target node area in the view area. + roam: true, // true, false, 'scale' or 'zoom', 'move'. + nodeClick: 'zoomToNode', // Leaf node click behaviour: 'zoomToNode', 'link', false. + // If leafDepth is set and clicking a node which has children but + // be on left depth, the behaviour would be changing root. Otherwise + // use behavious defined above. + animation: true, + animationDurationUpdate: 900, + animationEasing: 'quinticInOut', + breadcrumb: { + show: true, + height: 22, + left: 'center', + top: 'bottom', + // right + // bottom + emptyItemWidth: 25, // Width of empty node. + itemStyle: { + normal: { + color: 'rgba(0,0,0,0.7)', //'#5793f3', + borderColor: 'rgba(255,255,255,0.7)', + borderWidth: 1, + shadowColor: 'rgba(150,150,150,1)', + shadowBlur: 3, + shadowOffsetX: 0, + shadowOffsetY: 0, + textStyle: { + color: '#fff' + } + }, + emphasis: { + textStyle: {} + } + } + }, + label: { + normal: { + show: true, + position: 'inside', // Can be [5, '5%'] or position stirng like 'insideTopLeft', ... + // formatter: null, + textStyle: { + color: '#fff', + ellipsis: true + // align + // baseline + } + } + }, + upperLabel: { // Label when node is parent. + normal: { + show: false, + position: [0, '50%'], + height: 20, + // formatter: null, + textStyle: { + color: '#fff', + ellipsis: true, + // align: null, + baseline: 'middle' + } + }, + emphasis: { + show: true, + position: [0, '50%'], + textStyle: { + color: '#fff', + ellipsis: true, + baseline: 'middle' + } + } + }, + itemStyle: { + normal: { + color: null, // Can be 'none' if not necessary. + colorAlpha: null, // Can be 'none' if not necessary. + colorSaturation: null, // Can be 'none' if not necessary. + borderWidth: 0, + gapWidth: 0, + borderColor: '#fff', + borderColorSaturation: null // If specified, borderColor will be ineffective, and the + // border color is evaluated by color of current node and + // borderColorSaturation. + }, + emphasis: { + + } + }, + + visualDimension: 0, // Can be 0, 1, 2, 3. + visualMin: null, + visualMax: null, + + color: [], // + treemapSeries.color should not be modified. Please only modified + // level[n].color (if necessary). + // + Specify color list of each level. level[0].color would be global + // color list if not specified. (see method `setDefault`). + // + But set as a empty array to forbid fetch color from global palette + // when using nodeModel.get('color'), otherwise nodes on deep level + // will always has color palette set and are not able to inherit color + // from parent node. + // + TreemapSeries.color can not be set as 'none', otherwise effect + // legend color fetching (see seriesColor.js). + colorAlpha: null, // Array. Specify color alpha range of each level, like [0.2, 0.8] + colorSaturation: null, // Array. Specify color saturation of each level, like [0.2, 0.5] + colorMappingBy: 'index', // 'value' or 'index' or 'id'. + visibleMin: 10, // If area less than this threshold (unit: pixel^2), node will not + // be rendered. Only works when sort is 'asc' or 'desc'. + childrenVisibleMin: null, // If area of a node less than this threshold (unit: pixel^2), + // grandchildren will not show. + // Why grandchildren? If not grandchildren but children, + // some siblings show children and some not, + // the appearance may be mess and not consistent, + levels: [] // Each item: { + // visibleMin, itemStyle, visualDimension, label + // } + // data: { + // value: [], + // children: [], + // link: 'http://xxx.xxx.xxx', + // target: 'blank' or 'self' + // } + }, + + /** + * @override + */ + getInitialData: function (option, ecModel) { + // Create a virtual root. + var root = {name: option.name, children: option.data}; + + completeTreeValue(root); + + var levels = option.levels || []; + + levels = option.levels = setDefault(levels, ecModel); + + // Make sure always a new tree is created when setOption, + // in TreemapView, we check whether oldTree === newTree + // to choose mappings approach among old shapes and new shapes. + return Tree.createTree(root, this, levels).data; + }, + + optionUpdated: function () { + this.resetViewRoot(); + }, + + /** + * @override + * @param {number} dataIndex + * @param {boolean} [mutipleSeries=false] + */ + formatTooltip: function (dataIndex) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var formattedValue = zrUtil.isArray(value) + ? addCommas(value[0]) : addCommas(value); + var name = data.getName(dataIndex); + + return encodeHTML(name + ': ' + formattedValue); + }, + + /** + * Add tree path to tooltip param + * + * @override + * @param {number} dataIndex + * @return {Object} + */ + getDataParams: function (dataIndex) { + var params = SeriesModel.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treePathInfo = helper.wrapTreePathInfo(node, this); + + return params; + }, + + /** + * @public + * @param {Object} layoutInfo { + * x: containerGroup x + * y: containerGroup y + * width: containerGroup width + * height: containerGroup height + * } + */ + setLayoutInfo: function (layoutInfo) { + /** + * @readOnly + * @type {Object} + */ + this.layoutInfo = this.layoutInfo || {}; + zrUtil.extend(this.layoutInfo, layoutInfo); + }, + + /** + * @param {string} id + * @return {number} index + */ + mapIdToIndex: function (id) { + // A feature is implemented: + // index is monotone increasing with the sequence of + // input id at the first time. + // This feature can make sure that each data item and its + // mapped color have the same index between data list and + // color list at the beginning, which is useful for user + // to adjust data-color mapping. + + /** + * @private + * @type {Object} + */ + var idIndexMap = this._idIndexMap; + + if (!idIndexMap) { + idIndexMap = this._idIndexMap = zrUtil.createHashMap(); + /** + * @private + * @type {number} + */ + this._idIndexMapCount = 0; + } + + var index = idIndexMap.get(id); + if (index == null) { + idIndexMap.set(id, index = this._idIndexMapCount++); + } + + return index; + }, + + getViewRoot: function () { + return this._viewRoot; + }, + + /** + * @param {module:echarts/data/Tree~Node} [viewRoot] + */ + resetViewRoot: function (viewRoot) { + viewRoot + ? (this._viewRoot = viewRoot) + : (viewRoot = this._viewRoot); + + var root = this.getData().tree.root; + + if (!viewRoot + || (viewRoot !== root && !root.contains(viewRoot)) + ) { + this._viewRoot = root; + } + } + }); + + /** + * @param {Object} dataNode + */ + function completeTreeValue(dataNode) { + // Postorder travel tree. + // If value of none-leaf node is not set, + // calculate it by suming up the value of all children. + var sum = 0; + + zrUtil.each(dataNode.children, function (child) { + + completeTreeValue(child); + + var childValue = child.value; + zrUtil.isArray(childValue) && (childValue = childValue[0]); + + sum += childValue; + }); + + var thisValue = dataNode.value; + if (zrUtil.isArray(thisValue)) { + thisValue = thisValue[0]; + } + + if (thisValue == null || isNaN(thisValue)) { + thisValue = sum; + } + // Value should not less than 0. + if (thisValue < 0) { + thisValue = 0; + } + + zrUtil.isArray(dataNode.value) + ? (dataNode.value[0] = thisValue) + : (dataNode.value = thisValue); + } + + /** + * set default to level configuration + */ + function setDefault(levels, ecModel) { + var globalColorList = ecModel.get('color'); + + if (!globalColorList) { + return; + } + + levels = levels || []; + var hasColorDefine; + zrUtil.each(levels, function (levelDefine) { + var model = new Model(levelDefine); + var modelColor = model.get('color'); + + if (model.get('itemStyle.normal.color') + || (modelColor && modelColor !== 'none') + ) { + hasColorDefine = true; + } + }); + + if (!hasColorDefine) { + var level0 = levels[0] || (levels[0] = {}); + level0.color = globalColorList.slice(); + } + + return levels; + } + + + +/***/ }, +/* 195 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Tree data structure + * + * @module echarts/data/Tree + */ + + + var zrUtil = __webpack_require__(4); + var Model = __webpack_require__(12); + var List = __webpack_require__(98); + var linkList = __webpack_require__(196); + var completeDimensions = __webpack_require__(110); + + /** + * @constructor module:echarts/data/Tree~TreeNode + * @param {string} name + * @param {module:echarts/data/Tree} hostTree + */ + var TreeNode = function (name, hostTree) { + /** + * @type {string} + */ + this.name = name || ''; + + /** + * Depth of node + * + * @type {number} + * @readOnly + */ + this.depth = 0; + + /** + * Height of the subtree rooted at this node. + * @type {number} + * @readOnly + */ + this.height = 0; + + /** + * @type {module:echarts/data/Tree~TreeNode} + * @readOnly + */ + this.parentNode = null; + + /** + * Reference to list item. + * Do not persistent dataIndex outside, + * besause it may be changed by list. + * If dataIndex -1, + * this node is logical deleted (filtered) in list. + * + * @type {Object} + * @readOnly + */ + this.dataIndex = -1; + + /** + * @type {Array.} + * @readOnly + */ + this.children = []; + + /** + * @type {Array.} + * @pubilc + */ + this.viewChildren = []; + + /** + * @type {moduel:echarts/data/Tree} + * @readOnly + */ + this.hostTree = hostTree; + }; + + TreeNode.prototype = { + + constructor: TreeNode, + + /** + * The node is removed. + * @return {boolean} is removed. + */ + isRemoved: function () { + return this.dataIndex < 0; + }, + + /** + * Travel this subtree (include this node). + * Usage: + * node.eachNode(function () { ... }); // preorder + * node.eachNode('preorder', function () { ... }); // preorder + * node.eachNode('postorder', function () { ... }); // postorder + * node.eachNode( + * {order: 'postorder', attr: 'viewChildren'}, + * function () { ... } + * ); // postorder + * + * @param {(Object|string)} options If string, means order. + * @param {string=} options.order 'preorder' or 'postorder' + * @param {string=} options.attr 'children' or 'viewChildren' + * @param {Function} cb If in preorder and return false, + * its subtree will not be visited. + * @param {Object} [context] + */ + eachNode: function (options, cb, context) { + if (typeof options === 'function') { + context = cb; + cb = options; + options = null; + } + + options = options || {}; + if (zrUtil.isString(options)) { + options = {order: options}; + } + + var order = options.order || 'preorder'; + var children = this[options.attr || 'children']; + + var suppressVisitSub; + order === 'preorder' && (suppressVisitSub = cb.call(context, this)); + + for (var i = 0; !suppressVisitSub && i < children.length; i++) { + children[i].eachNode(options, cb, context); + } + + order === 'postorder' && cb.call(context, this); + }, + + /** + * Update depth and height of this subtree. + * + * @param {number} depth + */ + updateDepthAndHeight: function (depth) { + var height = 0; + this.depth = depth; + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + child.updateDepthAndHeight(depth + 1); + if (child.height > height) { + height = child.height; + } + } + this.height = height + 1; + }, + + /** + * @param {string} id + * @return {module:echarts/data/Tree~TreeNode} + */ + getNodeById: function (id) { + if (this.getId() === id) { + return this; + } + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].getNodeById(id); + if (res) { + return res; + } + } + }, + + /** + * @param {module:echarts/data/Tree~TreeNode} node + * @return {boolean} + */ + contains: function (node) { + if (node === this) { + return true; + } + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].contains(node); + if (res) { + return res; + } + } + }, + + /** + * @param {boolean} includeSelf Default false. + * @return {Array.} order: [root, child, grandchild, ...] + */ + getAncestors: function (includeSelf) { + var ancestors = []; + var node = includeSelf ? this : this.parentNode; + while (node) { + ancestors.push(node); + node = node.parentNode; + } + ancestors.reverse(); + return ancestors; + }, + + /** + * @param {string|Array=} [dimension='value'] Default 'value'. can be 0, 1, 2, 3 + * @return {number} Value. + */ + getValue: function (dimension) { + var data = this.hostTree.data; + return data.get(data.getDimension(dimension || 'value'), this.dataIndex); + }, + + /** + * @param {Object} layout + * @param {boolean=} [merge=false] + */ + setLayout: function (layout, merge) { + this.dataIndex >= 0 + && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge); + }, + + /** + * @return {Object} layout + */ + getLayout: function () { + return this.hostTree.data.getItemLayout(this.dataIndex); + }, + + /** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ + getModel: function (path) { + if (this.dataIndex < 0) { + return; + } + var hostTree = this.hostTree; + var itemModel = hostTree.data.getItemModel(this.dataIndex); + var levelModel = this.getLevelModel(); + + return itemModel.getModel(path, (levelModel || hostTree.hostModel).getModel(path)); + }, + + /** + * @return {module:echarts/model/Model} + */ + getLevelModel: function () { + return (this.hostTree.levelModels || [])[this.depth]; + }, + + /** + * @example + * setItemVisual('color', color); + * setItemVisual({ + * 'color': color + * }); + */ + setVisual: function (key, value) { + this.dataIndex >= 0 + && this.hostTree.data.setItemVisual(this.dataIndex, key, value); + }, + + /** + * Get item visual + */ + getVisual: function (key, ignoreParent) { + return this.hostTree.data.getItemVisual(this.dataIndex, key, ignoreParent); + }, + + /** + * @public + * @return {number} + */ + getRawIndex: function () { + return this.hostTree.data.getRawIndex(this.dataIndex); + }, + + /** + * @public + * @return {string} + */ + getId: function () { + return this.hostTree.data.getId(this.dataIndex); + } + }; + + /** + * @constructor + * @alias module:echarts/data/Tree + * @param {module:echarts/model/Model} hostModel + * @param {Array.} levelOptions + */ + function Tree(hostModel, levelOptions) { + /** + * @type {module:echarts/data/Tree~TreeNode} + * @readOnly + */ + this.root; + + /** + * @type {module:echarts/data/List} + * @readOnly + */ + this.data; + + /** + * Index of each item is the same as the raw index of coresponding list item. + * @private + * @type {Array.} levelOptions + * @return module:echarts/data/Tree + */ + Tree.createTree = function (dataRoot, hostModel, levelOptions) { + + var tree = new Tree(hostModel, levelOptions); + var listData = []; + var dimMax = 1; + + buildHierarchy(dataRoot); + + function buildHierarchy(dataNode, parentNode) { + var value = dataNode.value; + dimMax = Math.max(dimMax, zrUtil.isArray(value) ? value.length : 1); + + listData.push(dataNode); + + var node = new TreeNode(dataNode.name, tree); + parentNode + ? addChild(node, parentNode) + : (tree.root = node); + + tree._nodes.push(node); + + var children = dataNode.children; + if (children) { + for (var i = 0; i < children.length; i++) { + buildHierarchy(children[i], node); + } + } + } + + tree.root.updateDepthAndHeight(0); + + var dimensions = completeDimensions([{name: 'value'}], listData, {dimCount: dimMax}); + var list = new List(dimensions, hostModel); + list.initData(listData); + + linkList({ + mainData: list, + struct: tree, + structAttr: 'tree' + }); + + tree.update(); + + return tree; + }; + + /** + * It is needed to consider the mess of 'list', 'hostModel' when creating a TreeNote, + * so this function is not ready and not necessary to be public. + * + * @param {(module:echarts/data/Tree~TreeNode|Object)} child + */ + function addChild(child, node) { + var children = node.children; + if (child.parentNode === node) { + return; + } + + children.push(child); + child.parentNode = node; + } + + module.exports = Tree; + + +/***/ }, +/* 196 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Link lists and struct (graph or tree) + */ + + + var zrUtil = __webpack_require__(4); + var each = zrUtil.each; + + var DATAS = '\0__link_datas'; + var MAIN_DATA = '\0__link_mainData'; + + // Caution: + // In most case, either list or its shallow clones (see list.cloneShallow) + // is active in echarts process. So considering heap memory consumption, + // we do not clone tree or graph, but share them among list and its shallow clones. + // But in some rare case, we have to keep old list (like do animation in chart). So + // please take care that both the old list and the new list share the same tree/graph. + + /** + * @param {Object} opt + * @param {module:echarts/data/List} opt.mainData + * @param {Object} [opt.struct] For example, instance of Graph or Tree. + * @param {string} [opt.structAttr] designation: list[structAttr] = struct; + * @param {Object} [opt.datas] {dataType: data}, + * like: {node: nodeList, edge: edgeList}. + * Should contain mainData. + * @param {Object} [opt.datasAttr] {dataType: attr}, + * designation: struct[datasAttr[dataType]] = list; + */ + function linkList(opt) { + var mainData = opt.mainData; + var datas = opt.datas; + + if (!datas) { + datas = {main: mainData}; + opt.datasAttr = {main: 'data'}; + } + opt.datas = opt.mainData = null; + + linkAll(mainData, datas, opt); + + // Porxy data original methods. + each(datas, function (data) { + each(mainData.TRANSFERABLE_METHODS, function (methodName) { + data.wrapMethod(methodName, zrUtil.curry(transferInjection, opt)); + }); + + }); + + // Beyond transfer, additional features should be added to `cloneShallow`. + mainData.wrapMethod('cloneShallow', zrUtil.curry(cloneShallowInjection, opt)); + + // Only mainData trigger change, because struct.update may trigger + // another changable methods, which may bring about dead lock. + each(mainData.CHANGABLE_METHODS, function (methodName) { + mainData.wrapMethod(methodName, zrUtil.curry(changeInjection, opt)); + }); + + // Make sure datas contains mainData. + zrUtil.assert(datas[mainData.dataType] === mainData); + } + + function transferInjection(opt, res) { + if (isMainData(this)) { + // Transfer datas to new main data. + var datas = zrUtil.extend({}, this[DATAS]); + datas[this.dataType] = res; + linkAll(res, datas, opt); + } + else { + // Modify the reference in main data to point newData. + linkSingle(res, this.dataType, this[MAIN_DATA], opt); + } + return res; + } + + function changeInjection(opt, res) { + opt.struct && opt.struct.update(this); + return res; + } + + function cloneShallowInjection(opt, res) { + // cloneShallow, which brings about some fragilities, may be inappropriate + // to be exposed as an API. So for implementation simplicity we can make + // the restriction that cloneShallow of not-mainData should not be invoked + // outside, but only be invoked here. + each(res[DATAS], function (data, dataType) { + data !== res && linkSingle(data.cloneShallow(), dataType, res, opt); + }); + return res; + } + + /** + * Supplement method to List. + * + * @public + * @param {string} [dataType] If not specified, return mainData. + * @return {module:echarts/data/List} + */ + function getLinkedData(dataType) { + var mainData = this[MAIN_DATA]; + return (dataType == null || mainData == null) + ? mainData + : mainData[DATAS][dataType]; + } + + function isMainData(data) { + return data[MAIN_DATA] === data; + } + + function linkAll(mainData, datas, opt) { + mainData[DATAS] = {}; + each(datas, function (data, dataType) { + linkSingle(data, dataType, mainData, opt); + }); + } + + function linkSingle(data, dataType, mainData, opt) { + mainData[DATAS][dataType] = data; + data[MAIN_DATA] = mainData; + data.dataType = dataType; + + if (opt.struct) { + data[opt.structAttr] = opt.struct; + opt.struct[opt.datasAttr[dataType]] = data; + } + + // Supplement method. + data.getLinkedData = getLinkedData; + } + + module.exports = linkList; + + +/***/ }, +/* 197 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var helper = { + + retrieveTargetInfo: function (payload, seriesModel) { + if (payload + && ( + payload.type === 'treemapZoomToNode' + || payload.type === 'treemapRootToNode' + ) + ) { + var root = seriesModel.getData().tree.root; + var targetNode = payload.targetNode; + if (targetNode && root.contains(targetNode)) { + return {node: targetNode}; + } + + var targetNodeId = payload.targetNodeId; + if (targetNodeId != null && (targetNode = root.getNodeById(targetNodeId))) { + return {node: targetNode}; + } + } + }, + + // Not includes the given node at the last item. + getPathToRoot: function (node) { + var path = []; + while (node) { + node = node.parentNode; + node && path.push(node); + } + return path.reverse(); + }, + + aboveViewRoot: function (viewRoot, node) { + var viewPath = helper.getPathToRoot(viewRoot); + return zrUtil.indexOf(viewPath, node) >= 0; + }, + + // From root to the input node (the input node will be included). + wrapTreePathInfo: function (node, seriesModel) { + var treePathInfo = []; + + while (node) { + var nodeDataIndex = node.dataIndex; + treePathInfo.push({ + name: node.name, + dataIndex: nodeDataIndex, + value: seriesModel.getRawValue(nodeDataIndex) + }); + node = node.parentNode; + } + + treePathInfo.reverse(); + + return treePathInfo; + } + }; + + module.exports = helper; + + +/***/ }, +/* 198 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var DataDiffer = __webpack_require__(99); + var helper = __webpack_require__(197); + var Breadcrumb = __webpack_require__(199); + var RoamController = __webpack_require__(183); + var BoundingRect = __webpack_require__(9); + var matrix = __webpack_require__(11); + var animationUtil = __webpack_require__(200); + var bind = zrUtil.bind; + var Group = graphic.Group; + var Rect = graphic.Rect; + var each = zrUtil.each; + + var DRAG_THRESHOLD = 3; + var PATH_LABEL_NOAMAL = ['label', 'normal']; + var PATH_LABEL_EMPHASIS = ['label', 'emphasis']; + var PATH_UPPERLABEL_NORMAL = ['upperLabel', 'normal']; + var PATH_UPPERLABEL_EMPHASIS = ['upperLabel', 'emphasis']; + var Z_BASE = 10; // Should bigger than every z. + var Z_BG = 1; + var Z_CONTENT = 2; + + module.exports = __webpack_require__(1).extendChartView({ + + type: 'treemap', + + /** + * @override + */ + init: function (o, api) { + + /** + * @private + * @type {module:zrender/container/Group} + */ + this._containerGroup; + + /** + * @private + * @type {Object.>} + */ + this._storage = createStorage(); + + /** + * @private + * @type {module:echarts/data/Tree} + */ + this._oldTree; + + /** + * @private + * @type {module:echarts/chart/treemap/Breadcrumb} + */ + this._breadcrumb; + + /** + * @private + * @type {module:echarts/component/helper/RoamController} + */ + this._controller; + + /** + * 'ready', 'animating' + * @private + */ + this._state = 'ready'; + + /** + * @private + * @type {boolean} + */ + this._mayClick; + }, + + /** + * @override + */ + render: function (seriesModel, ecModel, api, payload) { + + var models = ecModel.findComponents({ + mainType: 'series', subType: 'treemap', query: payload + }); + if (zrUtil.indexOf(models, seriesModel) < 0) { + return; + } + + this.seriesModel = seriesModel; + this.api = api; + this.ecModel = ecModel; + + var targetInfo = helper.retrieveTargetInfo(payload, seriesModel); + var payloadType = payload && payload.type; + var layoutInfo = seriesModel.layoutInfo; + var isInit = !this._oldTree; + var thisStorage = this._storage; + + // Mark new root when action is treemapRootToNode. + var reRoot = (payloadType === 'treemapRootToNode' && targetInfo && thisStorage) + ? { + rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()], + direction: payload.direction + } + : null; + + var containerGroup = this._giveContainerGroup(layoutInfo); + + var renderResult = this._doRender(containerGroup, seriesModel, reRoot); + ( + !isInit && ( + !payloadType + || payloadType === 'treemapZoomToNode' + || payloadType === 'treemapRootToNode' + ) + ) + ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot) + : renderResult.renderFinally(); + + this._resetController(api); + + this._renderBreadcrumb(seriesModel, api, targetInfo); + }, + + /** + * @private + */ + _giveContainerGroup: function (layoutInfo) { + var containerGroup = this._containerGroup; + if (!containerGroup) { + // FIXME + // 加一层containerGroup是为了clip,但是现在clip功能并没有实现。 + containerGroup = this._containerGroup = new Group(); + this._initEvents(containerGroup); + this.group.add(containerGroup); + } + containerGroup.attr('position', [layoutInfo.x, layoutInfo.y]); + + return containerGroup; + }, + + /** + * @private + */ + _doRender: function (containerGroup, seriesModel, reRoot) { + var thisTree = seriesModel.getData().tree; + var oldTree = this._oldTree; + + // Clear last shape records. + var lastsForAnimation = createStorage(); + var thisStorage = createStorage(); + var oldStorage = this._storage; + var willInvisibleEls = []; + var doRenderNode = zrUtil.curry( + renderNode, seriesModel, + thisStorage, oldStorage, reRoot, + lastsForAnimation, willInvisibleEls + ); + + // Notice: when thisTree and oldTree are the same tree (see list.cloneShadow), + // the oldTree is actually losted, so we can not find all of the old graphic + // elements from tree. So we use this stragegy: make element storage, move + // from old storage to new storage, clear old storage. + + dualTravel( + thisTree.root ? [thisTree.root] : [], + (oldTree && oldTree.root) ? [oldTree.root] : [], + containerGroup, + thisTree === oldTree || !oldTree, + 0 + ); + + // Process all removing. + var willDeleteEls = clearStorage(oldStorage); + + this._oldTree = thisTree; + this._storage = thisStorage; + + return { + lastsForAnimation: lastsForAnimation, + willDeleteEls: willDeleteEls, + renderFinally: renderFinally + }; + + function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) { + // When 'render' is triggered by action, + // 'this' and 'old' may be the same tree, + // we use rawIndex in that case. + if (sameTree) { + oldViewChildren = thisViewChildren; + each(thisViewChildren, function (child, index) { + !child.isRemoved() && processNode(index, index); + }); + } + // Diff hierarchically (diff only in each subtree, but not whole). + // because, consistency of view is important. + else { + (new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey)) + .add(processNode) + .update(processNode) + .remove(zrUtil.curry(processNode, null)) + .execute(); + } + + function getKey(node) { + // Identify by name or raw index. + return node.getId(); + } + + function processNode(newIndex, oldIndex) { + var thisNode = newIndex != null ? thisViewChildren[newIndex] : null; + var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null; + + var group = doRenderNode(thisNode, oldNode, parentGroup, depth); + + group && dualTravel( + thisNode && thisNode.viewChildren || [], + oldNode && oldNode.viewChildren || [], + group, + sameTree, + depth + 1 + ); + } + } + + function clearStorage(storage) { + var willDeleteEls = createStorage(); + storage && each(storage, function (store, storageName) { + var delEls = willDeleteEls[storageName]; + each(store, function (el) { + el && (delEls.push(el), el.__tmWillDelete = 1); + }); + }); + return willDeleteEls; + } + + function renderFinally() { + each(willDeleteEls, function (els) { + each(els, function (el) { + el.parent && el.parent.remove(el); + }); + }); + each(willInvisibleEls, function (el) { + el.invisible = true; + // Setting invisible is for optimizing, so no need to set dirty, + // just mark as invisible. + el.dirty(); + }); + } + }, + + /** + * @private + */ + _doAnimation: function (containerGroup, renderResult, seriesModel, reRoot) { + if (!seriesModel.get('animation')) { + return; + } + + var duration = seriesModel.get('animationDurationUpdate'); + var easing = seriesModel.get('animationEasing'); + var animationWrap = animationUtil.createWrap(); + + // Make delete animations. + each(renderResult.willDeleteEls, function (store, storageName) { + each(store, function (el, rawIndex) { + if (el.invisible) { + return; + } + + var parent = el.parent; // Always has parent, and parent is nodeGroup. + var target; + + if (reRoot && reRoot.direction === 'drillDown') { + target = parent === reRoot.rootNodeGroup + // This is the content element of view root. + // Only `content` will enter this branch, because + // `background` and `nodeGroup` will not be deleted. + ? { + shape: { + x: 0, + y: 0, + width: parent.__tmNodeWidth, + height: parent.__tmNodeHeight + }, + style: { + opacity: 0 + } + } + // Others. + : {style: {opacity: 0}}; + } + else { + var targetX = 0; + var targetY = 0; + + if (!parent.__tmWillDelete) { + // Let node animate to right-bottom corner, cooperating with fadeout, + // which is appropriate for user understanding. + // Divided by 2 for reRoot rolling up effect. + targetX = parent.__tmNodeWidth / 2; + targetY = parent.__tmNodeHeight / 2; + } + + target = storageName === 'nodeGroup' + ? {position: [targetX, targetY], style: {opacity: 0}} + : { + shape: {x: targetX, y: targetY, width: 0, height: 0}, + style: {opacity: 0} + }; + } + + target && animationWrap.add(el, target, duration, easing); + }); + }); + + // Make other animations + each(this._storage, function (store, storageName) { + each(store, function (el, rawIndex) { + var last = renderResult.lastsForAnimation[storageName][rawIndex]; + var target = {}; + + if (!last) { + return; + } + + if (storageName === 'nodeGroup') { + if (last.old) { + target.position = el.position.slice(); + el.attr('position', last.old); + } + } + else { + if (last.old) { + target.shape = zrUtil.extend({}, el.shape); + el.setShape(last.old); + } + + if (last.fadein) { + el.setStyle('opacity', 0); + target.style = {opacity: 1}; + } + // When animation is stopped for succedent animation starting, + // el.style.opacity might not be 1 + else if (el.style.opacity !== 1) { + target.style = {opacity: 1}; + } + } + + animationWrap.add(el, target, duration, easing); + }); + }, this); + + this._state = 'animating'; + + animationWrap + .done(bind(function () { + this._state = 'ready'; + renderResult.renderFinally(); + }, this)) + .start(); + }, + + /** + * @private + */ + _resetController: function (api) { + var controller = this._controller; + + // Init controller. + if (!controller) { + controller = this._controller = new RoamController(api.getZr()); + controller.enable(this.seriesModel.get('roam')); + controller.on('pan', bind(this._onPan, this)); + controller.on('zoom', bind(this._onZoom, this)); + } + + var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight()); + controller.setPointerChecker(function (e, x, y) { + return rect.contain(x, y); + }); + }, + + /** + * @private + */ + _clearController: function () { + var controller = this._controller; + if (controller) { + controller.dispose(); + controller = null; + } + }, + + /** + * @private + */ + _onPan: function (dx, dy) { + this._mayClick = false; + + if (this._state !== 'animating' + && (Math.abs(dx) > DRAG_THRESHOLD || Math.abs(dy) > DRAG_THRESHOLD) + ) { + // These param must not be cached. + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + this.api.dispatchAction({ + type: 'treemapMove', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rootLayout.x + dx, y: rootLayout.y + dy, + width: rootLayout.width, height: rootLayout.height + } + }); + } + }, + + /** + * @private + */ + _onZoom: function (scale, mouseX, mouseY) { + this._mayClick = false; + + if (this._state !== 'animating') { + // These param must not be cached. + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + var rect = new BoundingRect( + rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height + ); + var layoutInfo = this.seriesModel.layoutInfo; + + // Transform mouse coord from global to containerGroup. + mouseX -= layoutInfo.x; + mouseY -= layoutInfo.y; + + // Scale root bounding rect. + var m = matrix.create(); + matrix.translate(m, m, [-mouseX, -mouseY]); + matrix.scale(m, m, [scale, scale]); + matrix.translate(m, m, [mouseX, mouseY]); + + rect.applyTransform(m); + + this.api.dispatchAction({ + type: 'treemapRender', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rect.x, y: rect.y, + width: rect.width, height: rect.height + } + }); + } + }, + + /** + * @private + */ + _initEvents: function (containerGroup) { + // FIXME + // 不用click以及silent的原因是,animate时视图设置silent true来避免click生效, + // 但是animate中,按下鼠标,animate结束后(silent设回为false)松开鼠标, + // 还是会触发click,期望是不触发。 + + // Mousedown occurs when drag start, and mouseup occurs when drag end, + // click event should not be triggered in that case. + + containerGroup.on('mousedown', function (e) { + this._state === 'ready' && (this._mayClick = true); + }, this); + containerGroup.on('mouseup', function (e) { + if (this._mayClick) { + this._mayClick = false; + this._state === 'ready' && onClick.call(this, e); + } + }, this); + + function onClick(e) { + var nodeClick = this.seriesModel.get('nodeClick', true); + + if (!nodeClick) { + return; + } + + var targetInfo = this.findTarget(e.offsetX, e.offsetY); + + if (!targetInfo) { + return; + } + + var node = targetInfo.node; + if (node.getLayout().isLeafRoot) { + this._rootToNode(targetInfo); + } + else { + if (nodeClick === 'zoomToNode') { + this._zoomToNode(targetInfo); + } + else if (nodeClick === 'link') { + var itemModel = node.hostTree.data.getItemModel(node.dataIndex); + var link = itemModel.get('link', true); + var linkTarget = itemModel.get('target', true) || 'blank'; + link && window.open(link, linkTarget); + } + } + } + }, + + /** + * @private + */ + _renderBreadcrumb: function (seriesModel, api, targetInfo) { + if (!targetInfo) { + targetInfo = seriesModel.get('leafDepth', true) != null + ? {node: seriesModel.getViewRoot()} + // FIXME + // better way? + // Find breadcrumb tail on center of containerGroup. + : this.findTarget(api.getWidth() / 2, api.getHeight() / 2); + + if (!targetInfo) { + targetInfo = {node: seriesModel.getData().tree.root}; + } + } + + (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group))) + .render(seriesModel, api, targetInfo.node, bind(onSelect, this)); + + function onSelect(node) { + if (this._state !== 'animating') { + helper.aboveViewRoot(seriesModel.getViewRoot(), node) + ? this._rootToNode({node: node}) + : this._zoomToNode({node: node}); + } + } + }, + + /** + * @override + */ + remove: function () { + this._clearController(); + this._containerGroup && this._containerGroup.removeAll(); + this._storage = createStorage(); + this._state = 'ready'; + this._breadcrumb && this._breadcrumb.remove(); + }, + + dispose: function () { + this._clearController(); + }, + + /** + * @private + */ + _zoomToNode: function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapZoomToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }, + + /** + * @private + */ + _rootToNode: function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapRootToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }, + + /** + * @public + * @param {number} x Global coord x. + * @param {number} y Global coord y. + * @return {Object} info If not found, return undefined; + * @return {number} info.node Target node. + * @return {number} info.offsetX x refer to target node. + * @return {number} info.offsetY y refer to target node. + */ + findTarget: function (x, y) { + var targetInfo; + var viewRoot = this.seriesModel.getViewRoot(); + + viewRoot.eachNode({attr: 'viewChildren', order: 'preorder'}, function (node) { + var bgEl = this._storage.background[node.getRawIndex()]; + // If invisible, there might be no element. + if (bgEl) { + var point = bgEl.transformCoordToLocal(x, y); + var shape = bgEl.shape; + + // For performance consideration, dont use 'getBoundingRect'. + if (shape.x <= point[0] + && point[0] <= shape.x + shape.width + && shape.y <= point[1] + && point[1] <= shape.y + shape.height + ) { + targetInfo = {node: node, offsetX: point[0], offsetY: point[1]}; + } + else { + return false; // Suppress visit subtree. + } + } + }, this); + + return targetInfo; + } + + }); + + /** + * @inner + */ + function createStorage() { + return {nodeGroup: [], background: [], content: []}; + } + + /** + * @inner + * @return Return undefined means do not travel further. + */ + function renderNode( + seriesModel, thisStorage, oldStorage, reRoot, + lastsForAnimation, willInvisibleEls, + thisNode, oldNode, parentGroup, depth + ) { + // Whether under viewRoot. + if (!thisNode) { + // Deleting nodes will be performed finally. This method just find + // element from old storage, or create new element, set them to new + // storage, and set styles. + return; + } + + // ------------------------------------------------------------------- + // Start of closure variables available in "Procedures in renderNode". + + var thisLayout = thisNode.getLayout(); + + if (!thisLayout || !thisLayout.isInView) { + return; + } + + var thisWidth = thisLayout.width; + var thisHeight = thisLayout.height; + var borderWidth = thisLayout.borderWidth; + var thisInvisible = thisLayout.invisible; + + var thisRawIndex = thisNode.getRawIndex(); + var oldRawIndex = oldNode && oldNode.getRawIndex(); + + var thisViewChildren = thisNode.viewChildren; + var upperHeight = thisLayout.upperHeight; + var isParent = thisViewChildren && thisViewChildren.length; + var itemStyleEmphasisModel = thisNode.getModel('itemStyle.emphasis'); + + // End of closure ariables available in "Procedures in renderNode". + // ----------------------------------------------------------------- + + // Node group + var group = giveGraphic('nodeGroup', Group); + + if (!group) { + return; + } + + parentGroup.add(group); + // x,y are not set when el is above view root. + group.attr('position', [thisLayout.x || 0, thisLayout.y || 0]); + group.__tmNodeWidth = thisWidth; + group.__tmNodeHeight = thisHeight; + + if (thisLayout.isAboveViewRoot) { + return group; + } + + // Background + var bg = giveGraphic('background', Rect, depth, Z_BG); + bg && renderBackground(group, bg, isParent && thisLayout.upperHeight); + + // No children, render content. + if (!isParent) { + var content = giveGraphic('content', Rect, depth, Z_CONTENT); + content && renderContent(group, content); + } + + return group; + + // ---------------------------- + // | Procedures in renderNode | + // ---------------------------- + + function renderBackground(group, bg, useUpperLabel) { + // For tooltip. + bg.dataIndex = thisNode.dataIndex; + bg.seriesIndex = seriesModel.seriesIndex; + + bg.setShape({x: 0, y: 0, width: thisWidth, height: thisHeight}); + var visualBorderColor = thisNode.getVisual('borderColor', true); + var emphasisBorderColor = itemStyleEmphasisModel.get('borderColor'); + + updateStyle(bg, function () { + var normalStyle = {fill: visualBorderColor}; + var emphasisStyle = {fill: emphasisBorderColor}; + + if (useUpperLabel) { + var upperLabelWidth = thisWidth - 2 * borderWidth; + + prepareText( + normalStyle, emphasisStyle, visualBorderColor, upperLabelWidth, upperHeight, + {x: borderWidth, y: 0, width: upperLabelWidth, height: upperHeight} + ); + } + // For old bg. + else { + normalStyle.text = emphasisStyle.text = ''; + } + + bg.setStyle(normalStyle); + graphic.setHoverStyle(bg, emphasisStyle); + }); + + group.add(bg); + } + + function renderContent(group, content) { + // For tooltip. + content.dataIndex = thisNode.dataIndex; + content.seriesIndex = seriesModel.seriesIndex; + + var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0); + var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0); + + content.culling = true; + content.setShape({ + x: borderWidth, + y: borderWidth, + width: contentWidth, + height: contentHeight + }); + + var visualColor = thisNode.getVisual('color', true); + updateStyle(content, function () { + var normalStyle = {fill: visualColor}; + var emphasisStyle = itemStyleEmphasisModel.getItemStyle(); + + prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight); + + content.setStyle(normalStyle); + graphic.setHoverStyle(content, emphasisStyle); + }); + + group.add(content); + } + + function updateStyle(element, cb) { + if (!thisInvisible) { + // If invisible, do not set visual, otherwise the element will + // change immediately before animation. We think it is OK to + // remain its origin color when moving out of the view window. + cb(); + + if (!element.__tmWillVisible) { + element.invisible = false; + } + } + else { + // Delay invisible setting utill animation finished, + // avoid element vanish suddenly before animation. + !element.invisible && willInvisibleEls.push(element); + } + } + + function prepareText(normalStyle, emphasisStyle, visualColor, width, height, upperLabelRect) { + var nodeModel = thisNode.getModel(); + var text = zrUtil.retrieve( + seriesModel.getFormattedLabel( + thisNode.dataIndex, 'normal', null, null, upperLabelRect ? 'upperLabel' : 'label' + ), + nodeModel.get('name') + ); + if (!upperLabelRect && thisLayout.isLeafRoot) { + var iconChar = seriesModel.get('drillDownIcon', true); + text = iconChar ? iconChar + ' ' + text : text; + } + + setText( + text, normalStyle, nodeModel, upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL, + visualColor, width, height, upperLabelRect + ); + setText( + text, emphasisStyle, nodeModel, upperLabelRect ? PATH_UPPERLABEL_EMPHASIS : PATH_LABEL_EMPHASIS, + visualColor, width, height, upperLabelRect + ); + } + + function setText(text, style, nodeModel, labelPath, visualColor, width, height, upperLabelRect) { + var labelModel = nodeModel.getModel(labelPath); + var labelTextStyleModel = labelModel.getModel('textStyle'); + + graphic.setText(style, labelModel, visualColor); + + // text.align and text.baseline is not included by graphic.setText, + // because in most cases the two attributes are not exposed to user, + // except in treemap. + style.textAlign = labelTextStyleModel.get('align'); + style.textVerticalAlign = labelTextStyleModel.get('baseline'); + upperLabelRect && (style.textPositionRect = zrUtil.clone(upperLabelRect)); + + var textRect = labelTextStyleModel.getTextRect(text); + if (!labelModel.getShallow('show') || textRect.height > height) { + style.text = ''; + } + else if (textRect.width > width) { + style.text = labelTextStyleModel.get('ellipsis') + ? labelTextStyleModel.truncateText( + text, width, null, {minChar: 2} + ) + : ''; + } + else { + style.text = text; + } + } + + function giveGraphic(storageName, Ctor, depth, z) { + var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex]; + var lasts = lastsForAnimation[storageName]; + + if (element) { + // Remove from oldStorage + oldStorage[storageName][oldRawIndex] = null; + prepareAnimationWhenHasOld(lasts, element, storageName); + } + // If invisible and no old element, do not create new element (for optimizing). + else if (!thisInvisible) { + element = new Ctor({z: calculateZ(depth, z)}); + element.__tmDepth = depth; + element.__tmStorageName = storageName; + prepareAnimationWhenNoOld(lasts, element, storageName); + } + + // Set to thisStorage + return (thisStorage[storageName][thisRawIndex] = element); + } + + function prepareAnimationWhenHasOld(lasts, element, storageName) { + var lastCfg = lasts[thisRawIndex] = {}; + lastCfg.old = storageName === 'nodeGroup' + ? element.position.slice() + : zrUtil.extend({}, element.shape); + } + + // If a element is new, we need to find the animation start point carefully, + // otherwise it will looks strange when 'zoomToNode'. + function prepareAnimationWhenNoOld(lasts, element, storageName) { + var lastCfg = lasts[thisRawIndex] = {}; + var parentNode = thisNode.parentNode; + + if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) { + var parentOldX = 0; + var parentOldY = 0; + + // New nodes appear from right-bottom corner in 'zoomToNode' animation. + // For convenience, get old bounding rect from background. + var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()]; + if (!reRoot && parentOldBg && parentOldBg.old) { + parentOldX = parentOldBg.old.width; + parentOldY = parentOldBg.old.height; + } + + // When no parent old shape found, its parent is new too, + // so we can just use {x:0, y:0}. + lastCfg.old = storageName === 'nodeGroup' + ? [0, parentOldY] + : {x: parentOldX, y: parentOldY, width: 0, height: 0}; + } + + // Fade in, user can be aware that these nodes are new. + lastCfg.fadein = storageName !== 'nodeGroup'; + } + } + + // We can not set all backgroud with the same z, Because the behaviour of + // drill down and roll up differ background creation sequence from tree + // hierarchy sequence, which cause that lowser background element overlap + // upper ones. So we calculate z based on depth. + // Moreover, we try to shrink down z interval to [0, 1] to avoid that + // treemap with large z overlaps other components. + function calculateZ(depth, zInLevel) { + var zb = depth * Z_BASE + zInLevel; + return (zb - 1) / zb; + } + + + +/***/ }, +/* 199 */ +/***/ function(module, exports, __webpack_require__) { + + + + var graphic = __webpack_require__(18); + var layout = __webpack_require__(71); + var zrUtil = __webpack_require__(4); + var helper = __webpack_require__(197); + + var TEXT_PADDING = 8; + var ITEM_GAP = 8; + var ARRAY_LENGTH = 5; + + function Breadcrumb(containerGroup) { + /** + * @private + * @type {module:zrender/container/Group} + */ + this.group = new graphic.Group(); + + containerGroup.add(this.group); + } + + Breadcrumb.prototype = { + + constructor: Breadcrumb, + + render: function (seriesModel, api, targetNode, onSelect) { + var model = seriesModel.getModel('breadcrumb'); + var thisGroup = this.group; + + thisGroup.removeAll(); + + if (!model.get('show') || !targetNode) { + return; + } + + var normalStyleModel = model.getModel('itemStyle.normal'); + // var emphasisStyleModel = model.getModel('itemStyle.emphasis'); + var textStyleModel = normalStyleModel.getModel('textStyle'); + + var layoutParam = { + pos: { + left: model.get('left'), + right: model.get('right'), + top: model.get('top'), + bottom: model.get('bottom') + }, + box: { + width: api.getWidth(), + height: api.getHeight() + }, + emptyItemWidth: model.get('emptyItemWidth'), + totalWidth: 0, + renderList: [] + }; + + this._prepare(targetNode, layoutParam, textStyleModel); + this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect); + + layout.positionElement(thisGroup, layoutParam.pos, layoutParam.box); + }, + + /** + * Prepare render list and total width + * @private + */ + _prepare: function (targetNode, layoutParam, textStyleModel) { + for (var node = targetNode; node; node = node.parentNode) { + var text = node.getModel().get('name'); + var textRect = textStyleModel.getTextRect(text); + var itemWidth = Math.max( + textRect.width + TEXT_PADDING * 2, + layoutParam.emptyItemWidth + ); + layoutParam.totalWidth += itemWidth + ITEM_GAP; + layoutParam.renderList.push({node: node, text: text, width: itemWidth}); + } + }, + + /** + * @private + */ + _renderContent: function ( + seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect + ) { + // Start rendering. + var lastX = 0; + var emptyItemWidth = layoutParam.emptyItemWidth; + var height = seriesModel.get('breadcrumb.height'); + var availableSize = layout.getAvailableSize(layoutParam.pos, layoutParam.box); + var totalWidth = layoutParam.totalWidth; + var renderList = layoutParam.renderList; + + for (var i = renderList.length - 1; i >= 0; i--) { + var item = renderList[i]; + var itemNode = item.node; + var itemWidth = item.width; + var text = item.text; + + // Hdie text and shorten width if necessary. + if (totalWidth > availableSize.width) { + totalWidth -= itemWidth - emptyItemWidth; + itemWidth = emptyItemWidth; + text = ''; + } + + var el = new graphic.Polygon({ + shape: { + points: makeItemPoints( + lastX, 0, itemWidth, height, + i === renderList.length - 1, i === 0 + ) + }, + style: zrUtil.defaults( + normalStyleModel.getItemStyle(), + { + lineJoin: 'bevel', + text: text, + textFill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont() + } + ), + z: 10, + onclick: zrUtil.curry(onSelect, itemNode) + }); + this.group.add(el); + + packEventData(el, seriesModel, itemNode); + + lastX += itemWidth + ITEM_GAP; + } + }, + + /** + * @override + */ + remove: function () { + this.group.removeAll(); + } + }; + + function makeItemPoints(x, y, itemWidth, itemHeight, head, tail) { + var points = [ + [head ? x : x - ARRAY_LENGTH, y], + [x + itemWidth, y], + [x + itemWidth, y + itemHeight], + [head ? x : x - ARRAY_LENGTH, y + itemHeight] + ]; + !tail && points.splice(2, 0, [x + itemWidth + ARRAY_LENGTH, y + itemHeight / 2]); + !head && points.push([x, y + itemHeight / 2]); + return points; + } + + // Package custom mouse event. + function packEventData(el, seriesModel, itemNode) { + el.eventData = { + componentType: 'series', + componentSubType: 'treemap', + seriesIndex: seriesModel.componentIndex, + seriesName: seriesModel.name, + seriesType: 'treemap', + selfType: 'breadcrumb', // Distinguish with click event on treemap node. + nodeData: { + dataIndex: itemNode && itemNode.dataIndex, + name: itemNode && itemNode.name + }, + treePathInfo: itemNode && helper.wrapTreePathInfo(itemNode, seriesModel) + }; + } + + module.exports = Breadcrumb; + + +/***/ }, +/* 200 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + /** + * @param {number} [time=500] Time in ms + * @param {string} [easing='linear'] + * @param {number} [delay=0] + * @param {Function} [callback] + * + * @example + * // Animate position + * animation + * .createWrap() + * .add(el1, {position: [10, 10]}) + * .add(el2, {shape: {width: 500}, style: {fill: 'red'}}, 400) + * .done(function () { // done }) + * .start('cubicOut'); + */ + function createWrap() { + + var storage = []; + var elExistsMap = {}; + var doneCallback; + + return { + + /** + * Caution: a el can only be added once, otherwise 'done' + * might not be called. This method checks this (by el.id), + * suppresses adding and returns false when existing el found. + * + * @param {modele:zrender/Element} el + * @param {Object} target + * @param {number} [time=500] + * @param {number} [delay=0] + * @param {string} [easing='linear'] + * @return {boolean} Whether adding succeeded. + * + * @example + * add(el, target, time, delay, easing); + * add(el, target, time, easing); + * add(el, target, time); + * add(el, target); + */ + add: function (el, target, time, delay, easing) { + if (zrUtil.isString(delay)) { + easing = delay; + delay = 0; + } + + if (elExistsMap[el.id]) { + return false; + } + elExistsMap[el.id] = 1; + + storage.push( + {el: el, target: target, time: time, delay: delay, easing: easing} + ); + + return true; + }, + + /** + * Only execute when animation finished. Will not execute when any + * of 'stop' or 'stopAnimation' called. + * + * @param {Function} callback + */ + done: function (callback) { + doneCallback = callback; + return this; + }, + + /** + * Will stop exist animation firstly. + */ + start: function () { + var count = storage.length; + + for (var i = 0, len = storage.length; i < len; i++) { + var item = storage[i]; + item.el.animateTo(item.target, item.time, item.delay, item.easing, done); + } + + return this; + + function done() { + count--; + if (!count) { + storage.length = 0; + elExistsMap = {}; + doneCallback && doneCallback(); + } + } + } + }; + } + + module.exports = {createWrap: createWrap}; + + +/***/ }, +/* 201 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Treemap action + */ + + + var echarts = __webpack_require__(1); + var helper = __webpack_require__(197); + + var noop = function () {}; + + var actionTypes = [ + 'treemapZoomToNode', + 'treemapRender', + 'treemapMove' + ]; + + for (var i = 0; i < actionTypes.length; i++) { + echarts.registerAction({type: actionTypes[i], update: 'updateView'}, noop); + } + + echarts.registerAction( + {type: 'treemapRootToNode', update: 'updateView'}, + function (payload, ecModel) { + + ecModel.eachComponent( + {mainType: 'series', subType: 'treemap', query: payload}, + handleRootToNode + ); + + function handleRootToNode(model, index) { + var targetInfo = helper.retrieveTargetInfo(payload, model); + + if (targetInfo) { + var originViewRoot = model.getViewRoot(); + if (originViewRoot) { + payload.direction = helper.aboveViewRoot(originViewRoot, targetInfo.node) + ? 'rollUp' : 'drillDown'; + } + model.resetViewRoot(targetInfo.node); + } + } + } + ); + + + +/***/ }, +/* 202 */ +/***/ function(module, exports, __webpack_require__) { + + + + var VisualMapping = __webpack_require__(203); + var zrColor = __webpack_require__(31); + var zrUtil = __webpack_require__(4); + var isArray = zrUtil.isArray; + + var ITEM_STYLE_NORMAL = 'itemStyle.normal'; + + module.exports = function (ecModel, api, payload) { + + var condition = {mainType: 'series', subType: 'treemap', query: payload}; + ecModel.eachComponent(condition, function (seriesModel) { + + var tree = seriesModel.getData().tree; + var root = tree.root; + var seriesItemStyleModel = seriesModel.getModel(ITEM_STYLE_NORMAL); + + if (root.isRemoved()) { + return; + } + + var levelItemStyles = zrUtil.map(tree.levelModels, function (levelModel) { + return levelModel ? levelModel.get(ITEM_STYLE_NORMAL) : null; + }); + + travelTree( + root, // Visual should calculate from tree root but not view root. + {}, + levelItemStyles, + seriesItemStyleModel, + seriesModel.getViewRoot().getAncestors(), + seriesModel + ); + }); + }; + + function travelTree( + node, designatedVisual, levelItemStyles, seriesItemStyleModel, + viewRootAncestors, seriesModel + ) { + var nodeModel = node.getModel(); + var nodeLayout = node.getLayout(); + + // Optimize + if (!nodeLayout || nodeLayout.invisible || !nodeLayout.isInView) { + return; + } + + var nodeItemStyleModel = node.getModel(ITEM_STYLE_NORMAL); + var levelItemStyle = levelItemStyles[node.depth]; + var visuals = buildVisuals( + nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel + ); + + // calculate border color + var borderColor = nodeItemStyleModel.get('borderColor'); + var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation'); + var thisNodeColor; + if (borderColorSaturation != null) { + // For performance, do not always execute 'calculateColor'. + thisNodeColor = calculateColor(visuals, node); + borderColor = calculateBorderColor(borderColorSaturation, thisNodeColor); + } + node.setVisual('borderColor', borderColor); + + var viewChildren = node.viewChildren; + if (!viewChildren || !viewChildren.length) { + thisNodeColor = calculateColor(visuals, node); + // Apply visual to this node. + node.setVisual('color', thisNodeColor); + } + else { + var mapping = buildVisualMapping( + node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren + ); + + // Designate visual to children. + zrUtil.each(viewChildren, function (child, index) { + // If higher than viewRoot, only ancestors of viewRoot is needed to visit. + if (child.depth >= viewRootAncestors.length + || child === viewRootAncestors[child.depth] + ) { + var childVisual = mapVisual( + nodeModel, visuals, child, index, mapping, seriesModel + ); + travelTree( + child, childVisual, levelItemStyles, seriesItemStyleModel, + viewRootAncestors, seriesModel + ); + } + }); + } + } + + function buildVisuals( + nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel + ) { + var visuals = zrUtil.extend({}, designatedVisual); + + zrUtil.each(['color', 'colorAlpha', 'colorSaturation'], function (visualName) { + // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel + var val = nodeItemStyleModel.get(visualName, true); // Ignore parent + val == null && levelItemStyle && (val = levelItemStyle[visualName]); + val == null && (val = designatedVisual[visualName]); + val == null && (val = seriesItemStyleModel.get(visualName)); + + val != null && (visuals[visualName] = val); + }); + + return visuals; + } + + function calculateColor(visuals) { + var color = getValueVisualDefine(visuals, 'color'); + + if (color) { + var colorAlpha = getValueVisualDefine(visuals, 'colorAlpha'); + var colorSaturation = getValueVisualDefine(visuals, 'colorSaturation'); + if (colorSaturation) { + color = zrColor.modifyHSL(color, null, null, colorSaturation); + } + if (colorAlpha) { + color = zrColor.modifyAlpha(color, colorAlpha); + } + + return color; + } + } + + function calculateBorderColor(borderColorSaturation, thisNodeColor) { + return thisNodeColor != null + ? zrColor.modifyHSL(thisNodeColor, null, null, borderColorSaturation) + : null; + } + + function getValueVisualDefine(visuals, name) { + var value = visuals[name]; + if (value != null && value !== 'none') { + return value; + } + } + + function buildVisualMapping( + node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren + ) { + if (!viewChildren || !viewChildren.length) { + return; + } + + var rangeVisual = getRangeVisual(nodeModel, 'color') + || ( + visuals.color != null + && visuals.color !== 'none' + && ( + getRangeVisual(nodeModel, 'colorAlpha') + || getRangeVisual(nodeModel, 'colorSaturation') + ) + ); + + if (!rangeVisual) { + return; + } + + var visualMin = nodeModel.get('visualMin'); + var visualMax = nodeModel.get('visualMax'); + var dataExtent = nodeLayout.dataExtent.slice(); + visualMin != null && visualMin < dataExtent[0] && (dataExtent[0] = visualMin); + visualMax != null && visualMax > dataExtent[1] && (dataExtent[1] = visualMax); + + var colorMappingBy = nodeModel.get('colorMappingBy'); + var opt = { + type: rangeVisual.name, + dataExtent: dataExtent, + visual: rangeVisual.range + }; + if (opt.type === 'color' + && (colorMappingBy === 'index' || colorMappingBy === 'id') + ) { + opt.mappingMethod = 'category'; + opt.loop = true; + // categories is ordinal, so do not set opt.categories. + } + else { + opt.mappingMethod = 'linear'; + } + + var mapping = new VisualMapping(opt); + mapping.__drColorMappingBy = colorMappingBy; + + return mapping; + } + + // Notice: If we dont have the attribute 'colorRange', but only use + // attribute 'color' to represent both concepts of 'colorRange' and 'color', + // (It means 'colorRange' when 'color' is Array, means 'color' when not array), + // this problem will be encountered: + // If a level-1 node dont have children, and its siblings has children, + // and colorRange is set on level-1, then the node can not be colored. + // So we separate 'colorRange' and 'color' to different attributes. + function getRangeVisual(nodeModel, name) { + // 'colorRange', 'colorARange', 'colorSRange'. + // If not exsits on this node, fetch from levels and series. + var range = nodeModel.get(name); + return (isArray(range) && range.length) ? {name: name, range: range} : null; + } + + function mapVisual(nodeModel, visuals, child, index, mapping, seriesModel) { + var childVisuals = zrUtil.extend({}, visuals); + + if (mapping) { + var mappingType = mapping.type; + var colorMappingBy = mappingType === 'color' && mapping.__drColorMappingBy; + var value = + colorMappingBy === 'index' + ? index + : colorMappingBy === 'id' + ? seriesModel.mapIdToIndex(child.getId()) + : child.getValue(nodeModel.get('visualDimension')); + + childVisuals[mappingType] = mapping.mapValueToVisual(value); + } + + return childVisuals; + } + + + +/***/ }, +/* 203 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Visual mapping. + */ + + + var zrUtil = __webpack_require__(4); + var zrColor = __webpack_require__(31); + var linearMap = __webpack_require__(7).linearMap; + var each = zrUtil.each; + var isObject = zrUtil.isObject; + + var CATEGORY_DEFAULT_VISUAL_INDEX = -1; + + /** + * @param {Object} option + * @param {string} [option.type] See visualHandlers. + * @param {string} [option.mappingMethod] 'linear' or 'piecewise' or 'category' or 'fixed' + * @param {Array.=} [option.dataExtent] [minExtent, maxExtent], + * required when mappingMethod is 'linear' + * @param {Array.=} [option.pieceList] [ + * {value: someValue}, + * {interval: [min1, max1], visual: {...}}, + * {interval: [min2, max2]} + * ], + * required when mappingMethod is 'piecewise'. + * Visual for only each piece can be specified. + * @param {Array.=} [option.categories] ['cate1', 'cate2'] + * required when mappingMethod is 'category'. + * If no option.categories, categories is set + * as [0, 1, 2, ...]. + * @param {boolean} [option.loop=false] Whether loop mapping when mappingMethod is 'category'. + * @param {(Array|Object|*)} [option.visual] Visual data. + * when mappingMethod is 'category', + * visual data can be array or object + * (like: {cate1: '#222', none: '#fff'}) + * or primary types (which represents + * defualt category visual), otherwise visual + * can be array or primary (which will be + * normalized to array). + * + */ + var VisualMapping = function (option) { + var mappingMethod = option.mappingMethod; + var visualType = option.type; + + /** + * @readOnly + * @type {Object} + */ + var thisOption = this.option = zrUtil.clone(option); + + /** + * @readOnly + * @type {string} + */ + this.type = visualType; + + /** + * @readOnly + * @type {string} + */ + this.mappingMethod = mappingMethod; + + /** + * @private + * @type {Function} + */ + this._normalizeData = normalizers[mappingMethod]; + + var visualHandler = visualHandlers[visualType]; + + /** + * @public + * @type {Function} + */ + this.applyVisual = visualHandler.applyVisual; + + /** + * @public + * @type {Function} + */ + this.getColorMapper = visualHandler.getColorMapper; + + /** + * @private + * @type {Function} + */ + this._doMap = visualHandler._doMap[mappingMethod]; + + if (mappingMethod === 'piecewise') { + normalizeVisualRange(thisOption); + preprocessForPiecewise(thisOption); + } + else if (mappingMethod === 'category') { + thisOption.categories + ? preprocessForSpecifiedCategory(thisOption) + // categories is ordinal when thisOption.categories not specified, + // which need no more preprocess except normalize visual. + : normalizeVisualRange(thisOption, true); + } + else { // mappingMethod === 'linear' or 'fixed' + zrUtil.assert(mappingMethod !== 'linear' || thisOption.dataExtent); + normalizeVisualRange(thisOption); + } + }; + + VisualMapping.prototype = { + + constructor: VisualMapping, + + mapValueToVisual: function (value) { + var normalized = this._normalizeData(value); + return this._doMap(normalized, value); + }, + + getNormalizer: function () { + return zrUtil.bind(this._normalizeData, this); + } + }; + + var visualHandlers = VisualMapping.visualHandlers = { + + color: { + + applyVisual: makeApplyVisual('color'), + + /** + * Create a mapper function + * @return {Function} + */ + getColorMapper: function () { + var thisOption = this.option; + + return zrUtil.bind( + thisOption.mappingMethod === 'category' + ? function (value, isNormalized) { + !isNormalized && (value = this._normalizeData(value)); + return doMapCategory.call(this, value); + } + : function (value, isNormalized, out) { + // If output rgb array + // which will be much faster and useful in pixel manipulation + var returnRGBArray = !!out; + !isNormalized && (value = this._normalizeData(value)); + out = zrColor.fastMapToColor(value, thisOption.parsedVisual, out); + return returnRGBArray ? out : zrColor.stringify(out, 'rgba'); + }, + this + ); + }, + + _doMap: { + linear: function (normalized) { + return zrColor.stringify( + zrColor.fastMapToColor(normalized, this.option.parsedVisual), + 'rgba' + ); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + if (result == null) { + result = zrColor.stringify( + zrColor.fastMapToColor(normalized, this.option.parsedVisual), + 'rgba' + ); + } + return result; + }, + fixed: doMapFixed + } + }, + + colorHue: makePartialColorVisualHandler(function (color, value) { + return zrColor.modifyHSL(color, value); + }), + + colorSaturation: makePartialColorVisualHandler(function (color, value) { + return zrColor.modifyHSL(color, null, value); + }), + + colorLightness: makePartialColorVisualHandler(function (color, value) { + return zrColor.modifyHSL(color, null, null, value); + }), + + colorAlpha: makePartialColorVisualHandler(function (color, value) { + return zrColor.modifyAlpha(color, value); + }), + + opacity: { + applyVisual: makeApplyVisual('opacity'), + _doMap: makeDoMap([0, 1]) + }, + + symbol: { + applyVisual: function (value, getter, setter) { + var symbolCfg = this.mapValueToVisual(value); + if (zrUtil.isString(symbolCfg)) { + setter('symbol', symbolCfg); + } + else if (isObject(symbolCfg)) { + for (var name in symbolCfg) { + if (symbolCfg.hasOwnProperty(name)) { + setter(name, symbolCfg[name]); + } + } + } + }, + _doMap: { + linear: doMapToArray, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + if (result == null) { + result = doMapToArray.call(this, normalized); + } + return result; + }, + fixed: doMapFixed + } + }, + + symbolSize: { + applyVisual: makeApplyVisual('symbolSize'), + _doMap: makeDoMap([0, 1]) + } + }; + + + function preprocessForPiecewise(thisOption) { + var pieceList = thisOption.pieceList; + thisOption.hasSpecialVisual = false; + + zrUtil.each(pieceList, function (piece, index) { + piece.originIndex = index; + // piece.visual is "result visual value" but not + // a visual range, so it does not need to be normalized. + if (piece.visual != null) { + thisOption.hasSpecialVisual = true; + } + }); + } + + function preprocessForSpecifiedCategory(thisOption) { + // Hash categories. + var categories = thisOption.categories; + var visual = thisOption.visual; + + var categoryMap = thisOption.categoryMap = {}; + each(categories, function (cate, index) { + categoryMap[cate] = index; + }); + + // Process visual map input. + if (!zrUtil.isArray(visual)) { + var visualArr = []; + + if (zrUtil.isObject(visual)) { + each(visual, function (v, cate) { + var index = categoryMap[cate]; + visualArr[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v; + }); + } + else { // Is primary type, represents default visual. + visualArr[CATEGORY_DEFAULT_VISUAL_INDEX] = visual; + } + + visual = setVisualToOption(thisOption, visualArr); + } + + // Remove categories that has no visual, + // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX. + for (var i = categories.length - 1; i >= 0; i--) { + if (visual[i] == null) { + delete categoryMap[categories[i]]; + categories.pop(); + } + } + } + + function normalizeVisualRange(thisOption, isCategory) { + var visual = thisOption.visual; + var visualArr = []; + + if (zrUtil.isObject(visual)) { + each(visual, function (v) { + visualArr.push(v); + }); + } + else if (visual != null) { + visualArr.push(visual); + } + + var doNotNeedPair = {color: 1, symbol: 1}; + + if (!isCategory + && visualArr.length === 1 + && !doNotNeedPair.hasOwnProperty(thisOption.type) + ) { + // Do not care visualArr.length === 0, which is illegal. + visualArr[1] = visualArr[0]; + } + + setVisualToOption(thisOption, visualArr); + } + + function makePartialColorVisualHandler(applyValue) { + return { + applyVisual: function (value, getter, setter) { + value = this.mapValueToVisual(value); + // Must not be array value + setter('color', applyValue(getter('color'), value)); + }, + _doMap: makeDoMap([0, 1]) + }; + } + + function doMapToArray(normalized) { + var visual = this.option.visual; + return visual[ + Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true)) + ] || {}; + } + + function makeApplyVisual(visualType) { + return function (value, getter, setter) { + setter(visualType, this.mapValueToVisual(value)); + }; + } + + function doMapCategory(normalized) { + var visual = this.option.visual; + return visual[ + (this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX) + ? normalized % visual.length + : normalized + ]; + } + + function doMapFixed() { + return this.option.visual[0]; + } + + function makeDoMap(sourceExtent) { + return { + linear: function (normalized) { + return linearMap(normalized, sourceExtent, this.option.visual, true); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + if (result == null) { + result = linearMap(normalized, sourceExtent, this.option.visual, true); + } + return result; + }, + fixed: doMapFixed + }; + } + + function getSpecifiedVisual(value) { + var thisOption = this.option; + var pieceList = thisOption.pieceList; + if (thisOption.hasSpecialVisual) { + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList); + var piece = pieceList[pieceIndex]; + if (piece && piece.visual) { + return piece.visual[this.type]; + } + } + } + + function setVisualToOption(thisOption, visualArr) { + thisOption.visual = visualArr; + if (thisOption.type === 'color') { + thisOption.parsedVisual = zrUtil.map(visualArr, function (item) { + return zrColor.parse(item); + }); + } + return visualArr; + } + + + /** + * Normalizers by mapping methods. + */ + var normalizers = { + + linear: function (value) { + return linearMap(value, this.option.dataExtent, [0, 1], true); + }, + + piecewise: function (value) { + var pieceList = this.option.pieceList; + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true); + if (pieceIndex != null) { + return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true); + } + }, + + category: function (value) { + var index = this.option.categories + ? this.option.categoryMap[value] + : value; // ordinal + return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index; + }, + + fixed: zrUtil.noop + }; + + + + /** + * List available visual types. + * + * @public + * @return {Array.} + */ + VisualMapping.listVisualTypes = function () { + var visualTypes = []; + zrUtil.each(visualHandlers, function (handler, key) { + visualTypes.push(key); + }); + return visualTypes; + }; + + /** + * @public + */ + VisualMapping.addVisualHandler = function (name, handler) { + visualHandlers[name] = handler; + }; + + /** + * @public + */ + VisualMapping.isValidType = function (visualType) { + return visualHandlers.hasOwnProperty(visualType); + }; + + /** + * Convinent method. + * Visual can be Object or Array or primary type. + * + * @public + */ + VisualMapping.eachVisual = function (visual, callback, context) { + if (zrUtil.isObject(visual)) { + zrUtil.each(visual, callback, context); + } + else { + callback.call(context, visual); + } + }; + + VisualMapping.mapVisual = function (visual, callback, context) { + var isPrimary; + var newVisual = zrUtil.isArray(visual) + ? [] + : zrUtil.isObject(visual) + ? {} + : (isPrimary = true, null); + + VisualMapping.eachVisual(visual, function (v, key) { + var newVal = callback.call(context, v, key); + isPrimary ? (newVisual = newVal) : (newVisual[key] = newVal); + }); + return newVisual; + }; + + /** + * @public + * @param {Object} obj + * @return {Oject} new object containers visual values. + * If no visuals, return null. + */ + VisualMapping.retrieveVisuals = function (obj) { + var ret = {}; + var hasVisual; + + obj && each(visualHandlers, function (h, visualType) { + if (obj.hasOwnProperty(visualType)) { + ret[visualType] = obj[visualType]; + hasVisual = true; + } + }); + + return hasVisual ? ret : null; + }; + + /** + * Give order to visual types, considering colorSaturation, colorAlpha depends on color. + * + * @public + * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...} + * IF Array, like: ['color', 'symbol', 'colorSaturation'] + * @return {Array.} Sorted visual types. + */ + VisualMapping.prepareVisualTypes = function (visualTypes) { + if (isObject(visualTypes)) { + var types = []; + each(visualTypes, function (item, type) { + types.push(type); + }); + visualTypes = types; + } + else if (zrUtil.isArray(visualTypes)) { + visualTypes = visualTypes.slice(); + } + else { + return []; + } + + visualTypes.sort(function (type1, type2) { + // color should be front of colorSaturation, colorAlpha, ... + // symbol and symbolSize do not matter. + return (type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0) + ? 1 : -1; + }); + + return visualTypes; + }; + + /** + * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'. + * Other visuals are only depends on themself. + * + * @public + * @param {string} visualType1 + * @param {string} visualType2 + * @return {boolean} + */ + VisualMapping.dependsOn = function (visualType1, visualType2) { + return visualType2 === 'color' + ? !!(visualType1 && visualType1.indexOf(visualType2) === 0) + : visualType1 === visualType2; + }; + + /** + * @param {number} value + * @param {Array.} pieceList [{value: ..., interval: [min, max]}, ...] + * Always from small to big. + * @param {boolean} [findClosestWhenOutside=false] + * @return {number} index + */ + VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) { + var possibleI; + var abs = Infinity; + + // value has the higher priority. + for (var i = 0, len = pieceList.length; i < len; i++) { + var pieceValue = pieceList[i].value; + if (pieceValue != null) { + if (pieceValue === value + // FIXME + // It is supposed to compare value according to value type of dimension, + // but currently value type can exactly be string or number. + // Compromise for numeric-like string (like '12'), especially + // in the case that visualMap.categories is ['22', '33']. + || (typeof pieceValue === 'string' && pieceValue === value + '') + ) { + return i; + } + findClosestWhenOutside && updatePossible(pieceValue, i); + } + } + + for (var i = 0, len = pieceList.length; i < len; i++) { + var piece = pieceList[i]; + var interval = piece.interval; + var close = piece.close; + + if (interval) { + if (interval[0] === -Infinity) { + if (littleThan(close[1], value, interval[1])) { + return i; + } + } + else if (interval[1] === Infinity) { + if (littleThan(close[0], interval[0], value)) { + return i; + } + } + else if ( + littleThan(close[0], interval[0], value) + && littleThan(close[1], value, interval[1]) + ) { + return i; + } + findClosestWhenOutside && updatePossible(interval[0], i); + findClosestWhenOutside && updatePossible(interval[1], i); + } + } + + if (findClosestWhenOutside) { + return value === Infinity + ? pieceList.length - 1 + : value === -Infinity + ? 0 + : possibleI; + } + + function updatePossible(val, index) { + var newAbs = Math.abs(val - value); + if (newAbs < abs) { + abs = newAbs; + possibleI = index; + } + } + + }; + + function littleThan(close, a, b) { + return close ? a <= b : a < b; + } + + module.exports = VisualMapping; + + + +/***/ }, +/* 204 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var layout = __webpack_require__(71); + var helper = __webpack_require__(197); + var BoundingRect = __webpack_require__(9); + var helper = __webpack_require__(197); + + var mathMax = Math.max; + var mathMin = Math.min; + var parsePercent = numberUtil.parsePercent; + var retrieveValue = zrUtil.retrieve; + var each = zrUtil.each; + + var PATH_BORDER_WIDTH = ['itemStyle', 'normal', 'borderWidth']; + var PATH_GAP_WIDTH = ['itemStyle', 'normal', 'gapWidth']; + var PATH_UPPER_LABEL_SHOW = ['upperLabel', 'normal', 'show']; + var PATH_UPPER_LABEL_HEIGHT = ['upperLabel', 'normal', 'height']; + + /** + * @public + */ + function update(ecModel, api, payload) { + // Layout result in each node: + // {x, y, width, height, area, borderWidth} + var condition = {mainType: 'series', subType: 'treemap', query: payload}; + ecModel.eachComponent(condition, function (seriesModel) { + + var ecWidth = api.getWidth(); + var ecHeight = api.getHeight(); + var seriesOption = seriesModel.option; + + var layoutInfo = layout.getLayoutRect( + seriesModel.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + } + ); + + var size = seriesOption.size || []; // Compatible with ec2. + var containerWidth = parsePercent( + retrieveValue(layoutInfo.width, size[0]), + ecWidth + ); + var containerHeight = parsePercent( + retrieveValue(layoutInfo.height, size[1]), + ecHeight + ); + + // Fetch payload info. + var payloadType = payload && payload.type; + var targetInfo = helper.retrieveTargetInfo(payload, seriesModel); + var rootRect = (payloadType === 'treemapRender' || payloadType === 'treemapMove') + ? payload.rootRect : null; + var viewRoot = seriesModel.getViewRoot(); + var viewAbovePath = helper.getPathToRoot(viewRoot); + + if (payloadType !== 'treemapMove') { + var rootSize = payloadType === 'treemapZoomToNode' + ? estimateRootSize( + seriesModel, targetInfo, viewRoot, containerWidth, containerHeight + ) + : rootRect + ? [rootRect.width, rootRect.height] + : [containerWidth, containerHeight]; + + var sort = seriesOption.sort; + if (sort && sort !== 'asc' && sort !== 'desc') { + sort = 'desc'; + } + var options = { + squareRatio: seriesOption.squareRatio, + sort: sort, + leafDepth: seriesOption.leafDepth + }; + + // layout should be cleared because using updateView but not update. + viewRoot.hostTree.clearLayouts(); + + // TODO + // optimize: if out of view clip, do not layout. + // But take care that if do not render node out of view clip, + // how to calculate start po + + var viewRootLayout = { + x: 0, y: 0, + width: rootSize[0], height: rootSize[1], + area: rootSize[0] * rootSize[1] + }; + viewRoot.setLayout(viewRootLayout); + + squarify(viewRoot, options, false, 0); + // Supplement layout. + var viewRootLayout = viewRoot.getLayout(); + each(viewAbovePath, function (node, index) { + var childValue = (viewAbovePath[index + 1] || viewRoot).getValue(); + node.setLayout(zrUtil.extend( + {dataExtent: [childValue, childValue], borderWidth: 0, upperHeight: 0}, + viewRootLayout + )); + }); + } + + var treeRoot = seriesModel.getData().tree.root; + + treeRoot.setLayout( + calculateRootPosition(layoutInfo, rootRect, targetInfo), + true + ); + + seriesModel.setLayoutInfo(layoutInfo); + + // FIXME + // 现在没有clip功能,暂时取ec高宽。 + prunning( + treeRoot, + // Transform to base element coordinate system. + new BoundingRect(-layoutInfo.x, -layoutInfo.y, ecWidth, ecHeight), + viewAbovePath, + viewRoot, + 0 + ); + }); + } + + /** + * Layout treemap with squarify algorithm. + * @see https://graphics.ethz.ch/teaching/scivis_common/Literature/squarifiedTreeMaps.pdf + * @see https://github.com/mbostock/d3/blob/master/src/layout/treemap.js + * + * @protected + * @param {module:echarts/data/Tree~TreeNode} node + * @param {Object} options + * @param {string} options.sort 'asc' or 'desc' + * @param {number} options.squareRatio + * @param {boolean} hideChildren + * @param {number} depth + */ + function squarify(node, options, hideChildren, depth) { + var width; + var height; + + if (node.isRemoved()) { + return; + } + + var thisLayout = node.getLayout(); + width = thisLayout.width; + height = thisLayout.height; + + // Considering border and gap + var nodeModel = node.getModel(); + var borderWidth = nodeModel.get(PATH_BORDER_WIDTH); + var halfGapWidth = nodeModel.get(PATH_GAP_WIDTH) / 2; + var upperLabelHeight = getUpperLabelHeight(nodeModel); + var upperHeight = Math.max(borderWidth, upperLabelHeight); + var layoutOffset = borderWidth - halfGapWidth; + var layoutOffsetUpper = upperHeight - halfGapWidth; + var nodeModel = node.getModel(); + + node.setLayout({ + borderWidth: borderWidth, + upperHeight: upperHeight, + upperLabelHeight: upperLabelHeight + }, true); + + width = mathMax(width - 2 * layoutOffset, 0); + height = mathMax(height - layoutOffset - layoutOffsetUpper, 0); + + var totalArea = width * height; + var viewChildren = initChildren( + node, nodeModel, totalArea, options, hideChildren, depth + ); + + if (!viewChildren.length) { + return; + } + + var rect = {x: layoutOffset, y: layoutOffsetUpper, width: width, height: height}; + var rowFixedLength = mathMin(width, height); + var best = Infinity; // the best row score so far + var row = []; + row.area = 0; + + for (var i = 0, len = viewChildren.length; i < len;) { + var child = viewChildren[i]; + + row.push(child); + row.area += child.getLayout().area; + var score = worst(row, rowFixedLength, options.squareRatio); + + // continue with this orientation + if (score <= best) { + i++; + best = score; + } + // abort, and try a different orientation + else { + row.area -= row.pop().getLayout().area; + position(row, rowFixedLength, rect, halfGapWidth, false); + rowFixedLength = mathMin(rect.width, rect.height); + row.length = row.area = 0; + best = Infinity; + } + } + + if (row.length) { + position(row, rowFixedLength, rect, halfGapWidth, true); + } + + if (!hideChildren) { + var childrenVisibleMin = nodeModel.get('childrenVisibleMin'); + if (childrenVisibleMin != null && totalArea < childrenVisibleMin) { + hideChildren = true; + } + } + + for (var i = 0, len = viewChildren.length; i < len; i++) { + squarify(viewChildren[i], options, hideChildren, depth + 1); + } + } + + /** + * Set area to each child, and calculate data extent for visual coding. + */ + function initChildren(node, nodeModel, totalArea, options, hideChildren, depth) { + var viewChildren = node.children || []; + var orderBy = options.sort; + orderBy !== 'asc' && orderBy !== 'desc' && (orderBy = null); + + var overLeafDepth = options.leafDepth != null && options.leafDepth <= depth; + + // leafDepth has higher priority. + if (hideChildren && !overLeafDepth) { + return (node.viewChildren = []); + } + + // Sort children, order by desc. + viewChildren = zrUtil.filter(viewChildren, function (child) { + return !child.isRemoved(); + }); + + sort(viewChildren, orderBy); + + var info = statistic(nodeModel, viewChildren, orderBy); + + if (info.sum === 0) { + return (node.viewChildren = []); + } + + info.sum = filterByThreshold(nodeModel, totalArea, info.sum, orderBy, viewChildren); + + if (info.sum === 0) { + return (node.viewChildren = []); + } + + // Set area to each child. + for (var i = 0, len = viewChildren.length; i < len; i++) { + var area = viewChildren[i].getValue() / info.sum * totalArea; + // Do not use setLayout({...}, true), because it is needed to clear last layout. + viewChildren[i].setLayout({area: area}); + } + + if (overLeafDepth) { + viewChildren.length && node.setLayout({isLeafRoot: true}, true); + viewChildren.length = 0; + } + + node.viewChildren = viewChildren; + node.setLayout({dataExtent: info.dataExtent}, true); + + return viewChildren; + } + + /** + * Consider 'visibleMin'. Modify viewChildren and get new sum. + */ + function filterByThreshold(nodeModel, totalArea, sum, orderBy, orderedChildren) { + + // visibleMin is not supported yet when no option.sort. + if (!orderBy) { + return sum; + } + + var visibleMin = nodeModel.get('visibleMin'); + var len = orderedChildren.length; + var deletePoint = len; + + // Always travel from little value to big value. + for (var i = len - 1; i >= 0; i--) { + var value = orderedChildren[ + orderBy === 'asc' ? len - i - 1 : i + ].getValue(); + + if (value / sum * totalArea < visibleMin) { + deletePoint = i; + sum -= value; + } + } + + orderBy === 'asc' + ? orderedChildren.splice(0, len - deletePoint) + : orderedChildren.splice(deletePoint, len - deletePoint); + + return sum; + } + + /** + * Sort + */ + function sort(viewChildren, orderBy) { + if (orderBy) { + viewChildren.sort(function (a, b) { + var diff = orderBy === 'asc' + ? a.getValue() - b.getValue() : b.getValue() - a.getValue(); + return diff === 0 + ? (orderBy === 'asc' + ? a.dataIndex - b.dataIndex : b.dataIndex - a.dataIndex + ) + : diff; + }); + } + return viewChildren; + } + + /** + * Statistic + */ + function statistic(nodeModel, children, orderBy) { + // Calculate sum. + var sum = 0; + for (var i = 0, len = children.length; i < len; i++) { + sum += children[i].getValue(); + } + + // Statistic data extent for latter visual coding. + // Notice: data extent should be calculate based on raw children + // but not filtered view children, otherwise visual mapping will not + // be stable when zoom (where children is filtered by visibleMin). + + var dimension = nodeModel.get('visualDimension'); + var dataExtent; + + // The same as area dimension. + if (!children || !children.length) { + dataExtent = [NaN, NaN]; + } + else if (dimension === 'value' && orderBy) { + dataExtent = [ + children[children.length - 1].getValue(), + children[0].getValue() + ]; + orderBy === 'asc' && dataExtent.reverse(); + } + // Other dimension. + else { + var dataExtent = [Infinity, -Infinity]; + each(children, function (child) { + var value = child.getValue(dimension); + value < dataExtent[0] && (dataExtent[0] = value); + value > dataExtent[1] && (dataExtent[1] = value); + }); + } + + return {sum: sum, dataExtent: dataExtent}; + } + + /** + * Computes the score for the specified row, + * as the worst aspect ratio. + */ + function worst(row, rowFixedLength, ratio) { + var areaMax = 0; + var areaMin = Infinity; + + for (var i = 0, area, len = row.length; i < len; i++) { + area = row[i].getLayout().area; + if (area) { + area < areaMin && (areaMin = area); + area > areaMax && (areaMax = area); + } + } + + var squareArea = row.area * row.area; + var f = rowFixedLength * rowFixedLength * ratio; + + return squareArea + ? mathMax( + (f * areaMax) / squareArea, + squareArea / (f * areaMin) + ) + : Infinity; + } + + /** + * Positions the specified row of nodes. Modifies `rect`. + */ + function position(row, rowFixedLength, rect, halfGapWidth, flush) { + // When rowFixedLength === rect.width, + // it is horizontal subdivision, + // rowFixedLength is the width of the subdivision, + // rowOtherLength is the height of the subdivision, + // and nodes will be positioned from left to right. + + // wh[idx0WhenH] means: when horizontal, + // wh[idx0WhenH] => wh[0] => 'width'. + // xy[idx1WhenH] => xy[1] => 'y'. + var idx0WhenH = rowFixedLength === rect.width ? 0 : 1; + var idx1WhenH = 1 - idx0WhenH; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + + var last = rect[xy[idx0WhenH]]; + var rowOtherLength = rowFixedLength + ? row.area / rowFixedLength : 0; + + if (flush || rowOtherLength > rect[wh[idx1WhenH]]) { + rowOtherLength = rect[wh[idx1WhenH]]; // over+underflow + } + for (var i = 0, rowLen = row.length; i < rowLen; i++) { + var node = row[i]; + var nodeLayout = {}; + var step = rowOtherLength + ? node.getLayout().area / rowOtherLength : 0; + + var wh1 = nodeLayout[wh[idx1WhenH]] = mathMax(rowOtherLength - 2 * halfGapWidth, 0); + + // We use Math.max/min to avoid negative width/height when considering gap width. + var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last; + var modWH = (i === rowLen - 1 || remain < step) ? remain : step; + var wh0 = nodeLayout[wh[idx0WhenH]] = mathMax(modWH - 2 * halfGapWidth, 0); + + nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + mathMin(halfGapWidth, wh1 / 2); + nodeLayout[xy[idx0WhenH]] = last + mathMin(halfGapWidth, wh0 / 2); + + last += modWH; + node.setLayout(nodeLayout, true); + } + + rect[xy[idx1WhenH]] += rowOtherLength; + rect[wh[idx1WhenH]] -= rowOtherLength; + } + + // Return [containerWidth, containerHeight] as defualt. + function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) { + // If targetInfo.node exists, we zoom to the node, + // so estimate whold width and heigth by target node. + var currNode = (targetInfo || {}).node; + var defaultSize = [containerWidth, containerHeight]; + + if (!currNode || currNode === viewRoot) { + return defaultSize; + } + + var parent; + var viewArea = containerWidth * containerHeight; + var area = viewArea * seriesModel.option.zoomToNodeRatio; + + while (parent = currNode.parentNode) { // jshint ignore:line + var sum = 0; + var siblings = parent.children; + + for (var i = 0, len = siblings.length; i < len; i++) { + sum += siblings[i].getValue(); + } + var currNodeValue = currNode.getValue(); + if (currNodeValue === 0) { + return defaultSize; + } + area *= sum / currNodeValue; + + // Considering border, suppose aspect ratio is 1. + var parentModel = parent.getModel(); + var borderWidth = parentModel.get(PATH_BORDER_WIDTH); + var upperHeight = Math.max(borderWidth, getUpperLabelHeight(parentModel, borderWidth)); + area += 4 * borderWidth * borderWidth + + (3 * borderWidth + upperHeight) * Math.pow(area, 0.5); + + area > numberUtil.MAX_SAFE_INTEGER && (area = numberUtil.MAX_SAFE_INTEGER); + + currNode = parent; + } + + area < viewArea && (area = viewArea); + var scale = Math.pow(area / viewArea, 0.5); + + return [containerWidth * scale, containerHeight * scale]; + } + + // Root postion base on coord of containerGroup + function calculateRootPosition(layoutInfo, rootRect, targetInfo) { + if (rootRect) { + return {x: rootRect.x, y: rootRect.y}; + } + + var defaultPosition = {x: 0, y: 0}; + if (!targetInfo) { + return defaultPosition; + } + + // If targetInfo is fetched by 'retrieveTargetInfo', + // old tree and new tree are the same tree, + // so the node still exists and we can visit it. + + var targetNode = targetInfo.node; + var layout = targetNode.getLayout(); + + if (!layout) { + return defaultPosition; + } + + // Transform coord from local to container. + var targetCenter = [layout.width / 2, layout.height / 2]; + var node = targetNode; + while (node) { + var nodeLayout = node.getLayout(); + targetCenter[0] += nodeLayout.x; + targetCenter[1] += nodeLayout.y; + node = node.parentNode; + } + + return { + x: layoutInfo.width / 2 - targetCenter[0], + y: layoutInfo.height / 2 - targetCenter[1] + }; + } + + // Mark nodes visible for prunning when visual coding and rendering. + // Prunning depends on layout and root position, so we have to do it after layout. + function prunning(node, clipRect, viewAbovePath, viewRoot, depth) { + var nodeLayout = node.getLayout(); + var nodeInViewAbovePath = viewAbovePath[depth]; + var isAboveViewRoot = nodeInViewAbovePath && nodeInViewAbovePath === node; + + if ( + (nodeInViewAbovePath && !isAboveViewRoot) + || (depth === viewAbovePath.length && node !== viewRoot) + ) { + return; + } + + node.setLayout({ + // isInView means: viewRoot sub tree + viewAbovePath + isInView: true, + // invisible only means: outside view clip so that the node can not + // see but still layout for animation preparation but not render. + invisible: !isAboveViewRoot && !clipRect.intersect(nodeLayout), + isAboveViewRoot: isAboveViewRoot + }, true); + + // Transform to child coordinate. + var childClipRect = new BoundingRect( + clipRect.x - nodeLayout.x, + clipRect.y - nodeLayout.y, + clipRect.width, + clipRect.height + ); + + each(node.viewChildren || [], function (child) { + prunning(child, childClipRect, viewAbovePath, viewRoot, depth + 1); + }); + } + + function getUpperLabelHeight(model) { + return model.get(PATH_UPPER_LABEL_SHOW) ? model.get(PATH_UPPER_LABEL_HEIGHT) : 0; + } + + module.exports = update; + + +/***/ }, +/* 205 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + + __webpack_require__(206); + __webpack_require__(209); + + __webpack_require__(214); + + echarts.registerProcessor(__webpack_require__(215)); + + echarts.registerVisual(zrUtil.curry( + __webpack_require__(121), 'graph', 'circle', null + )); + echarts.registerVisual(__webpack_require__(216)); + echarts.registerVisual(__webpack_require__(217)); + + echarts.registerLayout(__webpack_require__(218)); + echarts.registerLayout(__webpack_require__(221)); + echarts.registerLayout(__webpack_require__(223)); + + // Graph view coordinate system + echarts.registerCoordinateSystem('graphView', { + create: __webpack_require__(225) + }); + + +/***/ }, +/* 206 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var List = __webpack_require__(98); + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var Model = __webpack_require__(12); + var formatUtil = __webpack_require__(6); + + var createGraphFromNodeEdge = __webpack_require__(207); + + var GraphSeries = __webpack_require__(1).extendSeriesModel({ + + type: 'series.graph', + + init: function (option) { + GraphSeries.superApply(this, 'init', arguments); + + // Provide data for legend select + this.legendDataProvider = function () { + return this._categoriesData; + }; + + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }, + + mergeOption: function (option) { + GraphSeries.superApply(this, 'mergeOption', arguments); + + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }, + + mergeDefaultAndTheme: function (option) { + GraphSeries.superApply(this, 'mergeDefaultAndTheme', arguments); + modelUtil.defaultEmphasis(option.edgeLabel, modelUtil.LABEL_OPTIONS); + }, + + getInitialData: function (option, ecModel) { + var edges = option.edges || option.links || []; + var nodes = option.data || option.nodes || []; + var self = this; + + if (nodes && edges) { + return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data; + } + + function beforeLink(nodeData, edgeData) { + // Overwrite nodeData.getItemModel to + nodeData.wrapMethod('getItemModel', function (model) { + var categoriesModels = self._categoriesModels; + var categoryIdx = model.getShallow('category'); + var categoryModel = categoriesModels[categoryIdx]; + if (categoryModel) { + categoryModel.parentModel = model.parentModel; + model.parentModel = categoryModel; + } + return model; + }); + + var edgeLabelModel = self.getModel('edgeLabel'); + // For option `edgeLabel` can be found by label.xxx.xxx on item mode. + var fakeSeriesModel = new Model( + {label: edgeLabelModel.option}, + edgeLabelModel.parentModel, + ecModel + ); + + edgeData.wrapMethod('getItemModel', function (model) { + model.customizeGetParent(edgeGetParent); + return model; + }); + + function edgeGetParent(path) { + path = this.parsePath(path); + return (path && path[0] === 'label') + ? fakeSeriesModel + : this.parentModel; + } + } + }, + + /** + * @return {module:echarts/data/Graph} + */ + getGraph: function () { + return this.getData().graph; + }, + + /** + * @return {module:echarts/data/List} + */ + getEdgeData: function () { + return this.getGraph().edgeData; + }, + + /** + * @return {module:echarts/data/List} + */ + getCategoriesData: function () { + return this._categoriesData; + }, + + /** + * @override + */ + formatTooltip: function (dataIndex, multipleSeries, dataType) { + if (dataType === 'edge') { + var nodeData = this.getData(); + var params = this.getDataParams(dataIndex, dataType); + var edge = nodeData.graph.getEdgeByIndex(dataIndex); + var sourceName = nodeData.getName(edge.node1.dataIndex); + var targetName = nodeData.getName(edge.node2.dataIndex); + + var html = []; + sourceName != null && html.push(sourceName); + targetName != null && html.push(targetName); + html = formatUtil.encodeHTML(html.join(' > ')); + + if (params.value) { + html += ' : ' + formatUtil.encodeHTML(params.value); + } + return html; + } + else { // dataType === 'node' or empty + return GraphSeries.superApply(this, 'formatTooltip', arguments); + } + }, + + _updateCategoriesData: function () { + var categories = zrUtil.map(this.option.categories || [], function (category) { + // Data must has value + return category.value != null ? category : zrUtil.extend({ + value: 0 + }, category); + }); + var categoriesData = new List(['value'], this); + categoriesData.initData(categories); + + this._categoriesData = categoriesData; + + this._categoriesModels = categoriesData.mapArray(function (idx) { + return categoriesData.getItemModel(idx, true); + }); + }, + + setZoom: function (zoom) { + this.option.zoom = zoom; + }, + + setCenter: function (center) { + this.option.center = center; + }, + + isAnimationEnabled: function () { + return GraphSeries.superCall(this, 'isAnimationEnabled') + // Not enable animation when do force layout + && !(this.get('layout') === 'force' && this.get('force.layoutAnimation')); + }, + + defaultOption: { + zlevel: 0, + z: 2, + + coordinateSystem: 'view', + + // Default option for all coordinate systems + // xAxisIndex: 0, + // yAxisIndex: 0, + // polarIndex: 0, + // geoIndex: 0, + + legendHoverLink: true, + + hoverAnimation: true, + + layout: null, + + focusNodeAdjacency: false, + + // Configuration of circular layout + circular: { + rotateLabel: false + }, + // Configuration of force directed layout + force: { + initLayout: null, + // Node repulsion. Can be an array to represent range. + repulsion: [0, 50], + gravity: 0.1, + + // Edge length. Can be an array to represent range. + edgeLength: 30, + + layoutAnimation: true + }, + + left: 'center', + top: 'center', + // right: null, + // bottom: null, + // width: '80%', + // height: '80%', + + symbol: 'circle', + symbolSize: 10, + + edgeSymbol: ['none', 'none'], + edgeSymbolSize: 10, + edgeLabel: { + normal: { + position: 'middle' + }, + emphasis: {} + }, + + draggable: false, + + roam: false, + + // Default on center of graph + center: null, + + zoom: 1, + // Symbol size scale ratio in roam + nodeScaleRatio: 0.6, + // cursor: null, + + // categories: [], + + // data: [] + // Or + // nodes: [] + // + // links: [] + // Or + // edges: [] + + label: { + normal: { + show: false, + formatter: '{b}' + }, + emphasis: { + show: true + } + }, + + itemStyle: { + normal: {}, + emphasis: {} + }, + + lineStyle: { + normal: { + color: '#aaa', + width: 1, + curveness: 0, + opacity: 0.5 + }, + emphasis: {} + } + } + }); + + module.exports = GraphSeries; + + +/***/ }, +/* 207 */ +/***/ function(module, exports, __webpack_require__) { + + + + var List = __webpack_require__(98); + var Graph = __webpack_require__(208); + var linkList = __webpack_require__(196); + var completeDimensions = __webpack_require__(110); + var CoordinateSystem = __webpack_require__(76); + var zrUtil = __webpack_require__(4); + var createListFromArray = __webpack_require__(109); + + module.exports = function (nodes, edges, hostModel, directed, beforeLink) { + var graph = new Graph(directed); + for (var i = 0; i < nodes.length; i++) { + graph.addNode(zrUtil.retrieve( + // Id, name, dataIndex + nodes[i].id, nodes[i].name, i + ), i); + } + + var linkNameList = []; + var validEdges = []; + var linkCount = 0; + for (var i = 0; i < edges.length; i++) { + var link = edges[i]; + var source = link.source; + var target = link.target; + // addEdge may fail when source or target not exists + if (graph.addEdge(source, target, linkCount)) { + validEdges.push(link); + linkNameList.push(zrUtil.retrieve(link.id, source + ' > ' + target)); + linkCount++; + } + } + + var coordSys = hostModel.get('coordinateSystem'); + var nodeData; + if (coordSys === 'cartesian2d' || coordSys === 'polar') { + nodeData = createListFromArray(nodes, hostModel, hostModel.ecModel); + } + else { + // FIXME + var coordSysCtor = CoordinateSystem.get(coordSys); + // FIXME + var dimensionNames = completeDimensions( + ((coordSysCtor && coordSysCtor.type !== 'view') ? (coordSysCtor.dimensions || []) : []).concat(['value']), + nodes + ); + nodeData = new List(dimensionNames, hostModel); + nodeData.initData(nodes); + } + + var edgeData = new List(['value'], hostModel); + edgeData.initData(validEdges, linkNameList); + + beforeLink && beforeLink(nodeData, edgeData); + + linkList({ + mainData: nodeData, + struct: graph, + structAttr: 'graph', + datas: {node: nodeData, edge: edgeData}, + datasAttr: {node: 'data', edge: 'edgeData'} + }); + + // Update dataIndex of nodes and edges because invalid edge may be removed + graph.update(); + + return graph; + }; + + +/***/ }, +/* 208 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * Graph data structure + * + * @module echarts/data/Graph + * @author Yi Shen(https://www.github.com/pissang) + */ + + + var zrUtil = __webpack_require__(4); + + // id may be function name of Object, add a prefix to avoid this problem. + function generateNodeKey (id) { + return '_EC_' + id; + } + /** + * @alias module:echarts/data/Graph + * @constructor + * @param {boolean} directed + */ + var Graph = function(directed) { + /** + * 是否是有向图 + * @type {boolean} + * @private + */ + this._directed = directed || false; + + /** + * @type {Array.} + * @readOnly + */ + this.nodes = []; + + /** + * @type {Array.} + * @readOnly + */ + this.edges = []; + + /** + * @type {Object.} + * @private + */ + this._nodesMap = {}; + /** + * @type {Object.} + * @private + */ + this._edgesMap = {}; + + /** + * @type {module:echarts/data/List} + * @readOnly + */ + this.data; + + /** + * @type {module:echarts/data/List} + * @readOnly + */ + this.edgeData; + }; + + var graphProto = Graph.prototype; + /** + * @type {string} + */ + graphProto.type = 'graph'; + + /** + * If is directed graph + * @return {boolean} + */ + graphProto.isDirected = function () { + return this._directed; + }; + + /** + * Add a new node + * @param {string} id + * @param {number} [dataIndex] + */ + graphProto.addNode = function (id, dataIndex) { + id = id || ('' + dataIndex); + + var nodesMap = this._nodesMap; + + if (nodesMap[generateNodeKey(id)]) { + if (true) { + console.error('Graph nodes have duplicate name or id'); + } + return; + } + + var node = new Node(id, dataIndex); + node.hostGraph = this; + + this.nodes.push(node); + + nodesMap[generateNodeKey(id)] = node; + return node; + }; + + /** + * Get node by data index + * @param {number} dataIndex + * @return {module:echarts/data/Graph~Node} + */ + graphProto.getNodeByIndex = function (dataIndex) { + var rawIdx = this.data.getRawIndex(dataIndex); + return this.nodes[rawIdx]; + }; + /** + * Get node by id + * @param {string} id + * @return {module:echarts/data/Graph.Node} + */ + graphProto.getNodeById = function (id) { + return this._nodesMap[generateNodeKey(id)]; + }; + + /** + * Add a new edge + * @param {number|string|module:echarts/data/Graph.Node} n1 + * @param {number|string|module:echarts/data/Graph.Node} n2 + * @param {number} [dataIndex=-1] + * @return {module:echarts/data/Graph.Edge} + */ + graphProto.addEdge = function (n1, n2, dataIndex) { + var nodesMap = this._nodesMap; + var edgesMap = this._edgesMap; + + // PNEDING + if (typeof n1 === 'number') { + n1 = this.nodes[n1]; + } + if (typeof n2 === 'number') { + n2 = this.nodes[n2]; + } + + if (!(n1 instanceof Node)) { + n1 = nodesMap[generateNodeKey(n1)]; + } + if (!(n2 instanceof Node)) { + n2 = nodesMap[generateNodeKey(n2)]; + } + if (!n1 || !n2) { + return; + } + + var key = n1.id + '-' + n2.id; + // PENDING + if (edgesMap[key]) { + return; + } + + var edge = new Edge(n1, n2, dataIndex); + edge.hostGraph = this; + + if (this._directed) { + n1.outEdges.push(edge); + n2.inEdges.push(edge); + } + n1.edges.push(edge); + if (n1 !== n2) { + n2.edges.push(edge); + } + + this.edges.push(edge); + edgesMap[key] = edge; + + return edge; + }; + + /** + * Get edge by data index + * @param {number} dataIndex + * @return {module:echarts/data/Graph~Node} + */ + graphProto.getEdgeByIndex = function (dataIndex) { + var rawIdx = this.edgeData.getRawIndex(dataIndex); + return this.edges[rawIdx]; + }; + /** + * Get edge by two linked nodes + * @param {module:echarts/data/Graph.Node|string} n1 + * @param {module:echarts/data/Graph.Node|string} n2 + * @return {module:echarts/data/Graph.Edge} + */ + graphProto.getEdge = function (n1, n2) { + if (n1 instanceof Node) { + n1 = n1.id; + } + if (n2 instanceof Node) { + n2 = n2.id; + } + + var edgesMap = this._edgesMap; + + if (this._directed) { + return edgesMap[n1 + '-' + n2]; + } else { + return edgesMap[n1 + '-' + n2] + || edgesMap[n2 + '-' + n1]; + } + }; + + /** + * Iterate all nodes + * @param {Function} cb + * @param {*} [context] + */ + graphProto.eachNode = function (cb, context) { + var nodes = this.nodes; + var len = nodes.length; + for (var i = 0; i < len; i++) { + if (nodes[i].dataIndex >= 0) { + cb.call(context, nodes[i], i); + } + } + }; + + /** + * Iterate all edges + * @param {Function} cb + * @param {*} [context] + */ + graphProto.eachEdge = function (cb, context) { + var edges = this.edges; + var len = edges.length; + for (var i = 0; i < len; i++) { + if (edges[i].dataIndex >= 0 + && edges[i].node1.dataIndex >= 0 + && edges[i].node2.dataIndex >= 0 + ) { + cb.call(context, edges[i], i); + } + } + }; + + /** + * Breadth first traverse + * @param {Function} cb + * @param {module:echarts/data/Graph.Node} startNode + * @param {string} [direction='none'] 'none'|'in'|'out' + * @param {*} [context] + */ + graphProto.breadthFirstTraverse = function ( + cb, startNode, direction, context + ) { + if (!(startNode instanceof Node)) { + startNode = this._nodesMap[generateNodeKey(startNode)]; + } + if (!startNode) { + return; + } + + var edgeType = direction === 'out' + ? 'outEdges' : (direction === 'in' ? 'inEdges' : 'edges'); + + for (var i = 0; i < this.nodes.length; i++) { + this.nodes[i].__visited = false; + } + + if (cb.call(context, startNode, null)) { + return; + } + + var queue = [startNode]; + while (queue.length) { + var currentNode = queue.shift(); + var edges = currentNode[edgeType]; + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var otherNode = e.node1 === currentNode + ? e.node2 : e.node1; + if (!otherNode.__visited) { + if (cb.call(context, otherNode, currentNode)) { + // Stop traversing + return; + } + queue.push(otherNode); + otherNode.__visited = true; + } + } + } + }; + + // TODO + // graphProto.depthFirstTraverse = function ( + // cb, startNode, direction, context + // ) { + + // }; + + // Filter update + graphProto.update = function () { + var data = this.data; + var edgeData = this.edgeData; + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0, len = nodes.length; i < len; i++) { + nodes[i].dataIndex = -1; + } + for (var i = 0, len = data.count(); i < len; i++) { + nodes[data.getRawIndex(i)].dataIndex = i; + } + + edgeData.filterSelf(function (idx) { + var edge = edges[edgeData.getRawIndex(idx)]; + return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0; + }); + + // Update edge + for (var i = 0, len = edges.length; i < len; i++) { + edges[i].dataIndex = -1; + } + for (var i = 0, len = edgeData.count(); i < len; i++) { + edges[edgeData.getRawIndex(i)].dataIndex = i; + } + }; + + /** + * @return {module:echarts/data/Graph} + */ + graphProto.clone = function () { + var graph = new Graph(this._directed); + var nodes = this.nodes; + var edges = this.edges; + for (var i = 0; i < nodes.length; i++) { + graph.addNode(nodes[i].id, nodes[i].dataIndex); + } + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + graph.addEdge(e.node1.id, e.node2.id, e.dataIndex); + } + return graph; + }; + + + /** + * @alias module:echarts/data/Graph.Node + */ + function Node(id, dataIndex) { + /** + * @type {string} + */ + this.id = id == null ? '' : id; + + /** + * @type {Array.} + */ + this.inEdges = []; + /** + * @type {Array.} + */ + this.outEdges = []; + /** + * @type {Array.} + */ + this.edges = []; + /** + * @type {module:echarts/data/Graph} + */ + this.hostGraph; + + /** + * @type {number} + */ + this.dataIndex = dataIndex == null ? -1 : dataIndex; + } + + Node.prototype = { + + constructor: Node, + + /** + * @return {number} + */ + degree: function () { + return this.edges.length; + }, + + /** + * @return {number} + */ + inDegree: function () { + return this.inEdges.length; + }, + + /** + * @return {number} + */ + outDegree: function () { + return this.outEdges.length; + }, + + /** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ + getModel: function (path) { + if (this.dataIndex < 0) { + return; + } + var graph = this.hostGraph; + var itemModel = graph.data.getItemModel(this.dataIndex); + + return itemModel.getModel(path); + } + }; + + /** + * 图边 + * @alias module:echarts/data/Graph.Edge + * @param {module:echarts/data/Graph.Node} n1 + * @param {module:echarts/data/Graph.Node} n2 + * @param {number} [dataIndex=-1] + */ + function Edge(n1, n2, dataIndex) { + + /** + * 节点1,如果是有向图则为源节点 + * @type {module:echarts/data/Graph.Node} + */ + this.node1 = n1; + + /** + * 节点2,如果是有向图则为目标节点 + * @type {module:echarts/data/Graph.Node} + */ + this.node2 = n2; + + this.dataIndex = dataIndex == null ? -1 : dataIndex; + } + + /** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ + Edge.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + var graph = this.hostGraph; + var itemModel = graph.edgeData.getItemModel(this.dataIndex); + + return itemModel.getModel(path); + }; + + var createGraphDataProxyMixin = function (hostName, dataName) { + return { + /** + * @param {string=} [dimension='value'] Default 'value'. can be 'a', 'b', 'c', 'd', 'e'. + * @return {number} + */ + getValue: function (dimension) { + var data = this[hostName][dataName]; + return data.get(data.getDimension(dimension || 'value'), this.dataIndex); + }, + + /** + * @param {Object|string} key + * @param {*} [value] + */ + setVisual: function (key, value) { + this.dataIndex >= 0 + && this[hostName][dataName].setItemVisual(this.dataIndex, key, value); + }, + + /** + * @param {string} key + * @return {boolean} + */ + getVisual: function (key, ignoreParent) { + return this[hostName][dataName].getItemVisual(this.dataIndex, key, ignoreParent); + }, + + /** + * @param {Object} layout + * @return {boolean} [merge=false] + */ + setLayout: function (layout, merge) { + this.dataIndex >= 0 + && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge); + }, + + /** + * @return {Object} + */ + getLayout: function () { + return this[hostName][dataName].getItemLayout(this.dataIndex); + }, + + /** + * @return {module:zrender/Element} + */ + getGraphicEl: function () { + return this[hostName][dataName].getItemGraphicEl(this.dataIndex); + }, + + /** + * @return {number} + */ + getRawIndex: function () { + return this[hostName][dataName].getRawIndex(this.dataIndex); + } + }; + }; + + zrUtil.mixin(Node, createGraphDataProxyMixin('hostGraph', 'data')); + zrUtil.mixin(Edge, createGraphDataProxyMixin('hostGraph', 'edgeData')); + + Graph.Node = Node; + Graph.Edge = Edge; + + module.exports = Graph; + + +/***/ }, +/* 209 */ +/***/ function(module, exports, __webpack_require__) { + + + + + var SymbolDraw = __webpack_require__(116); + var LineDraw = __webpack_require__(210); + var RoamController = __webpack_require__(183); + var roamHelper = __webpack_require__(185); + var cursorHelper = __webpack_require__(186); + + var graphic = __webpack_require__(18); + var adjustEdge = __webpack_require__(213); + var zrUtil = __webpack_require__(4); + + var nodeOpacityPath = ['itemStyle', 'normal', 'opacity']; + var lineOpacityPath = ['lineStyle', 'normal', 'opacity']; + + function getItemOpacity(item, opacityPath) { + return item.getVisual('opacity') || item.getModel().get(opacityPath); + } + + __webpack_require__(1).extendChartView({ + + type: 'graph', + + init: function (ecModel, api) { + var symbolDraw = new SymbolDraw(); + var lineDraw = new LineDraw(); + var group = this.group; + + this._controller = new RoamController(api.getZr()); + this._controllerHost = {target: group}; + + group.add(symbolDraw.group); + group.add(lineDraw.group); + + this._symbolDraw = symbolDraw; + this._lineDraw = lineDraw; + + this._firstRender = true; + }, + + render: function (seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + + this._model = seriesModel; + this._nodeScaleRatio = seriesModel.get('nodeScaleRatio'); + + var symbolDraw = this._symbolDraw; + var lineDraw = this._lineDraw; + + var group = this.group; + + if (coordSys.type === 'view') { + var groupNewProp = { + position: coordSys.position, + scale: coordSys.scale + }; + if (this._firstRender) { + group.attr(groupNewProp); + } + else { + graphic.updateProps(group, groupNewProp, seriesModel); + } + } + // Fix edge contact point with node + adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel)); + + var data = seriesModel.getData(); + symbolDraw.updateData(data); + + var edgeData = seriesModel.getEdgeData(); + lineDraw.updateData(edgeData); + + this._updateNodeAndLinkScale(); + + this._updateController(seriesModel, ecModel, api); + + clearTimeout(this._layoutTimeout); + var forceLayout = seriesModel.forceLayout; + var layoutAnimation = seriesModel.get('force.layoutAnimation'); + if (forceLayout) { + this._startForceLayoutIteration(forceLayout, layoutAnimation); + } + data.eachItemGraphicEl(function (el, idx) { + var itemModel = data.getItemModel(idx); + // Update draggable + el.off('drag').off('dragend'); + var draggable = data.getItemModel(idx).get('draggable'); + if (draggable) { + el.on('drag', function () { + if (forceLayout) { + forceLayout.warmUp(); + !this._layouting + && this._startForceLayoutIteration(forceLayout, layoutAnimation); + forceLayout.setFixed(idx); + // Write position back to layout + data.setItemLayout(idx, el.position); + } + }, this).on('dragend', function () { + if (forceLayout) { + forceLayout.setUnfixed(idx); + } + }, this); + } + el.setDraggable(draggable && forceLayout); + + el.off('mouseover', el.__focusNodeAdjacency); + el.off('mouseout', el.__unfocusNodeAdjacency); + + if (itemModel.get('focusNodeAdjacency')) { + el.on('mouseover', el.__focusNodeAdjacency = function () { + api.dispatchAction({ + type: 'focusNodeAdjacency', + seriesId: seriesModel.id, + dataIndex: el.dataIndex + }); + }); + el.on('mouseout', el.__unfocusNodeAdjacency = function () { + api.dispatchAction({ + type: 'unfocusNodeAdjacency', + seriesId: seriesModel.id + }); + }); + } + + }, this); + + var circularRotateLabel = seriesModel.get('layout') === 'circular' && seriesModel.get('circular.rotateLabel'); + var cx = data.getLayout('cx'); + var cy = data.getLayout('cy'); + data.eachItemGraphicEl(function (el, idx) { + var symbolPath = el.getSymbolPath(); + if (circularRotateLabel) { + var pos = data.getItemLayout(idx); + var rad = Math.atan2(pos[1] - cy, pos[0] - cx); + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + var isLeft = pos[0] < cx; + if (isLeft) { + rad = rad - Math.PI; + } + var textPosition = isLeft ? 'left' : 'right'; + symbolPath.setStyle({ + textRotation: rad, + textPosition: textPosition + }); + symbolPath.hoverStyle && (symbolPath.hoverStyle.textPosition = textPosition); + } + else { + symbolPath.setStyle({ + textRotation: 0 + }); + } + }); + + this._firstRender = false; + }, + + dispose: function () { + this._controller && this._controller.dispose(); + this._controllerHost = {}; + }, + + focusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + var data = this._model.getData(); + var dataIndex = payload.dataIndex; + var el = data.getItemGraphicEl(dataIndex); + + if (!el) { + return; + } + + var graph = data.graph; + var dataType = el.dataType; + + function fadeOutItem(item, opacityPath) { + var opacity = getItemOpacity(item, opacityPath); + var el = item.getGraphicEl(); + if (opacity == null) { + opacity = 1; + } + + el.traverse(function (child) { + child.trigger('normal'); + if (child.type !== 'group') { + child.setStyle('opacity', opacity * 0.1); + } + }); + } + + function fadeInItem(item, opacityPath) { + var opacity = getItemOpacity(item, opacityPath); + var el = item.getGraphicEl(); + + el.traverse(function (child) { + child.trigger('emphasis'); + if (child.type !== 'group') { + child.setStyle('opacity', opacity); + } + }); + } + if (dataIndex !== null && dataType !== 'edge') { + graph.eachNode(function (node) { + fadeOutItem(node, nodeOpacityPath); + }); + graph.eachEdge(function (edge) { + fadeOutItem(edge, lineOpacityPath); + }); + + var node = graph.getNodeByIndex(dataIndex); + fadeInItem(node, nodeOpacityPath); + zrUtil.each(node.edges, function (edge) { + if (edge.dataIndex < 0) { + return; + } + fadeInItem(edge, lineOpacityPath); + fadeInItem(edge.node1, nodeOpacityPath); + fadeInItem(edge.node2, nodeOpacityPath); + }); + } + }, + + unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + var graph = this._model.getData().graph; + graph.eachNode(function (node) { + var opacity = getItemOpacity(node, nodeOpacityPath); + node.getGraphicEl().traverse(function (child) { + child.trigger('normal'); + if (child.type !== 'group') { + child.setStyle('opacity', opacity); + } + }); + }); + graph.eachEdge(function (edge) { + var opacity = getItemOpacity(edge, lineOpacityPath); + edge.getGraphicEl().traverse(function (child) { + child.trigger('normal'); + if (child.type !== 'group') { + child.setStyle('opacity', opacity); + } + }); + }); + }, + + _startForceLayoutIteration: function (forceLayout, layoutAnimation) { + var self = this; + (function step() { + forceLayout.step(function (stopped) { + self.updateLayout(self._model); + (self._layouting = !stopped) && ( + layoutAnimation + ? (self._layoutTimeout = setTimeout(step, 16)) + : step() + ); + }); + })(); + }, + + _updateController: function (seriesModel, ecModel, api) { + var controller = this._controller; + var controllerHost = this._controllerHost; + var group = this.group; + + controller.setPointerChecker(function (e, x, y) { + var rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) + && !cursorHelper.onIrrelevantElement(e, api, seriesModel); + }); + + if (seriesModel.coordinateSystem.type !== 'view') { + controller.disable(); + return; + } + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + + controller + .off('pan') + .off('zoom') + .on('pan', function (dx, dy) { + roamHelper.updateViewOnPan(controllerHost, dx, dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + dx: dx, + dy: dy + }); + }) + .on('zoom', function (zoom, mouseX, mouseY) { + roamHelper.updateViewOnZoom(controllerHost, zoom, mouseX, mouseY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + zoom: zoom, + originX: mouseX, + originY: mouseY + }); + this._updateNodeAndLinkScale(); + adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel)); + this._lineDraw.updateLayout(); + }, this); + }, + + _updateNodeAndLinkScale: function () { + var seriesModel = this._model; + var data = seriesModel.getData(); + + var nodeScale = this._getNodeGlobalScale(seriesModel); + var invScale = [nodeScale, nodeScale]; + + data.eachItemGraphicEl(function (el, idx) { + el.attr('scale', invScale); + }); + }, + + _getNodeGlobalScale: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys.type !== 'view') { + return 1; + } + + var nodeScaleRatio = this._nodeScaleRatio; + + var groupScale = coordSys.scale; + var groupZoom = (groupScale && groupScale[0]) || 1; + // Scale node when zoom changes + var roamZoom = coordSys.getZoom(); + var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1; + + return nodeScale / groupZoom; + }, + + updateLayout: function (seriesModel) { + adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel)); + + this._symbolDraw.updateLayout(); + this._lineDraw.updateLayout(); + }, + + remove: function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(); + this._lineDraw && this._lineDraw.remove(); + } + }); + + +/***/ }, +/* 210 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/chart/helper/LineDraw + */ + + + var graphic = __webpack_require__(18); + var LineGroup = __webpack_require__(211); + + + function isPointNaN(pt) { + return isNaN(pt[0]) || isNaN(pt[1]); + } + function lineNeedsDraw(pts) { + return !isPointNaN(pts[0]) && !isPointNaN(pts[1]); + } + /** + * @alias module:echarts/component/marker/LineDraw + * @constructor + */ + function LineDraw(ctor) { + this._ctor = ctor || LineGroup; + this.group = new graphic.Group(); + } + + var lineDrawProto = LineDraw.prototype; + + /** + * @param {module:echarts/data/List} lineData + */ + lineDrawProto.updateData = function (lineData) { + + var oldLineData = this._lineData; + var group = this.group; + var LineCtor = this._ctor; + + var hostModel = lineData.hostModel; + + var seriesScope = { + lineStyle: hostModel.getModel('lineStyle.normal').getLineStyle(), + hoverLineStyle: hostModel.getModel('lineStyle.emphasis').getLineStyle(), + labelModel: hostModel.getModel('label.normal'), + hoverLabelModel: hostModel.getModel('label.emphasis') + }; + + lineData.diff(oldLineData) + .add(function (idx) { + if (!lineNeedsDraw(lineData.getItemLayout(idx))) { + return; + } + var lineGroup = new LineCtor(lineData, idx, seriesScope); + + lineData.setItemGraphicEl(idx, lineGroup); + + group.add(lineGroup); + }) + .update(function (newIdx, oldIdx) { + var lineGroup = oldLineData.getItemGraphicEl(oldIdx); + if (!lineNeedsDraw(lineData.getItemLayout(newIdx))) { + group.remove(lineGroup); + return; + } + + if (!lineGroup) { + lineGroup = new LineCtor(lineData, newIdx, seriesScope); + } + else { + lineGroup.updateData(lineData, newIdx, seriesScope); + } + + lineData.setItemGraphicEl(newIdx, lineGroup); + + group.add(lineGroup); + }) + .remove(function (idx) { + group.remove(oldLineData.getItemGraphicEl(idx)); + }) + .execute(); + + this._lineData = lineData; + }; + + lineDrawProto.updateLayout = function () { + var lineData = this._lineData; + lineData.eachItemGraphicEl(function (el, idx) { + el.updateLayout(lineData, idx); + }, this); + }; + + lineDrawProto.remove = function () { + this.group.removeAll(); + }; + + module.exports = LineDraw; + + +/***/ }, +/* 211 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/chart/helper/Line + */ + + + var symbolUtil = __webpack_require__(111); + var vector = __webpack_require__(10); + // var matrix = require('zrender/lib/core/matrix'); + var LinePath = __webpack_require__(212); + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + + var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol']; + function makeSymbolTypeKey(symbolCategory) { + return '_' + symbolCategory + 'Type'; + } + /** + * @inner + */ + function createSymbol(name, lineData, idx) { + var color = lineData.getItemVisual(idx, 'color'); + var symbolType = lineData.getItemVisual(idx, name); + var symbolSize = lineData.getItemVisual(idx, name + 'Size'); + + if (!symbolType || symbolType === 'none') { + return; + } + + if (!zrUtil.isArray(symbolSize)) { + symbolSize = [symbolSize, symbolSize]; + } + var symbolPath = symbolUtil.createSymbol( + symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2, + symbolSize[0], symbolSize[1], color + ); + + symbolPath.name = name; + + return symbolPath; + } + + function createLine(points) { + var line = new LinePath({ + name: 'line' + }); + setLinePoints(line.shape, points); + return line; + } + + function setLinePoints(targetShape, points) { + var p1 = points[0]; + var p2 = points[1]; + var cp1 = points[2]; + targetShape.x1 = p1[0]; + targetShape.y1 = p1[1]; + targetShape.x2 = p2[0]; + targetShape.y2 = p2[1]; + targetShape.percent = 1; + + if (cp1) { + targetShape.cpx1 = cp1[0]; + targetShape.cpy1 = cp1[1]; + } + else { + targetShape.cpx1 = NaN; + targetShape.cpy1 = NaN; + } + } + + function updateSymbolAndLabelBeforeLineUpdate () { + var lineGroup = this; + var symbolFrom = lineGroup.childOfName('fromSymbol'); + var symbolTo = lineGroup.childOfName('toSymbol'); + var label = lineGroup.childOfName('label'); + // Quick reject + if (!symbolFrom && !symbolTo && label.ignore) { + return; + } + + var invScale = 1; + var parentNode = this.parent; + while (parentNode) { + if (parentNode.scale) { + invScale /= parentNode.scale[0]; + } + parentNode = parentNode.parent; + } + + var line = lineGroup.childOfName('line'); + // If line not changed + // FIXME Parent scale changed + if (!this.__dirty && !line.__dirty) { + return; + } + + var percent = line.shape.percent; + var fromPos = line.pointAt(0); + var toPos = line.pointAt(percent); + + var d = vector.sub([], toPos, fromPos); + vector.normalize(d, d); + + if (symbolFrom) { + symbolFrom.attr('position', fromPos); + var tangent = line.tangentAt(0); + symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2( + tangent[1], tangent[0] + )); + symbolFrom.attr('scale', [invScale * percent, invScale * percent]); + } + if (symbolTo) { + symbolTo.attr('position', toPos); + var tangent = line.tangentAt(1); + symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2( + tangent[1], tangent[0] + )); + symbolTo.attr('scale', [invScale * percent, invScale * percent]); + } + + if (!label.ignore) { + label.attr('position', toPos); + + var textPosition; + var textAlign; + var textVerticalAlign; + + var distance = 5 * invScale; + // End + if (label.__position === 'end') { + textPosition = [d[0] * distance + toPos[0], d[1] * distance + toPos[1]]; + textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center'); + textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle'); + } + // Middle + else if (label.__position === 'middle') { + var halfPercent = percent / 2; + var tangent = line.tangentAt(halfPercent); + var n = [tangent[1], -tangent[0]]; + var cp = line.pointAt(halfPercent); + if (n[1] > 0) { + n[0] = -n[0]; + n[1] = -n[1]; + } + textPosition = [cp[0] + n[0] * distance, cp[1] + n[1] * distance]; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + var rotation = -Math.atan2(tangent[1], tangent[0]); + if (toPos[0] < fromPos[0]) { + rotation = Math.PI + rotation; + } + label.attr('rotation', rotation); + } + // Start + else { + textPosition = [-d[0] * distance + fromPos[0], -d[1] * distance + fromPos[1]]; + textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center'); + textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle'); + } + label.attr({ + style: { + // Use the user specified text align and baseline first + textVerticalAlign: label.__verticalAlign || textVerticalAlign, + textAlign: label.__textAlign || textAlign + }, + position: textPosition, + scale: [invScale, invScale] + }); + } + } + + /** + * @constructor + * @extends {module:zrender/graphic/Group} + * @alias {module:echarts/chart/helper/Line} + */ + function Line(lineData, idx, seriesScope) { + graphic.Group.call(this); + + this._createLine(lineData, idx, seriesScope); + } + + var lineProto = Line.prototype; + + // Update symbol position and rotation + lineProto.beforeUpdate = updateSymbolAndLabelBeforeLineUpdate; + + lineProto._createLine = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var linePoints = lineData.getItemLayout(idx); + + var line = createLine(linePoints); + line.shape.percent = 0; + graphic.initProps(line, { + shape: { + percent: 1 + } + }, seriesModel, idx); + + this.add(line); + + var label = new graphic.Text({ + name: 'label' + }); + this.add(label); + + zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = createSymbol(symbolCategory, lineData, idx); + // symbols must added after line to make sure + // it will be updated after line#update. + // Or symbol position and rotation update in line#beforeUpdate will be one frame slow + this.add(symbol); + this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory); + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + lineProto.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + + var line = this.childOfName('line'); + var linePoints = lineData.getItemLayout(idx); + var target = { + shape: {} + }; + setLinePoints(target.shape, linePoints); + graphic.updateProps(line, target, seriesModel, idx); + + zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbolType = lineData.getItemVisual(idx, symbolCategory); + var key = makeSymbolTypeKey(symbolCategory); + // Symbol changed + if (this[key] !== symbolType) { + this.remove(this.childOfName(symbolCategory)); + var symbol = createSymbol(symbolCategory, lineData, idx); + this.add(symbol); + } + this[key] = symbolType; + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + lineProto._updateCommonStl = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + + var line = this.childOfName('line'); + + var lineStyle = seriesScope && seriesScope.lineStyle; + var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle; + var labelModel = seriesScope && seriesScope.labelModel; + var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel; + + // Optimization for large dataset + if (!seriesScope || lineData.hasItemOption) { + var itemModel = lineData.getItemModel(idx); + + lineStyle = itemModel.getModel('lineStyle.normal').getLineStyle(); + hoverLineStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle(); + + labelModel = itemModel.getModel('label.normal'); + hoverLabelModel = itemModel.getModel('label.emphasis'); + } + + var visualColor = lineData.getItemVisual(idx, 'color'); + var visualOpacity = zrUtil.retrieve( + lineData.getItemVisual(idx, 'opacity'), + lineStyle.opacity, + 1 + ); + + line.useStyle(zrUtil.defaults( + { + strokeNoScale: true, + fill: 'none', + stroke: visualColor, + opacity: visualOpacity + }, + lineStyle + )); + line.hoverStyle = hoverLineStyle; + + // Update symbol + zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = this.childOfName(symbolCategory); + if (symbol) { + symbol.setColor(visualColor); + symbol.setStyle({ + opacity: visualOpacity + }); + } + }, this); + + var showLabel = labelModel.getShallow('show'); + var hoverShowLabel = hoverLabelModel.getShallow('show'); + + var label = this.childOfName('label'); + var defaultLabelColor; + var defaultText; + + if (showLabel || hoverShowLabel) { + var rawVal = seriesModel.getRawValue(idx); + defaultText = rawVal == null + ? defaultText = lineData.getName(idx) + : isFinite(rawVal) + ? numberUtil.round(rawVal) + : rawVal; + defaultLabelColor = visualColor || '#000'; + } + + // label.afterUpdate = lineAfterUpdate; + if (showLabel) { + var textStyleModel = labelModel.getModel('textStyle'); + label.setStyle({ + text: zrUtil.retrieve( + seriesModel.getFormattedLabel(idx, 'normal', lineData.dataType), + defaultText + ), + textFont: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() || defaultLabelColor + }); + + label.__textAlign = textStyleModel.get('align'); + label.__verticalAlign = textStyleModel.get('baseline'); + label.__position = labelModel.get('position'); + } + else { + label.setStyle('text', ''); + } + if (hoverShowLabel) { + var textStyleHoverModel = hoverLabelModel.getModel('textStyle'); + + label.hoverStyle = { + text: zrUtil.retrieve( + seriesModel.getFormattedLabel(idx, 'emphasis', lineData.dataType), + defaultText + ), + textFont: textStyleHoverModel.getFont(), + fill: textStyleHoverModel.getTextColor() || defaultLabelColor + }; + } + else { + label.hoverStyle = { + text: '' + }; + } + + label.ignore = !showLabel && !hoverShowLabel; + + graphic.setHoverStyle(this); + }; + + lineProto.updateLayout = function (lineData, idx) { + this.setLinePoints(lineData.getItemLayout(idx)); + }; + + lineProto.setLinePoints = function (points) { + var linePath = this.childOfName('line'); + setLinePoints(linePath.shape, points); + linePath.dirty(); + }; + + zrUtil.inherits(Line, graphic.Group); + + module.exports = Line; + + +/***/ }, +/* 212 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Line path for bezier and straight line draw + */ + + var graphic = __webpack_require__(18); + var vec2 = __webpack_require__(10); + + var straightLineProto = graphic.Line.prototype; + var bezierCurveProto = graphic.BezierCurve.prototype; + + function isLine(shape) { + return isNaN(+shape.cpx1) || isNaN(+shape.cpy1); + } + + module.exports = graphic.extendShape({ + + type: 'ec-line', + + style: { + stroke: '#000', + fill: null + }, + + shape: { + x1: 0, + y1: 0, + x2: 0, + y2: 0, + percent: 1, + cpx1: null, + cpy1: null + }, + + buildPath: function (ctx, shape) { + (isLine(shape) ? straightLineProto : bezierCurveProto).buildPath(ctx, shape); + }, + + pointAt: function (t) { + return isLine(this.shape) + ? straightLineProto.pointAt.call(this, t) + : bezierCurveProto.pointAt.call(this, t); + }, + + tangentAt: function (t) { + var shape = this.shape; + var p = isLine(shape) + ? [shape.x2 - shape.x1, shape.y2 - shape.y1] + : bezierCurveProto.tangentAt.call(this, t); + return vec2.normalize(p, p); + } + }); + + +/***/ }, +/* 213 */ +/***/ function(module, exports, __webpack_require__) { + + + + var curveTool = __webpack_require__(37); + var vec2 = __webpack_require__(10); + + var v1 = []; + var v2 = []; + var v3 = []; + var quadraticAt = curveTool.quadraticAt; + var v2DistSquare = vec2.distSquare; + var mathAbs = Math.abs; + function intersectCurveCircle(curvePoints, center, radius) { + var p0 = curvePoints[0]; + var p1 = curvePoints[1]; + var p2 = curvePoints[2]; + + var d = Infinity; + var t; + var radiusSquare = radius * radius; + var interval = 0.1; + + for (var _t = 0.1; _t <= 0.9; _t += 0.1) { + v1[0] = quadraticAt(p0[0], p1[0], p2[0], _t); + v1[1] = quadraticAt(p0[1], p1[1], p2[1], _t); + var diff = mathAbs(v2DistSquare(v1, center) - radiusSquare); + if (diff < d) { + d = diff; + t = _t; + } + } + + // Assume the segment is monotone,Find root through Bisection method + // At most 32 iteration + for (var i = 0; i < 32; i++) { + // var prev = t - interval; + var next = t + interval; + // v1[0] = quadraticAt(p0[0], p1[0], p2[0], prev); + // v1[1] = quadraticAt(p0[1], p1[1], p2[1], prev); + v2[0] = quadraticAt(p0[0], p1[0], p2[0], t); + v2[1] = quadraticAt(p0[1], p1[1], p2[1], t); + v3[0] = quadraticAt(p0[0], p1[0], p2[0], next); + v3[1] = quadraticAt(p0[1], p1[1], p2[1], next); + + var diff = v2DistSquare(v2, center) - radiusSquare; + if (mathAbs(diff) < 1e-2) { + break; + } + + // var prevDiff = v2DistSquare(v1, center) - radiusSquare; + var nextDiff = v2DistSquare(v3, center) - radiusSquare; + + interval /= 2; + if (diff < 0) { + if (nextDiff >= 0) { + t = t + interval; + } + else { + t = t - interval; + } + } + else { + if (nextDiff >= 0) { + t = t - interval; + } + else { + t = t + interval; + } + } + } + + return t; + } + // Adjust edge to avoid + module.exports = function (graph, scale) { + var tmp0 = []; + var quadraticSubdivide = curveTool.quadraticSubdivide; + var pts = [[], [], []]; + var pts2 = [[], []]; + var v = []; + scale /= 2; + + function getSymbolSize(node) { + var symbolSize = node.getVisual('symbolSize'); + if (symbolSize instanceof Array) { + symbolSize = (symbolSize[0] + symbolSize[1]) / 2; + } + return symbolSize; + } + graph.eachEdge(function (edge, idx) { + var linePoints = edge.getLayout(); + var fromSymbol = edge.getVisual('fromSymbol'); + var toSymbol = edge.getVisual('toSymbol'); + + if (!linePoints.__original) { + linePoints.__original = [ + vec2.clone(linePoints[0]), + vec2.clone(linePoints[1]) + ]; + if (linePoints[2]) { + linePoints.__original.push(vec2.clone(linePoints[2])); + } + } + var originalPoints = linePoints.__original; + // Quadratic curve + if (linePoints[2] != null) { + vec2.copy(pts[0], originalPoints[0]); + vec2.copy(pts[1], originalPoints[2]); + vec2.copy(pts[2], originalPoints[1]); + if (fromSymbol && fromSymbol != 'none') { + var symbolSize = getSymbolSize(edge.node1); + + var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale); + // Subdivide and get the second + quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[0][0] = tmp0[3]; + pts[1][0] = tmp0[4]; + quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[0][1] = tmp0[3]; + pts[1][1] = tmp0[4]; + } + if (toSymbol && toSymbol != 'none') { + var symbolSize = getSymbolSize(edge.node2); + + var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale); + // Subdivide and get the first + quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[1][0] = tmp0[1]; + pts[2][0] = tmp0[2]; + quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[1][1] = tmp0[1]; + pts[2][1] = tmp0[2]; + } + // Copy back to layout + vec2.copy(linePoints[0], pts[0]); + vec2.copy(linePoints[1], pts[2]); + vec2.copy(linePoints[2], pts[1]); + } + // Line + else { + vec2.copy(pts2[0], originalPoints[0]); + vec2.copy(pts2[1], originalPoints[1]); + + vec2.sub(v, pts2[1], pts2[0]); + vec2.normalize(v, v); + if (fromSymbol && fromSymbol != 'none') { + + var symbolSize = getSymbolSize(edge.node1); + + vec2.scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale); + } + if (toSymbol && toSymbol != 'none') { + var symbolSize = getSymbolSize(edge.node2); + + vec2.scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale); + } + vec2.copy(linePoints[0], pts2[0]); + vec2.copy(linePoints[1], pts2[1]); + } + }); + }; + + +/***/ }, +/* 214 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + var roamHelper = __webpack_require__(188); + + var actionInfo = { + type: 'graphRoam', + event: 'graphRoam', + update: 'none' + }; + + /** + * @payload + * @property {string} name Series name + * @property {number} [dx] + * @property {number} [dy] + * @property {number} [zoom] + * @property {number} [originX] + * @property {number} [originY] + */ + echarts.registerAction(actionInfo, function (payload, ecModel) { + ecModel.eachComponent({mainType: 'series', query: payload}, function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + var res = roamHelper.updateCenterAndZoom(coordSys, payload); + + seriesModel.setCenter + && seriesModel.setCenter(res.center); + + seriesModel.setZoom + && seriesModel.setZoom(res.zoom); + }); + }); + + + /** + * @payload + * @property {number} [seriesIndex] + * @property {string} [seriesId] + * @property {string} [seriesName] + * @property {number} [dataIndex] + */ + echarts.registerAction({ + type: 'focusNodeAdjacency', + event: 'focusNodeAdjacency', + update: 'series.graph:focusNodeAdjacency' + }, function () {}); + + /** + * @payload + * @property {number} [seriesIndex] + * @property {string} [seriesId] + * @property {string} [seriesName] + */ + echarts.registerAction({ + type: 'unfocusNodeAdjacency', + event: 'unfocusNodeAdjacency', + update: 'series.graph:unfocusNodeAdjacency' + }, function () {}); + + + +/***/ }, +/* 215 */ +/***/ function(module, exports) { + + + + module.exports = function (ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + if (!legendModels || !legendModels.length) { + return; + } + ecModel.eachSeriesByType('graph', function (graphSeries) { + var categoriesData = graphSeries.getCategoriesData(); + var graph = graphSeries.getGraph(); + var data = graph.data; + + var categoryNames = categoriesData.mapArray(categoriesData.getName); + + data.filterSelf(function (idx) { + var model = data.getItemModel(idx); + var category = model.getShallow('category'); + if (category != null) { + if (typeof category === 'number') { + category = categoryNames[category]; + } + // If in any legend component the status is not selected. + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(category)) { + return false; + } + } + } + return true; + }); + }, this); + }; + + +/***/ }, +/* 216 */ +/***/ function(module, exports) { + + + + module.exports = function (ecModel) { + + var paletteScope = {}; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var categoriesData = seriesModel.getCategoriesData(); + var data = seriesModel.getData(); + + var categoryNameIdxMap = {}; + + categoriesData.each(function (idx) { + var name = categoriesData.getName(idx); + // Add prefix to avoid conflict with Object.prototype. + categoryNameIdxMap['ec-' + name] = idx; + + var itemModel = categoriesData.getItemModel(idx); + var color = itemModel.get('itemStyle.normal.color') + || seriesModel.getColorFromPalette(name, paletteScope); + categoriesData.setItemVisual(idx, 'color', color); + }); + + // Assign category color to visual + if (categoriesData.count()) { + data.each(function (idx) { + var model = data.getItemModel(idx); + var category = model.getShallow('category'); + if (category != null) { + if (typeof category === 'string') { + category = categoryNameIdxMap['ec-' + category]; + } + if (!data.getItemVisual(idx, 'color', true)) { + data.setItemVisual( + idx, 'color', + categoriesData.getItemVisual(category, 'color') + ); + } + } + }); + } + }); + }; + + +/***/ }, +/* 217 */ +/***/ function(module, exports) { + + + + function normalize(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + return a; + } + module.exports = function (ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var graph = seriesModel.getGraph(); + var edgeData = seriesModel.getEdgeData(); + var symbolType = normalize(seriesModel.get('edgeSymbol')); + var symbolSize = normalize(seriesModel.get('edgeSymbolSize')); + + var colorQuery = 'lineStyle.normal.color'.split('.'); + var opacityQuery = 'lineStyle.normal.opacity'.split('.'); + + edgeData.setVisual('fromSymbol', symbolType && symbolType[0]); + edgeData.setVisual('toSymbol', symbolType && symbolType[1]); + edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + edgeData.setVisual('color', seriesModel.get(colorQuery)); + edgeData.setVisual('opacity', seriesModel.get(opacityQuery)); + + edgeData.each(function (idx) { + var itemModel = edgeData.getItemModel(idx); + var edge = graph.getEdgeByIndex(idx); + var symbolType = normalize(itemModel.getShallow('symbol', true)); + var symbolSize = normalize(itemModel.getShallow('symbolSize', true)); + // Edge visual must after node visual + var color = itemModel.get(colorQuery); + var opacity = itemModel.get(opacityQuery); + switch (color) { + case 'source': + color = edge.node1.getVisual('color'); + break; + case 'target': + color = edge.node2.getVisual('color'); + break; + } + + symbolType[0] && edge.setVisual('fromSymbol', symbolType[0]); + symbolType[1] && edge.setVisual('toSymbol', symbolType[1]); + symbolSize[0] && edge.setVisual('fromSymbolSize', symbolSize[0]); + symbolSize[1] && edge.setVisual('toSymbolSize', symbolSize[1]); + + edge.setVisual('color', color); + edge.setVisual('opacity', opacity); + }); + }); + }; + + +/***/ }, +/* 218 */ +/***/ function(module, exports, __webpack_require__) { + + + + var simpleLayoutHelper = __webpack_require__(219); + var simpleLayoutEdge = __webpack_require__(220); + + module.exports = function (ecModel, api) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var layout = seriesModel.get('layout'); + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + var data = seriesModel.getData(); + var dimensions = coordSys.dimensions; + + data.each(dimensions, function () { + var hasValue; + var args = arguments; + var value = []; + for (var i = 0; i < dimensions.length; i++) { + if (!isNaN(args[i])) { + hasValue = true; + } + value.push(args[i]); + } + var idx = args[args.length - 1]; + + if (hasValue) { + data.setItemLayout(idx, coordSys.dataToPoint(value)); + } + else { + // Also {Array.}, not undefined to avoid if...else... statement + data.setItemLayout(idx, [NaN, NaN]); + } + }); + + simpleLayoutEdge(data.graph); + } + else if (!layout || layout === 'none') { + simpleLayoutHelper(seriesModel); + } + }); + }; + + + +/***/ }, +/* 219 */ +/***/ function(module, exports, __webpack_require__) { + + + + var simpleLayoutEdge = __webpack_require__(220); + + module.exports = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + return; + } + var graph = seriesModel.getGraph(); + + graph.eachNode(function (node) { + var model = node.getModel(); + node.setLayout([+model.get('x'), +model.get('y')]); + }); + + simpleLayoutEdge(graph); + }; + + +/***/ }, +/* 220 */ +/***/ function(module, exports, __webpack_require__) { + + + var vec2 = __webpack_require__(10); + module.exports = function (graph) { + graph.eachEdge(function (edge) { + var curveness = edge.getModel().get('lineStyle.normal.curveness') || 0; + var p1 = vec2.clone(edge.node1.getLayout()); + var p2 = vec2.clone(edge.node2.getLayout()); + var points = [p1, p2]; + if (+curveness) { + points.push([ + (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness, + (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness + ]); + } + edge.setLayout(points); + }); + }; + + +/***/ }, +/* 221 */ +/***/ function(module, exports, __webpack_require__) { + + + var circularLayoutHelper = __webpack_require__(222); + module.exports = function (ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + if (seriesModel.get('layout') === 'circular') { + circularLayoutHelper(seriesModel); + } + }); + }; + + +/***/ }, +/* 222 */ +/***/ function(module, exports, __webpack_require__) { + + + var vec2 = __webpack_require__(10); + module.exports = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + return; + } + + var rect = coordSys.getBoundingRect(); + + var nodeData = seriesModel.getData(); + var graph = nodeData.graph; + + var angle = 0; + var sum = nodeData.getSum('value'); + var unitAngle = Math.PI * 2 / (sum || nodeData.count()); + + var cx = rect.width / 2 + rect.x; + var cy = rect.height / 2 + rect.y; + + var r = Math.min(rect.width, rect.height) / 2; + + graph.eachNode(function (node) { + var value = node.getValue('value'); + + angle += unitAngle * (sum ? value : 1) / 2; + + node.setLayout([ + r * Math.cos(angle) + cx, + r * Math.sin(angle) + cy + ]); + + angle += unitAngle * (sum ? value : 1) / 2; + }); + + nodeData.setLayout({ + cx: cx, + cy: cy + }); + + graph.eachEdge(function (edge) { + var curveness = edge.getModel().get('lineStyle.normal.curveness') || 0; + var p1 = vec2.clone(edge.node1.getLayout()); + var p2 = vec2.clone(edge.node2.getLayout()); + var cp1; + var x12 = (p1[0] + p2[0]) / 2; + var y12 = (p1[1] + p2[1]) / 2; + if (+curveness) { + curveness *= 3; + cp1 = [ + cx * curveness + x12 * (1 - curveness), + cy * curveness + y12 * (1 - curveness) + ]; + } + edge.setLayout([p1, p2, cp1]); + }); + }; + + +/***/ }, +/* 223 */ +/***/ function(module, exports, __webpack_require__) { + + + + var forceHelper = __webpack_require__(224); + var numberUtil = __webpack_require__(7); + var simpleLayoutHelper = __webpack_require__(219); + var circularLayoutHelper = __webpack_require__(222); + var vec2 = __webpack_require__(10); + var zrUtil = __webpack_require__(4); + + module.exports = function (ecModel) { + ecModel.eachSeriesByType('graph', function (graphSeries) { + var coordSys = graphSeries.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + return; + } + if (graphSeries.get('layout') === 'force') { + var preservedPoints = graphSeries.preservedPoints || {}; + var graph = graphSeries.getGraph(); + var nodeData = graph.data; + var edgeData = graph.edgeData; + var forceModel = graphSeries.getModel('force'); + var initLayout = forceModel.get('initLayout'); + if (graphSeries.preservedPoints) { + nodeData.each(function (idx) { + var id = nodeData.getId(idx); + nodeData.setItemLayout(idx, preservedPoints[id] || [NaN, NaN]); + }); + } + else if (!initLayout || initLayout === 'none') { + simpleLayoutHelper(graphSeries); + } + else if (initLayout === 'circular') { + circularLayoutHelper(graphSeries); + } + + var nodeDataExtent = nodeData.getDataExtent('value'); + var edgeDataExtent = edgeData.getDataExtent('value'); + // var edgeDataExtent = edgeData.getDataExtent('value'); + var repulsion = forceModel.get('repulsion'); + var edgeLength = forceModel.get('edgeLength'); + if (!zrUtil.isArray(repulsion)) { + repulsion = [repulsion, repulsion]; + } + if (!zrUtil.isArray(edgeLength)) { + edgeLength = [edgeLength, edgeLength]; + } + // Larger value has smaller length + edgeLength = [edgeLength[1], edgeLength[0]]; + + var nodes = nodeData.mapArray('value', function (value, idx) { + var point = nodeData.getItemLayout(idx); + // var w = numberUtil.linearMap(value, nodeDataExtent, [0, 50]); + var rep = numberUtil.linearMap(value, nodeDataExtent, repulsion); + if (isNaN(rep)) { + rep = (repulsion[0] + repulsion[1]) / 2; + } + return { + w: rep, + rep: rep, + fixed: nodeData.getItemModel(idx).get('fixed'), + p: (!point || isNaN(point[0]) || isNaN(point[1])) ? null : point + }; + }); + var edges = edgeData.mapArray('value', function (value, idx) { + var edge = graph.getEdgeByIndex(idx); + var d = numberUtil.linearMap(value, edgeDataExtent, edgeLength); + if (isNaN(d)) { + d = (edgeLength[0] + edgeLength[1]) / 2; + } + return { + n1: nodes[edge.node1.dataIndex], + n2: nodes[edge.node2.dataIndex], + d: d, + curveness: edge.getModel().get('lineStyle.normal.curveness') || 0 + }; + }); + + var coordSys = graphSeries.coordinateSystem; + var rect = coordSys.getBoundingRect(); + var forceInstance = forceHelper(nodes, edges, { + rect: rect, + gravity: forceModel.get('gravity') + }); + var oldStep = forceInstance.step; + forceInstance.step = function (cb) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (nodes[i].fixed) { + // Write back to layout instance + vec2.copy(nodes[i].p, graph.getNodeByIndex(i).getLayout()); + } + } + oldStep(function (nodes, edges, stopped) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (!nodes[i].fixed) { + graph.getNodeByIndex(i).setLayout(nodes[i].p); + } + preservedPoints[nodeData.getId(i)] = nodes[i].p; + } + for (var i = 0, l = edges.length; i < l; i++) { + var e = edges[i]; + var edge = graph.getEdgeByIndex(i); + var p1 = e.n1.p; + var p2 = e.n2.p; + var points = edge.getLayout(); + points = points ? points.slice() : []; + points[0] = points[0] || []; + points[1] = points[1] || []; + vec2.copy(points[0], p1); + vec2.copy(points[1], p2); + if (+e.curveness) { + points[2] = [ + (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness, + (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness + ]; + } + edge.setLayout(points); + } + // Update layout + + cb && cb(stopped); + }); + }; + graphSeries.forceLayout = forceInstance; + graphSeries.preservedPoints = preservedPoints; + + // Step to get the layout + forceInstance.step(); + } + else { + // Remove prev injected forceLayout instance + graphSeries.forceLayout = null; + } + }); + }; + + +/***/ }, +/* 224 */ +/***/ function(module, exports, __webpack_require__) { + + + + var vec2 = __webpack_require__(10); + var scaleAndAdd = vec2.scaleAndAdd; + + // function adjacentNode(n, e) { + // return e.n1 === n ? e.n2 : e.n1; + // } + + module.exports = function (nodes, edges, opts) { + var rect = opts.rect; + var width = rect.width; + var height = rect.height; + var center = [rect.x + width / 2, rect.y + height / 2]; + // var scale = opts.scale || 1; + var gravity = opts.gravity == null ? 0.1 : opts.gravity; + + // for (var i = 0; i < edges.length; i++) { + // var e = edges[i]; + // var n1 = e.n1; + // var n2 = e.n2; + // n1.edges = n1.edges || []; + // n2.edges = n2.edges || []; + // n1.edges.push(e); + // n2.edges.push(e); + // } + // Init position + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + if (!n.p) { + // Use the position from first adjecent node with defined position + // Or use a random position + // From d3 + // if (n.edges) { + // var j = -1; + // while (++j < n.edges.length) { + // var e = n.edges[j]; + // var other = adjacentNode(n, e); + // if (other.p) { + // n.p = vec2.clone(other.p); + // break; + // } + // } + // } + // if (!n.p) { + n.p = vec2.create( + width * (Math.random() - 0.5) + center[0], + height * (Math.random() - 0.5) + center[1] + ); + // } + } + n.pp = vec2.clone(n.p); + n.edges = null; + } + + // Formula in 'Graph Drawing by Force-directed Placement' + // var k = scale * Math.sqrt(width * height / nodes.length); + // var k2 = k * k; + + var friction = 0.6; + + return { + warmUp: function () { + friction = 0.5; + }, + + setFixed: function (idx) { + nodes[idx].fixed = true; + }, + + setUnfixed: function (idx) { + nodes[idx].fixed = false; + }, + + step: function (cb) { + var v12 = []; + var nLen = nodes.length; + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var n1 = e.n1; + var n2 = e.n2; + + vec2.sub(v12, n2.p, n1.p); + var d = vec2.len(v12) - e.d; + var w = n2.w / (n1.w + n2.w); + vec2.normalize(v12, v12); + + !n1.fixed && scaleAndAdd(n1.p, n1.p, v12, w * d * friction); + !n2.fixed && scaleAndAdd(n2.p, n2.p, v12, -(1 - w) * d * friction); + } + // Gravity + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + if (!n.fixed) { + vec2.sub(v12, center, n.p); + // var d = vec2.len(v12); + // vec2.scale(v12, v12, 1 / d); + // var gravityFactor = gravity; + vec2.scaleAndAdd(n.p, n.p, v12, gravity * friction); + } + } + + // Repulsive + // PENDING + for (var i = 0; i < nLen; i++) { + var n1 = nodes[i]; + for (var j = i + 1; j < nLen; j++) { + var n2 = nodes[j]; + vec2.sub(v12, n2.p, n1.p); + var d = vec2.len(v12); + if (d === 0) { + // Random repulse + vec2.set(v12, Math.random() - 0.5, Math.random() - 0.5); + d = 1; + } + var repFact = (n1.rep + n2.rep) / d / d; + !n1.fixed && scaleAndAdd(n1.pp, n1.pp, v12, repFact); + !n2.fixed && scaleAndAdd(n2.pp, n2.pp, v12, -repFact); + } + } + var v = []; + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + if (!n.fixed) { + vec2.sub(v, n.p, n.pp); + vec2.scaleAndAdd(n.p, n.p, v, friction); + vec2.copy(n.pp, n.p); + } + } + + friction = friction * 0.992; + + cb && cb(nodes, edges, friction < 0.01); + } + }; + }; + + +/***/ }, +/* 225 */ +/***/ function(module, exports, __webpack_require__) { + + + // FIXME Where to create the simple view coordinate system + var View = __webpack_require__(176); + var layout = __webpack_require__(71); + var bbox = __webpack_require__(38); + + function getViewRect(seriesModel, api, aspect) { + var option = seriesModel.getBoxLayoutParams(); + option.aspect = aspect; + return layout.getLayoutRect(option, { + width: api.getWidth(), + height: api.getHeight() + }); + } + + module.exports = function (ecModel, api) { + var viewList = []; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var coordSysType = seriesModel.get('coordinateSystem'); + if (!coordSysType || coordSysType === 'view') { + + var data = seriesModel.getData(); + var positions = data.mapArray(function (idx) { + var itemModel = data.getItemModel(idx); + return [+itemModel.get('x'), +itemModel.get('y')]; + }); + + var min = []; + var max = []; + + bbox.fromPoints(positions, min, max); + + // If width or height is 0 + if (max[0] - min[0] === 0) { + max[0] += 1; + min[0] -= 1; + } + if (max[1] - min[1] === 0) { + max[1] += 1; + min[1] -= 1; + } + var aspect = (max[0] - min[0]) / (max[1] - min[1]); + // FIXME If get view rect after data processed? + var viewRect = getViewRect(seriesModel, api, aspect); + // Position may be NaN, use view rect instead + if (isNaN(aspect)) { + min = [viewRect.x, viewRect.y]; + max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height]; + } + + var bbWidth = max[0] - min[0]; + var bbHeight = max[1] - min[1]; + + var viewWidth = viewRect.width; + var viewHeight = viewRect.height; + + var viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + + viewCoordSys.setBoundingRect( + min[0], min[1], bbWidth, bbHeight + ); + viewCoordSys.setViewRect( + viewRect.x, viewRect.y, viewWidth, viewHeight + ); + + // Update roam info + viewCoordSys.setCenter(seriesModel.get('center')); + viewCoordSys.setZoom(seriesModel.get('zoom')); + + viewList.push(viewCoordSys); + } + }); + return viewList; + }; + + +/***/ }, +/* 226 */ +/***/ function(module, exports, __webpack_require__) { + + + __webpack_require__(227); + __webpack_require__(228); + + +/***/ }, +/* 227 */ +/***/ function(module, exports, __webpack_require__) { + + + + var List = __webpack_require__(98); + var SeriesModel = __webpack_require__(78); + var zrUtil = __webpack_require__(4); + + var GaugeSeries = SeriesModel.extend({ + + type: 'series.gauge', + + getInitialData: function (option, ecModel) { + var list = new List(['value'], this); + var dataOpt = option.data || []; + if (!zrUtil.isArray(dataOpt)) { + dataOpt = [dataOpt]; + } + // Only use the first data item + list.initData(dataOpt); + return list; + }, + + defaultOption: { + zlevel: 0, + z: 2, + // 默认全局居中 + center: ['50%', '50%'], + legendHoverLink: true, + radius: '75%', + startAngle: 225, + endAngle: -45, + clockwise: true, + // 最小值 + min: 0, + // 最大值 + max: 100, + // 分割段数,默认为10 + splitNumber: 10, + // 坐标轴线 + axisLine: { + // 默认显示,属性show控制显示与否 + show: true, + lineStyle: { // 属性lineStyle控制线条样式 + color: [[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']], + width: 30 + } + }, + // 分隔线 + splitLine: { + // 默认显示,属性show控制显示与否 + show: true, + // 属性length控制线长 + length: 30, + // 属性lineStyle(详见lineStyle)控制线条样式 + lineStyle: { + color: '#eee', + width: 2, + type: 'solid' + } + }, + // 坐标轴小标记 + axisTick: { + // 属性show控制显示与否,默认不显示 + show: true, + // 每份split细分多少段 + splitNumber: 5, + // 属性length控制线长 + length: 8, + // 属性lineStyle控制线条样式 + lineStyle: { + color: '#eee', + width: 1, + type: 'solid' + } + }, + axisLabel: { + show: true, + distance: 5, + // formatter: null, + textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: 'auto' + } + }, + pointer: { + show: true, + length: '80%', + width: 8 + }, + itemStyle: { + normal: { + color: 'auto' + } + }, + title: { + show: true, + // x, y,单位px + offsetCenter: [0, '-40%'], + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + textStyle: { + color: '#333', + fontSize: 15 + } + }, + detail: { + show: true, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 0, + borderColor: '#ccc', + width: 100, + height: 40, + // x, y,单位px + offsetCenter: [0, '40%'], + // formatter: null, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + textStyle: { + color: 'auto', + fontSize: 30 + } + } + } + }); + + module.exports = GaugeSeries; + + +/***/ }, +/* 228 */ +/***/ function(module, exports, __webpack_require__) { + + + + var PointerPath = __webpack_require__(229); + + var graphic = __webpack_require__(18); + var numberUtil = __webpack_require__(7); + var parsePercent = numberUtil.parsePercent; + + function parsePosition(seriesModel, api) { + var center = seriesModel.get('center'); + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent(center[0], api.getWidth()); + var cy = parsePercent(center[1], api.getHeight()); + var r = parsePercent(seriesModel.get('radius'), size / 2); + + return { + cx: cx, + cy: cy, + r: r + }; + } + + function formatLabel(label, labelFormatter) { + if (labelFormatter) { + if (typeof labelFormatter === 'string') { + label = labelFormatter.replace('{value}', label != null ? label : ''); + } + else if (typeof labelFormatter === 'function') { + label = labelFormatter(label); + } + } + + return label; + } + + var PI2 = Math.PI * 2; + + var GaugeView = __webpack_require__(80).extend({ + + type: 'gauge', + + render: function (seriesModel, ecModel, api) { + + this.group.removeAll(); + + var colorList = seriesModel.get('axisLine.lineStyle.color'); + var posInfo = parsePosition(seriesModel, api); + + this._renderMain( + seriesModel, ecModel, api, colorList, posInfo + ); + }, + + dispose: function () {}, + + _renderMain: function (seriesModel, ecModel, api, colorList, posInfo) { + var group = this.group; + + var axisLineModel = seriesModel.getModel('axisLine'); + var lineStyleModel = axisLineModel.getModel('lineStyle'); + + var clockwise = seriesModel.get('clockwise'); + var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI; + var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI; + + var angleRangeSpan = (endAngle - startAngle) % PI2; + + var prevEndAngle = startAngle; + var axisLineWidth = lineStyleModel.get('width'); + + for (var i = 0; i < colorList.length; i++) { + // Clamp + var percent = Math.min(Math.max(colorList[i][0], 0), 1); + var endAngle = startAngle + angleRangeSpan * percent; + var sector = new graphic.Sector({ + shape: { + startAngle: prevEndAngle, + endAngle: endAngle, + cx: posInfo.cx, + cy: posInfo.cy, + clockwise: clockwise, + r0: posInfo.r - axisLineWidth, + r: posInfo.r + }, + silent: true + }); + + sector.setStyle({ + fill: colorList[i][1] + }); + + sector.setStyle(lineStyleModel.getLineStyle( + // Because we use sector to simulate arc + // so the properties for stroking are useless + ['color', 'borderWidth', 'borderColor'] + )); + + group.add(sector); + + prevEndAngle = endAngle; + } + + var getColor = function (percent) { + // Less than 0 + if (percent <= 0) { + return colorList[0][1]; + } + for (var i = 0; i < colorList.length; i++) { + if (colorList[i][0] >= percent + && (i === 0 ? 0 : colorList[i - 1][0]) < percent + ) { + return colorList[i][1]; + } + } + // More than 1 + return colorList[i - 1][1]; + }; + + if (!clockwise) { + var tmp = startAngle; + startAngle = endAngle; + endAngle = tmp; + } + + this._renderTicks( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ); + + this._renderPointer( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ); + + this._renderTitle( + seriesModel, ecModel, api, getColor, posInfo + ); + this._renderDetail( + seriesModel, ecModel, api, getColor, posInfo + ); + }, + + _renderTicks: function ( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ) { + var group = this.group; + var cx = posInfo.cx; + var cy = posInfo.cy; + var r = posInfo.r; + + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + + var splitLineModel = seriesModel.getModel('splitLine'); + var tickModel = seriesModel.getModel('axisTick'); + var labelModel = seriesModel.getModel('axisLabel'); + + var splitNumber = seriesModel.get('splitNumber'); + var subSplitNumber = tickModel.get('splitNumber'); + + var splitLineLen = parsePercent( + splitLineModel.get('length'), r + ); + var tickLen = parsePercent( + tickModel.get('length'), r + ); + + var angle = startAngle; + var step = (endAngle - startAngle) / splitNumber; + var subStep = step / subSplitNumber; + + var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle(); + var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle(); + var textStyleModel = labelModel.getModel('textStyle'); + + for (var i = 0; i <= splitNumber; i++) { + var unitX = Math.cos(angle); + var unitY = Math.sin(angle); + // Split line + if (splitLineModel.get('show')) { + var splitLine = new graphic.Line({ + shape: { + x1: unitX * r + cx, + y1: unitY * r + cy, + x2: unitX * (r - splitLineLen) + cx, + y2: unitY * (r - splitLineLen) + cy + }, + style: splitLineStyle, + silent: true + }); + if (splitLineStyle.stroke === 'auto') { + splitLine.setStyle({ + stroke: getColor(i / splitNumber) + }); + } + + group.add(splitLine); + } + + // Label + if (labelModel.get('show')) { + var label = formatLabel( + numberUtil.round(i / splitNumber * (maxVal - minVal) + minVal), + labelModel.get('formatter') + ); + var distance = labelModel.get('distance'); + + var text = new graphic.Text({ + style: { + text: label, + x: unitX * (r - splitLineLen - distance) + cx, + y: unitY * (r - splitLineLen - distance) + cy, + fill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont(), + textVerticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'), + textAlign: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center') + }, + silent: true + }); + if (text.style.fill === 'auto') { + text.setStyle({ + fill: getColor(i / splitNumber) + }); + } + + group.add(text); + } + + // Axis tick + if (tickModel.get('show') && i !== splitNumber) { + for (var j = 0; j <= subSplitNumber; j++) { + var unitX = Math.cos(angle); + var unitY = Math.sin(angle); + var tickLine = new graphic.Line({ + shape: { + x1: unitX * r + cx, + y1: unitY * r + cy, + x2: unitX * (r - tickLen) + cx, + y2: unitY * (r - tickLen) + cy + }, + silent: true, + style: tickLineStyle + }); + + if (tickLineStyle.stroke === 'auto') { + tickLine.setStyle({ + stroke: getColor((i + j / subSplitNumber) / splitNumber) + }); + } + + group.add(tickLine); + angle += subStep; + } + angle -= subStep; + } + else { + angle += step; + } + } + }, + + _renderPointer: function ( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ) { + + var group = this.group; + var oldData = this._data; + + if (!seriesModel.get('pointer.show')) { + // Remove old element + oldData && oldData.eachItemGraphicEl(function (el) { + group.remove(el); + }); + return; + } + + var valueExtent = [+seriesModel.get('min'), +seriesModel.get('max')]; + var angleExtent = [startAngle, endAngle]; + + var data = seriesModel.getData(); + + data.diff(oldData) + .add(function (idx) { + var pointer = new PointerPath({ + shape: { + angle: startAngle + } + }); + + graphic.initProps(pointer, { + shape: { + angle: numberUtil.linearMap(data.get('value', idx), valueExtent, angleExtent, true) + } + }, seriesModel); + + group.add(pointer); + data.setItemGraphicEl(idx, pointer); + }) + .update(function (newIdx, oldIdx) { + var pointer = oldData.getItemGraphicEl(oldIdx); + + graphic.updateProps(pointer, { + shape: { + angle: numberUtil.linearMap(data.get('value', newIdx), valueExtent, angleExtent, true) + } + }, seriesModel); + + group.add(pointer); + data.setItemGraphicEl(newIdx, pointer); + }) + .remove(function (idx) { + var pointer = oldData.getItemGraphicEl(idx); + group.remove(pointer); + }) + .execute(); + + data.eachItemGraphicEl(function (pointer, idx) { + var itemModel = data.getItemModel(idx); + var pointerModel = itemModel.getModel('pointer'); + + pointer.setShape({ + x: posInfo.cx, + y: posInfo.cy, + width: parsePercent( + pointerModel.get('width'), posInfo.r + ), + r: parsePercent(pointerModel.get('length'), posInfo.r) + }); + + pointer.useStyle(itemModel.getModel('itemStyle.normal').getItemStyle()); + + if (pointer.style.fill === 'auto') { + pointer.setStyle('fill', getColor( + numberUtil.linearMap(data.get('value', idx), valueExtent, [0, 1], true) + )); + } + + graphic.setHoverStyle( + pointer, itemModel.getModel('itemStyle.emphasis').getItemStyle() + ); + }); + + this._data = data; + }, + + _renderTitle: function ( + seriesModel, ecModel, api, getColor, posInfo + ) { + var titleModel = seriesModel.getModel('title'); + if (titleModel.get('show')) { + var textStyleModel = titleModel.getModel('textStyle'); + var offsetCenter = titleModel.get('offsetCenter'); + var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r); + var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r); + + var text = new graphic.Text({ + style: { + x: x, + y: y, + // FIXME First data name ? + text: seriesModel.getData().getName(0), + fill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont(), + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + if (text.style.fill === 'auto') { + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var value = seriesModel.getData().get('value', 0); + text.setStyle('fill', getColor( + numberUtil.linearMap(value, [minVal, maxVal], [0, 1], true) + )); + } + + this.group.add(text); + } + }, + + _renderDetail: function ( + seriesModel, ecModel, api, getColor, posInfo + ) { + var detailModel = seriesModel.getModel('detail'); + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + if (detailModel.get('show')) { + var textStyleModel = detailModel.getModel('textStyle'); + var offsetCenter = detailModel.get('offsetCenter'); + var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r); + var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r); + var width = parsePercent(detailModel.get('width'), posInfo.r); + var height = parsePercent(detailModel.get('height'), posInfo.r); + var value = seriesModel.getData().get('value', 0); + var rect = new graphic.Rect({ + shape: { + x: x - width / 2, + y: y - height / 2, + width: width, + height: height + }, + style: { + text: formatLabel( + // FIXME First data name ? + value, detailModel.get('formatter') + ), + fill: detailModel.get('backgroundColor'), + textFill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont() + } + }); + if (rect.style.textFill === 'auto') { + rect.setStyle('textFill', getColor( + numberUtil.linearMap(value, [minVal, maxVal], [0, 1], true) + )); + } + rect.setStyle(detailModel.getItemStyle(['color'])); + this.group.add(rect); + } + } + }); + + module.exports = GaugeView; + + +/***/ }, +/* 229 */ +/***/ function(module, exports, __webpack_require__) { + + + + module.exports = __webpack_require__(20).extend({ + + type: 'echartsGaugePointer', + + shape: { + angle: 0, + + width: 10, + + r: 10, + + x: 0, + + y: 0 + }, + + buildPath: function (ctx, shape) { + var mathCos = Math.cos; + var mathSin = Math.sin; + + var r = shape.r; + var width = shape.width; + var angle = shape.angle; + var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2); + var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2); + + angle = shape.angle - Math.PI / 2; + ctx.moveTo(x, y); + ctx.lineTo( + shape.x + mathCos(angle) * width, + shape.y + mathSin(angle) * width + ); + ctx.lineTo( + shape.x + mathCos(shape.angle) * r, + shape.y + mathSin(shape.angle) * r + ); + ctx.lineTo( + shape.x - mathCos(angle) * width, + shape.y - mathSin(angle) * width + ); + ctx.lineTo(x, y); + return; + } + }); + + +/***/ }, +/* 230 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var echarts = __webpack_require__(1); + + __webpack_require__(231); + __webpack_require__(232); + + echarts.registerVisual(zrUtil.curry(__webpack_require__(151), 'funnel')); + echarts.registerLayout(__webpack_require__(233)); + + echarts.registerProcessor(zrUtil.curry(__webpack_require__(154), 'funnel')); + + +/***/ }, +/* 231 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var List = __webpack_require__(98); + var modelUtil = __webpack_require__(5); + var completeDimensions = __webpack_require__(110); + + var FunnelSeries = __webpack_require__(1).extendSeriesModel({ + + type: 'series.funnel', + + init: function (option) { + FunnelSeries.superApply(this, 'init', arguments); + + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + // Extend labelLine emphasis + this._defaultLabelLine(option); + }, + + getInitialData: function (option, ecModel) { + var dimensions = completeDimensions(['value'], option.data); + var list = new List(dimensions, this); + list.initData(option.data); + return list; + }, + + _defaultLabelLine: function (option) { + // Extend labelLine emphasis + modelUtil.defaultEmphasis(option.labelLine, ['show']); + + var labelLineNormalOpt = option.labelLine.normal; + var labelLineEmphasisOpt = option.labelLine.emphasis; + // Not show label line if `label.normal.show = false` + labelLineNormalOpt.show = labelLineNormalOpt.show + && option.label.normal.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show + && option.label.emphasis.show; + }, + + // Overwrite + getDataParams: function (dataIndex) { + var data = this.getData(); + var params = FunnelSeries.superCall(this, 'getDataParams', dataIndex); + var sum = data.getSum('value'); + // Percent is 0 if sum is 0 + params.percent = !sum ? 0 : +(data.get('value', dataIndex) / sum * 100).toFixed(2); + + params.$vars.push('percent'); + return params; + }, + + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + legendHoverLink: true, + left: 80, + top: 60, + right: 80, + bottom: 60, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + + // 默认取数据最小最大值 + // min: 0, + // max: 100, + minSize: '0%', + maxSize: '100%', + sort: 'descending', // 'ascending', 'descending' + gap: 0, + funnelAlign: 'center', + label: { + normal: { + show: true, + position: 'outer' + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + // textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE + }, + emphasis: { + show: true + } + }, + labelLine: { + normal: { + show: true, + length: 20, + lineStyle: { + // color: 各异, + width: 1, + type: 'solid' + } + }, + emphasis: {} + }, + itemStyle: { + normal: { + // color: 各异, + borderColor: '#fff', + borderWidth: 1 + }, + emphasis: { + // color: 各异, + } + } + } + }); + + module.exports = FunnelSeries; + + + +/***/ }, +/* 232 */ +/***/ function(module, exports, __webpack_require__) { + + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + + /** + * Piece of pie including Sector, Label, LabelLine + * @constructor + * @extends {module:zrender/graphic/Group} + */ + function FunnelPiece(data, idx) { + + graphic.Group.call(this); + + var polygon = new graphic.Polygon(); + var labelLine = new graphic.Polyline(); + var text = new graphic.Text(); + this.add(polygon); + this.add(labelLine); + this.add(text); + + this.updateData(data, idx, true); + + // Hover to change label and labelLine + function onEmphasis() { + labelLine.ignore = labelLine.hoverIgnore; + text.ignore = text.hoverIgnore; + } + function onNormal() { + labelLine.ignore = labelLine.normalIgnore; + text.ignore = text.normalIgnore; + } + this.on('emphasis', onEmphasis) + .on('normal', onNormal) + .on('mouseover', onEmphasis) + .on('mouseout', onNormal); + } + + var funnelPieceProto = FunnelPiece.prototype; + + function getLabelStyle(data, idx, state, labelModel) { + var textStyleModel = labelModel.getModel('textStyle'); + var position = labelModel.get('position'); + var isLabelInside = position === 'inside' || position === 'inner' || position === 'center'; + return { + fill: textStyleModel.getTextColor() + || (isLabelInside ? '#fff' : data.getItemVisual(idx, 'color')), + textFont: textStyleModel.getFont(), + text: zrUtil.retrieve( + data.hostModel.getFormattedLabel(idx, state), + data.getName(idx) + ) + }; + } + + var opacityAccessPath = ['itemStyle', 'normal', 'opacity']; + funnelPieceProto.updateData = function (data, idx, firstCreate) { + + var polygon = this.childAt(0); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var opacity = data.getItemModel(idx).get(opacityAccessPath); + opacity = opacity == null ? 1 : opacity; + + // Reset style + polygon.useStyle({}); + + if (firstCreate) { + polygon.setShape({ + points: layout.points + }); + polygon.setStyle({ opacity : 0 }); + graphic.initProps(polygon, { + style: { + opacity: opacity + } + }, seriesModel, idx); + } + else { + graphic.updateProps(polygon, { + style: { + opacity: opacity + }, + shape: { + points: layout.points + } + }, seriesModel, idx); + } + + // Update common style + var itemStyleModel = itemModel.getModel('itemStyle'); + var visualColor = data.getItemVisual(idx, 'color'); + + polygon.setStyle( + zrUtil.defaults( + { + lineJoin: 'round', + fill: visualColor + }, + itemStyleModel.getModel('normal').getItemStyle(['opacity']) + ) + ); + polygon.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle(); + + this._updateLabel(data, idx); + + graphic.setHoverStyle(this); + }; + + funnelPieceProto._updateLabel = function (data, idx) { + + var labelLine = this.childAt(1); + var labelText = this.childAt(2); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var labelLayout = layout.label; + var visualColor = data.getItemVisual(idx, 'color'); + + graphic.updateProps(labelLine, { + shape: { + points: labelLayout.linePoints || labelLayout.linePoints + } + }, seriesModel, idx); + + graphic.updateProps(labelText, { + style: { + x: labelLayout.x, + y: labelLayout.y + } + }, seriesModel, idx); + labelText.attr({ + style: { + textAlign: labelLayout.textAlign, + textVerticalAlign: labelLayout.verticalAlign, + textFont: labelLayout.font + }, + rotation: labelLayout.rotation, + origin: [labelLayout.x, labelLayout.y], + z2: 10 + }); + + var labelModel = itemModel.getModel('label.normal'); + var labelHoverModel = itemModel.getModel('label.emphasis'); + var labelLineModel = itemModel.getModel('labelLine.normal'); + var labelLineHoverModel = itemModel.getModel('labelLine.emphasis'); + + labelText.setStyle(getLabelStyle(data, idx, 'normal', labelModel)); + + labelText.ignore = labelText.normalIgnore = !labelModel.get('show'); + labelText.hoverIgnore = !labelHoverModel.get('show'); + + labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show'); + labelLine.hoverIgnore = !labelLineHoverModel.get('show'); + + // Default use item visual color + labelLine.setStyle({ + stroke: visualColor + }); + labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle()); + + labelText.hoverStyle = getLabelStyle(data, idx, 'emphasis', labelHoverModel); + labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle(); + }; + + zrUtil.inherits(FunnelPiece, graphic.Group); + + + var Funnel = __webpack_require__(80).extend({ + + type: 'funnel', + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var oldData = this._data; + + var group = this.group; + + data.diff(oldData) + .add(function (idx) { + var funnelPiece = new FunnelPiece(data, idx); + + data.setItemGraphicEl(idx, funnelPiece); + + group.add(funnelPiece); + }) + .update(function (newIdx, oldIdx) { + var piePiece = oldData.getItemGraphicEl(oldIdx); + + piePiece.updateData(data, newIdx); + + group.add(piePiece); + data.setItemGraphicEl(newIdx, piePiece); + }) + .remove(function (idx) { + var piePiece = oldData.getItemGraphicEl(idx); + group.remove(piePiece); + }) + .execute(); + + this._data = data; + }, + + remove: function () { + this.group.removeAll(); + this._data = null; + }, + + dispose: function () {} + }); + + module.exports = Funnel; + + +/***/ }, +/* 233 */ +/***/ function(module, exports, __webpack_require__) { + + + + var layout = __webpack_require__(71); + var number = __webpack_require__(7); + + var parsePercent = number.parsePercent; + + function getViewRect(seriesModel, api) { + return layout.getLayoutRect( + seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + } + ); + } + + function getSortedIndices(data, sort) { + var valueArr = data.mapArray('value', function (val) { + return val; + }); + var indices = []; + var isAscending = sort === 'ascending'; + for (var i = 0, len = data.count(); i < len; i++) { + indices[i] = i; + } + + // Add custom sortable function & none sortable opetion by "options.sort" + if (typeof sort === 'function') { + indices.sort(sort); + } else if (sort !== 'none') { + indices.sort(function (a, b) { + return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a]; + }); + } + return indices; + } + + function labelLayout (data) { + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label.normal'); + var labelPosition = labelModel.get('position'); + + var labelLineModel = itemModel.getModel('labelLine.normal'); + + var layout = data.getItemLayout(idx); + var points = layout.points; + + var isLabelInside = labelPosition === 'inner' + || labelPosition === 'inside' || labelPosition === 'center'; + + var textAlign; + var textX; + var textY; + var linePoints; + + if (isLabelInside) { + textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4; + textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4; + textAlign = 'center'; + linePoints = [ + [textX, textY], [textX, textY] + ]; + } + else { + var x1; + var y1; + var x2; + var labelLineLen = labelLineModel.get('length'); + if (labelPosition === 'left') { + // Left side + x1 = (points[3][0] + points[0][0]) / 2; + y1 = (points[3][1] + points[0][1]) / 2; + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } + else { + // Right side + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'left'; + } + var y2 = y1; + + linePoints = [[x1, y1], [x2, y2]]; + textY = y2; + } + + layout.label = { + linePoints: linePoints, + x: textX, + y: textY, + verticalAlign: 'middle', + textAlign: textAlign, + inside: isLabelInside + }; + }); + } + + module.exports = function (ecModel, api, payload) { + ecModel.eachSeriesByType('funnel', function (seriesModel) { + var data = seriesModel.getData(); + var sort = seriesModel.get('sort'); + var viewRect = getViewRect(seriesModel, api); + var indices = getSortedIndices(data, sort); + + var sizeExtent = [ + parsePercent(seriesModel.get('minSize'), viewRect.width), + parsePercent(seriesModel.get('maxSize'), viewRect.width) + ]; + var dataExtent = data.getDataExtent('value'); + var min = seriesModel.get('min'); + var max = seriesModel.get('max'); + if (min == null) { + min = Math.min(dataExtent[0], 0); + } + if (max == null) { + max = dataExtent[1]; + } + + var funnelAlign = seriesModel.get('funnelAlign'); + var gap = seriesModel.get('gap'); + var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count(); + + var y = viewRect.y; + + var getLinePoints = function (idx, offY) { + // End point index is data.count() and we assign it 0 + var val = data.get('value', idx) || 0; + var itemWidth = number.linearMap(val, [min, max], sizeExtent, true); + var x0; + switch (funnelAlign) { + case 'left': + x0 = viewRect.x; + break; + case 'center': + x0 = viewRect.x + (viewRect.width - itemWidth) / 2; + break; + case 'right': + x0 = viewRect.x + viewRect.width - itemWidth; + break; + } + return [ + [x0, offY], + [x0 + itemWidth, offY] + ]; + }; + + if (sort === 'ascending') { + // From bottom to top + itemHeight = -itemHeight; + gap = -gap; + y += viewRect.height; + indices = indices.reverse(); + } + + for (var i = 0; i < indices.length; i++) { + var idx = indices[i]; + var nextIdx = indices[i + 1]; + var start = getLinePoints(idx, y); + var end = getLinePoints(nextIdx, y + itemHeight); + + y += itemHeight + gap; + + data.setItemLayout(idx, { + points: start.concat(end.slice().reverse()) + }); + } + + labelLayout(data); + }); + }; + + + +/***/ }, +/* 234 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + + __webpack_require__(235); + + __webpack_require__(248); + __webpack_require__(249); + + echarts.registerVisual(__webpack_require__(250)); + + + +/***/ }, +/* 235 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(236); + __webpack_require__(240); + __webpack_require__(242); + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + var throttle = __webpack_require__(81); + + var CLICK_THRESHOLD = 5; // > 4 + + // Parallel view + echarts.extendComponentView({ + type: 'parallel', + + render: function (parallelModel, ecModel, api) { + this._model = parallelModel; + this._api = api; + + if (!this._handlers) { + this._handlers = {}; + zrUtil.each(handlers, function (handler, eventName) { + api.getZr().on(eventName, this._handlers[eventName] = zrUtil.bind(handler, this)); + }, this); + } + + throttle.createOrUpdate( + this, + '_throttledDispatchExpand', + parallelModel.get('axisExpandRate'), + 'fixRate' + ); + }, + + dispose: function (ecModel, api) { + zrUtil.each(this._handlers, function (handler, eventName) { + api.getZr().off(eventName, handler); + }); + this._handlers = null; + }, + + /** + * @param {Object} [opt] If null, cancle the last action triggering for debounce. + */ + _throttledDispatchExpand: function (opt) { + this._dispatchExpand(opt); + }, + + _dispatchExpand: function (opt) { + opt && this._api.dispatchAction( + zrUtil.extend({type: 'parallelAxisExpand'}, opt) + ); + } + + }); + + var handlers = { + + mousedown: function (e) { + if (checkTrigger(this, 'click')) { + this._mouseDownPoint = [e.offsetX, e.offsetY]; + } + }, + + mouseup: function (e) { + var mouseDownPoint = this._mouseDownPoint; + + if (checkTrigger(this, 'click') && mouseDownPoint) { + var point = [e.offsetX, e.offsetY]; + var dist = Math.pow(mouseDownPoint[0] - point[0], 2) + + Math.pow(mouseDownPoint[1] - point[1], 2); + + if (dist > CLICK_THRESHOLD) { + return; + } + + var result = this._model.coordinateSystem.getSlidedAxisExpandWindow( + [e.offsetX, e.offsetY] + ); + + result.behavior !== 'none' && this._dispatchExpand({ + axisExpandWindow: result.axisExpandWindow + }); + } + + this._mouseDownPoint = null; + }, + + mousemove: function (e) { + // Should do nothing when brushing. + if (this._mouseDownPoint || !checkTrigger(this, 'mousemove')) { + return; + } + var model = this._model; + var result = model.coordinateSystem.getSlidedAxisExpandWindow( + [e.offsetX, e.offsetY] + ); + + var behavior = result.behavior; + behavior === 'jump' && this._throttledDispatchExpand.debounceNextCall(model.get('axisExpandDebounce')); + this._throttledDispatchExpand( + behavior === 'none' + ? null // Cancle the last trigger, in case that mouse slide out of the area quickly. + : { + axisExpandWindow: result.axisExpandWindow, + // Jumping uses animation, and sliding suppresses animation. + animation: behavior === 'jump' ? null : false + } + ); + } + }; + + function checkTrigger(view, triggerOn) { + var model = view._model; + return model.get('axisExpandable') && model.get('axisExpandTriggerOn') === triggerOn; + } + + echarts.registerPreprocessor( + __webpack_require__(247) + ); + + + +/***/ }, +/* 236 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Parallel coordinate system creater. + */ + + + var Parallel = __webpack_require__(237); + + function create(ecModel, api) { + var coordSysList = []; + + ecModel.eachComponent('parallel', function (parallelModel, idx) { + var coordSys = new Parallel(parallelModel, ecModel, api); + + coordSys.name = 'parallel_' + idx; + coordSys.resize(parallelModel, api); + + parallelModel.coordinateSystem = coordSys; + coordSys.model = parallelModel; + + coordSysList.push(coordSys); + }); + + // Inject the coordinateSystems into seriesModel + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'parallel') { + var parallelModel = ecModel.queryComponents({ + mainType: 'parallel', + index: seriesModel.get('parallelIndex'), + id: seriesModel.get('parallelId') + })[0]; + seriesModel.coordinateSystem = parallelModel.coordinateSystem; + } + }); + + return coordSysList; + } + + __webpack_require__(76).register('parallel', {create: create}); + + + +/***/ }, +/* 237 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Parallel Coordinates + * + */ + + + var layoutUtil = __webpack_require__(71); + var axisHelper = __webpack_require__(101); + var zrUtil = __webpack_require__(4); + var ParallelAxis = __webpack_require__(238); + var graphic = __webpack_require__(18); + var matrix = __webpack_require__(11); + var numberUtil = __webpack_require__(7); + var sliderMove = __webpack_require__(239); + + var each = zrUtil.each; + var mathMin = Math.min; + var mathMax = Math.max; + var mathFloor = Math.floor; + var mathCeil = Math.ceil; + var round = numberUtil.round; + + var PI = Math.PI; + + function Parallel(parallelModel, ecModel, api) { + + /** + * key: dimension + * @type {Object.} + * @private + */ + this._axesMap = zrUtil.createHashMap(); + + /** + * key: dimension + * value: {position: [], rotation, } + * @type {Object.} + * @private + */ + this._axesLayout = {}; + + /** + * Always follow axis order. + * @type {Array.} + * @readOnly + */ + this.dimensions = parallelModel.dimensions; + + /** + * @type {module:zrender/core/BoundingRect} + */ + this._rect; + + /** + * @type {module:echarts/coord/parallel/ParallelModel} + */ + this._model = parallelModel; + + this._init(parallelModel, ecModel, api); + } + + Parallel.prototype = { + + type: 'parallel', + + constructor: Parallel, + + /** + * Initialize cartesian coordinate systems + * @private + */ + _init: function (parallelModel, ecModel, api) { + + var dimensions = parallelModel.dimensions; + var parallelAxisIndex = parallelModel.parallelAxisIndex; + + each(dimensions, function (dim, idx) { + + var axisIndex = parallelAxisIndex[idx]; + var axisModel = ecModel.getComponent('parallelAxis', axisIndex); + + var axis = this._axesMap.set(dim, new ParallelAxis( + dim, + axisHelper.createScaleByModel(axisModel), + [0, 0], + axisModel.get('type'), + axisIndex + )); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + + // Injection + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = axisModel.coordinateSystem = this; + + }, this); + }, + + /** + * Update axis scale after data processed + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + update: function (ecModel, api) { + this._updateAxesFromSeries(this._model, ecModel); + }, + + /** + * @override + */ + containPoint: function (point) { + var layoutInfo = this._makeLayoutInfo(); + var axisBase = layoutInfo.axisBase; + var layoutBase = layoutInfo.layoutBase; + var pixelDimIndex = layoutInfo.pixelDimIndex; + var pAxis = point[1 - pixelDimIndex]; + var pLayout = point[pixelDimIndex]; + + return pAxis >= axisBase + && pAxis <= axisBase + layoutInfo.axisLength + && pLayout >= layoutBase + && pLayout <= layoutBase + layoutInfo.layoutLength; + }, + + /** + * Update properties from series + * @private + */ + _updateAxesFromSeries: function (parallelModel, ecModel) { + ecModel.eachSeries(function (seriesModel) { + + if (!parallelModel.contains(seriesModel, ecModel)) { + return; + } + + var data = seriesModel.getData(); + + each(this.dimensions, function (dim) { + var axis = this._axesMap.get(dim); + axis.scale.unionExtentFromData(data, dim); + axisHelper.niceScaleExtent(axis.scale, axis.model); + }, this); + }, this); + }, + + /** + * Resize the parallel coordinate system. + * @param {module:echarts/coord/parallel/ParallelModel} parallelModel + * @param {module:echarts/ExtensionAPI} api + */ + resize: function (parallelModel, api) { + this._rect = layoutUtil.getLayoutRect( + parallelModel.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + } + ); + + this._layoutAxes(); + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getRect: function () { + return this._rect; + }, + + /** + * @private + */ + _makeLayoutInfo: function () { + var parallelModel = this._model; + var rect = this._rect; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + var layout = parallelModel.get('layout'); + var pixelDimIndex = layout === 'horizontal' ? 0 : 1; + var layoutLength = rect[wh[pixelDimIndex]]; + var layoutExtent = [0, layoutLength]; + var axisCount = this.dimensions.length; + + var axisExpandWidth = restrict(parallelModel.get('axisExpandWidth'), layoutExtent); + var axisExpandCount = restrict(parallelModel.get('axisExpandCount') || 0, [0, axisCount]); + var axisExpandable = parallelModel.get('axisExpandable') + && axisCount > 3 + && axisCount > axisExpandCount + && axisExpandCount > 1 + && axisExpandWidth > 0 + && layoutLength > 0; + + // `axisExpandWindow` is According to the coordinates of [0, axisExpandLength], + // for sake of consider the case that axisCollapseWidth is 0 (when screen is narrow), + // where collapsed axes should be overlapped. + var axisExpandWindow = parallelModel.get('axisExpandWindow'); + var winSize; + if (!axisExpandWindow) { + winSize = restrict(axisExpandWidth * (axisExpandCount - 1), layoutExtent); + var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor(axisCount / 2); + axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2]; + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } + else { + winSize = restrict(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent); + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } + + var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount); + // Avoid axisCollapseWidth is too small. + axisCollapseWidth < 3 && (axisCollapseWidth = 0); + + // Find the first and last indices > ewin[0] and < ewin[1]. + var winInnerIndices = [ + mathFloor(round(axisExpandWindow[0] / axisExpandWidth, 1)) + 1, + mathCeil(round(axisExpandWindow[1] / axisExpandWidth, 1)) - 1 + ]; + + // Pos in ec coordinates. + var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0]; + + return { + layout: layout, + pixelDimIndex: pixelDimIndex, + layoutBase: rect[xy[pixelDimIndex]], + layoutLength: layoutLength, + axisBase: rect[xy[1 - pixelDimIndex]], + axisLength: rect[wh[1 - pixelDimIndex]], + axisExpandable: axisExpandable, + axisExpandWidth: axisExpandWidth, + axisCollapseWidth: axisCollapseWidth, + axisExpandWindow: axisExpandWindow, + axisCount: axisCount, + winInnerIndices: winInnerIndices, + axisExpandWindow0Pos: axisExpandWindow0Pos + }; + }, + + /** + * @private + */ + _layoutAxes: function () { + var rect = this._rect; + var axes = this._axesMap; + var dimensions = this.dimensions; + var layoutInfo = this._makeLayoutInfo(); + var layout = layoutInfo.layout; + + axes.each(function (axis) { + var axisExtent = [0, layoutInfo.axisLength]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(axisExtent[idx], axisExtent[1 - idx]); + }); + + each(dimensions, function (dim, idx) { + var posInfo = (layoutInfo.axisExpandable + ? layoutAxisWithExpand : layoutAxisWithoutExpand + )(idx, layoutInfo); + + var positionTable = { + horizontal: { + x: posInfo.position, + y: layoutInfo.axisLength + }, + vertical: { + x: 0, + y: posInfo.position + } + }; + var rotationTable = { + horizontal: PI / 2, + vertical: 0 + }; + + var position = [ + positionTable[layout].x + rect.x, + positionTable[layout].y + rect.y + ]; + + var rotation = rotationTable[layout]; + var transform = matrix.create(); + matrix.rotate(transform, transform, rotation); + matrix.translate(transform, transform, position); + + // TODO + // tick等排布信息。 + + // TODO + // 根据axis order 更新 dimensions顺序。 + + this._axesLayout[dim] = { + position: position, + rotation: rotation, + transform: transform, + axisNameAvailableWidth: posInfo.axisNameAvailableWidth, + axisLabelShow: posInfo.axisLabelShow, + nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth, + tickDirection: 1, + labelDirection: 1, + labelInterval: axes.get(dim).getLabelInterval() + }; + }, this); + }, + + /** + * Get axis by dim. + * @param {string} dim + * @return {module:echarts/coord/parallel/ParallelAxis} [description] + */ + getAxis: function (dim) { + return this._axesMap.get(dim); + }, + + /** + * Convert a dim value of a single item of series data to Point. + * @param {*} value + * @param {string} dim + * @return {Array} + */ + dataToPoint: function (value, dim) { + return this.axisCoordToPoint( + this._axesMap.get(dim).dataToCoord(value), + dim + ); + }, + + /** + * Travel data for one time, get activeState of each data item. + * @param {module:echarts/data/List} data + * @param {Functio} cb param: {string} activeState 'active' or 'inactive' or 'normal' + * {number} dataIndex + * @param {Object} context + */ + eachActiveState: function (data, callback, context) { + var dimensions = this.dimensions; + var axesMap = this._axesMap; + var hasActiveSet = this.hasAxisBrushed(); + + for (var i = 0, len = data.count(); i < len; i++) { + var values = data.getValues(dimensions, i); + var activeState; + + if (!hasActiveSet) { + activeState = 'normal'; + } + else { + activeState = 'active'; + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + var dimName = dimensions[j]; + var state = axesMap.get(dimName).model.getActiveState(values[j], j); + + if (state === 'inactive') { + activeState = 'inactive'; + break; + } + } + } + + callback.call(context, activeState, i); + } + }, + + /** + * Whether has any activeSet. + * @return {boolean} + */ + hasAxisBrushed: function () { + var dimensions = this.dimensions; + var axesMap = this._axesMap; + var hasActiveSet = false; + + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') { + hasActiveSet = true; + } + } + + return hasActiveSet; + }, + + /** + * Convert coords of each axis to Point. + * Return point. For example: [10, 20] + * @param {Array.} coords + * @param {string} dim + * @return {Array.} + */ + axisCoordToPoint: function (coord, dim) { + var axisLayout = this._axesLayout[dim]; + return graphic.applyTransform([coord, 0], axisLayout.transform); + }, + + /** + * Get axis layout. + */ + getAxisLayout: function (dim) { + return zrUtil.clone(this._axesLayout[dim]); + }, + + /** + * @param {Array.} point + * @return {Object} {axisExpandWindow, delta, behavior: 'jump' | 'slide' | 'none'}. + */ + getSlidedAxisExpandWindow: function (point) { + var layoutInfo = this._makeLayoutInfo(); + var pixelDimIndex = layoutInfo.pixelDimIndex; + var axisExpandWindow = layoutInfo.axisExpandWindow.slice(); + var winSize = axisExpandWindow[1] - axisExpandWindow[0]; + var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)]; + + // Out of the area of coordinate system. + if (!this.containPoint(point)) { + return {behavior: 'none', axisExpandWindow: axisExpandWindow}; + } + + // Conver the point from global to expand coordinates. + var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos; + + // For dragging operation convenience, the window should not be + // slided when mouse is the center area of the window. + var delta; + var behavior = 'slide'; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + var triggerArea = this._model.get('axisExpandSlideTriggerArea'); + // But consider touch device, jump is necessary. + var useJump = triggerArea[0] != null; + + if (axisCollapseWidth) { + if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) { + behavior = 'jump'; + delta = pointCoord - winSize * triggerArea[2]; + } + else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) { + behavior = 'jump'; + delta = pointCoord - winSize * (1 - triggerArea[2]); + } + else { + (delta = pointCoord - winSize * triggerArea[1]) >= 0 + && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0 + && (delta = 0); + } + delta *= layoutInfo.axisExpandWidth / axisCollapseWidth; + delta + ? sliderMove(delta, axisExpandWindow, extent, 'all') + // Avoid nonsense triger on mousemove. + : (behavior = 'none'); + } + // When screen is too narrow, make it visible and slidable, although it is hard to interact. + else { + var winSize = axisExpandWindow[1] - axisExpandWindow[0]; + var pos = extent[1] * pointCoord / winSize; + axisExpandWindow = [mathMax(0, pos - winSize / 2)]; + axisExpandWindow[1] = mathMin(extent[1], axisExpandWindow[0] + winSize); + axisExpandWindow[0] = axisExpandWindow[1] - winSize; + } + + return { + axisExpandWindow: axisExpandWindow, + behavior: behavior + }; + } + }; + + function restrict(len, extent) { + return mathMin(mathMax(len, extent[0]), extent[1]); + } + + function layoutAxisWithoutExpand(axisIndex, layoutInfo) { + var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1); + return { + position: step * axisIndex, + axisNameAvailableWidth: step, + axisLabelShow: true + }; + } + + function layoutAxisWithExpand(axisIndex, layoutInfo) { + var layoutLength = layoutInfo.layoutLength; + var axisExpandWidth = layoutInfo.axisExpandWidth; + var axisCount = layoutInfo.axisCount; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + var winInnerIndices = layoutInfo.winInnerIndices; + + var position; + var axisNameAvailableWidth = axisCollapseWidth; + var axisLabelShow = false; + var nameTruncateMaxWidth; + + if (axisIndex < winInnerIndices[0]) { + position = axisIndex * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } + else if (axisIndex <= winInnerIndices[1]) { + position = layoutInfo.axisExpandWindow0Pos + + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0]; + axisNameAvailableWidth = axisExpandWidth; + axisLabelShow = true; + } + else { + position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } + + return { + position: position, + axisNameAvailableWidth: axisNameAvailableWidth, + axisLabelShow: axisLabelShow, + nameTruncateMaxWidth: nameTruncateMaxWidth + }; + } + + module.exports = Parallel; + + +/***/ }, +/* 238 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var Axis = __webpack_require__(100); + + /** + * @constructor module:echarts/coord/parallel/ParallelAxis + * @extends {module:echarts/coord/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + */ + var ParallelAxis = function (dim, scale, coordExtent, axisType, axisIndex) { + + Axis.call(this, dim, scale, coordExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * @type {number} + * @readOnly + */ + this.axisIndex = axisIndex; + }; + + ParallelAxis.prototype = { + + constructor: ParallelAxis, + + /** + * Axis model + * @param {module:echarts/coord/parallel/AxisModel} + */ + model: null + + }; + + zrUtil.inherits(ParallelAxis, Axis); + + module.exports = ParallelAxis; + + +/***/ }, +/* 239 */ +/***/ function(module, exports) { + + + + /** + * Calculate slider move result. + * Usage: + * (1) If both handle0 and handle1 are needed to be moved, set minSpan the same as + * maxSpan and the same as `Math.abs(handleEnd[1] - handleEnds[0])`. + * (2) If handle0 is forbidden to cross handle1, set minSpan as `0`. + * + * @param {number} delta Move length. + * @param {Array.} handleEnds handleEnds[0] can be bigger then handleEnds[1]. + * handleEnds will be modified in this method. + * @param {Array.} extent handleEnds is restricted by extent. + * extent[0] should less or equals than extent[1]. + * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds, + * where the input minSpan and maxSpan will not work. + * @param {number} [minSpan] The range of dataZoom can not be smaller than that. + * If not set, handle0 and cross handle1. If set as a non-negative + * number (including `0`), handles will push each other when reaching + * the minSpan. + * @param {number} [maxSpan] The range of dataZoom can not be larger than that. + * @return {Array.} The input handleEnds. + */ + module.exports = function (delta, handleEnds, extent, handleIndex, minSpan, maxSpan) { + // Normalize firstly. + handleEnds[0] = restrict(handleEnds[0], extent); + handleEnds[1] = restrict(handleEnds[1], extent); + + delta = delta || 0; + + var extentSpan = extent[1] - extent[0]; + + // Notice maxSpan and minSpan can be null/undefined. + if (minSpan != null) { + minSpan = restrict(minSpan, [0, extentSpan]); + } + if (maxSpan != null) { + maxSpan = Math.max(maxSpan, minSpan != null ? minSpan : 0); + } + if (handleIndex === 'all') { + minSpan = maxSpan = Math.abs(handleEnds[1] - handleEnds[0]); + handleIndex = 0; + } + + var originalDistSign = getSpanSign(handleEnds, handleIndex); + + handleEnds[handleIndex] += delta; + + // Restrict in extent. + var extentMinSpan = minSpan || 0; + var realExtent = extent.slice(); + originalDistSign.sign < 0 ? (realExtent[0] += extentMinSpan) : (realExtent[1] -= extentMinSpan); + handleEnds[handleIndex] = restrict(handleEnds[handleIndex], realExtent); + + // Expand span. + var currDistSign = getSpanSign(handleEnds, handleIndex); + if (minSpan != null && ( + currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan + )) { + // If minSpan exists, 'cross' is forbinden. + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan; + } + + // Shrink span. + var currDistSign = getSpanSign(handleEnds, handleIndex); + if (maxSpan != null && currDistSign.span > maxSpan) { + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + currDistSign.sign * maxSpan; + } + + return handleEnds; + }; + + function getSpanSign(handleEnds, handleIndex) { + var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex]; + // If `handleEnds[0] === handleEnds[1]`, always believe that handleEnd[0] + // is at left of handleEnds[1] for non-cross case. + return {span: Math.abs(dist), sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1}; + } + + function restrict(value, extend) { + return Math.min(extend[1], Math.max(extend[0], value)); + } + + +/***/ }, +/* 240 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var Component = __webpack_require__(69); + + __webpack_require__(241); + + Component.extend({ + + type: 'parallel', + + dependencies: ['parallelAxis'], + + /** + * @type {module:echarts/coord/parallel/Parallel} + */ + coordinateSystem: null, + + /** + * Each item like: 'dim0', 'dim1', 'dim2', ... + * @type {Array.} + * @readOnly + */ + dimensions: null, + + /** + * Coresponding to dimensions. + * @type {Array.} + * @readOnly + */ + parallelAxisIndex: null, + + layoutMode: 'box', + + defaultOption: { + zlevel: 0, + z: 0, + left: 80, + top: 60, + right: 80, + bottom: 60, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + + layout: 'horizontal', // 'horizontal' or 'vertical' + + // FIXME + // naming? + axisExpandable: false, + axisExpandCenter: null, + axisExpandCount: 0, + axisExpandWidth: 50, // FIXME '10%' ? + axisExpandRate: 17, + axisExpandDebounce: 50, + // [out, in, jumpTarget]. In percentage. If use [null, 0.05], null means full. + // Do not doc to user until necessary. + axisExpandSlideTriggerArea: [-0.15, 0.05, 0.4], + axisExpandTriggerOn: 'click', // 'mousemove' or 'click' + + parallelAxisDefault: null + }, + + /** + * @override + */ + init: function () { + Component.prototype.init.apply(this, arguments); + + this.mergeOption({}); + }, + + /** + * @override + */ + mergeOption: function (newOption) { + var thisOption = this.option; + + newOption && zrUtil.merge(thisOption, newOption, true); + + this._initDimensions(); + }, + + /** + * Whether series or axis is in this coordinate system. + * @param {module:echarts/model/Series|module:echarts/coord/parallel/AxisModel} model + * @param {module:echarts/model/Global} ecModel + */ + contains: function (model, ecModel) { + var parallelIndex = model.get('parallelIndex'); + return parallelIndex != null + && ecModel.getComponent('parallel', parallelIndex) === this; + }, + + setAxisExpand: function (opt) { + zrUtil.each( + ['axisExpandable', 'axisExpandCenter', 'axisExpandCount', 'axisExpandWidth', 'axisExpandWindow'], + function (name) { + if (opt.hasOwnProperty(name)) { + this.option[name] = opt[name]; + } + }, + this + ); + }, + + /** + * @private + */ + _initDimensions: function () { + var dimensions = this.dimensions = []; + var parallelAxisIndex = this.parallelAxisIndex = []; + + var axisModels = zrUtil.filter(this.dependentModels.parallelAxis, function (axisModel) { + // Can not use this.contains here, because + // initialization has not been completed yet. + return axisModel.get('parallelIndex') === this.componentIndex; + }); + + zrUtil.each(axisModels, function (axisModel) { + dimensions.push('dim' + axisModel.get('dim')); + parallelAxisIndex.push(axisModel.componentIndex); + }); + } + + }); + + + +/***/ }, +/* 241 */ +/***/ function(module, exports, __webpack_require__) { + + + + var ComponentModel = __webpack_require__(69); + var zrUtil = __webpack_require__(4); + var makeStyleMapper = __webpack_require__(15); + var axisModelCreator = __webpack_require__(131); + var numberUtil = __webpack_require__(7); + + var AxisModel = ComponentModel.extend({ + + type: 'baseParallelAxis', + + /** + * @type {module:echarts/coord/parallel/Axis} + */ + axis: null, + + /** + * @type {Array.} + * @readOnly + */ + activeIntervals: [], + + /** + * @return {Object} + */ + getAreaSelectStyle: function () { + return makeStyleMapper( + [ + ['fill', 'color'], + ['lineWidth', 'borderWidth'], + ['stroke', 'borderColor'], + ['width', 'width'], + ['opacity', 'opacity'] + ] + ).call(this.getModel('areaSelectStyle')); + }, + + /** + * The code of this feature is put on AxisModel but not ParallelAxis, + * because axisModel can be alive after echarts updating but instance of + * ParallelAxis having been disposed. this._activeInterval should be kept + * when action dispatched (i.e. legend click). + * + * @param {Array.>} intervals interval.length === 0 + * means set all active. + * @public + */ + setActiveIntervals: function (intervals) { + var activeIntervals = this.activeIntervals = zrUtil.clone(intervals); + + // Normalize + if (activeIntervals) { + for (var i = activeIntervals.length - 1; i >= 0; i--) { + numberUtil.asc(activeIntervals[i]); + } + } + }, + + /** + * @param {number|string} [value] When attempting to detect 'no activeIntervals set', + * value can not be input. + * @return {string} 'normal': no activeIntervals set, + * 'active', + * 'inactive'. + * @public + */ + getActiveState: function (value) { + var activeIntervals = this.activeIntervals; + + if (!activeIntervals.length) { + return 'normal'; + } + + if (value == null) { + return 'inactive'; + } + + for (var i = 0, len = activeIntervals.length; i < len; i++) { + if (activeIntervals[i][0] <= value && value <= activeIntervals[i][1]) { + return 'active'; + } + } + return 'inactive'; + } + + }); + + var defaultOption = { + + type: 'value', + + /** + * @type {Array.} + */ + dim: null, // 0, 1, 2, ... + + // parallelIndex: null, + + areaSelectStyle: { + width: 20, + borderWidth: 1, + borderColor: 'rgba(160,197,232)', + color: 'rgba(160,197,232)', + opacity: 0.3 + }, + + realtime: true, // Whether realtime update view when select. + + z: 10 + }; + + zrUtil.merge(AxisModel.prototype, __webpack_require__(112)); + + function getAxisType(axisName, option) { + return option.type || (option.data ? 'category' : 'value'); + } + + axisModelCreator('parallel', AxisModel, getAxisType, defaultOption); + + module.exports = AxisModel; + + +/***/ }, +/* 242 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(236); + __webpack_require__(243); + __webpack_require__(244); + + + +/***/ }, +/* 243 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + + /** + * @payload + * @property {string} parallelAxisId + * @property {Array.>} intervals + */ + var actionInfo = { + type: 'axisAreaSelect', + event: 'axisAreaSelected', + update: 'updateVisual' + }; + echarts.registerAction(actionInfo, function (payload, ecModel) { + ecModel.eachComponent( + {mainType: 'parallelAxis', query: payload}, + function (parallelAxisModel) { + parallelAxisModel.axis.model.setActiveIntervals(payload.intervals); + } + ); + }); + + /** + * @payload + */ + echarts.registerAction('parallelAxisExpand', function (payload, ecModel) { + ecModel.eachComponent( + {mainType: 'parallel', query: payload}, + function (parallelModel) { + parallelModel.setAxisExpand(payload); + } + ); + + }); + + +/***/ }, +/* 244 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var AxisBuilder = __webpack_require__(135); + var BrushController = __webpack_require__(245); + var brushHelper = __webpack_require__(246); + var graphic = __webpack_require__(18); + + var elementList = ['axisLine', 'axisLabel', 'axisTick', 'axisName']; + + var AxisView = __webpack_require__(1).extendComponentView({ + + type: 'parallelAxis', + + /** + * @override + */ + init: function (ecModel, api) { + AxisView.superApply(this, 'init', arguments); + + /** + * @type {module:echarts/component/helper/BrushController} + */ + (this._brushController = new BrushController(api.getZr())) + .on('brush', zrUtil.bind(this._onBrush, this)); + }, + + /** + * @override + */ + render: function (axisModel, ecModel, api, payload) { + if (fromAxisAreaSelect(axisModel, ecModel, payload)) { + return; + } + + this.axisModel = axisModel; + this.api = api; + + this.group.removeAll(); + + var oldAxisGroup = this._axisGroup; + this._axisGroup = new graphic.Group(); + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var coordSysModel = getCoordSysModel(axisModel, ecModel); + var coordSys = coordSysModel.coordinateSystem; + + var areaSelectStyle = axisModel.getAreaSelectStyle(); + var areaWidth = areaSelectStyle.width; + + var dim = axisModel.axis.dim; + var axisLayout = coordSys.getAxisLayout(dim); + + var builderOpt = zrUtil.extend( + {strokeContainThreshold: areaWidth}, + axisLayout + ); + + var axisBuilder = new AxisBuilder(axisModel, builderOpt); + + zrUtil.each(elementList, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + this._refreshBrushController( + builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api + ); + + var animationModel = (payload && payload.animation === false) ? null : axisModel; + graphic.groupTransition(oldAxisGroup, this._axisGroup, animationModel); + }, + + /** + * @override + */ + updateVisual: function (axisModel, ecModel, api, payload) { + this._brushController && this._brushController + .updateCovers(getCoverInfoList(axisModel)); + }, + + _refreshBrushController: function ( + builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api + ) { + // After filtering, axis may change, select area needs to be update. + var extent = axisModel.axis.getExtent(); + var extentLen = extent[1] - extent[0]; + var extra = Math.min(30, Math.abs(extentLen) * 0.1); // Arbitrary value. + + // width/height might be negative, which will be + // normalized in BoundingRect. + var rect = graphic.BoundingRect.create({ + x: extent[0], + y: -areaWidth / 2, + width: extentLen, + height: areaWidth + }); + rect.x -= extra; + rect.width += 2 * extra; + + this._brushController + .mount({ + enableGlobalPan: true, + rotation: builderOpt.rotation, + position: builderOpt.position + }) + .setPanels([{ + panelId: 'pl', + clipPath: brushHelper.makeRectPanelClipPath(rect), + isTargetByCursor: brushHelper.makeRectIsTargetByCursor(rect, api, coordSysModel), + getLinearBrushOtherExtent: brushHelper.makeLinearBrushOtherExtent(rect, 0) + }]) + .enableBrush({ + brushType: 'lineX', + brushStyle: areaSelectStyle, + removeOnClick: true + }) + .updateCovers(getCoverInfoList(axisModel)); + }, + + _onBrush: function (coverInfoList, opt) { + // Do not cache these object, because the mey be changed. + var axisModel = this.axisModel; + var axis = axisModel.axis; + var intervals = zrUtil.map(coverInfoList, function (coverInfo) { + return [ + axis.coordToData(coverInfo.range[0], true), + axis.coordToData(coverInfo.range[1], true) + ]; + }); + + // If realtime is true, action is not dispatched on drag end, because + // the drag end emits the same params with the last drag move event, + // and may have some delay when using touch pad. + if (!axisModel.option.realtime === opt.isEnd || opt.removeOnClick) { // jshint ignore:line + this.api.dispatchAction({ + type: 'axisAreaSelect', + parallelAxisId: axisModel.id, + intervals: intervals + }); + } + }, + + /** + * @override + */ + dispose: function () { + this._brushController.dispose(); + } + }); + + function fromAxisAreaSelect(axisModel, ecModel, payload) { + return payload + && payload.type === 'axisAreaSelect' + && ecModel.findComponents( + {mainType: 'parallelAxis', query: payload} + )[0] === axisModel; + } + + function getCoverInfoList(axisModel) { + var axis = axisModel.axis; + return zrUtil.map(axisModel.activeIntervals, function (interval) { + return { + brushType: 'lineX', + panelId: 'pl', + range: [ + axis.dataToCoord(interval[0], true), + axis.dataToCoord(interval[1], true) + ] + }; + }); + } + + function getCoordSysModel(axisModel, ecModel) { + return ecModel.getComponent( + 'parallel', axisModel.get('parallelIndex') + ); + } + + module.exports = AxisView; + + +/***/ }, +/* 245 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Box selection tool. + * + * @module echarts/component/helper/BrushController + */ + + + + var Eventful = __webpack_require__(25); + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var interactionMutex = __webpack_require__(184); + var DataDiffer = __webpack_require__(99); + + var curry = zrUtil.curry; + var each = zrUtil.each; + var map = zrUtil.map; + var mathMin = Math.min; + var mathMax = Math.max; + var mathPow = Math.pow; + + var COVER_Z = 10000; + var UNSELECT_THRESHOLD = 6; + var MIN_RESIZE_LINE_WIDTH = 6; + var MUTEX_RESOURCE_KEY = 'globalPan'; + + var DIRECTION_MAP = { + w: [0, 0], + e: [0, 1], + n: [1, 0], + s: [1, 1] + }; + var CURSOR_MAP = { + w: 'ew', + e: 'ew', + n: 'ns', + s: 'ns', + ne: 'nesw', + sw: 'nesw', + nw: 'nwse', + se: 'nwse' + }; + var DEFAULT_BRUSH_OPT = { + brushStyle: { + lineWidth: 2, + stroke: 'rgba(0,0,0,0.3)', + fill: 'rgba(0,0,0,0.1)' + }, + transformable: true, + brushMode: 'single', + removeOnClick: false + }; + + var baseUID = 0; + + /** + * @alias module:echarts/component/helper/BrushController + * @constructor + * @mixin {module:zrender/mixin/Eventful} + * @event module:echarts/component/helper/BrushController#brush + * params: + * areas: Array., coord relates to container group, + * If no container specified, to global. + * opt { + * isEnd: boolean, + * removeOnClick: boolean + * } + * + * @param {module:zrender/zrender~ZRender} zr + */ + function BrushController(zr) { + + if (true) { + zrUtil.assert(zr); + } + + Eventful.call(this); + + /** + * @type {module:zrender/zrender~ZRender} + * @private + */ + this._zr = zr; + + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = new graphic.Group(); + + /** + * Only for drawing (after enabledBrush). + * 'line', 'rect', 'polygon' or false + * If passing false/null/undefined, disable brush. + * If passing 'auto', determined by panel.defaultBrushType + * @private + * @type {string} + */ + this._brushType; + + /** + * Only for drawing (after enabledBrush). + * + * @private + * @type {Object} + */ + this._brushOption; + + /** + * @private + * @type {Object} + */ + this._panels; + + /** + * @private + * @type {Array.} + */ + this._track = []; + + /** + * @private + * @type {boolean} + */ + this._dragging; + + /** + * @private + * @type {Array} + */ + this._covers = []; + + /** + * @private + * @type {moudule:zrender/container/Group} + */ + this._creatingCover; + + /** + * `true` means global panel + * @private + * @type {module:zrender/container/Group|boolean} + */ + this._creatingPanel; + + /** + * @private + * @type {boolean} + */ + this._enableGlobalPan; + + /** + * @private + * @type {boolean} + */ + if (true) { + this._mounted; + } + + /** + * @private + * @type {string} + */ + this._uid = 'brushController_' + baseUID++; + + /** + * @private + * @type {Object} + */ + this._handlers = {}; + each(mouseHandlers, function (handler, eventName) { + this._handlers[eventName] = zrUtil.bind(handler, this); + }, this); + } + + BrushController.prototype = { + + constructor: BrushController, + + /** + * If set to null/undefined/false, select disabled. + * @param {Object} brushOption + * @param {string|boolean} brushOption.brushType 'line', 'rect', 'polygon' or false + * If passing false/null/undefined, disable brush. + * If passing 'auto', determined by panel.defaultBrushType. + * ('auto' can not be used in global panel) + * @param {number} [brushOption.brushMode='single'] 'single' or 'multiple' + * @param {boolean} [brushOption.transformable=true] + * @param {boolean} [brushOption.removeOnClick=false] + * @param {Object} [brushOption.brushStyle] + * @param {number} [brushOption.brushStyle.width] + * @param {number} [brushOption.brushStyle.lineWidth] + * @param {string} [brushOption.brushStyle.stroke] + * @param {string} [brushOption.brushStyle.fill] + * @param {number} [brushOption.z] + */ + enableBrush: function (brushOption) { + if (true) { + zrUtil.assert(this._mounted); + } + + this._brushType && doDisableBrush(this); + brushOption.brushType && doEnableBrush(this, brushOption); + + return this; + }, + + /** + * @param {Array.} panelOpts If not pass, it is global brush. + * Each items: { + * panelId, // mandatory. + * clipPath, // mandatory. function. + * isTargetByCursor, // mandatory. function. + * defaultBrushType, // optional, only used when brushType is 'auto'. + * getLinearBrushOtherExtent, // optional. function. + * } + */ + setPanels: function (panelOpts) { + if (panelOpts && panelOpts.length) { + var panels = this._panels = {}; + zrUtil.each(panelOpts, function (panelOpts) { + panels[panelOpts.panelId] = zrUtil.clone(panelOpts); + }); + } + else { + this._panels = null; + } + return this; + }, + + /** + * @param {Object} [opt] + * @return {boolean} [opt.enableGlobalPan=false] + */ + mount: function (opt) { + opt = opt || {}; + + if (true) { + this._mounted = true; // should be at first. + } + + this._enableGlobalPan = opt.enableGlobalPan; + + var thisGroup = this.group; + this._zr.add(thisGroup); + + thisGroup.attr({ + position: opt.position || [0, 0], + rotation: opt.rotation || 0, + scale: opt.scale || [1, 1] + }); + this._transform = thisGroup.getLocalTransform(); + + return this; + }, + + eachCover: function (cb, context) { + each(this._covers, cb, context); + }, + + /** + * Update covers. + * @param {Array.} brushOptionList Like: + * [ + * {id: 'xx', brushType: 'line', range: [23, 44], brushStyle, transformable}, + * {id: 'yy', brushType: 'rect', range: [[23, 44], [23, 54]]}, + * ... + * ] + * `brushType` is required in each cover info. (can not be 'auto') + * `id` is not mandatory. + * `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default. + * If brushOptionList is null/undefined, all covers removed. + */ + updateCovers: function (brushOptionList) { + if (true) { + zrUtil.assert(this._mounted); + } + + brushOptionList = zrUtil.map(brushOptionList, function (brushOption) { + return zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true); + }); + + var tmpIdPrefix = '\0-brush-index-'; + var oldCovers = this._covers; + var newCovers = this._covers = []; + var controller = this; + var creatingCover = this._creatingCover; + + (new DataDiffer(oldCovers, brushOptionList, oldGetKey, getKey)) + .add(addOrUpdate) + .update(addOrUpdate) + .remove(remove) + .execute(); + + return this; + + function getKey(brushOption, index) { + return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index) + + '-' + brushOption.brushType; + } + + function oldGetKey(cover, index) { + return getKey(cover.__brushOption, index); + } + + function addOrUpdate(newIndex, oldIndex) { + var newBrushOption = brushOptionList[newIndex]; + // Consider setOption in event listener of brushSelect, + // where updating cover when creating should be forbiden. + if (oldIndex != null && oldCovers[oldIndex] === creatingCover) { + newCovers[newIndex] = oldCovers[oldIndex]; + } + else { + var cover = newCovers[newIndex] = oldIndex != null + ? ( + oldCovers[oldIndex].__brushOption = newBrushOption, + oldCovers[oldIndex] + ) + : endCreating(controller, createCover(controller, newBrushOption)); + updateCoverAfterCreation(controller, cover); + } + } + + function remove(oldIndex) { + if (oldCovers[oldIndex] !== creatingCover) { + controller.group.remove(oldCovers[oldIndex]); + } + } + }, + + unmount: function () { + if (true) { + if (!this._mounted) { + return; + } + } + + this.enableBrush(false); + + // container may 'removeAll' outside. + clearCovers(this); + this._zr.remove(this.group); + + if (true) { + this._mounted = false; // should be at last. + } + + return this; + }, + + dispose: function () { + this.unmount(); + this.off(); + } + }; + + zrUtil.mixin(BrushController, Eventful); + + function doEnableBrush(controller, brushOption) { + var zr = controller._zr; + + // Consider roam, which takes globalPan too. + if (!controller._enableGlobalPan) { + interactionMutex.take(zr, MUTEX_RESOURCE_KEY, controller._uid); + } + + each(controller._handlers, function (handler, eventName) { + zr.on(eventName, handler); + }); + + controller._brushType = brushOption.brushType; + controller._brushOption = zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true); + } + + function doDisableBrush(controller) { + var zr = controller._zr; + + interactionMutex.release(zr, MUTEX_RESOURCE_KEY, controller._uid); + + each(controller._handlers, function (handler, eventName) { + zr.off(eventName, handler); + }); + + controller._brushType = controller._brushOption = null; + } + + function createCover(controller, brushOption) { + var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption); + cover.__brushOption = brushOption; + updateZ(cover, brushOption); + controller.group.add(cover); + return cover; + } + + function endCreating(controller, creatingCover) { + var coverRenderer = getCoverRenderer(creatingCover); + if (coverRenderer.endCreating) { + coverRenderer.endCreating(controller, creatingCover); + updateZ(creatingCover, creatingCover.__brushOption); + } + return creatingCover; + } + + function updateCoverShape(controller, cover) { + var brushOption = cover.__brushOption; + getCoverRenderer(cover).updateCoverShape( + controller, cover, brushOption.range, brushOption + ); + } + + function updateZ(cover, brushOption) { + var z = brushOption.z; + z == null && (z = COVER_Z); + cover.traverse(function (el) { + el.z = z; + el.z2 = z; // Consider in given container. + }); + } + + function updateCoverAfterCreation(controller, cover) { + getCoverRenderer(cover).updateCommon(controller, cover); + updateCoverShape(controller, cover); + } + + function getCoverRenderer(cover) { + return coverRenderers[cover.__brushOption.brushType]; + } + + // return target panel or `true` (means global panel) + function getPanelByPoint(controller, e, localCursorPoint) { + var panels = controller._panels; + if (!panels) { + return true; // Global panel + } + var panel; + var transform = controller._transform; + each(panels, function (pn) { + pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn); + }); + return panel; + } + + // Return a panel or true + function getPanelByCover(controller, cover) { + var panels = controller._panels; + if (!panels) { + return true; // Global panel + } + var panelId = cover.__brushOption.panelId; + // User may give cover without coord sys info, + // which is then treated as global panel. + return panelId != null ? panels[panelId] : true; + } + + function clearCovers(controller) { + var covers = controller._covers; + var originalLength = covers.length; + each(covers, function (cover) { + controller.group.remove(cover); + }, controller); + covers.length = 0; + + return !!originalLength; + } + + function trigger(controller, opt) { + var areas = map(controller._covers, function (cover) { + var brushOption = cover.__brushOption; + var range = zrUtil.clone(brushOption.range); + return { + brushType: brushOption.brushType, + panelId: brushOption.panelId, + range: range + }; + }); + + controller.trigger('brush', areas, { + isEnd: !!opt.isEnd, + removeOnClick: !!opt.removeOnClick + }); + } + + function shouldShowCover(controller) { + var track = controller._track; + + if (!track.length) { + return false; + } + + var p2 = track[track.length - 1]; + var p1 = track[0]; + var dx = p2[0] - p1[0]; + var dy = p2[1] - p1[1]; + var dist = mathPow(dx * dx + dy * dy, 0.5); + + return dist > UNSELECT_THRESHOLD; + } + + function getTrackEnds(track) { + var tail = track.length - 1; + tail < 0 && (tail = 0); + return [track[0], track[tail]]; + } + + function createBaseRectCover(doDrift, controller, brushOption, edgeNames) { + var cover = new graphic.Group(); + + cover.add(new graphic.Rect({ + name: 'main', + style: makeStyle(brushOption), + silent: true, + draggable: true, + cursor: 'move', + drift: curry(doDrift, controller, cover, 'nswe'), + ondragend: curry(trigger, controller, {isEnd: true}) + })); + + each( + edgeNames, + function (name) { + cover.add(new graphic.Rect({ + name: name, + style: {opacity: 0}, + draggable: true, + silent: true, + invisible: true, + drift: curry(doDrift, controller, cover, name), + ondragend: curry(trigger, controller, {isEnd: true}) + })); + } + ); + + return cover; + } + + function updateBaseRect(controller, cover, localRange, brushOption) { + var lineWidth = brushOption.brushStyle.lineWidth || 0; + var handleSize = mathMax(lineWidth, MIN_RESIZE_LINE_WIDTH); + var x = localRange[0][0]; + var y = localRange[1][0]; + var xa = x - lineWidth / 2; + var ya = y - lineWidth / 2; + var x2 = localRange[0][1]; + var y2 = localRange[1][1]; + var x2a = x2 - handleSize + lineWidth / 2; + var y2a = y2 - handleSize + lineWidth / 2; + var width = x2 - x; + var height = y2 - y; + var widtha = width + lineWidth; + var heighta = height + lineWidth; + + updateRectShape(controller, cover, 'main', x, y, width, height); + + if (brushOption.transformable) { + updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta); + updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta); + updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize); + updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize); + + updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize); + updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize); + } + } + + function updateCommon(controller, cover) { + var brushOption = cover.__brushOption; + var transformable = brushOption.transformable; + + var mainEl = cover.childAt(0); + mainEl.useStyle(makeStyle(brushOption)); + mainEl.attr({ + silent: !transformable, + cursor: transformable ? 'move' : 'default' + }); + + each( + ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'], + function (name) { + var el = cover.childOfName(name); + var globalDir = getGlobalDirection(controller, name); + + el && el.attr({ + silent: !transformable, + invisible: !transformable, + cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null + }); + } + ); + } + + function updateRectShape(controller, cover, name, x, y, w, h) { + var el = cover.childOfName(name); + el && el.setShape(pointsToRect( + clipByPanel(controller, cover, [[x, y], [x + w, y + h]]) + )); + } + + function makeStyle(brushOption) { + return zrUtil.defaults({strokeNoScale: true}, brushOption.brushStyle); + } + + function formatRectRange(x, y, x2, y2) { + var min = [mathMin(x, x2), mathMin(y, y2)]; + var max = [mathMax(x, x2), mathMax(y, y2)]; + + return [ + [min[0], max[0]], // x range + [min[1], max[1]] // y range + ]; + } + + function getTransform(controller) { + return graphic.getTransform(controller.group); + } + + function getGlobalDirection(controller, localDirection) { + if (localDirection.length > 1) { + localDirection = localDirection.split(''); + var globalDir = [ + getGlobalDirection(controller, localDirection[0]), + getGlobalDirection(controller, localDirection[1]) + ]; + (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse(); + return globalDir.join(''); + } + else { + var map = {w: 'left', e: 'right', n: 'top', s: 'bottom'}; + var inverseMap = {left: 'w', right: 'e', top: 'n', bottom: 's'}; + var globalDir = graphic.transformDirection( + map[localDirection], getTransform(controller) + ); + return inverseMap[globalDir]; + } + } + + function driftRect(toRectRange, fromRectRange, controller, cover, name, dx, dy, e) { + var brushOption = cover.__brushOption; + var rectRange = toRectRange(brushOption.range); + var localDelta = toLocalDelta(controller, dx, dy); + + each(name.split(''), function (namePart) { + var ind = DIRECTION_MAP[namePart]; + rectRange[ind[0]][ind[1]] += localDelta[ind[0]]; + }); + + brushOption.range = fromRectRange(formatRectRange( + rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1] + )); + + updateCoverAfterCreation(controller, cover); + trigger(controller, {isEnd: false}); + } + + function driftPolygon(controller, cover, dx, dy, e) { + var range = cover.__brushOption.range; + var localDelta = toLocalDelta(controller, dx, dy); + + each(range, function (point) { + point[0] += localDelta[0]; + point[1] += localDelta[1]; + }); + + updateCoverAfterCreation(controller, cover); + trigger(controller, {isEnd: false}); + } + + function toLocalDelta(controller, dx, dy) { + var thisGroup = controller.group; + var localD = thisGroup.transformCoordToLocal(dx, dy); + var localZero = thisGroup.transformCoordToLocal(0, 0); + + return [localD[0] - localZero[0], localD[1] - localZero[1]]; + } + + function clipByPanel(controller, cover, data) { + var panel = getPanelByCover(controller, cover); + + return (panel && panel !== true) + ? panel.clipPath(data, controller._transform) + : zrUtil.clone(data); + } + + function pointsToRect(points) { + var xmin = mathMin(points[0][0], points[1][0]); + var ymin = mathMin(points[0][1], points[1][1]); + var xmax = mathMax(points[0][0], points[1][0]); + var ymax = mathMax(points[0][1], points[1][1]); + + return { + x: xmin, + y: ymin, + width: xmax - xmin, + height: ymax - ymin + }; + } + + function resetCursor(controller, e, localCursorPoint) { + // Check active + if (!controller._brushType) { + return; + } + + var zr = controller._zr; + var covers = controller._covers; + var currPanel = getPanelByPoint(controller, e, localCursorPoint); + + // Check whether in covers. + if (!controller._dragging) { + for (var i = 0; i < covers.length; i++) { + var brushOption = covers[i].__brushOption; + if (currPanel + && (currPanel === true || brushOption.panelId === currPanel.panelId) + && coverRenderers[brushOption.brushType].contain( + covers[i], localCursorPoint[0], localCursorPoint[1] + ) + ) { + // Use cursor style set on cover. + return; + } + } + } + + currPanel && zr.setCursorStyle('crosshair'); + } + + function preventDefault(e) { + var rawE = e.event; + rawE.preventDefault && rawE.preventDefault(); + } + + function mainShapeContain(cover, x, y) { + return cover.childOfName('main').contain(x, y); + } + + function updateCoverByMouse(controller, e, localCursorPoint, isEnd) { + var creatingCover = controller._creatingCover; + var panel = controller._creatingPanel; + var thisBrushOption = controller._brushOption; + var eventParams; + + controller._track.push(localCursorPoint.slice()); + + if (shouldShowCover(controller) || creatingCover) { + + if (panel && !creatingCover) { + thisBrushOption.brushMode === 'single' && clearCovers(controller); + var brushOption = zrUtil.clone(thisBrushOption); + brushOption.brushType = determineBrushType(brushOption.brushType, panel); + brushOption.panelId = panel === true ? null : panel.panelId; + creatingCover = controller._creatingCover = createCover(controller, brushOption); + controller._covers.push(creatingCover); + } + + if (creatingCover) { + var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)]; + var coverBrushOption = creatingCover.__brushOption; + + coverBrushOption.range = coverRenderer.getCreatingRange( + clipByPanel(controller, creatingCover, controller._track) + ); + + if (isEnd) { + endCreating(controller, creatingCover); + coverRenderer.updateCommon(controller, creatingCover); + } + + updateCoverShape(controller, creatingCover); + + eventParams = {isEnd: isEnd}; + } + } + else if ( + isEnd + && thisBrushOption.brushMode === 'single' + && thisBrushOption.removeOnClick + ) { + // Help user to remove covers easily, only by a tiny drag, in 'single' mode. + // But a single click do not clear covers, because user may have casual + // clicks (for example, click on other component and do not expect covers + // disappear). + // Only some cover removed, trigger action, but not every click trigger action. + if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) { + eventParams = {isEnd: isEnd, removeOnClick: true}; + } + } + + return eventParams; + } + + function determineBrushType(brushType, panel) { + if (brushType === 'auto') { + if (true) { + zrUtil.assert( + panel && panel.defaultBrushType, + 'MUST have defaultBrushType when brushType is "atuo"' + ); + } + return panel.defaultBrushType; + } + return brushType; + } + + var mouseHandlers = { + + mousedown: function (e) { + if (this._dragging) { + // In case some browser do not support globalOut, + // and release mose out side the browser. + handleDragEnd.call(this, e); + } + else if (!e.target || !e.target.draggable) { + + preventDefault(e); + + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + + this._creatingCover = null; + var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint); + + if (panel) { + this._dragging = true; + this._track = [localCursorPoint.slice()]; + } + } + }, + + mousemove: function (e) { + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + + resetCursor(this, e, localCursorPoint); + + if (this._dragging) { + + preventDefault(e); + + var eventParams = updateCoverByMouse(this, e, localCursorPoint, false); + + eventParams && trigger(this, eventParams); + } + }, + + mouseup: handleDragEnd //, + + // FIXME + // in tooltip, globalout should not be triggered. + // globalout: handleDragEnd + }; + + function handleDragEnd(e) { + if (this._dragging) { + + preventDefault(e); + + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + var eventParams = updateCoverByMouse(this, e, localCursorPoint, true); + + this._dragging = false; + this._track = []; + this._creatingCover = null; + + // trigger event shoule be at final, after procedure will be nested. + eventParams && trigger(this, eventParams); + } + } + + /** + * key: brushType + * @type {Object} + */ + var coverRenderers = { + + lineX: getLineRenderer(0), + + lineY: getLineRenderer(1), + + rect: { + createCover: function (controller, brushOption) { + return createBaseRectCover( + curry( + driftRect, + function (range) { + return range; + }, + function (range) { + return range; + } + ), + controller, + brushOption, + ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'] + ); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + updateBaseRect(controller, cover, localRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }, + + polygon: { + createCover: function (controller, brushOption) { + var cover = new graphic.Group(); + + // Do not use graphic.Polygon because graphic.Polyline do not close the + // border of the shape when drawing, which is a better experience for user. + cover.add(new graphic.Polyline({ + name: 'main', + style: makeStyle(brushOption), + silent: true + })); + + return cover; + }, + getCreatingRange: function (localTrack) { + return localTrack; + }, + endCreating: function (controller, cover) { + cover.remove(cover.childAt(0)); + // Use graphic.Polygon close the shape. + cover.add(new graphic.Polygon({ + name: 'main', + draggable: true, + drift: curry(driftPolygon, controller, cover), + ondragend: curry(trigger, controller, {isEnd: true}) + })); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + cover.childAt(0).setShape({ + points: clipByPanel(controller, cover, localRange) + }); + }, + updateCommon: updateCommon, + contain: mainShapeContain + } + }; + + function getLineRenderer(xyIndex) { + return { + createCover: function (controller, brushOption) { + return createBaseRectCover( + curry( + driftRect, + function (range) { + var rectRange = [range, [0, 100]]; + xyIndex && rectRange.reverse(); + return rectRange; + }, + function (rectRange) { + return rectRange[xyIndex]; + } + ), + controller, + brushOption, + [['w', 'e'], ['n', 's']][xyIndex] + ); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + var min = mathMin(ends[0][xyIndex], ends[1][xyIndex]); + var max = mathMax(ends[0][xyIndex], ends[1][xyIndex]); + + return [min, max]; + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + var otherExtent; + // If brushWidth not specified, fit the panel. + var panel = getPanelByCover(controller, cover); + if (panel !== true && panel.getLinearBrushOtherExtent) { + otherExtent = panel.getLinearBrushOtherExtent( + xyIndex, controller._transform + ); + } + else { + var zr = controller._zr; + otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]]; + } + var rectRange = [localRange, otherExtent]; + xyIndex && rectRange.reverse(); + + updateBaseRect(controller, cover, rectRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }; + } + + module.exports = BrushController; + + +/***/ }, +/* 246 */ +/***/ function(module, exports, __webpack_require__) { + + + + var cursorHelper = __webpack_require__(186); + var BoundingRect = __webpack_require__(9); + var graphicUtil = __webpack_require__(18); + + var helper = {}; + + helper.makeRectPanelClipPath = function (rect) { + rect = normalizeRect(rect); + return function (localPoints, transform) { + return graphicUtil.clipPointsByRect(localPoints, rect); + }; + }; + + helper.makeLinearBrushOtherExtent = function (rect, specifiedXYIndex) { + rect = normalizeRect(rect); + return function (xyIndex) { + var idx = specifiedXYIndex != null ? specifiedXYIndex : xyIndex; + var brushWidth = idx ? rect.width : rect.height; + var base = idx ? rect.x : rect.y; + return [base, base + (brushWidth || 0)]; + }; + }; + + helper.makeRectIsTargetByCursor = function (rect, api, targetModel) { + rect = normalizeRect(rect); + return function (e, localCursorPoint, transform) { + return rect.contain(localCursorPoint[0], localCursorPoint[1]) + && !cursorHelper.onIrrelevantElement(e, api, targetModel); + }; + }; + + // Consider width/height is negative. + function normalizeRect(rect) { + return BoundingRect.create(rect); + } + + module.exports = helper; + + + +/***/ }, +/* 247 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + + module.exports = function (option) { + createParallelIfNeeded(option); + mergeAxisOptionFromParallel(option); + }; + + /** + * Create a parallel coordinate if not exists. + * @inner + */ + function createParallelIfNeeded(option) { + if (option.parallel) { + return; + } + + var hasParallelSeries = false; + + zrUtil.each(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'parallel') { + hasParallelSeries = true; + } + }); + + if (hasParallelSeries) { + option.parallel = [{}]; + } + } + + /** + * Merge aixs definition from parallel option (if exists) to axis option. + * @inner + */ + function mergeAxisOptionFromParallel(option) { + var axes = modelUtil.normalizeToArray(option.parallelAxis); + + zrUtil.each(axes, function (axisOption) { + if (!zrUtil.isObject(axisOption)) { + return; + } + + var parallelIndex = axisOption.parallelIndex || 0; + var parallelOption = modelUtil.normalizeToArray(option.parallel)[parallelIndex]; + + if (parallelOption && parallelOption.parallelAxisDefault) { + zrUtil.merge(axisOption, parallelOption.parallelAxisDefault, false); + } + }); + } + + + +/***/ }, +/* 248 */ +/***/ function(module, exports, __webpack_require__) { + + + + var List = __webpack_require__(98); + var zrUtil = __webpack_require__(4); + var SeriesModel = __webpack_require__(78); + var completeDimensions = __webpack_require__(110); + + module.exports = SeriesModel.extend({ + + type: 'series.parallel', + + dependencies: ['parallel'], + + visualColorAccessPath: 'lineStyle.normal.color', + + getInitialData: function (option, ecModel) { + var parallelModel = ecModel.getComponent( + 'parallel', this.get('parallelIndex') + ); + var parallelAxisIndices = parallelModel.parallelAxisIndex; + + var rawData = option.data; + var modelDims = parallelModel.dimensions; + + var dataDims = generateDataDims(modelDims, rawData); + + var dataDimsInfo = zrUtil.map(dataDims, function (dim, dimIndex) { + + var modelDimsIndex = zrUtil.indexOf(modelDims, dim); + var axisModel = modelDimsIndex >= 0 && ecModel.getComponent( + 'parallelAxis', parallelAxisIndices[modelDimsIndex] + ); + + if (axisModel && axisModel.get('type') === 'category') { + translateCategoryValue(axisModel, dim, rawData); + return {name: dim, type: 'ordinal'}; + } + else if (modelDimsIndex < 0) { + return completeDimensions.guessOrdinal(rawData, dimIndex) + ? {name: dim, type: 'ordinal'} + : dim; + } + else { + return dim; + } + }); + + var list = new List(dataDimsInfo, this); + list.initData(rawData); + + // Anication is forbiden in progressive data mode. + if (this.option.progressive) { + this.option.animation = false; + } + + return list; + }, + + /** + * User can get data raw indices on 'axisAreaSelected' event received. + * + * @public + * @param {string} activeState 'active' or 'inactive' or 'normal' + * @return {Array.} Raw indices + */ + getRawIndicesByActiveState: function (activeState) { + var coordSys = this.coordinateSystem; + var data = this.getData(); + var indices = []; + + coordSys.eachActiveState(data, function (theActiveState, dataIndex) { + if (activeState === theActiveState) { + indices.push(data.getRawIndex(dataIndex)); + } + }); + + return indices; + }, + + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + + coordinateSystem: 'parallel', + parallelIndex: 0, + + label: { + normal: { + show: false + }, + emphasis: { + show: false + } + }, + + inactiveOpacity: 0.05, + activeOpacity: 1, + + lineStyle: { + normal: { + width: 1, + opacity: 0.45, + type: 'solid' + } + }, + progressive: false, // 100 + smooth: false, + + animationEasing: 'linear' + } + }); + + function translateCategoryValue(axisModel, dim, rawData) { + var axisData = axisModel.get('data'); + var numberDim = convertDimNameToNumber(dim); + + if (axisData && axisData.length) { + zrUtil.each(rawData, function (dataItem) { + if (!dataItem) { + return; + } + // FIXME + // time consuming, should use hash? + var index = zrUtil.indexOf(axisData, dataItem[numberDim]); + dataItem[numberDim] = index >= 0 ? index : NaN; + }); + } + // FIXME + // 如果没有设置axis data, 应自动算出,或者提示。 + } + + function convertDimNameToNumber(dimName) { + return +dimName.replace('dim', ''); + } + + function generateDataDims(modelDims, rawData) { + // parallelModel.dimension should not be regarded as data + // dimensions. Consider dimensions = ['dim4', 'dim2', 'dim6']; + + // We detect max dim by parallelModel.dimensions and fist + // item in rawData arbitrarily. + var maxDimNum = 0; + zrUtil.each(modelDims, function (dimName) { + var numberDim = convertDimNameToNumber(dimName); + numberDim > maxDimNum && (maxDimNum = numberDim); + }); + + var firstItem = rawData[0]; + if (firstItem && firstItem.length - 1 > maxDimNum) { + maxDimNum = firstItem.length - 1; + } + + var dataDims = []; + for (var i = 0; i <= maxDimNum; i++) { + dataDims.push('dim' + i); + } + + return dataDims; + } + + +/***/ }, +/* 249 */ +/***/ function(module, exports, __webpack_require__) { + + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + + var SMOOTH = 0.3; + + var ParallelView = __webpack_require__(80).extend({ + + type: 'parallel', + + init: function () { + + /** + * @type {module:zrender/container/Group} + * @private + */ + this._dataGroup = new graphic.Group(); + + this.group.add(this._dataGroup); + + /** + * @type {module:echarts/data/List} + */ + this._data; + }, + + /** + * @override + */ + render: function (seriesModel, ecModel, api, payload) { + this._renderForNormal(seriesModel, payload); + // this[ + // seriesModel.option.progressive + // ? '_renderForProgressive' + // : '_renderForNormal' + // ](seriesModel); + }, + + dispose: function () {}, + + /** + * @private + */ + _renderForNormal: function (seriesModel, payload) { + var dataGroup = this._dataGroup; + var data = seriesModel.getData(); + var oldData = this._data; + var coordSys = seriesModel.coordinateSystem; + var dimensions = coordSys.dimensions; + var option = seriesModel.option; + var smooth = option.smooth ? SMOOTH : null; + + // Consider switch between progressive and not. + // oldData && oldData.__plProgressive && dataGroup.removeAll(); + + data.diff(oldData) + .add(add) + .update(update) + .remove(remove) + .execute(); + + // Update style + updateElCommon(data, smooth); + + // First create + if (!this._data) { + var clipPath = createGridClipShape( + coordSys, seriesModel, function () { + // Callback will be invoked immediately if there is no animation + setTimeout(function () { + dataGroup.removeClipPath(); + }); + } + ); + dataGroup.setClipPath(clipPath); + } + + this._data = data; + + function add(newDataIndex) { + addEl(data, dataGroup, newDataIndex, dimensions, coordSys, null, smooth); + } + + function update(newDataIndex, oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + var points = createLinePoints(data, newDataIndex, dimensions, coordSys); + data.setItemGraphicEl(newDataIndex, line); + var animationModel = (payload && payload.animation === false) ? null : seriesModel; + graphic.updateProps(line, {shape: {points: points}}, animationModel, newDataIndex); + } + + function remove(oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + dataGroup.remove(line); + } + + }, + + /** + * @private + */ + // _renderForProgressive: function (seriesModel) { + // var dataGroup = this._dataGroup; + // var data = seriesModel.getData(); + // var oldData = this._data; + // var coordSys = seriesModel.coordinateSystem; + // var dimensions = coordSys.dimensions; + // var option = seriesModel.option; + // var progressive = option.progressive; + // var smooth = option.smooth ? SMOOTH : null; + + // // In progressive animation is disabled, so use simple data diff, + // // which effects performance less. + // // (Typically performance for data with length 7000+ like: + // // simpleDiff: 60ms, addEl: 184ms, + // // in RMBP 2.4GHz intel i7, OSX 10.9 chrome 50.0.2661.102 (64-bit)) + // if (simpleDiff(oldData, data, dimensions)) { + // dataGroup.removeAll(); + // data.each(function (dataIndex) { + // addEl(data, dataGroup, dataIndex, dimensions, coordSys); + // }); + // } + + // updateElCommon(data, progressive, smooth); + + // // Consider switch between progressive and not. + // data.__plProgressive = true; + // this._data = data; + // }, + + /** + * @override + */ + remove: function () { + this._dataGroup && this._dataGroup.removeAll(); + this._data = null; + } + }); + + function createGridClipShape(coordSys, seriesModel, cb) { + var parallelModel = coordSys.model; + var rect = coordSys.getRect(); + var rectEl = new graphic.Rect({ + shape: { + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + } + }); + + var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height'; + rectEl.setShape(dim, 0); + graphic.initProps(rectEl, { + shape: { + width: rect.width, + height: rect.height + } + }, seriesModel, cb); + return rectEl; + } + + function createLinePoints(data, dataIndex, dimensions, coordSys) { + var points = []; + for (var i = 0; i < dimensions.length; i++) { + var dimName = dimensions[i]; + var value = data.get(dimName, dataIndex); + if (!isEmptyValue(value, coordSys.getAxis(dimName).type)) { + points.push(coordSys.dataToPoint(value, dimName)); + } + } + return points; + } + + function addEl(data, dataGroup, dataIndex, dimensions, coordSys) { + var points = createLinePoints(data, dataIndex, dimensions, coordSys); + var line = new graphic.Polyline({ + shape: {points: points}, + silent: true, + z2: 10 + }); + dataGroup.add(line); + data.setItemGraphicEl(dataIndex, line); + } + + function updateElCommon(data, smooth) { + var seriesStyleModel = data.hostModel.getModel('lineStyle.normal'); + var lineStyle = seriesStyleModel.getLineStyle(); + data.eachItemGraphicEl(function (line, dataIndex) { + if (data.hasItemOption) { + var itemModel = data.getItemModel(dataIndex); + var lineStyleModel = itemModel.getModel('lineStyle.normal', seriesStyleModel); + lineStyle = lineStyleModel.getLineStyle(['color', 'stroke']); + } + + line.useStyle(zrUtil.extend(lineStyle, { + fill: null, + // lineStyle.color have been set to itemVisual in module:echarts/visual/seriesColor. + stroke: data.getItemVisual(dataIndex, 'color'), + // lineStyle.opacity have been set to itemVisual in parallelVisual. + opacity: data.getItemVisual(dataIndex, 'opacity') + })); + + line.shape.smooth = smooth; + }); + } + + // function simpleDiff(oldData, newData, dimensions) { + // var oldLen; + // if (!oldData + // || !oldData.__plProgressive + // || (oldLen = oldData.count()) !== newData.count() + // ) { + // return true; + // } + + // var dimLen = dimensions.length; + // for (var i = 0; i < oldLen; i++) { + // for (var j = 0; j < dimLen; j++) { + // if (oldData.get(dimensions[j], i) !== newData.get(dimensions[j], i)) { + // return true; + // } + // } + // } + + // return false; + // } + + // FIXME + // 公用方法? + function isEmptyValue(val, axisType) { + return axisType === 'category' + ? val == null + : (val == null || isNaN(val)); // axisType === 'value' + } + + module.exports = ParallelView; + + +/***/ }, +/* 250 */ +/***/ function(module, exports) { + + + + var opacityAccessPath = ['lineStyle', 'normal', 'opacity']; + + module.exports = function (ecModel) { + + ecModel.eachSeriesByType('parallel', function (seriesModel) { + + var itemStyleModel = seriesModel.getModel('itemStyle.normal'); + var lineStyleModel = seriesModel.getModel('lineStyle.normal'); + var globalColors = ecModel.get('color'); + + var color = lineStyleModel.get('color') + || itemStyleModel.get('color') + || globalColors[seriesModel.seriesIndex % globalColors.length]; + var inactiveOpacity = seriesModel.get('inactiveOpacity'); + var activeOpacity = seriesModel.get('activeOpacity'); + var lineStyle = seriesModel.getModel('lineStyle.normal').getLineStyle(); + + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + + var opacityMap = { + normal: lineStyle.opacity, + active: activeOpacity, + inactive: inactiveOpacity + }; + + coordSys.eachActiveState(data, function (activeState, dataIndex) { + var itemModel = data.getItemModel(dataIndex); + var opacity = opacityMap[activeState]; + if (activeState === 'normal') { + var itemOpacity = itemModel.get(opacityAccessPath, true); + itemOpacity != null && (opacity = itemOpacity); + } + data.setItemVisual(dataIndex, 'opacity', opacity); + }); + + data.setVisual('color', color); + }); + }; + + +/***/ }, +/* 251 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + + __webpack_require__(252); + __webpack_require__(253); + echarts.registerLayout(__webpack_require__(254)); + echarts.registerVisual(__webpack_require__(256)); + + +/***/ }, +/* 252 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Get initial data and define sankey view's series model + * @author Deqing Li(annong035@gmail.com) + */ + + + var SeriesModel = __webpack_require__(78); + var createGraphFromNodeEdge = __webpack_require__(207); + var encodeHTML = __webpack_require__(6).encodeHTML; + + var SankeySeries = SeriesModel.extend({ + + type: 'series.sankey', + + layoutInfo: null, + + /** + * Init a graph data structure from data in option series + * + * @param {Object} option the object used to config echarts view + * @return {module:echarts/data/List} storage initial data + */ + getInitialData: function (option) { + var links = option.edges || option.links; + var nodes = option.data || option.nodes; + if (nodes && links) { + var graph = createGraphFromNodeEdge(nodes, links, this, true); + return graph.data; + } + }, + + /** + * Return the graphic data structure + * + * @return {module:echarts/data/Graph} graphic data structure + */ + getGraph: function () { + return this.getData().graph; + }, + + /** + * Get edge data of graphic data structure + * + * @return {module:echarts/data/List} data structure of list + */ + getEdgeData: function () { + return this.getGraph().edgeData; + }, + + /** + * @override + */ + formatTooltip: function (dataIndex, multipleSeries, dataType) { + // dataType === 'node' or empty do not show tooltip by default + if (dataType === 'edge') { + var params = this.getDataParams(dataIndex, dataType); + var rawDataOpt = params.data; + var html = rawDataOpt.source + ' -- ' + rawDataOpt.target; + if (params.value) { + html += ' : ' + params.value; + } + return encodeHTML(html); + } + + return SankeySeries.superCall(this, 'formatTooltip', dataIndex, multipleSeries); + }, + + defaultOption: { + zlevel: 0, + z: 2, + + coordinateSystem: 'view', + + layout: null, + + // the position of the whole view + left: '5%', + top: '5%', + right: '20%', + bottom: '5%', + + // the dx of the node + nodeWidth: 20, + + // the vertical distance between two nodes + nodeGap: 8, + + // the number of iterations to change the position of the node + layoutIterations: 32, + + label: { + normal: { + show: true, + position: 'right', + textStyle: { + color: '#000', + fontSize: 12 + } + }, + emphasis: { + show: true + } + }, + + itemStyle: { + normal: { + borderWidth: 1, + borderColor: '#333' + } + }, + + lineStyle: { + normal: { + color: '#314656', + opacity: 0.2, + curveness: 0.5 + }, + emphasis: { + opacity: 0.6 + } + }, + + animationEasing: 'linear', + + animationDuration: 1000 + } + + }); + + module.exports = SankeySeries; + + + +/***/ }, +/* 253 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file The file used to draw sankey view + * @author Deqing Li(annong035@gmail.com) + */ + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + + var SankeyShape = graphic.extendShape({ + shape: { + x1: 0, y1: 0, + x2: 0, y2: 0, + cpx1: 0, cpy1: 0, + cpx2: 0, cpy2: 0, + + extent: 0 + }, + + buildPath: function (ctx, shape) { + var halfExtent = shape.extent / 2; + ctx.moveTo(shape.x1, shape.y1 - halfExtent); + ctx.bezierCurveTo( + shape.cpx1, shape.cpy1 - halfExtent, + shape.cpx2, shape.cpy2 - halfExtent, + shape.x2, shape.y2 - halfExtent + ); + ctx.lineTo(shape.x2, shape.y2 + halfExtent); + ctx.bezierCurveTo( + shape.cpx2, shape.cpy2 + halfExtent, + shape.cpx1, shape.cpy1 + halfExtent, + shape.x1, shape.y1 + halfExtent + ); + ctx.closePath(); + } + }); + + module.exports = __webpack_require__(1).extendChartView({ + + type: 'sankey', + + /** + * @private + * @type {module:echarts/chart/sankey/SankeySeries} + */ + _model: null, + + render: function (seriesModel, ecModel, api) { + var graph = seriesModel.getGraph(); + var group = this.group; + var layoutInfo = seriesModel.layoutInfo; + var nodeData = seriesModel.getData(); + var edgeData = seriesModel.getData('edge'); + + this._model = seriesModel; + + group.removeAll(); + + group.position = [layoutInfo.x, layoutInfo.y]; + + // generate a bezire Curve for each edge + graph.eachEdge(function (edge) { + var curve = new SankeyShape(); + + curve.dataIndex = edge.dataIndex; + curve.seriesIndex = seriesModel.seriesIndex; + curve.dataType = 'edge'; + + var lineStyleModel = edge.getModel('lineStyle.normal'); + var curvature = lineStyleModel.get('curveness'); + var n1Layout = edge.node1.getLayout(); + var n2Layout = edge.node2.getLayout(); + var edgeLayout = edge.getLayout(); + + curve.shape.extent = Math.max(1, edgeLayout.dy); + + var x1 = n1Layout.x + n1Layout.dx; + var y1 = n1Layout.y + edgeLayout.sy + edgeLayout.dy / 2; + var x2 = n2Layout.x; + var y2 = n2Layout.y + edgeLayout.ty + edgeLayout.dy / 2; + var cpx1 = x1 * (1 - curvature) + x2 * curvature; + var cpy1 = y1; + var cpx2 = x1 * curvature + x2 * (1 - curvature); + var cpy2 = y2; + + curve.setShape({ + x1: x1, + y1: y1, + x2: x2, + y2: y2, + cpx1: cpx1, + cpy1: cpy1, + cpx2: cpx2, + cpy2: cpy2 + }); + + curve.setStyle(lineStyleModel.getItemStyle()); + // Special color, use source node color or target node color + switch (curve.style.fill) { + case 'source': + curve.style.fill = edge.node1.getVisual('color'); + break; + case 'target': + curve.style.fill = edge.node2.getVisual('color'); + break; + } + + graphic.setHoverStyle(curve, edge.getModel('lineStyle.emphasis').getItemStyle()); + + group.add(curve); + + edgeData.setItemGraphicEl(edge.dataIndex, curve); + }); + + // generate a rect for each node + graph.eachNode(function (node) { + var layout = node.getLayout(); + var itemModel = node.getModel(); + var labelModel = itemModel.getModel('label.normal'); + var textStyleModel = labelModel.getModel('textStyle'); + var labelHoverModel = itemModel.getModel('label.emphasis'); + var textStyleHoverModel = labelHoverModel.getModel('textStyle'); + + var rect = new graphic.Rect({ + shape: { + x: layout.x, + y: layout.y, + width: node.getLayout().dx, + height: node.getLayout().dy + }, + style: { + // Get formatted label in label.normal option + // Use node id if it is not specified + text: labelModel.get('show') + ? seriesModel.getFormattedLabel(node.dataIndex, 'normal') || node.id + // Use empty string to hide the label + : '', + textFont: textStyleModel.getFont(), + textFill: textStyleModel.getTextColor(), + textPosition: labelModel.get('position') + } + }); + + rect.setStyle(zrUtil.defaults( + { + fill: node.getVisual('color') + }, + itemModel.getModel('itemStyle.normal').getItemStyle() + )); + + graphic.setHoverStyle(rect, zrUtil.extend( + node.getModel('itemStyle.emphasis'), + { + text: labelHoverModel.get('show') + ? seriesModel.getFormattedLabel(node.dataIndex, 'emphasis') || node.id + : '', + textFont: textStyleHoverModel.getFont(), + textFill: textStyleHoverModel.getTextColor(), + textPosition: labelHoverModel.get('position') + } + )); + + group.add(rect); + + nodeData.setItemGraphicEl(node.dataIndex, rect); + + rect.dataType = 'node'; + }); + + if (!this._data && seriesModel.get('animation')) { + group.setClipPath(createGridClipShape(group.getBoundingRect(), seriesModel, function () { + group.removeClipPath(); + })); + } + + this._data = seriesModel.getData(); + }, + + dispose: function () {} + }); + + // add animation to the view + function createGridClipShape(rect, seriesModel, cb) { + var rectEl = new graphic.Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + graphic.initProps(rectEl, { + shape: { + width: rect.width + 20, + height: rect.height + 20 + } + }, seriesModel, cb); + + return rectEl; + } + + + +/***/ }, +/* 254 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file The layout algorithm of sankey view + * @author Deqing Li(annong035@gmail.com) + */ + + + var layout = __webpack_require__(71); + var nest = __webpack_require__(255); + var zrUtil = __webpack_require__(4); + + module.exports = function (ecModel, api, payload) { + + ecModel.eachSeriesByType('sankey', function (seriesModel) { + + var nodeWidth = seriesModel.get('nodeWidth'); + var nodeGap = seriesModel.get('nodeGap'); + + var layoutInfo = getViewRect(seriesModel, api); + + seriesModel.layoutInfo = layoutInfo; + + var width = layoutInfo.width; + var height = layoutInfo.height; + + var graph = seriesModel.getGraph(); + + var nodes = graph.nodes; + var edges = graph.edges; + + computeNodeValues(nodes); + + var filteredNodes = zrUtil.filter(nodes, function (node) { + return node.getLayout().value === 0; + }); + + var iterations = filteredNodes.length !== 0 + ? 0 : seriesModel.get('layoutIterations'); + + layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations); + }); + }; + + /** + * Get the layout position of the whole view + * + * @param {module:echarts/model/Series} seriesModel the model object of sankey series + * @param {module:echarts/ExtensionAPI} api provide the API list that the developer can call + * @return {module:zrender/core/BoundingRect} size of rect to draw the sankey view + */ + function getViewRect(seriesModel, api) { + return layout.getLayoutRect( + seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + } + ); + } + + function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations) { + computeNodeBreadths(nodes, nodeWidth, width); + computeNodeDepths(nodes, edges, height, nodeGap, iterations); + computeEdgeDepths(nodes); + } + + /** + * Compute the value of each node by summing the associated edge's value + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + */ + function computeNodeValues(nodes) { + zrUtil.each(nodes, function (node) { + var value1 = sum(node.outEdges, getEdgeValue); + var value2 = sum(node.inEdges, getEdgeValue); + var value = Math.max(value1, value2); + node.setLayout({value: value}, true); + }); + } + + /** + * Compute the x-position for each node + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {number} nodeWidth the dx of the node + * @param {number} width the whole width of the area to draw the view + */ + function computeNodeBreadths(nodes, nodeWidth, width) { + var remainNodes = nodes; + var nextNode = null; + var x = 0; + var kx = 0; + + while (remainNodes.length) { + nextNode = []; + for (var i = 0, len = remainNodes.length; i < len; i++) { + var node = remainNodes[i]; + node.setLayout({x: x}, true); + node.setLayout({dx: nodeWidth}, true); + for (var j = 0, lenj = node.outEdges.length; j < lenj; j++) { + nextNode.push(node.outEdges[j].node2); + } + } + remainNodes = nextNode; + ++x; + } + + moveSinksRight(nodes, x); + kx = (width - nodeWidth) / (x - 1); + + scaleNodeBreadths(nodes, kx); + } + + /** + * All the node without outEgdes are assigned maximum x-position and + * be aligned in the last column. + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {number} x value (x-1) use to assign to node without outEdges + * as x-position + */ + function moveSinksRight(nodes, x) { + zrUtil.each(nodes, function (node) { + if (!node.outEdges.length) { + node.setLayout({x: x - 1}, true); + } + }); + } + + /** + * Scale node x-position to the width + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {number} kx multiple used to scale nodes + */ + function scaleNodeBreadths(nodes, kx) { + zrUtil.each(nodes, function (node) { + var nodeX = node.getLayout().x * kx; + node.setLayout({x: nodeX}, true); + }); + } + + /** + * Using Gauss-Seidel iterations method to compute the node depth(y-position) + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {module:echarts/data/Graph~Edge} edges edge of sankey view + * @param {number} height the whole height of the area to draw the view + * @param {numbber} nodeGap the vertical distance between two nodes + * in the same column. + * @param {number} iterations the number of iterations for the algorithm + */ + function computeNodeDepths(nodes, edges, height, nodeGap, iterations) { + var nodesByBreadth = nest() + .key(function (d) { + return d.getLayout().x; + }) + .sortKeys(ascending) + .entries(nodes) + .map(function (d) { + return d.values; + }); + + initializeNodeDepth(nodes, nodesByBreadth, edges, height, nodeGap); + resolveCollisions(nodesByBreadth, nodeGap, height); + + for (var alpha = 1; iterations > 0; iterations--) { + // 0.99 is a experience parameter, ensure that each iterations of + // changes as small as possible. + alpha *= 0.99; + relaxRightToLeft(nodesByBreadth, alpha); + resolveCollisions(nodesByBreadth, nodeGap, height); + relaxLeftToRight(nodesByBreadth, alpha); + resolveCollisions(nodesByBreadth, nodeGap, height); + } + } + + /** + * Compute the original y-position for each node + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the nodes x-position. + * @param {module:echarts/data/Graph~Edge} edges edge of sankey view + * @param {number} height the whole height of the area to draw the view + * @param {number} nodeGap the vertical distance between two nodes + */ + function initializeNodeDepth(nodes, nodesByBreadth, edges, height, nodeGap) { + var kyArray = []; + zrUtil.each(nodesByBreadth, function (nodes) { + var n = nodes.length; + var sum = 0; + zrUtil.each(nodes, function (node) { + sum += node.getLayout().value; + }); + var ky = (height - (n - 1) * nodeGap) / sum; + kyArray.push(ky); + }); + + kyArray.sort(function (a, b) { + return a - b; + }); + var ky0 = kyArray[0]; + + zrUtil.each(nodesByBreadth, function (nodes) { + zrUtil.each(nodes, function (node, i) { + node.setLayout({y: i}, true); + var nodeDy = node.getLayout().value * ky0; + node.setLayout({dy: nodeDy}, true); + }); + }); + + zrUtil.each(edges, function (edge) { + var edgeDy = +edge.getValue() * ky0; + edge.setLayout({dy: edgeDy}, true); + }); + } + + /** + * Resolve the collision of initialized depth (y-position) + * + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the nodes x-position. + * @param {number} nodeGap the vertical distance between two nodes + * @param {number} height the whole height of the area to draw the view + */ + function resolveCollisions(nodesByBreadth, nodeGap, height) { + zrUtil.each(nodesByBreadth, function (nodes) { + var node; + var dy; + var y0 = 0; + var n = nodes.length; + var i; + + nodes.sort(ascendingDepth); + + for (i = 0; i < n; i++) { + node = nodes[i]; + dy = y0 - node.getLayout().y; + if (dy > 0) { + var nodeY = node.getLayout().y + dy; + node.setLayout({y: nodeY}, true); + } + y0 = node.getLayout().y + node.getLayout().dy + nodeGap; + } + + // if the bottommost node goes outside the bounds, push it back up + dy = y0 - nodeGap - height; + if (dy > 0) { + var nodeY = node.getLayout().y - dy; + node.setLayout({y: nodeY}, true); + y0 = node.getLayout().y; + for (i = n - 2; i >= 0; --i) { + node = nodes[i]; + dy = node.getLayout().y + node.getLayout().dy + nodeGap - y0; + if (dy > 0) { + nodeY = node.getLayout().y - dy; + node.setLayout({y: nodeY}, true); + } + y0 = node.getLayout().y; + } + } + }); + } + + /** + * Change the y-position of the nodes, except most the right side nodes + * + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the node x-position. + * @param {number} alpha parameter used to adjust the nodes y-position + */ + function relaxRightToLeft(nodesByBreadth, alpha) { + zrUtil.each(nodesByBreadth.slice().reverse(), function (nodes) { + zrUtil.each(nodes, function (node) { + if (node.outEdges.length) { + var y = sum(node.outEdges, weightedTarget) / sum(node.outEdges, getEdgeValue); + var nodeY = node.getLayout().y + (y - center(node)) * alpha; + node.setLayout({y: nodeY}, true); + } + }); + }); + } + + function weightedTarget(edge) { + return center(edge.node2) * edge.getValue(); + } + + /** + * Change the y-position of the nodes, except most the left side nodes + * + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the node x-position. + * @param {number} alpha parameter used to adjust the nodes y-position + */ + function relaxLeftToRight(nodesByBreadth, alpha) { + zrUtil.each(nodesByBreadth, function (nodes) { + zrUtil.each(nodes, function (node) { + if (node.inEdges.length) { + var y = sum(node.inEdges, weightedSource) / sum(node.inEdges, getEdgeValue); + var nodeY = node.getLayout().y + (y - center(node)) * alpha; + node.setLayout({y: nodeY}, true); + } + }); + }); + } + + function weightedSource(edge) { + return center(edge.node1) * edge.getValue(); + } + + /** + * Compute the depth(y-position) of each edge + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + */ + function computeEdgeDepths(nodes) { + zrUtil.each(nodes, function (node) { + node.outEdges.sort(ascendingTargetDepth); + node.inEdges.sort(ascendingSourceDepth); + }); + zrUtil.each(nodes, function (node) { + var sy = 0; + var ty = 0; + zrUtil.each(node.outEdges, function (edge) { + edge.setLayout({sy: sy}, true); + sy += edge.getLayout().dy; + }); + zrUtil.each(node.inEdges, function (edge) { + edge.setLayout({ty: ty}, true); + ty += edge.getLayout().dy; + }); + }); + } + + function ascendingTargetDepth(a, b) { + return a.node2.getLayout().y - b.node2.getLayout().y; + } + + function ascendingSourceDepth(a, b) { + return a.node1.getLayout().y - b.node1.getLayout().y; + } + + function sum(array, f) { + var sum = 0; + var len = array.length; + var i = -1; + while (++i < len) { + var value = +f.call(array, array[i], i); + if (!isNaN(value)) { + sum += value; + } + } + return sum; + } + + function center(node) { + return node.getLayout().y + node.getLayout().dy / 2; + } + + function ascendingDepth(a, b) { + return a.getLayout().y - b.getLayout().y; + } + + function ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a === b ? 0 : NaN; + } + + function getEdgeValue(edge) { + return edge.getValue(); + } + + + +/***/ }, +/* 255 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + /** + * nest helper used to group by the array. + * can specified the keys and sort the keys. + */ + function nest() { + + var keysFunction = []; + var sortKeysFunction = []; + + /** + * map an Array into the mapObject. + * @param {Array} array + * @param {number} depth + */ + function map(array, depth) { + if (depth >= keysFunction.length) { + return array; + } + var i = -1; + var n = array.length; + var keyFunction = keysFunction[depth++]; + var mapObject = {}; + var valuesByKey = {}; + + while (++i < n) { + var keyValue = keyFunction(array[i]); + var values = valuesByKey[keyValue]; + + if (values) { + values.push(array[i]); + } + else { + valuesByKey[keyValue] = [array[i]]; + } + } + + zrUtil.each(valuesByKey, function (value, key) { + mapObject[key] = map(value, depth); + }); + + return mapObject; + } + + /** + * transform the Map Object to multidimensional Array + * @param {Object} map + * @param {number} depth + */ + function entriesMap(mapObject, depth) { + if (depth >= keysFunction.length) { + return mapObject; + } + var array = []; + var sortKeyFunction = sortKeysFunction[depth++]; + + zrUtil.each(mapObject, function (value, key) { + array.push({ + key: key, values: entriesMap(value, depth) + }); + }); + + if (sortKeyFunction) { + return array.sort(function (a, b) { + return sortKeyFunction(a.key, b.key); + }); + } + else { + return array; + } + } + + return { + /** + * specified the key to groupby the arrays. + * users can specified one more keys. + * @param {Function} d + */ + key: function (d) { + keysFunction.push(d); + return this; + }, + + /** + * specified the comparator to sort the keys + * @param {Function} order + */ + sortKeys: function (order) { + sortKeysFunction[keysFunction.length - 1] = order; + return this; + }, + + /** + * the array to be grouped by. + * @param {Array} array + */ + entries: function (array) { + return entriesMap(map(array, 0), 0); + } + }; + } + module.exports = nest; + + +/***/ }, +/* 256 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Visual encoding for sankey view + * @author Deqing Li(annong035@gmail.com) + */ + + + var VisualMapping = __webpack_require__(203); + var zrUtil = __webpack_require__(4); + + module.exports = function (ecModel, payload) { + ecModel.eachSeriesByType('sankey', function (seriesModel) { + var graph = seriesModel.getGraph(); + var nodes = graph.nodes; + + nodes.sort(function (a, b) { + return a.getLayout().value - b.getLayout().value; + }); + + var minValue = nodes[0].getLayout().value; + var maxValue = nodes[nodes.length - 1].getLayout().value; + + zrUtil.each(nodes, function (node) { + var mapping = new VisualMapping({ + type: 'color', + mappingMethod: 'linear', + dataExtent: [minValue, maxValue], + visual: seriesModel.get('color') + }); + + var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value); + node.setVisual('color', mapValueToColor); + // If set itemStyle.normal.color + var itemModel = node.getModel(); + var customColor = itemModel.get('itemStyle.normal.color'); + if (customColor != null) { + node.setVisual('color', customColor); + } + }); + + }); + }; + + + +/***/ }, +/* 257 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + + __webpack_require__(258); + __webpack_require__(261); + + echarts.registerVisual(__webpack_require__(262)); + echarts.registerLayout(__webpack_require__(263)); + + + +/***/ }, +/* 258 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var SeriesModel = __webpack_require__(78); + var whiskerBoxCommon = __webpack_require__(259); + + var BoxplotSeries = SeriesModel.extend({ + + type: 'series.boxplot', + + dependencies: ['xAxis', 'yAxis', 'grid'], + + // TODO + // box width represents group size, so dimension should have 'size'. + + /** + * @see + * The meanings of 'min' and 'max' depend on user, + * and echarts do not need to know it. + * @readOnly + */ + defaultValueDimensions: ['min', 'Q1', 'median', 'Q3', 'max'], + + /** + * @type {Array.} + * @readOnly + */ + dimensions: null, + + /** + * @override + */ + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + + hoverAnimation: true, + + // xAxisIndex: 0, + // yAxisIndex: 0, + + layout: null, // 'horizontal' or 'vertical' + boxWidth: [7, 50], // [min, max] can be percent of band width. + + itemStyle: { + normal: { + color: '#fff', + borderWidth: 1 + }, + emphasis: { + borderWidth: 2, + shadowBlur: 5, + shadowOffsetX: 2, + shadowOffsetY: 2, + shadowColor: 'rgba(0,0,0,0.4)' + } + }, + + animationEasing: 'elasticOut', + animationDuration: 800 + } + }); + + zrUtil.mixin(BoxplotSeries, whiskerBoxCommon.seriesModelMixin, true); + + module.exports = BoxplotSeries; + + + +/***/ }, +/* 259 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var List = __webpack_require__(98); + var completeDimensions = __webpack_require__(110); + var WhiskerBoxDraw = __webpack_require__(260); + var zrUtil = __webpack_require__(4); + + var seriesModelMixin = { + + /** + * @private + * @type {string} + */ + _baseAxisDim: null, + + /** + * @override + */ + getInitialData: function (option, ecModel) { + // When both types of xAxis and yAxis are 'value', layout is + // needed to be specified by user. Otherwise, layout can be + // judged by which axis is category. + + var categories; + + var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex')); + var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex')); + var xAxisType = xAxisModel.get('type'); + var yAxisType = yAxisModel.get('type'); + var addOrdinal; + + // FIXME + // 考虑时间轴 + + if (xAxisType === 'category') { + option.layout = 'horizontal'; + categories = xAxisModel.getCategories(); + addOrdinal = true; + } + else if (yAxisType === 'category') { + option.layout = 'vertical'; + categories = yAxisModel.getCategories(); + addOrdinal = true; + } + else { + option.layout = option.layout || 'horizontal'; + } + + var coordDims = ['x', 'y']; + var baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1; + var baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex]; + var otherAxisDim = coordDims[1 - baseAxisDimIndex]; + var data = option.data; + + addOrdinal && zrUtil.each(data, function (item, index) { + zrUtil.isArray(item) && item.unshift(index); + }); + + var dimensions = [{ + name: baseAxisDim, + otherDims: { + tooltip: false + }, + dimsDef: ['base'] + }, { + name: otherAxisDim, + dimsDef: this.defaultValueDimensions.slice() + }]; + + dimensions = completeDimensions(dimensions, data, { + encodeDef: this.get('encode'), + dimsDef: this.get('dimensions') + }); + + var list = new List(dimensions, this); + list.initData(data, categories ? categories.slice() : null); + + return list; + }, + + /** + * If horizontal, base axis is x, otherwise y. + * @override + */ + getBaseAxis: function () { + var dim = this._baseAxisDim; + return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis; + } + + }; + + var viewMixin = { + + init: function () { + /** + * Old data. + * @private + * @type {module:echarts/chart/helper/WhiskerBoxDraw} + */ + var whiskerBoxDraw = this._whiskerBoxDraw = new WhiskerBoxDraw( + this.getStyleUpdater() + ); + this.group.add(whiskerBoxDraw.group); + }, + + render: function (seriesModel, ecModel, api) { + this._whiskerBoxDraw.updateData(seriesModel.getData()); + }, + + remove: function (ecModel) { + this._whiskerBoxDraw.remove(); + } + }; + + module.exports = { + seriesModelMixin: seriesModelMixin, + viewMixin: viewMixin + }; + + +/***/ }, +/* 260 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/chart/helper/Symbol + */ + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var Path = __webpack_require__(20); + + var WhiskerPath = Path.extend({ + + type: 'whiskerInBox', + + shape: {}, + + buildPath: function (ctx, shape) { + for (var i in shape) { + if (shape.hasOwnProperty(i) && i.indexOf('ends') === 0) { + var pts = shape[i]; + ctx.moveTo(pts[0][0], pts[0][1]); + ctx.lineTo(pts[1][0], pts[1][1]); + } + } + } + }); + + /** + * @constructor + * @alias {module:echarts/chart/helper/WhiskerBox} + * @param {module:echarts/data/List} data + * @param {number} idx + * @param {Function} styleUpdater + * @param {boolean} isInit + * @extends {module:zrender/graphic/Group} + */ + function WhiskerBox(data, idx, styleUpdater, isInit) { + graphic.Group.call(this); + + /** + * @type {number} + * @readOnly + */ + this.bodyIndex; + + /** + * @type {number} + * @readOnly + */ + this.whiskerIndex; + + /** + * @type {Function} + */ + this.styleUpdater = styleUpdater; + + this._createContent(data, idx, isInit); + + this.updateData(data, idx, isInit); + + /** + * Last series model. + * @type {module:echarts/model/Series} + */ + this._seriesModel; + } + + var whiskerBoxProto = WhiskerBox.prototype; + + whiskerBoxProto._createContent = function (data, idx, isInit) { + var itemLayout = data.getItemLayout(idx); + var constDim = itemLayout.chartLayout === 'horizontal' ? 1 : 0; + var count = 0; + + // Whisker element. + this.add(new graphic.Polygon({ + shape: { + points: isInit + ? transInit(itemLayout.bodyEnds, constDim, itemLayout) + : itemLayout.bodyEnds + }, + style: {strokeNoScale: true}, + z2: 100 + })); + this.bodyIndex = count++; + + // Box element. + var whiskerEnds = zrUtil.map(itemLayout.whiskerEnds, function (ends) { + return isInit ? transInit(ends, constDim, itemLayout) : ends; + }); + this.add(new WhiskerPath({ + shape: makeWhiskerEndsShape(whiskerEnds), + style: {strokeNoScale: true}, + z2: 100 + })); + this.whiskerIndex = count++; + }; + + function transInit(points, dim, itemLayout) { + return zrUtil.map(points, function (point) { + point = point.slice(); + point[dim] = itemLayout.initBaseline; + return point; + }); + } + + function makeWhiskerEndsShape(whiskerEnds) { + // zr animation only support 2-dim array. + var shape = {}; + zrUtil.each(whiskerEnds, function (ends, i) { + shape['ends' + i] = ends; + }); + return shape; + } + + /** + * Update symbol properties + * @param {module:echarts/data/List} data + * @param {number} idx + */ + whiskerBoxProto.updateData = function (data, idx, isInit) { + var seriesModel = this._seriesModel = data.hostModel; + var itemLayout = data.getItemLayout(idx); + var updateMethod = graphic[isInit ? 'initProps' : 'updateProps']; + // this.childAt(this.bodyIndex).stopAnimation(true); + // this.childAt(this.whiskerIndex).stopAnimation(true); + updateMethod( + this.childAt(this.bodyIndex), + {shape: {points: itemLayout.bodyEnds}}, + seriesModel, idx + ); + updateMethod( + this.childAt(this.whiskerIndex), + {shape: makeWhiskerEndsShape(itemLayout.whiskerEnds)}, + seriesModel, idx + ); + + this.styleUpdater.call(null, this, data, idx); + }; + + zrUtil.inherits(WhiskerBox, graphic.Group); + + + /** + * @constructor + * @alias module:echarts/chart/helper/WhiskerBoxDraw + */ + function WhiskerBoxDraw(styleUpdater) { + this.group = new graphic.Group(); + this.styleUpdater = styleUpdater; + } + + var whiskerBoxDrawProto = WhiskerBoxDraw.prototype; + + /** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + */ + whiskerBoxDrawProto.updateData = function (data) { + var group = this.group; + var oldData = this._data; + var styleUpdater = this.styleUpdater; + + data.diff(oldData) + .add(function (newIdx) { + if (data.hasValue(newIdx)) { + var symbolEl = new WhiskerBox(data, newIdx, styleUpdater, true); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }) + .update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + + // Empty data + if (!data.hasValue(newIdx)) { + group.remove(symbolEl); + return; + } + + if (!symbolEl) { + symbolEl = new WhiskerBox(data, newIdx, styleUpdater); + } + else { + symbolEl.updateData(data, newIdx); + } + + // Add back + group.add(symbolEl); + + data.setItemGraphicEl(newIdx, symbolEl); + }) + .remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }) + .execute(); + + this._data = data; + }; + + /** + * Remove symbols. + * @param {module:echarts/data/List} data + */ + whiskerBoxDrawProto.remove = function () { + var group = this.group; + var data = this._data; + this._data = null; + data && data.eachItemGraphicEl(function (el) { + el && group.remove(el); + }); + }; + + module.exports = WhiskerBoxDraw; + + +/***/ }, +/* 261 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var ChartView = __webpack_require__(80); + var graphic = __webpack_require__(18); + var whiskerBoxCommon = __webpack_require__(259); + + var BoxplotView = ChartView.extend({ + + type: 'boxplot', + + getStyleUpdater: function () { + return updateStyle; + }, + + dispose: zrUtil.noop + }); + + zrUtil.mixin(BoxplotView, whiskerBoxCommon.viewMixin, true); + + // Update common properties + var normalStyleAccessPath = ['itemStyle', 'normal']; + var emphasisStyleAccessPath = ['itemStyle', 'emphasis']; + + function updateStyle(itemGroup, data, idx) { + var itemModel = data.getItemModel(idx); + var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath); + var borderColor = data.getItemVisual(idx, 'color'); + + // Exclude borderColor. + var itemStyle = normalItemStyleModel.getItemStyle(['borderColor']); + + var whiskerEl = itemGroup.childAt(itemGroup.whiskerIndex); + whiskerEl.style.set(itemStyle); + whiskerEl.style.stroke = borderColor; + whiskerEl.dirty(); + + var bodyEl = itemGroup.childAt(itemGroup.bodyIndex); + bodyEl.style.set(itemStyle); + bodyEl.style.stroke = borderColor; + bodyEl.dirty(); + + var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle(); + graphic.setHoverStyle(itemGroup, hoverStyle); + } + + module.exports = BoxplotView; + + + +/***/ }, +/* 262 */ +/***/ function(module, exports) { + + + + var borderColorQuery = ['itemStyle', 'normal', 'borderColor']; + + module.exports = function (ecModel, api) { + + var globalColors = ecModel.get('color'); + + ecModel.eachRawSeriesByType('boxplot', function (seriesModel) { + + var defaulColor = globalColors[seriesModel.seriesIndex % globalColors.length]; + var data = seriesModel.getData(); + + data.setVisual({ + legendSymbol: 'roundRect', + // Use name 'color' but not 'borderColor' for legend usage and + // visual coding from other component like dataRange. + color: seriesModel.get(borderColorQuery) || defaulColor + }); + + // Only visible series has each data be visual encoded + if (!ecModel.isSeriesFiltered(seriesModel)) { + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + data.setItemVisual( + idx, + {color: itemModel.get(borderColorQuery, true)} + ); + }); + } + }); + + }; + + +/***/ }, +/* 263 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var parsePercent = numberUtil.parsePercent; + var each = zrUtil.each; + + module.exports = function (ecModel) { + + var groupResult = groupSeriesByAxis(ecModel); + + each(groupResult, function (groupItem) { + var seriesModels = groupItem.seriesModels; + + if (!seriesModels.length) { + return; + } + + calculateBase(groupItem); + + each(seriesModels, function (seriesModel, idx) { + layoutSingleSeries( + seriesModel, + groupItem.boxOffsetList[idx], + groupItem.boxWidthList[idx] + ); + }); + }); + }; + + /** + * Group series by axis. + */ + function groupSeriesByAxis(ecModel) { + var result = []; + var axisList = []; + + ecModel.eachSeriesByType('boxplot', function (seriesModel) { + var baseAxis = seriesModel.getBaseAxis(); + var idx = zrUtil.indexOf(axisList, baseAxis); + + if (idx < 0) { + idx = axisList.length; + axisList[idx] = baseAxis; + result[idx] = {axis: baseAxis, seriesModels: []}; + } + + result[idx].seriesModels.push(seriesModel); + }); + + return result; + } + + /** + * Calculate offset and box width for each series. + */ + function calculateBase(groupItem) { + var extent; + var baseAxis = groupItem.axis; + var seriesModels = groupItem.seriesModels; + var seriesCount = seriesModels.length; + + var boxWidthList = groupItem.boxWidthList = []; + var boxOffsetList = groupItem.boxOffsetList = []; + var boundList = []; + + var bandWidth; + if (baseAxis.type === 'category') { + bandWidth = baseAxis.getBandWidth(); + } + else { + var maxDataCount = 0; + each(seriesModels, function (seriesModel) { + maxDataCount = Math.max(maxDataCount, seriesModel.getData().count()); + }); + extent = baseAxis.getExtent(), + Math.abs(extent[1] - extent[0]) / maxDataCount; + } + + each(seriesModels, function (seriesModel) { + var boxWidthBound = seriesModel.get('boxWidth'); + if (!zrUtil.isArray(boxWidthBound)) { + boxWidthBound = [boxWidthBound, boxWidthBound]; + } + boundList.push([ + parsePercent(boxWidthBound[0], bandWidth) || 0, + parsePercent(boxWidthBound[1], bandWidth) || 0 + ]); + }); + + var availableWidth = bandWidth * 0.8 - 2; + var boxGap = availableWidth / seriesCount * 0.3; + var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount; + var base = boxWidth / 2 - availableWidth / 2; + + each(seriesModels, function (seriesModel, idx) { + boxOffsetList.push(base); + base += boxGap + boxWidth; + + boxWidthList.push( + Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1]) + ); + }); + } + + /** + * Calculate points location for each series. + */ + function layoutSingleSeries(seriesModel, offset, boxWidth) { + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var halfWidth = boxWidth / 2; + var chartLayout = seriesModel.get('layout'); + var variableDim = chartLayout === 'horizontal' ? 0 : 1; + var constDim = 1 - variableDim; + var coordDims = ['x', 'y']; + var vDims = []; + var cDim; + + zrUtil.each(data.dimensions, function (dimName) { + var dimInfo = data.getDimensionInfo(dimName); + var coordDim = dimInfo.coordDim; + if (coordDim === coordDims[constDim]) { + vDims.push(dimName); + } + else if (coordDim === coordDims[variableDim]) { + cDim = dimName; + } + }); + + if (cDim == null || vDims.length < 5) { + return; + } + + data.each([cDim].concat(vDims), function () { + var args = arguments; + var axisDimVal = args[0]; + var idx = args[vDims.length + 1]; + + var median = getPoint(args[3]); + var end1 = getPoint(args[1]); + var end5 = getPoint(args[5]); + var whiskerEnds = [ + [end1, getPoint(args[2])], + [end5, getPoint(args[4])] + ]; + layEndLine(end1); + layEndLine(end5); + layEndLine(median); + + var bodyEnds = []; + addBodyEnd(whiskerEnds[0][1], 0); + addBodyEnd(whiskerEnds[1][1], 1); + + data.setItemLayout(idx, { + chartLayout: chartLayout, + initBaseline: median[constDim], + median: median, + bodyEnds: bodyEnds, + whiskerEnds: whiskerEnds + }); + + function getPoint(val) { + var p = []; + p[variableDim] = axisDimVal; + p[constDim] = val; + var point; + if (isNaN(axisDimVal) || isNaN(val)) { + point = [NaN, NaN]; + } + else { + point = coordSys.dataToPoint(p); + point[variableDim] += offset; + } + return point; + } + + function addBodyEnd(point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + point1[variableDim] += halfWidth; + point2[variableDim] -= halfWidth; + start + ? bodyEnds.push(point1, point2) + : bodyEnds.push(point2, point1); + } + + function layEndLine(endCenter) { + var line = [endCenter.slice(), endCenter.slice()]; + line[0][variableDim] -= halfWidth; + line[1][variableDim] += halfWidth; + whiskerEnds.push(line); + } + }); + } + + + +/***/ }, +/* 264 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + + __webpack_require__(265); + __webpack_require__(266); + + echarts.registerPreprocessor( + __webpack_require__(267) + ); + + echarts.registerVisual(__webpack_require__(268)); + echarts.registerLayout(__webpack_require__(269)); + + + +/***/ }, +/* 265 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var SeriesModel = __webpack_require__(78); + var whiskerBoxCommon = __webpack_require__(259); + + var CandlestickSeries = SeriesModel.extend({ + + type: 'series.candlestick', + + dependencies: ['xAxis', 'yAxis', 'grid'], + + /** + * @readOnly + */ + defaultValueDimensions: ['open', 'close', 'lowest', 'highest'], + + /** + * @type {Array.} + * @readOnly + */ + dimensions: null, + + /** + * @override + */ + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + + hoverAnimation: true, + + // xAxisIndex: 0, + // yAxisIndex: 0, + + layout: null, // 'horizontal' or 'vertical' + + itemStyle: { + normal: { + color: '#c23531', // 阳线 positive + color0: '#314656', // 阴线 negative '#c23531', '#314656' + borderWidth: 1, + // FIXME + // ec2中使用的是lineStyle.color 和 lineStyle.color0 + borderColor: '#c23531', + borderColor0: '#314656' + }, + emphasis: { + borderWidth: 2 + } + }, + + barMaxWidth: null, + barMinWidth: null, + barWidth: null, + + animationUpdate: false, + animationEasing: 'linear', + animationDuration: 300 + }, + + /** + * Get dimension for shadow in dataZoom + * @return {string} dimension name + */ + getShadowDim: function () { + return 'open'; + }, + + brushSelector: function (dataIndex, data, selectors) { + var itemLayout = data.getItemLayout(dataIndex); + return selectors.rect(itemLayout.brushRect); + } + + }); + + zrUtil.mixin(CandlestickSeries, whiskerBoxCommon.seriesModelMixin, true); + + module.exports = CandlestickSeries; + + + +/***/ }, +/* 266 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var ChartView = __webpack_require__(80); + var graphic = __webpack_require__(18); + var whiskerBoxCommon = __webpack_require__(259); + + var CandlestickView = ChartView.extend({ + + type: 'candlestick', + + getStyleUpdater: function () { + return updateStyle; + }, + + dispose: zrUtil.noop + }); + + zrUtil.mixin(CandlestickView, whiskerBoxCommon.viewMixin, true); + + // Update common properties + var normalStyleAccessPath = ['itemStyle', 'normal']; + var emphasisStyleAccessPath = ['itemStyle', 'emphasis']; + + function updateStyle(itemGroup, data, idx) { + var itemModel = data.getItemModel(idx); + var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath); + var color = data.getItemVisual(idx, 'color'); + var borderColor = data.getItemVisual(idx, 'borderColor') || color; + + // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + var itemStyle = normalItemStyleModel.getItemStyle( + ['color', 'color0', 'borderColor', 'borderColor0'] + ); + + var whiskerEl = itemGroup.childAt(itemGroup.whiskerIndex); + whiskerEl.useStyle(itemStyle); + whiskerEl.style.stroke = borderColor; + + var bodyEl = itemGroup.childAt(itemGroup.bodyIndex); + bodyEl.useStyle(itemStyle); + bodyEl.style.fill = color; + bodyEl.style.stroke = borderColor; + + var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle(); + graphic.setHoverStyle(itemGroup, hoverStyle); + } + + + module.exports = CandlestickView; + + + +/***/ }, +/* 267 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + module.exports = function (option) { + if (!option || !zrUtil.isArray(option.series)) { + return; + } + + // Translate 'k' to 'candlestick'. + zrUtil.each(option.series, function (seriesItem) { + if (zrUtil.isObject(seriesItem) && seriesItem.type === 'k') { + seriesItem.type = 'candlestick'; + } + }); + }; + + + +/***/ }, +/* 268 */ +/***/ function(module, exports) { + + + + var positiveBorderColorQuery = ['itemStyle', 'normal', 'borderColor']; + var negativeBorderColorQuery = ['itemStyle', 'normal', 'borderColor0']; + var positiveColorQuery = ['itemStyle', 'normal', 'color']; + var negativeColorQuery = ['itemStyle', 'normal', 'color0']; + + module.exports = function (ecModel, api) { + + ecModel.eachRawSeriesByType('candlestick', function (seriesModel) { + + var data = seriesModel.getData(); + + data.setVisual({ + legendSymbol: 'roundRect' + }); + + // Only visible series has each data be visual encoded + if (!ecModel.isSeriesFiltered(seriesModel)) { + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var sign = data.getItemLayout(idx).sign; + + data.setItemVisual( + idx, + { + color: itemModel.get( + sign > 0 ? positiveColorQuery : negativeColorQuery + ), + borderColor: itemModel.get( + sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery + ) + } + ); + }); + } + }); + + }; + + +/***/ }, +/* 269 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var retrieve = __webpack_require__(4).retrieve; + var parsePercent = __webpack_require__(7).parsePercent; + + module.exports = function (ecModel) { + + ecModel.eachSeriesByType('candlestick', function (seriesModel) { + + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var candleWidth = calculateCandleWidth(seriesModel, data); + var chartLayout = seriesModel.get('layout'); + var variableDim = chartLayout === 'horizontal' ? 0 : 1; + var constDim = 1 - variableDim; + var coordDims = ['x', 'y']; + var vDims = []; + var cDim; + + zrUtil.each(data.dimensions, function (dimName) { + var dimInfo = data.getDimensionInfo(dimName); + var coordDim = dimInfo.coordDim; + if (coordDim === coordDims[constDim]) { + vDims.push(dimName); + } + else if (coordDim === coordDims[variableDim]) { + cDim = dimName; + } + }); + + if (cDim == null || vDims.length < 4) { + return; + } + + data.each([cDim].concat(vDims), function () { + var args = arguments; + var axisDimVal = args[0]; + var idx = args[vDims.length + 1]; + + var openVal = args[1]; + var closeVal = args[2]; + var lowestVal = args[3]; + var highestVal = args[4]; + + var ocLow = Math.min(openVal, closeVal); + var ocHigh = Math.max(openVal, closeVal); + + var ocLowPoint = getPoint(ocLow); + var ocHighPoint = getPoint(ocHigh); + var lowestPoint = getPoint(lowestVal); + var highestPoint = getPoint(highestVal); + + var whiskerEnds = [ + [highestPoint, ocHighPoint], + [lowestPoint, ocLowPoint] + ]; + + var bodyEnds = []; + addBodyEnd(ocHighPoint, 0); + addBodyEnd(ocLowPoint, 1); + + data.setItemLayout(idx, { + chartLayout: chartLayout, + sign: openVal > closeVal ? -1 : openVal < closeVal ? 1 : 0, + initBaseline: openVal > closeVal + ? ocHighPoint[constDim] : ocLowPoint[constDim], // open point. + bodyEnds: bodyEnds, + whiskerEnds: whiskerEnds, + brushRect: makeBrushRect() + }); + + function getPoint(val) { + var p = []; + p[variableDim] = axisDimVal; + p[constDim] = val; + return (isNaN(axisDimVal) || isNaN(val)) + ? [NaN, NaN] + : coordSys.dataToPoint(p); + } + + function addBodyEnd(point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + point1[variableDim] += candleWidth / 2; + point2[variableDim] -= candleWidth / 2; + start + ? bodyEnds.push(point1, point2) + : bodyEnds.push(point2, point1); + } + + function makeBrushRect() { + var pmin = getPoint(Math.min(openVal, closeVal, lowestVal, highestVal)); + var pmax = getPoint(Math.max(openVal, closeVal, lowestVal, highestVal)); + + pmin[variableDim] -= candleWidth / 2; + pmax[variableDim] -= candleWidth / 2; + + return { + x: pmin[0], + y: pmin[1], + width: constDim ? candleWidth : pmax[0] - pmin[0], + height: constDim ? pmax[1] - pmin[1] : candleWidth + }; + } + + }, true); + }); + }; + + function calculateCandleWidth(seriesModel, data) { + var baseAxis = seriesModel.getBaseAxis(); + var extent; + + var bandWidth = baseAxis.type === 'category' + ? baseAxis.getBandWidth() + : ( + extent = baseAxis.getExtent(), + Math.abs(extent[1] - extent[0]) / data.count() + ); + + var barMaxWidth = parsePercent( + retrieve(seriesModel.get('barMaxWidth'), bandWidth), + bandWidth + ); + var barMinWidth = parsePercent( + retrieve(seriesModel.get('barMinWidth'), 1), + bandWidth + ); + var barWidth = seriesModel.get('barWidth'); + return barWidth != null + ? parsePercent(barWidth, bandWidth) + // Put max outer to ensure bar visible in spite of overlap. + : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth); + } + + + +/***/ }, +/* 270 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var echarts = __webpack_require__(1); + + __webpack_require__(271); + __webpack_require__(272); + + echarts.registerVisual(zrUtil.curry( + __webpack_require__(121), 'effectScatter', 'circle', null + )); + echarts.registerLayout(zrUtil.curry( + __webpack_require__(122), 'effectScatter' + )); + + +/***/ }, +/* 271 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var createListFromArray = __webpack_require__(109); + var SeriesModel = __webpack_require__(78); + + module.exports = SeriesModel.extend({ + + type: 'series.effectScatter', + + dependencies: ['grid', 'polar'], + + getInitialData: function (option, ecModel) { + var list = createListFromArray(option.data, this, ecModel); + return list; + }, + + brushSelector: 'point', + + defaultOption: { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true, + + effectType: 'ripple', + + progressive: 0, + + // When to show the effect, option: 'render'|'emphasis' + showEffectOn: 'render', + + // Ripple effect config + rippleEffect: { + period: 4, + // Scale of ripple + scale: 2.5, + // Brush type can be fill or stroke + brushType: 'fill' + }, + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Polar coordinate system + // polarIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + // symbol: null, // 图形类型 + symbolSize: 10 // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2 + // symbolRotate: null, // 图形旋转控制 + + // large: false, + // Available when large is true + // largeThreshold: 2000, + + // itemStyle: { + // normal: { + // opacity: 1 + // } + // } + } + + }); + + +/***/ }, +/* 272 */ +/***/ function(module, exports, __webpack_require__) { + + + + var SymbolDraw = __webpack_require__(116); + var EffectSymbol = __webpack_require__(273); + + __webpack_require__(1).extendChartView({ + + type: 'effectScatter', + + init: function () { + this._symbolDraw = new SymbolDraw(EffectSymbol); + }, + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var effectSymbolDraw = this._symbolDraw; + effectSymbolDraw.updateData(data); + this.group.add(effectSymbolDraw.group); + }, + + updateLayout: function () { + this._symbolDraw.updateLayout(); + }, + + remove: function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(api); + }, + + dispose: function () {} + }); + + +/***/ }, +/* 273 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Symbol with ripple effect + * @module echarts/chart/helper/EffectSymbol + */ + + + var zrUtil = __webpack_require__(4); + var symbolUtil = __webpack_require__(111); + var graphic = __webpack_require__(18); + var numberUtil = __webpack_require__(7); + var Symbol = __webpack_require__(117); + var Group = graphic.Group; + + var EFFECT_RIPPLE_NUMBER = 3; + + function normalizeSymbolSize(symbolSize) { + if (!zrUtil.isArray(symbolSize)) { + symbolSize = [+symbolSize, +symbolSize]; + } + return symbolSize; + } + + function updateRipplePath(rippleGroup, effectCfg) { + rippleGroup.eachChild(function (ripplePath) { + ripplePath.attr({ + z: effectCfg.z, + zlevel: effectCfg.zlevel, + style: { + stroke: effectCfg.brushType === 'stroke' ? effectCfg.color : null, + fill: effectCfg.brushType === 'fill' ? effectCfg.color : null + } + }); + }); + } + /** + * @constructor + * @param {module:echarts/data/List} data + * @param {number} idx + * @extends {module:zrender/graphic/Group} + */ + function EffectSymbol(data, idx) { + Group.call(this); + + var symbol = new Symbol(data, idx); + var rippleGroup = new Group(); + this.add(symbol); + this.add(rippleGroup); + + rippleGroup.beforeUpdate = function () { + this.attr(symbol.getScale()); + }; + this.updateData(data, idx); + } + + var effectSymbolProto = EffectSymbol.prototype; + + effectSymbolProto.stopEffectAnimation = function () { + this.childAt(1).removeAll(); + }; + + effectSymbolProto.startEffectAnimation = function (effectCfg) { + var symbolType = effectCfg.symbolType; + var color = effectCfg.color; + var rippleGroup = this.childAt(1); + + for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) { + // var ripplePath = symbolUtil.createSymbol( + // symbolType, -0.5, -0.5, 1, 1, color + // ); + // If width/height are set too small (e.g., set to 1) on ios10 + // and macOS Sierra, a circle stroke become a rect, no matter what + // the scale is set. So we set width/height as 2. See #4136. + var ripplePath = symbolUtil.createSymbol( + symbolType, -1, -1, 2, 2, color + ); + ripplePath.attr({ + style: { + strokeNoScale: true + }, + z2: 99, + silent: true, + scale: [0.5, 0.5] + }); + + var delay = -i / EFFECT_RIPPLE_NUMBER * effectCfg.period + effectCfg.effectOffset; + // TODO Configurable effectCfg.period + ripplePath.animate('', true) + .when(effectCfg.period, { + scale: [effectCfg.rippleScale / 2, effectCfg.rippleScale / 2] + }) + .delay(delay) + .start(); + ripplePath.animateStyle(true) + .when(effectCfg.period, { + opacity: 0 + }) + .delay(delay) + .start(); + + rippleGroup.add(ripplePath); + } + + updateRipplePath(rippleGroup, effectCfg); + }; + + /** + * Update effect symbol + */ + effectSymbolProto.updateEffectAnimation = function (effectCfg) { + var oldEffectCfg = this._effectCfg; + var rippleGroup = this.childAt(1); + + // Must reinitialize effect if following configuration changed + var DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale']; + for (var i = 0; i < DIFFICULT_PROPS; i++) { + var propName = DIFFICULT_PROPS[i]; + if (oldEffectCfg[propName] !== effectCfg[propName]) { + this.stopEffectAnimation(); + this.startEffectAnimation(effectCfg); + return; + } + } + + updateRipplePath(rippleGroup, effectCfg); + }; + + /** + * Highlight symbol + */ + effectSymbolProto.highlight = function () { + this.trigger('emphasis'); + }; + + /** + * Downplay symbol + */ + effectSymbolProto.downplay = function () { + this.trigger('normal'); + }; + + /** + * Update symbol properties + * @param {module:echarts/data/List} data + * @param {number} idx + */ + effectSymbolProto.updateData = function (data, idx) { + var seriesModel = data.hostModel; + + this.childAt(0).updateData(data, idx); + + var rippleGroup = this.childAt(1); + var itemModel = data.getItemModel(idx); + var symbolType = data.getItemVisual(idx, 'symbol'); + var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize')); + var color = data.getItemVisual(idx, 'color'); + + rippleGroup.attr('scale', symbolSize); + + rippleGroup.traverse(function (ripplePath) { + ripplePath.attr({ + fill: color + }); + }); + + var symbolOffset = itemModel.getShallow('symbolOffset'); + if (symbolOffset) { + var pos = rippleGroup.position; + pos[0] = numberUtil.parsePercent(symbolOffset[0], symbolSize[0]); + pos[1] = numberUtil.parsePercent(symbolOffset[1], symbolSize[1]); + } + rippleGroup.rotation = (itemModel.getShallow('symbolRotate') || 0) * Math.PI / 180 || 0; + + var effectCfg = {}; + + effectCfg.showEffectOn = seriesModel.get('showEffectOn'); + effectCfg.rippleScale = itemModel.get('rippleEffect.scale'); + effectCfg.brushType = itemModel.get('rippleEffect.brushType'); + effectCfg.period = itemModel.get('rippleEffect.period') * 1000; + effectCfg.effectOffset = idx / data.count(); + effectCfg.z = itemModel.getShallow('z') || 0; + effectCfg.zlevel = itemModel.getShallow('zlevel') || 0; + effectCfg.symbolType = symbolType; + effectCfg.color = color; + + this.off('mouseover').off('mouseout').off('emphasis').off('normal'); + + if (effectCfg.showEffectOn === 'render') { + this._effectCfg + ? this.updateEffectAnimation(effectCfg) + : this.startEffectAnimation(effectCfg); + + this._effectCfg = effectCfg; + } + else { + // Not keep old effect config + this._effectCfg = null; + + this.stopEffectAnimation(); + var symbol = this.childAt(0); + var onEmphasis = function () { + symbol.trigger('emphasis'); + if (effectCfg.showEffectOn !== 'render') { + this.startEffectAnimation(effectCfg); + } + }; + var onNormal = function () { + symbol.trigger('normal'); + if (effectCfg.showEffectOn !== 'render') { + this.stopEffectAnimation(); + } + }; + this.on('mouseover', onEmphasis, this) + .on('mouseout', onNormal, this) + .on('emphasis', onEmphasis, this) + .on('normal', onNormal, this); + } + + this._effectCfg = effectCfg; + }; + + effectSymbolProto.fadeOut = function (cb) { + this.off('mouseover').off('mouseout').off('emphasis').off('normal'); + cb && cb(); + }; + + zrUtil.inherits(EffectSymbol, Group); + + module.exports = EffectSymbol; + + +/***/ }, +/* 274 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(275); + __webpack_require__(276); + + var echarts = __webpack_require__(1); + echarts.registerLayout( + __webpack_require__(281) + ); + echarts.registerVisual( + __webpack_require__(282) + ); + + +/***/ }, +/* 275 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var SeriesModel = __webpack_require__(78); + var List = __webpack_require__(98); + var zrUtil = __webpack_require__(4); + var formatUtil = __webpack_require__(6); + var CoordinateSystem = __webpack_require__(76); + + // Convert [ [{coord: []}, {coord: []}] ] + // to [ { coords: [[]] } ] + function preprocessOption (seriesOpt) { + var data = seriesOpt.data; + if (data && data[0] && data[0][0] && data[0][0].coord) { + if (true) { + console.warn('Lines data configuration has been changed to' + + ' { coords:[[1,2],[2,3]] }'); + } + seriesOpt.data = zrUtil.map(data, function (itemOpt) { + var coords = [ + itemOpt[0].coord, itemOpt[1].coord + ]; + var target = { + coords: coords + }; + if (itemOpt[0].name) { + target.fromName = itemOpt[0].name; + } + if (itemOpt[1].name) { + target.toName = itemOpt[1].name; + } + return zrUtil.mergeAll([target, itemOpt[0], itemOpt[1]]); + }); + } + } + + var LinesSeries = SeriesModel.extend({ + + type: 'series.lines', + + dependencies: ['grid', 'polar'], + + visualColorAccessPath: 'lineStyle.normal.color', + + init: function (option) { + // Not using preprocessor because mergeOption may not have series.type + preprocessOption(option); + + LinesSeries.superApply(this, 'init', arguments); + }, + + mergeOption: function (option) { + preprocessOption(option); + + LinesSeries.superApply(this, 'mergeOption', arguments); + }, + + getInitialData: function (option, ecModel) { + if (true) { + var CoordSys = CoordinateSystem.get(option.coordinateSystem); + if (!CoordSys) { + throw new Error('Unkown coordinate system ' + option.coordinateSystem); + } + } + + var lineData = new List(['value'], this); + lineData.hasItemOption = false; + lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) { + // dataItem is simply coords + if (dataItem instanceof Array) { + return NaN; + } + else { + lineData.hasItemOption = true; + var value = dataItem.value; + if (value != null) { + return value instanceof Array ? value[dimIndex] : value; + } + } + }); + + return lineData; + }, + + formatTooltip: function (dataIndex) { + var data = this.getData(); + var itemModel = data.getItemModel(dataIndex); + var name = itemModel.get('name'); + if (name) { + return name; + } + var fromName = itemModel.get('fromName'); + var toName = itemModel.get('toName'); + var html = []; + fromName != null && html.push(fromName); + toName != null && html.push(toName); + + return formatUtil.encodeHTML(html.join(' > ')); + }, + + defaultOption: { + coordinateSystem: 'geo', + zlevel: 0, + z: 2, + legendHoverLink: true, + + hoverAnimation: true, + // Cartesian coordinate system + xAxisIndex: 0, + yAxisIndex: 0, + + symbol: ['none', 'none'], + symbolSize: [10, 10], + // Geo coordinate system + geoIndex: 0, + + effect: { + show: false, + period: 4, + // Animation delay. support callback + // delay: 0, + // If move with constant speed px/sec + // period will be ignored if this property is > 0, + constantSpeed: 0, + symbol: 'circle', + symbolSize: 3, + loop: true, + // Length of trail, 0 - 1 + trailLength: 0.2 + // Same with lineStyle.normal.color + // color + }, + + large: false, + // Available when large is true + largeThreshold: 2000, + + // If lines are polyline + // polyline not support curveness, label, animation + polyline: false, + + label: { + normal: { + show: false, + position: 'end' + // distance: 5, + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + } + }, + + lineStyle: { + normal: { + opacity: 0.5 + } + } + } + }); + + +/***/ }, +/* 276 */ +/***/ function(module, exports, __webpack_require__) { + + + + var LineDraw = __webpack_require__(210); + var EffectLine = __webpack_require__(277); + var Line = __webpack_require__(211); + var Polyline = __webpack_require__(278); + var EffectPolyline = __webpack_require__(279); + var LargeLineDraw = __webpack_require__(280); + + __webpack_require__(1).extendChartView({ + + type: 'lines', + + init: function () {}, + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var lineDraw = this._lineDraw; + + var hasEffect = seriesModel.get('effect.show'); + var isPolyline = seriesModel.get('polyline'); + var isLarge = seriesModel.get('large') && data.count() >= seriesModel.get('largeThreshold'); + + if (true) { + if (hasEffect && isLarge) { + console.warn('Large lines not support effect'); + } + } + if (hasEffect !== this._hasEffet || isPolyline !== this._isPolyline || isLarge !== this._isLarge) { + if (lineDraw) { + lineDraw.remove(); + } + lineDraw = this._lineDraw = isLarge + ? new LargeLineDraw() + : new LineDraw( + isPolyline + ? (hasEffect ? EffectPolyline : Polyline) + : (hasEffect ? EffectLine : Line) + ); + this._hasEffet = hasEffect; + this._isPolyline = isPolyline; + this._isLarge = isLarge; + } + + var zlevel = seriesModel.get('zlevel'); + var trailLength = seriesModel.get('effect.trailLength'); + + var zr = api.getZr(); + // Avoid the drag cause ghost shadow + // FIXME Better way ? + zr.painter.getLayer(zlevel).clear(true); + // Config layer with motion blur + if (this._lastZlevel != null) { + zr.configLayer(this._lastZlevel, { + motionBlur: false + }); + } + if (hasEffect && trailLength) { + if (true) { + var notInIndividual = false; + ecModel.eachSeries(function (otherSeriesModel) { + if (otherSeriesModel !== seriesModel && otherSeriesModel.get('zlevel') === zlevel) { + notInIndividual = true; + } + }); + notInIndividual && console.warn('Lines with trail effect should have an individual zlevel'); + } + + zr.configLayer(zlevel, { + motionBlur: true, + lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0) + }); + } + + this.group.add(lineDraw.group); + + lineDraw.updateData(data); + + this._lastZlevel = zlevel; + }, + + updateLayout: function (seriesModel, ecModel, api) { + this._lineDraw.updateLayout(seriesModel); + // Not use motion when dragging or zooming + var zr = api.getZr(); + zr.painter.getLayer(this._lastZlevel).clear(true); + }, + + remove: function (ecModel, api) { + this._lineDraw && this._lineDraw.remove(api, true); + }, + + dispose: function () {} + }); + + +/***/ }, +/* 277 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Provide effect for line + * @module echarts/chart/helper/EffectLine + */ + + + var graphic = __webpack_require__(18); + var Line = __webpack_require__(211); + var zrUtil = __webpack_require__(4); + var symbolUtil = __webpack_require__(111); + var vec2 = __webpack_require__(10); + + var curveUtil = __webpack_require__(37); + + /** + * @constructor + * @extends {module:zrender/graphic/Group} + * @alias {module:echarts/chart/helper/Line} + */ + function EffectLine(lineData, idx, seriesScope) { + graphic.Group.call(this); + + this.add(this.createLine(lineData, idx, seriesScope)); + + this._updateEffectSymbol(lineData, idx); + } + + var effectLineProto = EffectLine.prototype; + + effectLineProto.createLine = function (lineData, idx, seriesScope) { + return new Line(lineData, idx, seriesScope); + }; + + effectLineProto._updateEffectSymbol = function (lineData, idx) { + var itemModel = lineData.getItemModel(idx); + var effectModel = itemModel.getModel('effect'); + var size = effectModel.get('symbolSize'); + var symbolType = effectModel.get('symbol'); + if (!zrUtil.isArray(size)) { + size = [size, size]; + } + var color = effectModel.get('color') || lineData.getItemVisual(idx, 'color'); + var symbol = this.childAt(1); + + if (this._symbolType !== symbolType) { + // Remove previous + this.remove(symbol); + + symbol = symbolUtil.createSymbol( + symbolType, -0.5, -0.5, 1, 1, color + ); + symbol.z2 = 100; + symbol.culling = true; + + this.add(symbol); + } + + // Symbol may be removed if loop is false + if (!symbol) { + return; + } + + // Shadow color is same with color in default + symbol.setStyle('shadowColor', color); + symbol.setStyle(effectModel.getItemStyle(['color'])); + + symbol.attr('scale', size); + + symbol.setColor(color); + symbol.attr('scale', size); + + this._symbolType = symbolType; + + this._updateEffectAnimation(lineData, effectModel, idx); + }; + + effectLineProto._updateEffectAnimation = function (lineData, effectModel, idx) { + + var symbol = this.childAt(1); + if (!symbol) { + return; + } + + var self = this; + + var points = lineData.getItemLayout(idx); + + var period = effectModel.get('period') * 1000; + var loop = effectModel.get('loop'); + var constantSpeed = effectModel.get('constantSpeed'); + var delayExpr = zrUtil.retrieve(effectModel.get('delay'), function (idx) { + return idx / lineData.count() * period / 3; + }); + var isDelayFunc = typeof delayExpr === 'function'; + + // Ignore when updating + symbol.ignore = true; + + this.updateAnimationPoints(symbol, points); + + if (constantSpeed > 0) { + period = this.getLineLength(symbol) / constantSpeed * 1000; + } + + if (period !== this._period || loop !== this._loop) { + + symbol.stopAnimation(); + + var delay = delayExpr; + if (isDelayFunc) { + delay = delayExpr(idx); + } + if (symbol.__t > 0) { + delay = -period * symbol.__t; + } + symbol.__t = 0; + var animator = symbol.animate('', loop) + .when(period, { + __t: 1 + }) + .delay(delay) + .during(function () { + self.updateSymbolPosition(symbol); + }); + if (!loop) { + animator.done(function () { + self.remove(symbol); + }); + } + animator.start(); + } + + this._period = period; + this._loop = loop; + }; + + effectLineProto.getLineLength = function (symbol) { + // Not so accurate + return (vec2.dist(symbol.__p1, symbol.__cp1) + + vec2.dist(symbol.__cp1, symbol.__p2)); + }; + + effectLineProto.updateAnimationPoints = function (symbol, points) { + symbol.__p1 = points[0]; + symbol.__p2 = points[1]; + symbol.__cp1 = points[2] || [ + (points[0][0] + points[1][0]) / 2, + (points[0][1] + points[1][1]) / 2 + ]; + }; + + effectLineProto.updateData = function (lineData, idx, seriesScope) { + this.childAt(0).updateData(lineData, idx, seriesScope); + this._updateEffectSymbol(lineData, idx); + }; + + effectLineProto.updateSymbolPosition = function (symbol) { + var p1 = symbol.__p1; + var p2 = symbol.__p2; + var cp1 = symbol.__cp1; + var t = symbol.__t; + var pos = symbol.position; + var quadraticAt = curveUtil.quadraticAt; + var quadraticDerivativeAt = curveUtil.quadraticDerivativeAt; + pos[0] = quadraticAt(p1[0], cp1[0], p2[0], t); + pos[1] = quadraticAt(p1[1], cp1[1], p2[1], t); + + // Tangent + var tx = quadraticDerivativeAt(p1[0], cp1[0], p2[0], t); + var ty = quadraticDerivativeAt(p1[1], cp1[1], p2[1], t); + + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; + + symbol.ignore = false; + }; + + + effectLineProto.updateLayout = function (lineData, idx) { + this.childAt(0).updateLayout(lineData, idx); + + var effectModel = lineData.getItemModel(idx).getModel('effect'); + this._updateEffectAnimation(lineData, effectModel, idx); + }; + + zrUtil.inherits(EffectLine, graphic.Group); + + module.exports = EffectLine; + + +/***/ }, +/* 278 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/chart/helper/Line + */ + + + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + + /** + * @constructor + * @extends {module:zrender/graphic/Group} + * @alias {module:echarts/chart/helper/Polyline} + */ + function Polyline(lineData, idx, seriesScope) { + graphic.Group.call(this); + + this._createPolyline(lineData, idx, seriesScope); + } + + var polylineProto = Polyline.prototype; + + polylineProto._createPolyline = function (lineData, idx, seriesScope) { + // var seriesModel = lineData.hostModel; + var points = lineData.getItemLayout(idx); + + var line = new graphic.Polyline({ + shape: { + points: points + } + }); + + this.add(line); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + polylineProto.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + + var line = this.childAt(0); + var target = { + shape: { + points: lineData.getItemLayout(idx) + } + }; + graphic.updateProps(line, target, seriesModel, idx); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + polylineProto._updateCommonStl = function (lineData, idx, seriesScope) { + var line = this.childAt(0); + var itemModel = lineData.getItemModel(idx); + + var visualColor = lineData.getItemVisual(idx, 'color'); + + var lineStyle = seriesScope && seriesScope.lineStyle; + var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle; + + if (!seriesScope || lineData.hasItemOption) { + lineStyle = itemModel.getModel('lineStyle.normal').getLineStyle(); + hoverLineStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle(); + } + line.useStyle(zrUtil.defaults( + { + strokeNoScale: true, + fill: 'none', + stroke: visualColor + }, + lineStyle + )); + line.hoverStyle = hoverLineStyle; + + graphic.setHoverStyle(this); + }; + + polylineProto.updateLayout = function (lineData, idx) { + var polyline = this.childAt(0); + polyline.setShape('points', lineData.getItemLayout(idx)); + }; + + zrUtil.inherits(Polyline, graphic.Group); + + module.exports = Polyline; + + +/***/ }, +/* 279 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Provide effect for line + * @module echarts/chart/helper/EffectLine + */ + + + var Polyline = __webpack_require__(278); + var zrUtil = __webpack_require__(4); + var EffectLine = __webpack_require__(277); + var vec2 = __webpack_require__(10); + + /** + * @constructor + * @extends {module:echarts/chart/helper/EffectLine} + * @alias {module:echarts/chart/helper/Polyline} + */ + function EffectPolyline(lineData, idx, seriesScope) { + EffectLine.call(this, lineData, idx, seriesScope); + this._lastFrame = 0; + this._lastFramePercent = 0; + } + + var effectPolylineProto = EffectPolyline.prototype; + + // Overwrite + effectPolylineProto.createLine = function (lineData, idx, seriesScope) { + return new Polyline(lineData, idx, seriesScope); + }; + + // Overwrite + effectPolylineProto.updateAnimationPoints = function (symbol, points) { + this._points = points; + var accLenArr = [0]; + var len = 0; + for (var i = 1; i < points.length; i++) { + var p1 = points[i - 1]; + var p2 = points[i]; + len += vec2.dist(p1, p2); + accLenArr.push(len); + } + if (len === 0) { + return; + } + + for (var i = 0; i < accLenArr.length; i++) { + accLenArr[i] /= len; + } + this._offsets = accLenArr; + this._length = len; + }; + + // Overwrite + effectPolylineProto.getLineLength = function (symbol) { + return this._length; + }; + + // Overwrite + effectPolylineProto.updateSymbolPosition = function (symbol) { + var t = symbol.__t; + var points = this._points; + var offsets = this._offsets; + var len = points.length; + + if (!offsets) { + // Has length 0 + return; + } + + var lastFrame = this._lastFrame; + var frame; + + if (t < this._lastFramePercent) { + // Start from the next frame + // PENDING start from lastFrame ? + var start = Math.min(lastFrame + 1, len - 1); + for (frame = start; frame >= 0; frame--) { + if (offsets[frame] <= t) { + break; + } + } + // PENDING really need to do this ? + frame = Math.min(frame, len - 2); + } + else { + for (var frame = lastFrame; frame < len; frame++) { + if (offsets[frame] > t) { + break; + } + } + frame = Math.min(frame - 1, len - 2); + } + + vec2.lerp( + symbol.position, points[frame], points[frame + 1], + (t - offsets[frame]) / (offsets[frame + 1] - offsets[frame]) + ); + + var tx = points[frame + 1][0] - points[frame][0]; + var ty = points[frame + 1][1] - points[frame][1]; + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; + + this._lastFrame = frame; + this._lastFramePercent = t; + + symbol.ignore = false; + }; + + zrUtil.inherits(EffectPolyline, EffectLine); + + module.exports = EffectPolyline; + + +/***/ }, +/* 280 */ +/***/ function(module, exports, __webpack_require__) { + + // TODO Batch by color + + + + var graphic = __webpack_require__(18); + + var quadraticContain = __webpack_require__(42); + var lineContain = __webpack_require__(40); + + var LargeLineShape = graphic.extendShape({ + shape: { + polyline: false, + + segs: [] + }, + + buildPath: function (path, shape) { + var segs = shape.segs; + var isPolyline = shape.polyline; + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if (isPolyline) { + path.moveTo(seg[0][0], seg[0][1]); + for (var j = 1; j < seg.length; j++) { + path.lineTo(seg[j][0], seg[j][1]); + } + } + else { + path.moveTo(seg[0][0], seg[0][1]); + if (seg.length > 2) { + path.quadraticCurveTo(seg[2][0], seg[2][1], seg[1][0], seg[1][1]); + } + else { + path.lineTo(seg[1][0], seg[1][1]); + } + } + } + }, + + findDataIndex: function (x, y) { + var shape = this.shape; + var segs = shape.segs; + var isPolyline = shape.polyline; + var lineWidth = Math.max(this.style.lineWidth, 1); + + // Not consider transform + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if (isPolyline) { + for (var j = 1; j < seg.length; j++) { + if (lineContain.containStroke( + seg[j - 1][0], seg[j - 1][1], seg[j][0], seg[j][1], lineWidth, x, y + )) { + return i; + } + } + } + else { + if (seg.length > 2) { + if (quadraticContain.containStroke( + seg[0][0], seg[0][1], seg[2][0], seg[2][1], seg[1][0], seg[1][1], lineWidth, x, y + )) { + return i; + } + } + else { + if (lineContain.containStroke( + seg[0][0], seg[0][1], seg[1][0], seg[1][1], lineWidth, x, y + )) { + return i; + } + } + } + } + + return -1; + } + }); + + function LargeLineDraw() { + this.group = new graphic.Group(); + + this._lineEl = new LargeLineShape(); + } + + var largeLineProto = LargeLineDraw.prototype; + + /** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + */ + largeLineProto.updateData = function (data) { + this.group.removeAll(); + + var lineEl = this._lineEl; + + var seriesModel = data.hostModel; + + lineEl.setShape({ + segs: data.mapArray(data.getItemLayout), + polyline: seriesModel.get('polyline') + }); + + lineEl.useStyle( + seriesModel.getModel('lineStyle.normal').getLineStyle() + ); + + var visualColor = data.getVisual('color'); + if (visualColor) { + lineEl.setStyle('stroke', visualColor); + } + lineEl.setStyle('fill'); + + // Enable tooltip + // PENDING May have performance issue when path is extremely large + lineEl.seriesIndex = seriesModel.seriesIndex; + lineEl.on('mousemove', function (e) { + lineEl.dataIndex = null; + var dataIndex = lineEl.findDataIndex(e.offsetX, e.offsetY); + if (dataIndex > 0) { + // Provide dataIndex for tooltip + lineEl.dataIndex = dataIndex; + } + }); + + // Add back + this.group.add(lineEl); + }; + + largeLineProto.updateLayout = function (seriesModel) { + var data = seriesModel.getData(); + this._lineEl.setShape({ + segs: data.mapArray(data.getItemLayout) + }); + }; + + largeLineProto.remove = function () { + this.group.removeAll(); + }; + + module.exports = LargeLineDraw; + + +/***/ }, +/* 281 */ +/***/ function(module, exports, __webpack_require__) { + + + + module.exports = function (ecModel) { + ecModel.eachSeriesByType('lines', function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var lineData = seriesModel.getData(); + + // FIXME Use data dimensions ? + lineData.each(function (idx) { + var itemModel = lineData.getItemModel(idx); + + var coords = (itemModel.option instanceof Array) ? + itemModel.option : itemModel.get('coords'); + + if (true) { + if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) { + throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.'); + } + } + var pts = []; + + if (seriesModel.get('polyline')) { + for (var i = 0; i < coords.length; i++) { + pts.push(coordSys.dataToPoint(coords[i])); + } + } + else { + pts[0] = coordSys.dataToPoint(coords[0]); + pts[1] = coordSys.dataToPoint(coords[1]); + + var curveness = itemModel.get('lineStyle.normal.curveness'); + if (+curveness) { + pts[2] = [ + (pts[0][0] + pts[1][0]) / 2 - (pts[0][1] - pts[1][1]) * curveness, + (pts[0][1] + pts[1][1]) / 2 - (pts[1][0] - pts[0][0]) * curveness + ]; + } + } + lineData.setItemLayout(idx, pts); + }); + }); + }; + + +/***/ }, +/* 282 */ +/***/ function(module, exports) { + + + + function normalize(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + return a; + } + module.exports = function (ecModel) { + ecModel.eachSeriesByType('lines', function (seriesModel) { + var data = seriesModel.getData(); + var symbolType = normalize(seriesModel.get('symbol')); + var symbolSize = normalize(seriesModel.get('symbolSize')); + + var opacityQuery = 'lineStyle.normal.opacity'.split('.'); + + data.setVisual('fromSymbol', symbolType && symbolType[0]); + data.setVisual('toSymbol', symbolType && symbolType[1]); + data.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + data.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + data.setVisual('opacity', seriesModel.get(opacityQuery)); + + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var symbolType = normalize(itemModel.getShallow('symbol', true)); + var symbolSize = normalize(itemModel.getShallow('symbolSize', true)); + var opacity = itemModel.get(opacityQuery); + + symbolType[0] && data.setItemVisual(idx, 'fromSymbol', symbolType[0]); + symbolType[1] && data.setItemVisual(idx, 'toSymbol', symbolType[1]); + symbolSize[0] && data.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]); + symbolSize[1] && data.setItemVisual(idx, 'toSymbolSize', symbolSize[1]); + + data.setItemVisual(idx, 'opacity', opacity); + }); + }); + }; + + +/***/ }, +/* 283 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(284); + __webpack_require__(285); + + +/***/ }, +/* 284 */ +/***/ function(module, exports, __webpack_require__) { + + + + var SeriesModel = __webpack_require__(78); + var createListFromArray = __webpack_require__(109); + + module.exports = SeriesModel.extend({ + type: 'series.heatmap', + + getInitialData: function (option, ecModel) { + return createListFromArray(option.data, this, ecModel); + }, + + defaultOption: { + + // Cartesian2D or geo + coordinateSystem: 'cartesian2d', + + zlevel: 0, + + z: 2, + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Geo coordinate system + geoIndex: 0, + + blurSize: 30, + + pointSize: 20, + + maxOpacity: 1, + + minOpacity: 0 + } + }); + + +/***/ }, +/* 285 */ +/***/ function(module, exports, __webpack_require__) { + + + + var graphic = __webpack_require__(18); + var HeatmapLayer = __webpack_require__(286); + var zrUtil = __webpack_require__(4); + + function getIsInPiecewiseRange(dataExtent, pieceList, selected) { + var dataSpan = dataExtent[1] - dataExtent[0]; + pieceList = zrUtil.map(pieceList, function (piece) { + return { + interval: [ + (piece.interval[0] - dataExtent[0]) / dataSpan, + (piece.interval[1] - dataExtent[0]) / dataSpan + ] + }; + }); + var len = pieceList.length; + var lastIndex = 0; + return function (val) { + // Try to find in the location of the last found + for (var i = lastIndex; i < len; i++) { + var interval = pieceList[i].interval; + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + if (i === len) { // Not found, back interation + for (var i = lastIndex - 1; i >= 0; i--) { + var interval = pieceList[i].interval; + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + } + return i >= 0 && i < len && selected[i]; + }; + } + + function getIsInContinuousRange(dataExtent, range) { + var dataSpan = dataExtent[1] - dataExtent[0]; + range = [ + (range[0] - dataExtent[0]) / dataSpan, + (range[1] - dataExtent[0]) / dataSpan + ]; + return function (val) { + return val >= range[0] && val <= range[1]; + }; + } + + function isGeoCoordSys(coordSys) { + var dimensions = coordSys.dimensions; + // Not use coorSys.type === 'geo' because coordSys maybe extended + return dimensions[0] === 'lng' && dimensions[1] === 'lat'; + } + + module.exports = __webpack_require__(1).extendChartView({ + + type: 'heatmap', + + render: function (seriesModel, ecModel, api) { + var visualMapOfThisSeries; + ecModel.eachComponent('visualMap', function (visualMap) { + visualMap.eachTargetSeries(function (targetSeries) { + if (targetSeries === seriesModel) { + visualMapOfThisSeries = visualMap; + } + }); + }); + + if (true) { + if (!visualMapOfThisSeries) { + throw new Error('Heatmap must use with visualMap'); + } + } + + this.group.removeAll(); + var coordSys = seriesModel.coordinateSystem; + if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') { + this._renderOnCartesianAndCalendar(coordSys, seriesModel, api); + } + else if (isGeoCoordSys(coordSys)) { + this._renderOnGeo( + coordSys, seriesModel, visualMapOfThisSeries, api + ); + } + }, + + dispose: function () {}, + + _renderOnCartesianAndCalendar: function (coordSys, seriesModel, api) { + + if (coordSys.type === 'cartesian2d') { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + + if (true) { + if (!(xAxis.type === 'category' && yAxis.type === 'category')) { + throw new Error('Heatmap on cartesian must have two category axes'); + } + if (!(xAxis.onBand && yAxis.onBand)) { + throw new Error('Heatmap on cartesian must have two axes with boundaryGap true'); + } + } + + var width = xAxis.getBandWidth(); + var height = yAxis.getBandWidth(); + + } + + var group = this.group; + var data = seriesModel.getData(); + + var itemStyleQuery = 'itemStyle.normal'; + var hoverItemStyleQuery = 'itemStyle.emphasis'; + var labelQuery = 'label.normal'; + var hoverLabelQuery = 'label.emphasis'; + var style = seriesModel.getModel(itemStyleQuery).getItemStyle(['color']); + var hoverStl = seriesModel.getModel(hoverItemStyleQuery).getItemStyle(); + var labelModel = seriesModel.getModel('label.normal'); + var hoverLabelModel = seriesModel.getModel('label.emphasis'); + var coordSysType = coordSys.type; + + var dataDims = coordSysType === 'cartesian2d' + ? [ + seriesModel.coordDimToDataDim('x')[0], + seriesModel.coordDimToDataDim('y')[0], + seriesModel.coordDimToDataDim('value')[0] + ] + : [ + seriesModel.coordDimToDataDim('time')[0], + seriesModel.coordDimToDataDim('value')[0] + ]; + + data.each(function (idx) { + var rect; + + if (coordSysType === 'cartesian2d') { + // Ignore empty data + if (isNaN(data.get(dataDims[2], idx))) { + return; + } + + var point = coordSys.dataToPoint([ + data.get(dataDims[0], idx), + data.get(dataDims[1], idx) + ]); + + rect = new graphic.Rect({ + shape: { + x: point[0] - width / 2, + y: point[1] - height / 2, + width: width, + height: height + }, + style: { + fill: data.getItemVisual(idx, 'color'), + opacity: data.getItemVisual(idx, 'opacity') + } + }); + } + else { + // Ignore empty data + if (isNaN(data.get(dataDims[1], idx))) { + return; + } + + rect = new graphic.Rect({ + z2: 1, + shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape, + style: { + fill: data.getItemVisual(idx, 'color'), + opacity: data.getItemVisual(idx, 'opacity') + } + }); + } + + var itemModel = data.getItemModel(idx); + + // Optimization for large datset + if (data.hasItemOption) { + style = itemModel.getModel(itemStyleQuery).getItemStyle(['color']); + hoverStl = itemModel.getModel(hoverItemStyleQuery).getItemStyle(); + labelModel = itemModel.getModel(labelQuery); + hoverLabelModel = itemModel.getModel(hoverLabelQuery); + } + + var rawValue = seriesModel.getRawValue(idx); + var defaultText = '-'; + if (rawValue && rawValue[2] != null) { + defaultText = rawValue[2]; + } + if (labelModel.getShallow('show')) { + graphic.setText(style, labelModel); + style.text = seriesModel.getFormattedLabel(idx, 'normal') || defaultText; + } + if (hoverLabelModel.getShallow('show')) { + graphic.setText(hoverStl, hoverLabelModel); + hoverStl.text = seriesModel.getFormattedLabel(idx, 'emphasis') || defaultText; + } + + rect.setStyle(style); + + graphic.setHoverStyle(rect, data.hasItemOption ? hoverStl : zrUtil.extend({}, hoverStl)); + + group.add(rect); + data.setItemGraphicEl(idx, rect); + }); + }, + + _renderOnGeo: function (geo, seriesModel, visualMapModel, api) { + var inRangeVisuals = visualMapModel.targetVisuals.inRange; + var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange; + // if (!visualMapping) { + // throw new Error('Data range must have color visuals'); + // } + + var data = seriesModel.getData(); + var hmLayer = this._hmLayer || (this._hmLayer || new HeatmapLayer()); + hmLayer.blurSize = seriesModel.get('blurSize'); + hmLayer.pointSize = seriesModel.get('pointSize'); + hmLayer.minOpacity = seriesModel.get('minOpacity'); + hmLayer.maxOpacity = seriesModel.get('maxOpacity'); + + var rect = geo.getViewRect().clone(); + var roamTransform = geo.getRoamTransform().transform; + rect.applyTransform(roamTransform); + + // Clamp on viewport + var x = Math.max(rect.x, 0); + var y = Math.max(rect.y, 0); + var x2 = Math.min(rect.width + rect.x, api.getWidth()); + var y2 = Math.min(rect.height + rect.y, api.getHeight()); + var width = x2 - x; + var height = y2 - y; + + var points = data.mapArray(['lng', 'lat', 'value'], function (lng, lat, value) { + var pt = geo.dataToPoint([lng, lat]); + pt[0] -= x; + pt[1] -= y; + pt.push(value); + return pt; + }); + + var dataExtent = visualMapModel.getExtent(); + var isInRange = visualMapModel.type === 'visualMap.continuous' + ? getIsInContinuousRange(dataExtent, visualMapModel.option.range) + : getIsInPiecewiseRange( + dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected + ); + + hmLayer.update( + points, width, height, + inRangeVisuals.color.getNormalizer(), + { + inRange: inRangeVisuals.color.getColorMapper(), + outOfRange: outOfRangeVisuals.color.getColorMapper() + }, + isInRange + ); + var img = new graphic.Image({ + style: { + width: width, + height: height, + x: x, + y: y, + image: hmLayer.canvas + }, + silent: true + }); + this.group.add(img); + } + }); + + + +/***/ }, +/* 286 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file defines echarts Heatmap Chart + * @author Ovilia (me@zhangwenli.com) + * Inspired by https://github.com/mourner/simpleheat + * + * @module + */ + + + var GRADIENT_LEVELS = 256; + var zrUtil = __webpack_require__(4); + + /** + * Heatmap Chart + * + * @class + */ + function Heatmap() { + var canvas = zrUtil.createCanvas(); + this.canvas = canvas; + + this.blurSize = 30; + this.pointSize = 20; + + this.maxOpacity = 1; + this.minOpacity = 0; + + this._gradientPixels = {}; + } + + Heatmap.prototype = { + /** + * Renders Heatmap and returns the rendered canvas + * @param {Array} data array of data, each has x, y, value + * @param {number} width canvas width + * @param {number} height canvas height + */ + update: function(data, width, height, normalize, colorFunc, isInRange) { + var brush = this._getBrush(); + var gradientInRange = this._getGradient(data, colorFunc, 'inRange'); + var gradientOutOfRange = this._getGradient(data, colorFunc, 'outOfRange'); + var r = this.pointSize + this.blurSize; + + var canvas = this.canvas; + var ctx = canvas.getContext('2d'); + var len = data.length; + canvas.width = width; + canvas.height = height; + for (var i = 0; i < len; ++i) { + var p = data[i]; + var x = p[0]; + var y = p[1]; + var value = p[2]; + + // calculate alpha using value + var alpha = normalize(value); + + // draw with the circle brush with alpha + ctx.globalAlpha = alpha; + ctx.drawImage(brush, x - r, y - r); + } + + // colorize the canvas using alpha value and set with gradient + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + var pixels = imageData.data; + var offset = 0; + var pixelLen = pixels.length; + var minOpacity = this.minOpacity; + var maxOpacity = this.maxOpacity; + var diffOpacity = maxOpacity - minOpacity; + + while(offset < pixelLen) { + var alpha = pixels[offset + 3] / 256; + var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4; + // Simple optimize to ignore the empty data + if (alpha > 0) { + var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange; + // Any alpha > 0 will be mapped to [minOpacity, maxOpacity] + alpha > 0 && (alpha = alpha * diffOpacity + minOpacity); + pixels[offset++] = gradient[gradientOffset]; + pixels[offset++] = gradient[gradientOffset + 1]; + pixels[offset++] = gradient[gradientOffset + 2]; + pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256; + } + else { + offset += 4; + } + } + ctx.putImageData(imageData, 0, 0); + + return canvas; + }, + + /** + * get canvas of a black circle brush used for canvas to draw later + * @private + * @returns {Object} circle brush canvas + */ + _getBrush: function() { + var brushCanvas = this._brushCanvas || (this._brushCanvas = zrUtil.createCanvas()); + // set brush size + var r = this.pointSize + this.blurSize; + var d = r * 2; + brushCanvas.width = d; + brushCanvas.height = d; + + var ctx = brushCanvas.getContext('2d'); + ctx.clearRect(0, 0, d, d); + + // in order to render shadow without the distinct circle, + // draw the distinct circle in an invisible place, + // and use shadowOffset to draw shadow in the center of the canvas + ctx.shadowOffsetX = d; + ctx.shadowBlur = this.blurSize; + // draw the shadow in black, and use alpha and shadow blur to generate + // color in color map + ctx.shadowColor = '#000'; + + // draw circle in the left to the canvas + ctx.beginPath(); + ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fill(); + return brushCanvas; + }, + + /** + * get gradient color map + * @private + */ + _getGradient: function (data, colorFunc, state) { + var gradientPixels = this._gradientPixels; + var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4)); + var color = [0, 0, 0, 0]; + var off = 0; + for (var i = 0; i < 256; i++) { + colorFunc[state](i / 255, true, color); + pixelsSingleState[off++] = color[0]; + pixelsSingleState[off++] = color[1]; + pixelsSingleState[off++] = color[2]; + pixelsSingleState[off++] = color[3]; + } + return pixelsSingleState; + } + }; + + module.exports = Heatmap; + + + +/***/ }, +/* 287 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + __webpack_require__(125); + + __webpack_require__(288); + __webpack_require__(289); + + var barLayoutGrid = __webpack_require__(145); + var echarts = __webpack_require__(1); + + echarts.registerLayout(zrUtil.curry(barLayoutGrid, 'pictorialBar')); + + echarts.registerVisual(zrUtil.curry( + __webpack_require__(121), 'pictorialBar', 'roundRect', null + )); + + // In case developer forget to include grid component + __webpack_require__(124); + + +/***/ }, +/* 288 */ +/***/ function(module, exports, __webpack_require__) { + + + + var PictorialBarSeries = __webpack_require__(141).extend({ + + type: 'series.pictorialBar', + + dependencies: ['grid'], + + defaultOption: { + symbol: 'circle', // Customized bar shape + symbolSize: null, // Can be ['100%', '100%'], null means auto. + symbolRotate: null, + + symbolPosition: null, // 'start' or 'end' or 'center', null means auto. + symbolOffset: null, + symbolMargin: null, // start margin and end margin. Can be a number or a percent string. + // Auto margin by defualt. + symbolRepeat: false, // false/null/undefined, means no repeat. + // Can be true, means auto calculate repeat times and cut by data. + // Can be a number, specifies repeat times, and do not cut by data. + // Can be 'fixed', means auto calculate repeat times but do not cut by data. + symbolRepeatDirection: 'end', // 'end' means from 'start' to 'end'. + + symbolClip: false, + symbolBoundingData: null, // Can be 60 or -40 or [-40, 60] + symbolPatternSize: 400, // 400 * 400 px + + barGap: '-100%', // In most case, overlap is needed. + + // z can be set in data item, which is z2 actually. + + // Disable progressive + progressive: 0, + hoverAnimation: false // Open only when needed. + }, + + getInitialData: function (option) { + // Disable stack. + option.stack = null; + return PictorialBarSeries.superApply(this, 'getInitialData', arguments); + } + }); + + module.exports = PictorialBarSeries; + + +/***/ }, +/* 289 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var symbolUtil = __webpack_require__(111); + var numberUtil = __webpack_require__(7); + var helper = __webpack_require__(143); + + var parsePercent = numberUtil.parsePercent; + + var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'normal', 'borderWidth']; + + // index: +isHorizontal + var LAYOUT_ATTRS = [ + {xy: 'x', wh: 'width', index: 0, posDesc: ['left', 'right']}, + {xy: 'y', wh: 'height', index: 1, posDesc: ['top', 'bottom']} + ]; + + var pathForLineWidth = new graphic.Circle(); + + var BarView = __webpack_require__(1).extendChartView({ + + type: 'pictorialBar', + + render: function (seriesModel, ecModel, api) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var isHorizontal = !!baseAxis.isHorizontal(); + var coordSysRect = cartesian.grid.getRect(); + + var opt = { + ecSize: {width: api.getWidth(), height: api.getHeight()}, + seriesModel: seriesModel, + coordSys: cartesian, + coordSysExtent: [ + [coordSysRect.x, coordSysRect.x + coordSysRect.width], + [coordSysRect.y, coordSysRect.y + coordSysRect.height] + ], + isHorizontal: isHorizontal, + valueDim: LAYOUT_ATTRS[+isHorizontal], + categoryDim: LAYOUT_ATTRS[1 - isHorizontal] + }; + + data.diff(oldData) + .add(function (dataIndex) { + if (!data.hasValue(dataIndex)) { + return; + } + + var itemModel = getItemModel(data, dataIndex); + var symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt); + + var bar = createBar(data, opt, symbolMeta); + + data.setItemGraphicEl(dataIndex, bar); + group.add(bar); + + updateCommon(bar, opt, symbolMeta); + }) + .update(function (newIndex, oldIndex) { + var bar = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex)) { + group.remove(bar); + return; + } + + var itemModel = getItemModel(data, newIndex); + var symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt); + + var pictorialShapeStr = getShapeStr(data, symbolMeta); + if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) { + group.remove(bar); + data.setItemGraphicEl(newIndex, null); + bar = null; + } + + if (bar) { + updateBar(bar, opt, symbolMeta); + } + else { + bar = createBar(data, opt, symbolMeta, true); + } + + data.setItemGraphicEl(newIndex, bar); + bar.__pictorialSymbolMeta = symbolMeta; + // Add back + group.add(bar); + + updateCommon(bar, opt, symbolMeta); + }) + .remove(function (dataIndex) { + var bar = oldData.getItemGraphicEl(dataIndex); + bar && removeBar(oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar); + }) + .execute(); + + this._data = data; + + return this.group; + }, + + dispose: zrUtil.noop, + + remove: function (ecModel, api) { + var group = this.group; + var data = this._data; + if (ecModel.get('animation')) { + if (data) { + data.eachItemGraphicEl(function (bar) { + removeBar(data, bar.dataIndex, ecModel, bar); + }); + } + } + else { + group.removeAll(); + } + } + }); + + + // Set or calculate default value about symbol, and calculate layout info. + function getSymbolMeta(data, dataIndex, itemModel, opt) { + var layout = data.getItemLayout(dataIndex); + var symbolRepeat = itemModel.get('symbolRepeat'); + var symbolClip = itemModel.get('symbolClip'); + var symbolPosition = itemModel.get('symbolPosition') || 'start'; + var symbolRotate = itemModel.get('symbolRotate'); + var rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + var symbolPatternSize = itemModel.get('symbolPatternSize') || 2; + var isAnimationEnabled = itemModel.isAnimationEnabled(); + + var symbolMeta = { + dataIndex: dataIndex, + layout: layout, + itemModel: itemModel, + symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle', + color: data.getItemVisual(dataIndex, 'color'), + symbolClip: symbolClip, + symbolRepeat: symbolRepeat, + symbolRepeatDirection: itemModel.get('symbolRepeatDirection'), + symbolPatternSize: symbolPatternSize, + rotation: rotation, + animationModel: isAnimationEnabled ? itemModel : null, + hoverAnimation: isAnimationEnabled && itemModel.get('hoverAnimation'), + z2: itemModel.getShallow('z', true) || 0 + }; + + prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta); + + prepareSymbolSize( + data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength, + symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta + ); + + prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta); + + var symbolSize = symbolMeta.symbolSize; + var symbolOffset = itemModel.get('symbolOffset'); + if (zrUtil.isArray(symbolOffset)) { + symbolOffset = [ + parsePercent(symbolOffset[0], symbolSize[0]), + parsePercent(symbolOffset[1], symbolSize[1]) + ]; + } + + prepareLayoutInfo( + itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, + symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength, + opt, symbolMeta + ); + + return symbolMeta; + } + + // bar length can be negative. + function prepareBarLength(itemModel, symbolRepeat, layout, opt, output) { + var valueDim = opt.valueDim; + var symbolBoundingData = itemModel.get('symbolBoundingData'); + var valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis()); + var zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0)); + var pxSignIdx = 1 - +(layout[valueDim.wh] <= 0); + var boundingLength; + + if (zrUtil.isArray(symbolBoundingData)) { + var symbolBoundingExtent = [ + convertToCoordOnAxis(valueAxis, symbolBoundingData[0]) - zeroPx, + convertToCoordOnAxis(valueAxis, symbolBoundingData[1]) - zeroPx + ]; + symbolBoundingExtent[1] < symbolBoundingExtent[0] && (symbolBoundingExtent.reverse()); + boundingLength = symbolBoundingExtent[pxSignIdx]; + } + else if (symbolBoundingData != null) { + boundingLength = convertToCoordOnAxis(valueAxis, symbolBoundingData) - zeroPx; + } + else if (symbolRepeat) { + boundingLength = opt.coordSysExtent[valueDim.index][pxSignIdx] - zeroPx; + } + else { + boundingLength = layout[valueDim.wh]; + } + + output.boundingLength = boundingLength; + + if (symbolRepeat) { + output.repeatCutLength = layout[valueDim.wh]; + } + + output.pxSign = boundingLength > 0 ? 1 : boundingLength < 0 ? -1 : 0; + } + + function convertToCoordOnAxis(axis, value) { + return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value))); + } + + // Support ['100%', '100%'] + function prepareSymbolSize( + data, dataIndex, layout, symbolRepeat, symbolClip, boundingLength, + pxSign, symbolPatternSize, opt, output + ) { + var valueDim = opt.valueDim; + var categoryDim = opt.categoryDim; + var categorySize = Math.abs(layout[categoryDim.wh]); + + var symbolSize = data.getItemVisual(dataIndex, 'symbolSize'); + if (zrUtil.isArray(symbolSize)) { + symbolSize = symbolSize.slice(); + } + else { + if (symbolSize == null) { + symbolSize = '100%'; + } + symbolSize = [symbolSize, symbolSize]; + } + + // Note: percentage symbolSize (like '100%') do not consider lineWidth, because it is + // to complicated to calculate real percent value if considering scaled lineWidth. + // So the actual size will bigger than layout size if lineWidth is bigger than zero, + // which can be tolerated in pictorial chart. + + symbolSize[categoryDim.index] = parsePercent( + symbolSize[categoryDim.index], + categorySize + ); + symbolSize[valueDim.index] = parsePercent( + symbolSize[valueDim.index], + symbolRepeat ? categorySize : Math.abs(boundingLength) + ); + + output.symbolSize = symbolSize; + + // If x or y is less than zero, show reversed shape. + var symbolScale = output.symbolScale = [ + symbolSize[0] / symbolPatternSize, + symbolSize[1] / symbolPatternSize + ]; + // Follow convention, 'right' and 'top' is the normal scale. + symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign; + } + + function prepareLineWidth(itemModel, symbolScale, rotation, opt, output) { + // In symbols are drawn with scale, so do not need to care about the case that width + // or height are too small. But symbol use strokeNoScale, where acture lineWidth should + // be calculated. + var valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; + + if (valueLineWidth) { + pathForLineWidth.attr({ + scale: symbolScale.slice(), + rotation: rotation + }); + pathForLineWidth.updateTransform(); + valueLineWidth /= pathForLineWidth.getLineScale(); + valueLineWidth *= symbolScale[opt.valueDim.index]; + } + + output.valueLineWidth = valueLineWidth; + } + + function prepareLayoutInfo( + itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, + symbolPosition, valueLineWidth, boundingLength, repeatCutLength, opt, output + ) { + var categoryDim = opt.categoryDim; + var valueDim = opt.valueDim; + var pxSign = output.pxSign; + + var unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0); + var pathLen = unitLength; + + // Note: rotation will not effect the layout of symbols, because user may + // want symbols to rotate on its center, which should not be translated + // when rotating. + + if (symbolRepeat) { + var absBoundingLength = Math.abs(boundingLength); + + var symbolMargin = zrUtil.retrieve(itemModel.get('symbolMargin'), '15%') + ''; + var hasEndGap = false; + if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) { + hasEndGap = true; + symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1); + } + symbolMargin = parsePercent(symbolMargin, symbolSize[valueDim.index]); + + var uLenWithMargin = Math.max(unitLength + symbolMargin * 2, 0); + + // When symbol margin is less than 0, margin at both ends will be subtracted + // to ensure that all of the symbols will not be overflow the given area. + var endFix = hasEndGap ? 0 : symbolMargin * 2; + + // Both final repeatTimes and final symbolMargin area calculated based on + // boundingLength. + var repeatSpecified = numberUtil.isNumeric(symbolRepeat); + var repeatTimes = repeatSpecified + ? symbolRepeat + : toIntTimes((absBoundingLength + endFix) / uLenWithMargin); + + // Adjust calculate margin, to ensure each symbol is displayed + // entirely in the given layout area. + var mDiff = absBoundingLength - repeatTimes * unitLength; + symbolMargin = mDiff / 2 / (hasEndGap ? repeatTimes : repeatTimes - 1); + uLenWithMargin = unitLength + symbolMargin * 2; + endFix = hasEndGap ? 0 : symbolMargin * 2; + + // Update repeatTimes when not all symbol will be shown. + if (!repeatSpecified && symbolRepeat !== 'fixed') { + repeatTimes = repeatCutLength + ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin) + : 0; + } + + pathLen = repeatTimes * uLenWithMargin - endFix; + output.repeatTimes = repeatTimes; + output.symbolMargin = symbolMargin; + } + + var sizeFix = pxSign * (pathLen / 2); + var pathPosition = output.pathPosition = []; + pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2; + pathPosition[valueDim.index] = symbolPosition === 'start' + ? sizeFix + : symbolPosition === 'end' + ? boundingLength - sizeFix + : boundingLength / 2; // 'center' + if (symbolOffset) { + pathPosition[0] += symbolOffset[0]; + pathPosition[1] += symbolOffset[1]; + } + + var bundlePosition = output.bundlePosition = []; + bundlePosition[categoryDim.index] = layout[categoryDim.xy]; + bundlePosition[valueDim.index] = layout[valueDim.xy]; + + var barRectShape = output.barRectShape = zrUtil.extend({}, layout); + barRectShape[valueDim.wh] = pxSign * Math.max( + Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix) + ); + barRectShape[categoryDim.wh] = layout[categoryDim.wh]; + + var clipShape = output.clipShape = {}; + // Consider that symbol may be overflow layout rect. + clipShape[categoryDim.xy] = -layout[categoryDim.xy]; + clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh]; + clipShape[valueDim.xy] = 0; + clipShape[valueDim.wh] = layout[valueDim.wh]; + } + + function createPath(symbolMeta) { + var symbolPatternSize = symbolMeta.symbolPatternSize; + var path = symbolUtil.createSymbol( + // Consider texture img, make a big size. + symbolMeta.symbolType, + -symbolPatternSize / 2, + -symbolPatternSize / 2, + symbolPatternSize, + symbolPatternSize, + symbolMeta.color + ); + path.attr({ + culling: true + }); + path.type !== 'image' && path.setStyle({ + strokeNoScale: true + }); + + return path; + } + + function createOrUpdateRepeatSymbols(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var symbolSize = symbolMeta.symbolSize; + var valueLineWidth = symbolMeta.valueLineWidth; + var pathPosition = symbolMeta.pathPosition; + var valueDim = opt.valueDim; + var repeatTimes = symbolMeta.repeatTimes || 0; + + var index = 0; + var unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2; + + eachPath(bar, function (path) { + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + if (index < repeatTimes) { + updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate); + } + else { + updateAttr(path, null, {scale: [0, 0]}, symbolMeta, isUpdate, function () { + bundle.remove(path); + }); + } + + updateHoverAnimation(path, symbolMeta); + + index++; + }); + + for (; index < repeatTimes; index++) { + var path = createPath(symbolMeta); + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + bundle.add(path); + + var target = makeTarget(index, true); + + updateAttr( + path, + { + position: target.position, + scale: [0, 0] + }, + { + scale: target.scale, + rotation: target.rotation + }, + symbolMeta, + isUpdate + ); + + // FIXME + // If all emphasis/normal through action. + path + .on('mouseover', onMouseOver) + .on('mouseout', onMouseOut); + + updateHoverAnimation(path, symbolMeta); + } + + function makeTarget(index) { + var position = pathPosition.slice(); + // (start && pxSign > 0) || (end && pxSign < 0): i = repeatTimes - index + // Otherwise: i = index; + var pxSign = symbolMeta.pxSign; + var i = index; + if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) { + i = repeatTimes - 1 - index; + } + position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index]; + + return { + position: position, + scale: symbolMeta.symbolScale.slice(), + rotation: symbolMeta.rotation + }; + } + + function onMouseOver() { + eachPath(bar, function (path) { + path.trigger('emphasis'); + }); + } + + function onMouseOut() { + eachPath(bar, function (path) { + path.trigger('normal'); + }); + } + } + + function createOrUpdateSingleSymbol(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var mainPath = bar.__pictorialMainPath; + + if (!mainPath) { + mainPath = bar.__pictorialMainPath = createPath(symbolMeta); + bundle.add(mainPath); + + updateAttr( + mainPath, + { + position: symbolMeta.pathPosition.slice(), + scale: [0, 0], + rotation: symbolMeta.rotation + }, + { + scale: symbolMeta.symbolScale.slice() + }, + symbolMeta, + isUpdate + ); + + mainPath + .on('mouseover', onMouseOver) + .on('mouseout', onMouseOut); + } + else { + updateAttr( + mainPath, + null, + { + position: symbolMeta.pathPosition.slice(), + scale: symbolMeta.symbolScale.slice(), + rotation: symbolMeta.rotation + }, + symbolMeta, + isUpdate + ); + } + + updateHoverAnimation(mainPath, symbolMeta); + + function onMouseOver() { + this.trigger('emphasis'); + } + + function onMouseOut() { + this.trigger('normal'); + } + } + + // bar rect is used for label. + function createOrUpdateBarRect(bar, symbolMeta, isUpdate) { + var rectShape = zrUtil.extend({}, symbolMeta.barRectShape); + + var barRect = bar.__pictorialBarRect; + if (!barRect) { + barRect = bar.__pictorialBarRect = new graphic.Rect({ + z2: 2, + shape: rectShape, + silent: true, + style: { + stroke: 'transparent', + fill: 'transparent', + lineWidth: 0 + } + }); + + bar.add(barRect); + } + else { + updateAttr(barRect, null, {shape: rectShape}, symbolMeta, isUpdate); + } + } + + function createOrUpdateClip(bar, opt, symbolMeta, isUpdate) { + // If not clip, symbol will be remove and rebuilt. + if (symbolMeta.symbolClip) { + var clipPath = bar.__pictorialClipPath; + var clipShape = zrUtil.extend({}, symbolMeta.clipShape); + var valueDim = opt.valueDim; + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + + if (clipPath) { + graphic.updateProps( + clipPath, {shape: clipShape}, animationModel, dataIndex + ); + } + else { + clipShape[valueDim.wh] = 0; + clipPath = new graphic.Rect({shape: clipShape}); + bar.__pictorialBundle.setClipPath(clipPath); + bar.__pictorialClipPath = clipPath; + + var target = {}; + target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh]; + + graphic[isUpdate ? 'updateProps' : 'initProps']( + clipPath, {shape: target}, animationModel, dataIndex + ); + } + } + } + + function getItemModel(data, dataIndex) { + var itemModel = data.getItemModel(dataIndex); + itemModel.getAnimationDelayParams = getAnimationDelayParams; + itemModel.isAnimationEnabled = isAnimationEnabled; + return itemModel; + } + + function getAnimationDelayParams(path) { + // The order is the same as the z-order, see `symbolRepeatDiretion`. + return { + index: path.__pictorialAnimationIndex, + count: path.__pictorialRepeatTimes + }; + } + + function isAnimationEnabled() { + // `animation` prop can be set on itemModel in pictorial bar chart. + return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation'); + } + + function updateHoverAnimation(path, symbolMeta) { + path.off('emphasis').off('normal'); + + var scale = symbolMeta.symbolScale.slice(); + + symbolMeta.hoverAnimation && path + .on('emphasis', function() { + this.animateTo({ + scale: [scale[0] * 1.1, scale[1] * 1.1] + }, 400, 'elasticOut'); + }) + .on('normal', function() { + this.animateTo({ + scale: scale.slice() + }, 400, 'elasticOut'); + }); + } + + function createBar(data, opt, symbolMeta, isUpdate) { + // bar is the main element for each data. + var bar = new graphic.Group(); + // bundle is used for location and clip. + var bundle = new graphic.Group(); + bar.add(bundle); + bar.__pictorialBundle = bundle; + bundle.attr('position', symbolMeta.bundlePosition.slice()); + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta); + } + else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta); + } + + createOrUpdateBarRect(bar, symbolMeta, isUpdate); + + createOrUpdateClip(bar, opt, symbolMeta, isUpdate); + + bar.__pictorialShapeStr = getShapeStr(data, symbolMeta); + bar.__pictorialSymbolMeta = symbolMeta; + + return bar; + } + + function updateBar(bar, opt, symbolMeta) { + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + var bundle = bar.__pictorialBundle; + + graphic.updateProps( + bundle, {position: symbolMeta.bundlePosition.slice()}, animationModel, dataIndex + ); + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true); + } + else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta, true); + } + + createOrUpdateBarRect(bar, symbolMeta, true); + + createOrUpdateClip(bar, opt, symbolMeta, true); + } + + function removeBar(data, dataIndex, animationModel, bar) { + // Not show text when animating + var labelRect = bar.__pictorialBarRect; + labelRect && (labelRect.style.text = ''); + + var pathes = []; + eachPath(bar, function (path) { + pathes.push(path); + }); + bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath); + + // I do not find proper remove animation for clip yet. + bar.__pictorialClipPath && (animationModel = null); + + zrUtil.each(pathes, function (path) { + graphic.updateProps( + path, {scale: [0, 0]}, animationModel, dataIndex, + function () { + bar.parent && bar.parent.remove(bar); + } + ); + }); + + data.setItemGraphicEl(dataIndex, null); + } + + function getShapeStr(data, symbolMeta) { + return [ + data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none', + !!symbolMeta.symbolRepeat, + !!symbolMeta.symbolClip + ].join(':'); + } + + function eachPath(bar, cb, context) { + // Do not use Group#eachChild, because it do not support remove. + zrUtil.each(bar.__pictorialBundle.children(), function (el) { + el !== bar.__pictorialBarRect && cb.call(context, el); + }); + } + + function updateAttr(el, immediateAttrs, animationAttrs, symbolMeta, isUpdate, cb) { + immediateAttrs && el.attr(immediateAttrs); + // when symbolCip used, only clip path has init animation, otherwise it would be weird effect. + if (symbolMeta.symbolClip && !isUpdate) { + animationAttrs && el.attr(animationAttrs); + } + else { + animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps']( + el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb + ); + } + } + + function updateCommon(bar, opt, symbolMeta) { + var color = symbolMeta.color; + var dataIndex = symbolMeta.dataIndex; + var itemModel = symbolMeta.itemModel; + // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + var normalStyle = itemModel.getModel('itemStyle.normal').getItemStyle(['color']); + var hoverStyle = itemModel.getModel('itemStyle.emphasis').getItemStyle(); + var cursorStyle = itemModel.getShallow('cursor'); + + eachPath(bar, function (path) { + // PENDING setColor should be before setStyle!!! + path.setColor(color); + path.setStyle(zrUtil.defaults( + { + fill: color, + opacity: symbolMeta.opacity + }, + normalStyle + )); + graphic.setHoverStyle(path, hoverStyle); + + cursorStyle && (path.cursor = cursorStyle); + path.z2 = symbolMeta.z2; + }); + + var barRectHoverStyle = {}; + var barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)]; + var barRect = bar.__pictorialBarRect; + + helper.setLabel( + barRect.style, barRectHoverStyle, itemModel, + color, opt.seriesModel, dataIndex, barPositionOutside + ); + + graphic.setHoverStyle(barRect, barRectHoverStyle); + } + + function toIntTimes(times) { + var roundedTimes = Math.round(times); + // Escapse accurate error + return Math.abs(times - roundedTimes) < 1e-4 + ? roundedTimes + : Math.ceil(times); + } + + module.exports = BarView; + + +/***/ }, +/* 290 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + + __webpack_require__(291); + + __webpack_require__(308); + + __webpack_require__(309); + + echarts.registerLayout(__webpack_require__(311)); + + echarts.registerVisual(__webpack_require__(312)); + + echarts.registerProcessor( + zrUtil.curry(__webpack_require__(154), 'themeRiver') + ); + + +/***/ }, +/* 291 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(292); + __webpack_require__(295); + __webpack_require__(297); + __webpack_require__(298); + + __webpack_require__(307); + + var echarts = __webpack_require__(1); + + echarts.extendComponentView({ + type: 'single' + }); + + + +/***/ }, +/* 292 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Single coordinate system creator. + */ + + + var Single = __webpack_require__(293); + + /** + * Create single coordinate system and inject it into seriesModel. + * + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @return {Array.} + */ + function create(ecModel, api) { + var singles = []; + + ecModel.eachComponent('singleAxis', function(axisModel, idx) { + + var single = new Single(axisModel, ecModel, api); + single.name = 'single_' + idx; + single.resize(axisModel, api); + axisModel.coordinateSystem = single; + singles.push(single); + + }); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'singleAxis') { + var singleAxisModel = ecModel.queryComponents({ + mainType: 'singleAxis', + index: seriesModel.get('singleAxisIndex'), + id: seriesModel.get('singleAxisId') + })[0]; + seriesModel.coordinateSystem = singleAxisModel && singleAxisModel.coordinateSystem; + } + }); + + return singles; + } + + __webpack_require__(76).register('single', { + create: create, + dimensions: Single.prototype.dimensions + }); + + +/***/ }, +/* 293 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Single coordinates system. + */ + + + var SingleAxis = __webpack_require__(294); + var axisHelper = __webpack_require__(101); + var layout = __webpack_require__(71); + + /** + * Create a single coordinates system. + * + * @param {module:echarts/coord/single/AxisModel} axisModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + function Single(axisModel, ecModel, api) { + + /** + * @type {string} + * @readOnly + */ + this.dimension = 'single'; + + /** + * Add it just for draw tooltip. + * + * @type {Array.} + * @readOnly + */ + this.dimensions = ['single']; + + /** + * @private + * @type {module:echarts/coord/single/SingleAxis}. + */ + this._axis = null; + + /** + * @private + * @type {module:zrender/core/BoundingRect} + */ + this._rect; + + this._init(axisModel, ecModel, api); + + /** + * @type {module:echarts/coord/single/AxisModel} + */ + this.model = axisModel; + } + + Single.prototype = { + + type: 'singleAxis', + + axisPointerEnabled: true, + + constructor: Single, + + /** + * Initialize single coordinate system. + * + * @param {module:echarts/coord/single/AxisModel} axisModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @private + */ + _init: function (axisModel, ecModel, api) { + + var dim = this.dimension; + + var axis = new SingleAxis( + dim, + axisHelper.createScaleByModel(axisModel), + [0, 0], + axisModel.get('type'), + axisModel.get('position') + ); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + axis.orient = axisModel.get('orient'); + + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = this; + this._axis = axis; + }, + + /** + * Update axis scale after data processed + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + update: function (ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === this) { + var data = seriesModel.getData(); + var dim = this.dimension; + this._axis.scale.unionExtentFromData( + data, seriesModel.coordDimToDataDim(dim) + ); + axisHelper.niceScaleExtent(this._axis.scale, this._axis.model); + } + }, this); + }, + + /** + * Resize the single coordinate system. + * + * @param {module:echarts/coord/single/AxisModel} axisModel + * @param {module:echarts/ExtensionAPI} api + */ + resize: function (axisModel, api) { + this._rect = layout.getLayoutRect( + { + left: axisModel.get('left'), + top: axisModel.get('top'), + right: axisModel.get('right'), + bottom: axisModel.get('bottom'), + width: axisModel.get('width'), + height: axisModel.get('height') + }, + { + width: api.getWidth(), + height: api.getHeight() + } + ); + + this._adjustAxis(); + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getRect: function () { + return this._rect; + }, + + /** + * @private + */ + _adjustAxis: function () { + + var rect = this._rect; + var axis = this._axis; + + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, rect.width] : [0, rect.height]; + var idx = axis.reverse ? 1 : 0; + + axis.setExtent(extent[idx], extent[1 - idx]); + + this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y); + + }, + + /** + * @param {module:echarts/coord/single/SingleAxis} axis + * @param {number} coordBase + */ + _updateAxisTransform: function (axis, coordBase) { + + var axisExtent = axis.getExtent(); + var extentSum = axisExtent[0] + axisExtent[1]; + var isHorizontal = axis.isHorizontal(); + + axis.toGlobalCoord = isHorizontal + ? function (coord) { + return coord + coordBase; + } + : function (coord) { + return extentSum - coord + coordBase; + }; + + axis.toLocalCoord = isHorizontal + ? function (coord) { + return coord - coordBase; + } + : function (coord) { + return extentSum - coord + coordBase; + }; + }, + + /** + * Get axis. + * + * @return {module:echarts/coord/single/SingleAxis} + */ + getAxis: function () { + return this._axis; + }, + + /** + * Get axis, add it just for draw tooltip. + * + * @return {[type]} [description] + */ + getBaseAxis: function () { + return this._axis; + }, + + /** + * @return {Array.} + */ + getAxes: function () { + return [this._axis]; + }, + + /** + * @return {Object} {baseAxes: [], otherAxes: []} + */ + getTooltipAxes: function () { + return {baseAxes: [this.getAxis()]}; + }, + + /** + * If contain point. + * + * @param {Array.} point + * @return {boolean} + */ + containPoint: function (point) { + var rect = this.getRect(); + var axis = this.getAxis(); + var orient = axis.orient; + if (orient === 'horizontal') { + return axis.contain(axis.toLocalCoord(point[0])) + && (point[1] >= rect.y && point[1] <= (rect.y + rect.height)); + } + else { + return axis.contain(axis.toLocalCoord(point[1])) + && (point[0] >= rect.y && point[0] <= (rect.y + rect.height)); + } + }, + + /** + * @param {Array.} point + * @return {Array.} + */ + pointToData: function (point) { + var axis = this.getAxis(); + return [axis.coordToData(axis.toLocalCoord( + point[axis.orient === 'horizontal' ? 0 : 1] + ))]; + }, + + /** + * Convert the series data to concrete point. + * + * @param {number|Array.} val + * @return {Array.} + */ + dataToPoint: function (val) { + var axis = this.getAxis(); + var rect = this.getRect(); + var pt = []; + var idx = axis.orient === 'horizontal' ? 0 : 1; + + if (val instanceof Array) { + val = val[0]; + } + + pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val)); + pt[1 - idx] = idx === 0 ? (rect.y + rect.height / 2) : (rect.x + rect.width / 2); + return pt; + } + + }; + + module.exports = Single; + + + +/***/ }, +/* 294 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var Axis = __webpack_require__(100); + + /** + * @constructor module:echarts/coord/single/SingleAxis + * @extends {module:echarts/coord/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + * @param {string} position + */ + var SingleAxis = function (dim, scale, coordExtent, axisType, position) { + + Axis.call(this, dim, scale, coordExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * Axis position + * - 'top' + * - 'bottom' + * - 'left' + * - 'right' + * @type {string} + */ + this.position = position || 'bottom'; + + /** + * Axis orient + * - 'horizontal' + * - 'vertical' + * @type {[type]} + */ + this.orient = null; + + /** + * @type {number} + */ + this._labelInterval = null; + + }; + + SingleAxis.prototype = { + + constructor: SingleAxis, + + /** + * Axis model + * @type {module:echarts/coord/single/AxisModel} + */ + model: null, + + /** + * Judge the orient of the axis. + * @return {boolean} + */ + isHorizontal: function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + + }, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.coordinateSystem.pointToData(point, clamp)[0]; + }, + + /** + * Convert the local coord(processed by dataToCoord()) + * to global coord(concrete pixel coord). + * designated by module:echarts/coord/single/Single. + * @type {Function} + */ + toGlobalCoord: null, + + /** + * Convert the global coord to local coord. + * designated by module:echarts/coord/single/Single. + * @type {Function} + */ + toLocalCoord: null + + }; + + zrUtil.inherits(SingleAxis, Axis); + + module.exports = SingleAxis; + + +/***/ }, +/* 295 */ +/***/ function(module, exports, __webpack_require__) { + + + + var AxisBuilder = __webpack_require__(135); + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var singleAxisHelper = __webpack_require__(296); + var getInterval = AxisBuilder.getInterval; + var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick; + + var axisBuilderAttrs = [ + 'axisLine', 'axisLabel', 'axisTick', 'axisName' + ]; + + var selfBuilderAttr = 'splitLine'; + + var SingleAxisView = __webpack_require__(136).extend({ + + type: 'singleAxis', + + axisPointerClass: 'SingleAxisPointer', + + render: function (axisModel, ecModel, api, payload) { + + var group = this.group; + + group.removeAll(); + + var layout = singleAxisHelper.layout(axisModel); + + var axisBuilder = new AxisBuilder(axisModel, layout); + + zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder); + + group.add(axisBuilder.getGroup()); + + if (axisModel.get(selfBuilderAttr + '.show')) { + this['_' + selfBuilderAttr](axisModel, layout.labelInterval); + } + + SingleAxisView.superCall(this, 'render', axisModel, ecModel, api, payload); + }, + + _splitLine: function(axisModel, labelInterval) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineWidth = lineStyleModel.get('width'); + var lineColors = lineStyleModel.get('color'); + var lineInterval = getInterval(splitLineModel, labelInterval); + + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + + var gridRect = axisModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + + var splitLines = []; + var lineCount = 0; + + var ticksCoords = axis.getTicksCoords(); + + var p1 = []; + var p2 = []; + + for (var i = 0; i < ticksCoords.length; ++i) { + if (ifIgnoreOnTick(axis, i, lineInterval)) { + continue; + } + var tickCoord = axis.toGlobalCoord(ticksCoords[i]); + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } + else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + var colorIndex = (lineCount++) % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new graphic.Line( + graphic.subPixelOptimizeLine({ + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: { + lineWidth: lineWidth + }, + silent: true + }))); + } + + for (var i = 0; i < splitLines.length; ++i) { + this.group.add(graphic.mergePath(splitLines[i], { + style: { + stroke: lineColors[i % lineColors.length], + lineDash: lineStyleModel.getLineDash(lineWidth), + lineWidth: lineWidth + }, + silent: true + })); + } + } + }); + + module.exports = SingleAxisView; + + + +/***/ }, +/* 296 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + var helper = {}; + + /** + * @param {Object} opt {labelInside} + * @return {Object} { + * position, rotation, labelDirection, labelOffset, + * tickDirection, labelRotate, labelInterval, z2 + * } + */ + helper.layout = function (axisModel, opt) { + opt = opt || {}; + var single = axisModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + + var axisPosition = axis.position; + var orient = axis.orient; + + var rect = single.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + + var positionMap = { + horizontal: {top: rectBound[2], bottom: rectBound[3]}, + vertical: {left: rectBound[0], right: rectBound[1]} + }; + + layout.position = [ + orient === 'vertical' + ? positionMap.vertical[axisPosition] + : rectBound[0], + orient === 'horizontal' + ? positionMap.horizontal[axisPosition] + : rectBound[3] + ]; + + var r = {horizontal: 0, vertical: 1}; + layout.rotation = Math.PI / 2 * r[orient]; + + var directionMap = {top: -1, bottom: 1, right: 1, left: -1}; + + layout.labelDirection = layout.tickDirection + = layout.nameDirection + = directionMap[axisPosition]; + + if (axisModel.get('axisTick.inside')) { + layout.tickDirection = -layout.tickDirection; + } + + if (zrUtil.retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) { + layout.labelDirection = -layout.labelDirection; + } + + var labelRotation = opt.rotate; + labelRotation == null && (labelRotation = axisModel.get('axisLabel.rotate')); + layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation; + + layout.labelInterval = axis.getLabelInterval(); + + layout.z2 = 1; + + return layout; + }; + + module.exports = helper; + + + +/***/ }, +/* 297 */ +/***/ function(module, exports, __webpack_require__) { + + + + var ComponentModel = __webpack_require__(69); + var axisModelCreator = __webpack_require__(131); + var zrUtil = __webpack_require__(4); + + var AxisModel = ComponentModel.extend({ + + type: 'singleAxis', + + layoutMode: 'box', + + /** + * @type {module:echarts/coord/single/SingleAxis} + */ + axis: null, + + /** + * @type {module:echarts/coord/single/Single} + */ + coordinateSystem: null, + + /** + * @override + */ + getCoordSysModel: function () { + return this; + } + + }); + + var defaultOption = { + + left: '5%', + top: '5%', + right: '5%', + bottom: '5%', + + type: 'value', + + position: 'bottom', + + orient: 'horizontal', + + axisLine: { + show: true, + lineStyle: { + width: 2, + type: 'solid' + } + }, + + // Single coordinate system and single axis is the, + // which is used as the parent tooltip model. + // same model, so we set default tooltip show as true. + tooltip: { + show: true + }, + + axisTick: { + show: true, + length: 6, + lineStyle: { + width: 2 + } + }, + + axisLabel: { + show: true, + interval: 'auto' + }, + + splitLine: { + show: true, + lineStyle: { + type: 'dashed', + opacity: 0.2 + } + } + }; + + function getAxisType(axisName, option) { + return option.type || (option.data ? 'category' : 'value'); + } + + zrUtil.merge(AxisModel.prototype, __webpack_require__(112)); + + axisModelCreator('single', AxisModel, getAxisType, defaultOption); + + module.exports = AxisModel; + + +/***/ }, +/* 298 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + var axisPointerModelHelper = __webpack_require__(137); + var axisTrigger = __webpack_require__(299); + var zrUtil = __webpack_require__(4); + + __webpack_require__(301); + __webpack_require__(302); + + // CartesianAxisPointer is not supposed to be required here. But consider + // echarts.simple.js and online build tooltip, which only require gridSimple, + // CartesianAxisPointer should be able to required somewhere. + __webpack_require__(304); + + echarts.registerPreprocessor(function (option) { + // Always has a global axisPointerModel for default setting. + if (option) { + (!option.axisPointer || option.axisPointer.length === 0) + && (option.axisPointer = {}); + + var link = option.axisPointer.link; + // Normalize to array to avoid object mergin. But if link + // is not set, remain null/undefined, otherwise it will + // override existent link setting. + if (link && !zrUtil.isArray(link)) { + option.axisPointer.link = [link]; + } + } + }); + + // This process should proformed after coordinate systems created + // and series data processed. So put it on statistic processing stage. + echarts.registerProcessor(echarts.PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) { + // Build axisPointerModel, mergin tooltip.axisPointer model for each axis. + // allAxesInfo should be updated when setOption performed. + ecModel.getComponent('axisPointer').coordSysAxesInfo + = axisPointerModelHelper.collect(ecModel, api); + }); + + // Broadcast to all views. + echarts.registerAction({ + type: 'updateAxisPointer', + event: 'updateAxisPointer', + update: ':updateAxisPointer' + }, axisTrigger); + + + +/***/ }, +/* 299 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var modelHelper = __webpack_require__(137); + var findPointFromSeries = __webpack_require__(300); + + var each = zrUtil.each; + var curry = zrUtil.curry; + var get = modelUtil.makeGetter(); + + /** + * Basic logic: check all axis, if they do not demand show/highlight, + * then hide/downplay them. + * + * @param {Object} coordSysAxesInfo + * @param {Object} payload + * @param {string} [payload.currTrigger] 'click' | 'mousemove' | 'leave' + * @param {Array.} [payload.x] x and y, which are mandatory, specify a point to + * trigger axisPointer and tooltip. + * @param {Array.} [payload.y] x and y, which are mandatory, specify a point to + * trigger axisPointer and tooltip. + * @param {Object} [payload.seriesIndex] finder, optional, restrict target axes. + * @param {Object} [payload.dataIndex] finder, restrict target axes. + * @param {Object} [payload.axesInfo] finder, restrict target axes. + * [{ + * axisDim: 'x'|'y'|'angle'|..., + * axisIndex: ..., + * value: ... + * }, ...] + * @param {Function} [payload.dispatchAction] + * @param {Object} [payload.tooltipOption] + * @param {Object|Array.|Function} [payload.position] Tooltip position, + * which can be specified in dispatchAction + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @return {Object} content of event obj for echarts.connect. + */ + function axisTrigger(payload, ecModel, api) { + var currTrigger = payload.currTrigger; + var point = [payload.x, payload.y]; + var finder = payload; + var dispatchAction = payload.dispatchAction || zrUtil.bind(api.dispatchAction, api); + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; + + if (illegalPoint(point)) { + // Used in the default behavior of `connection`: use the sample seriesIndex + // and dataIndex. And also used in the tooltipView trigger. + point = findPointFromSeries({ + seriesIndex: finder.seriesIndex, + // Do not use dataIndexInside from other ec instance. + // FIXME: auto detect it? + dataIndex: finder.dataIndex + }, ecModel).point; + } + var isIllegalPoint = illegalPoint(point); + + // Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}). + // Notice: In this case, it is difficult to get the `point` (which is necessary to show + // tooltip, so if point is not given, we just use the point found by sample seriesIndex + // and dataIndex. + var inputAxesInfo = finder.axesInfo; + + var axesInfo = coordSysAxesInfo.axesInfo; + var shouldHide = currTrigger === 'leave' || illegalPoint(point); + var outputFinder = {}; + + var showValueMap = {}; + var dataByCoordSys = {list: [], map: {}}; + var updaters = { + showPointer: curry(showPointer, showValueMap), + showTooltip: curry(showTooltip, dataByCoordSys) + }; + + // Process for triggered axes. + each(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) { + // If a point given, it must be contained by the coordinate system. + var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point); + + each(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) { + var axis = axisInfo.axis; + var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo); + // If no inputAxesInfo, no axis is restricted. + if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) { + var val = inputAxisInfo && inputAxisInfo.value; + if (val == null && !isIllegalPoint) { + val = axis.pointToData(point); + } + val != null && processOnAxis(axisInfo, val, updaters, false, outputFinder); + } + }); + }); + + // Process for linked axes. + var linkTriggers = {}; + each(axesInfo, function (tarAxisInfo, tarKey) { + var linkGroup = tarAxisInfo.linkGroup; + + // If axis has been triggered in the previous stage, it should not be triggered by link. + if (linkGroup && !showValueMap[tarKey]) { + each(linkGroup.axesInfo, function (srcAxisInfo, srcKey) { + var srcValItem = showValueMap[srcKey]; + // If srcValItem exist, source axis is triggered, so link to target axis. + if (srcAxisInfo !== tarAxisInfo && srcValItem) { + var val = srcValItem.value; + linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper( + val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo) + ))); + linkTriggers[tarAxisInfo.key] = val; + } + }); + } + }); + each(linkTriggers, function (val, tarKey) { + processOnAxis(axesInfo[tarKey], val, updaters, true, outputFinder); + }); + + updateModelActually(showValueMap, axesInfo, outputFinder); + dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction); + dispatchHighDownActually(axesInfo, dispatchAction, api); + + return outputFinder; + } + + function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) { + var axis = axisInfo.axis; + + if (axis.scale.isBlank() || !axis.containData(newValue)) { + return; + } + + if (!axisInfo.involveSeries) { + updaters.showPointer(axisInfo, newValue); + return; + } + + // Heavy calculation. So put it after axis.containData checking. + var payloadInfo = buildPayloadsBySeries(newValue, axisInfo); + var payloadBatch = payloadInfo.payloadBatch; + var snapToValue = payloadInfo.snapToValue; + + // Fill content of event obj for echarts.connect. + // By defualt use the first involved series data as a sample to connect. + if (payloadBatch[0] && outputFinder.seriesIndex == null) { + zrUtil.extend(outputFinder, payloadBatch[0]); + } + + // If no linkSource input, this process is for collecting link + // target, where snap should not be accepted. + if (!dontSnap && axisInfo.snap) { + if (axis.containData(snapToValue) && snapToValue != null) { + newValue = snapToValue; + } + } + + updaters.showPointer(axisInfo, newValue, payloadBatch, outputFinder); + // Tooltip should always be snapToValue, otherwise there will be + // incorrect "axis value ~ series value" mapping displayed in tooltip. + updaters.showTooltip(axisInfo, payloadInfo, snapToValue); + } + + function buildPayloadsBySeries(value, axisInfo) { + var axis = axisInfo.axis; + var dim = axis.dim; + var snapToValue = value; + var payloadBatch = []; + var minDist = Number.MAX_VALUE; + var minDiff = -1; + + each(axisInfo.seriesModels, function (series, idx) { + var dataDim = series.coordDimToDataDim(dim); + var seriesNestestValue; + var dataIndices; + + if (series.getAxisTooltipData) { + var result = series.getAxisTooltipData(dataDim, value, axis); + dataIndices = result.dataIndices; + seriesNestestValue = result.nestestValue; + } + else { + dataIndices = series.getData().indicesOfNearest( + dataDim[0], + value, + // Add a threshold to avoid find the wrong dataIndex + // when data length is not same. + false, axis.type === 'category' ? 0.5 : null + ); + if (!dataIndices.length) { + return; + } + seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]); + } + + if (seriesNestestValue == null || !isFinite(seriesNestestValue)) { + return; + } + + var diff = value - seriesNestestValue; + var dist = Math.abs(diff); + // Consider category case + if (dist <= minDist) { + if (dist < minDist || (diff >= 0 && minDiff < 0)) { + minDist = dist; + minDiff = diff; + snapToValue = seriesNestestValue; + payloadBatch.length = 0; + } + each(dataIndices, function (dataIndex) { + payloadBatch.push({ + seriesIndex: series.seriesIndex, + dataIndexInside: dataIndex, + dataIndex: series.getData().getRawIndex(dataIndex) + }); + }); + } + }); + + return { + payloadBatch: payloadBatch, + snapToValue: snapToValue + }; + } + + function showPointer(showValueMap, axisInfo, value, payloadBatch) { + showValueMap[axisInfo.key] = {value: value, payloadBatch: payloadBatch}; + } + + function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) { + var payloadBatch = payloadInfo.payloadBatch; + var axis = axisInfo.axis; + var axisModel = axis.model; + var axisPointerModel = axisInfo.axisPointerModel; + + // If no data, do not create anything in dataByCoordSys, + // whose length will be used to judge whether dispatch action. + if (!axisInfo.triggerTooltip || !payloadBatch.length) { + return; + } + + var coordSysModel = axisInfo.coordSys.model; + var coordSysKey = modelHelper.makeKey(coordSysModel); + var coordSysItem = dataByCoordSys.map[coordSysKey]; + if (!coordSysItem) { + coordSysItem = dataByCoordSys.map[coordSysKey] = { + coordSysId: coordSysModel.id, + coordSysIndex: coordSysModel.componentIndex, + coordSysType: coordSysModel.type, + coordSysMainType: coordSysModel.mainType, + dataByAxis: [] + }; + dataByCoordSys.list.push(coordSysItem); + } + + coordSysItem.dataByAxis.push({ + axisDim: axis.dim, + axisIndex: axisModel.componentIndex, + axisType: axisModel.type, + axisId: axisModel.id, + value: value, + // Caustion: viewHelper.getValueLabel is actually on "view stage", which + // depends that all models have been updated. So it should not be performed + // here. Considering axisPointerModel used here is volatile, which is hard + // to be retrieve in TooltipView, we prepare parameters here. + valueLabelOpt: { + precision: axisPointerModel.get('label.precision'), + formatter: axisPointerModel.get('label.formatter') + }, + seriesDataIndices: payloadBatch.slice() + }); + } + + function updateModelActually(showValueMap, axesInfo, outputFinder) { + var outputAxesInfo = outputFinder.axesInfo = []; + // Basic logic: If no 'show' required, 'hide' this axisPointer. + each(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + var valItem = showValueMap[key]; + + if (valItem) { + !axisInfo.useHandle && (option.status = 'show'); + option.value = valItem.value; + // For label formatter param and highlight. + option.seriesDataIndices = (valItem.payloadBatch || []).slice(); + } + // When always show (e.g., handle used), remain + // original value and status. + else { + // If hide, value still need to be set, consider + // click legend to toggle axis blank. + !axisInfo.useHandle && (option.status = 'hide'); + } + + // If status is 'hide', should be no info in payload. + option.status === 'show' && outputAxesInfo.push({ + axisDim: axisInfo.axis.dim, + axisIndex: axisInfo.axis.model.componentIndex, + value: option.value + }); + }); + } + + function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) { + // Basic logic: If no showTip required, hideTip will be dispatched. + if (illegalPoint(point) || !dataByCoordSys.list.length) { + dispatchAction({type: 'hideTip'}); + return; + } + + // In most case only one axis (or event one series is used). It is + // convinient to fetch payload.seriesIndex and payload.dataIndex + // dirtectly. So put the first seriesIndex and dataIndex of the first + // axis on the payload. + var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {}; + + dispatchAction({ + type: 'showTip', + escapeConnect: true, + x: point[0], + y: point[1], + tooltipOption: payload.tooltipOption, + position: payload.position, + dataIndexInside: sampleItem.dataIndexInside, + dataIndex: sampleItem.dataIndex, + seriesIndex: sampleItem.seriesIndex, + dataByCoordSys: dataByCoordSys.list + }); + } + + function dispatchHighDownActually(axesInfo, dispatchAction, api) { + // FIXME + // highlight status modification shoule be a stage of main process? + // (Consider confilct (e.g., legend and axisPointer) and setOption) + + var zr = api.getZr(); + var highDownKey = 'axisPointerLastHighlights'; + var lastHighlights = get(zr)[highDownKey] || {}; + var newHighlights = get(zr)[highDownKey] = {}; + + // Update highlight/downplay status according to axisPointer model. + // Build hash map and remove duplicate incidentally. + each(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + option.status === 'show' && each(option.seriesDataIndices, function (batchItem) { + var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex; + newHighlights[key] = batchItem; + }); + }); + + // Diff. + var toHighlight = []; + var toDownplay = []; + zrUtil.each(lastHighlights, function (batchItem, key) { + !newHighlights[key] && toDownplay.push(batchItem); + }); + zrUtil.each(newHighlights, function (batchItem, key) { + !lastHighlights[key] && toHighlight.push(batchItem); + }); + + toDownplay.length && api.dispatchAction({ + type: 'downplay', escapeConnect: true, batch: toDownplay + }); + toHighlight.length && api.dispatchAction({ + type: 'highlight', escapeConnect: true, batch: toHighlight + }); + } + + function findInputAxisInfo(inputAxesInfo, axisInfo) { + for (var i = 0; i < (inputAxesInfo || []).length; i++) { + var inputAxisInfo = inputAxesInfo[i]; + if (axisInfo.axis.dim === inputAxisInfo.axisDim + && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex + ) { + return inputAxisInfo; + } + } + } + + function makeMapperParam(axisInfo) { + var axisModel = axisInfo.axis.model; + var item = {}; + var dim = item.axisDim = axisInfo.axis.dim; + item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex; + item.axisName = item[dim + 'AxisName'] = axisModel.name; + item.axisId = item[dim + 'AxisId'] = axisModel.id; + return item; + } + + function illegalPoint(point) { + return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]); + } + + module.exports = axisTrigger; + + +/***/ }, +/* 300 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + + /** + * @param {Object} finder contains {seriesIndex, dataIndex, dataIndexInside} + * @param {module:echarts/model/Global} ecModel + * @return {Object} {point: [x, y], el: ...} point Will not be null. + */ + module.exports = function (finder, ecModel) { + var point = []; + var seriesIndex = finder.seriesIndex; + var seriesModel; + if (seriesIndex == null || !( + seriesModel = ecModel.getSeriesByIndex(seriesIndex) + )) { + return {point: []}; + } + + var data = seriesModel.getData(); + var dataIndex = modelUtil.queryDataIndex(data, finder); + if (dataIndex == null || zrUtil.isArray(dataIndex)) { + return {point: []}; + } + + var el = data.getItemGraphicEl(dataIndex); + var coordSys = seriesModel.coordinateSystem; + + if (seriesModel.getTooltipPosition) { + point = seriesModel.getTooltipPosition(dataIndex) || []; + } + else if (coordSys && coordSys.dataToPoint) { + point = coordSys.dataToPoint( + data.getValues( + zrUtil.map(coordSys.dimensions, function (dim) { + return seriesModel.coordDimToDataDim(dim)[0]; + }), dataIndex, true + ) + ) || []; + } + else if (el) { + // Use graphic bounding rect + var rect = el.getBoundingRect().clone(); + rect.applyTransform(el.transform); + point = [ + rect.x + rect.width / 2, + rect.y + rect.height / 2 + ]; + } + + return {point: point, el: el}; + }; + + + + +/***/ }, +/* 301 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + + var AxisPointerModel = echarts.extendComponentModel({ + + type: 'axisPointer', + + coordSysAxesInfo: null, + + defaultOption: { + // 'auto' means that show when triggered by tooltip or handle. + show: 'auto', + // 'click' | 'mousemove' | 'none' + triggerOn: null, // set default in AxisPonterView.js + + zlevel: 0, + z: 50, + + type: 'line', + // axispointer triggered by tootip determine snap automatically, + // see `modelHelper`. + snap: false, + triggerTooltip: true, + + value: null, + status: null, // Init value depends on whether handle is used. + + // [group0, group1, ...] + // Each group can be: { + // mapper: function () {}, + // singleTooltip: 'multiple', // 'multiple' or 'single' + // xAxisId: ..., + // yAxisName: ..., + // angleAxisIndex: ... + // } + // mapper: can be ignored. + // input: {axisInfo, value} + // output: {axisInfo, value} + link: [], + + // Do not set 'auto' here, otherwise global animation: false + // will not effect at this axispointer. + animation: null, + animationDurationUpdate: 200, + + lineStyle: { + color: '#aaa', + width: 1, + type: 'solid' + }, + + shadowStyle: { + color: 'rgba(150,150,150,0.3)' + }, + + label: { + show: true, + formatter: null, // string | Function + precision: 'auto', // Or a number like 0, 1, 2 ... + margin: 3, + textStyle: { + color: '#fff' + }, + padding: [5, 7, 5, 7], + backgroundColor: 'auto', // default: axis line color + borderColor: null, + borderWidth: 0, + shadowBlur: 3, + shadowColor: '#aaa' + // Considering applicability, common style should + // better not have shadowOffset. + // shadowOffsetX: 0, + // shadowOffsetY: 2 + }, + + handle: { + show: false, + icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', // jshint ignore:line + size: 45, + // handle margin is from symbol center to axis, which is stable when circular move. + margin: 50, + // color: '#1b8bbd' + // color: '#2f4554' + color: '#333', + shadowBlur: 3, + shadowColor: '#aaa', + shadowOffsetX: 0, + shadowOffsetY: 2, + + // For mobile performance + throttle: 40 + } + } + + }); + + module.exports = AxisPointerModel; + + + +/***/ }, +/* 302 */ +/***/ function(module, exports, __webpack_require__) { + + + + var globalListener = __webpack_require__(303); + + var AxisPonterView = __webpack_require__(1).extendComponentView({ + + type: 'axisPointer', + + render: function (globalAxisPointerModel, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var triggerOn = globalAxisPointerModel.get('triggerOn') + || (globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click'); + + // Register global listener in AxisPointerView to enable + // AxisPointerView to be independent to Tooltip. + globalListener.register( + 'axisPointer', + api, + function (currTrigger, e, dispatchAction) { + // If 'none', it is not controlled by mouse totally. + if (triggerOn !== 'none' + && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0) + ) { + dispatchAction({ + type: 'updateAxisPointer', + currTrigger: currTrigger, + x: e && e.offsetX, + y: e && e.offsetY + }); + } + } + ); + }, + + /** + * @override + */ + remove: function (ecModel, api) { + globalListener.disopse(api.getZr(), 'axisPointer'); + AxisPonterView.superApply(this._model, 'remove', arguments); + }, + + /** + * @override + */ + dispose: function (ecModel, api) { + globalListener.unregister('axisPointer', api); + AxisPonterView.superApply(this._model, 'dispose', arguments); + } + + }); + + + +/***/ }, +/* 303 */ +/***/ function(module, exports, __webpack_require__) { + + + + var env = __webpack_require__(2); + var zrUtil = __webpack_require__(4); + var get = __webpack_require__(5).makeGetter(); + + var each = zrUtil.each; + + var globalListener = {}; + + /** + * @param {string} key + * @param {module:echarts/ExtensionAPI} api + * @param {Function} handler + * param: {string} currTrigger + * param: {Array.} point + */ + globalListener.register = function (key, api, handler) { + if (env.node) { + return; + } + + var zr = api.getZr(); + get(zr).records || (get(zr).records = {}); + + initGlobalListeners(zr, api); + + var record = get(zr).records[key] || (get(zr).records[key] = {}); + record.handler = handler; + }; + + function initGlobalListeners(zr, api) { + if (get(zr).initialized) { + return; + } + + get(zr).initialized = true; + + useHandler('click', zrUtil.curry(doEnter, 'click')); + useHandler('mousemove', zrUtil.curry(doEnter, 'mousemove')); + // useHandler('mouseout', onLeave); + useHandler('globalout', onLeave); + + function useHandler(eventType, cb) { + zr.on(eventType, function (e) { + var dis = makeDispatchAction(api); + + each(get(zr).records, function (record) { + record && cb(record, e, dis.dispatchAction); + }); + + dispatchTooltipFinally(dis.pendings, api); + }); + } + } + + function dispatchTooltipFinally(pendings, api) { + var showLen = pendings.showTip.length; + var hideLen = pendings.hideTip.length; + + var actuallyPayload; + if (showLen) { + actuallyPayload = pendings.showTip[showLen - 1]; + } + else if (hideLen) { + actuallyPayload = pendings.hideTip[hideLen - 1]; + } + if (actuallyPayload) { + actuallyPayload.dispatchAction = null; + api.dispatchAction(actuallyPayload); + } + } + + function onLeave(record, e, dispatchAction) { + record.handler('leave', null, dispatchAction); + } + + function doEnter(currTrigger, record, e, dispatchAction) { + record.handler(currTrigger, e, dispatchAction); + } + + function makeDispatchAction(api) { + var pendings = { + showTip: [], + hideTip: [] + }; + // FIXME + // better approach? + // 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip, + // which may be conflict, (axisPointer call showTip but tooltip call hideTip); + // So we have to add "final stage" to merge those dispatched actions. + var dispatchAction = function (payload) { + var pendingList = pendings[payload.type]; + if (pendingList) { + pendingList.push(payload); + } + else { + payload.dispatchAction = dispatchAction; + api.dispatchAction(payload); + } + }; + + return { + dispatchAction: dispatchAction, + pendings: pendings + }; + } + + /** + * @param {string} key + * @param {module:echarts/ExtensionAPI} api + */ + globalListener.unregister = function (key, api) { + if (env.node) { + return; + } + var zr = api.getZr(); + var record = (get(zr).records || {})[key]; + if (record) { + get(zr).records[key] = null; + } + }; + + module.exports = globalListener; + + +/***/ }, +/* 304 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var graphic = __webpack_require__(18); + var BaseAxisPointer = __webpack_require__(305); + var viewHelper = __webpack_require__(306); + var cartesianAxisHelper = __webpack_require__(138); + var AxisView = __webpack_require__(136); + + var CartesianAxisPointer = BaseAxisPointer.extend({ + + /** + * @override + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisPointerType = axisPointerModel.get('type'); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true)); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = viewHelper.buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder[axisPointerType]( + axis, pixelValue, otherExtent, elStyle + ); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = cartesianAxisHelper.layout(grid.model, axisModel); + viewHelper.buildCartesianSingleLabelElOption( + value, elOption, layoutInfo, axisModel, axisPointerModel, api + ); + }, + + /** + * @override + */ + getHandleTransform: function (value, axisModel, axisPointerModel) { + var layoutInfo = cartesianAxisHelper.layout(axisModel.axis.grid.model, axisModel, { + labelInside: false + }); + layoutInfo.labelMargin = axisPointerModel.get('handle.margin'); + return { + position: viewHelper.getTransformedPosition(axisModel.axis, value, layoutInfo), + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }, + + /** + * @override + */ + updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisExtent = axis.getGlobalExtent(true); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var dimIndex = axis.dim === 'x' ? 0 : 1; + + var currPosition = transform.position; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; + + // Make tooltip do not overlap axisPointer and in the middle of the grid. + var tooltipOptions = [{verticalAlign: 'middle'}, {align: 'center'}]; + + return { + position: currPosition, + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: tooltipOptions[dimIndex] + }; + } + + }); + + function getCartesian(grid, axis) { + var opt = {}; + opt[axis.dim + 'AxisIndex'] = axis.index; + return grid.getCartesian(opt); + } + + var pointerShapeBuilder = { + + line: function (axis, pixelValue, otherExtent, elStyle) { + var targetShape = viewHelper.makeLineShape( + [pixelValue, otherExtent[0]], + [pixelValue, otherExtent[1]], + getAxisDimIndex(axis) + ); + graphic.subPixelOptimizeLine({ + shape: targetShape, + style: elStyle + }); + return { + type: 'Line', + shape: targetShape + }; + }, + + shadow: function (axis, pixelValue, otherExtent, elStyle) { + var bandWidth = axis.getBandWidth(); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: viewHelper.makeRectShape( + [pixelValue - bandWidth / 2, otherExtent[0]], + [bandWidth, span], + getAxisDimIndex(axis) + ) + }; + } + }; + + function getAxisDimIndex(axis) { + return axis.dim === 'x' ? 0 : 1; + } + + AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer); + + module.exports = CartesianAxisPointer; + + +/***/ }, +/* 305 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var clazzUtil = __webpack_require__(13); + var graphic = __webpack_require__(18); + var get = __webpack_require__(5).makeGetter(); + var axisPointerModelHelper = __webpack_require__(137); + var eventTool = __webpack_require__(88); + var throttle = __webpack_require__(81); + + var clone = zrUtil.clone; + var bind = zrUtil.bind; + + /** + * Base axis pointer class in 2D. + * Implemenents {module:echarts/component/axis/IAxisPointer}. + */ + function BaseAxisPointer () { + } + + BaseAxisPointer.prototype = { + + /** + * @private + */ + _group: null, + + /** + * @private + */ + _lastGraphicKey: null, + + /** + * @private + */ + _handle: null, + + /** + * @private + */ + _dragging: false, + + /** + * @private + */ + _lastValue: null, + + /** + * @private + */ + _lastStatus: null, + + /** + * @private + */ + _payloadInfo: null, + + /** + * In px, arbitrary value. Do not set too small, + * no animation is ok for most cases. + * @protected + */ + animationThreshold: 15, + + /** + * @implement + */ + render: function (axisModel, axisPointerModel, api, forceRender) { + var value = axisPointerModel.get('value'); + var status = axisPointerModel.get('status'); + + // Bind them to `this`, not in closure, otherwise they will not + // be replaced when user calling setOption in not merge mode. + this._axisModel = axisModel; + this._axisPointerModel = axisPointerModel; + this._api = api; + + // Optimize: `render` will be called repeatly during mouse move. + // So it is power consuming if performing `render` each time, + // especially on mobile device. + if (!forceRender + && this._lastValue === value + && this._lastStatus === status + ) { + return; + } + this._lastValue = value; + this._lastStatus = status; + + var group = this._group; + var handle = this._handle; + + if (!status || status === 'hide') { + // Do not clear here, for animation better. + group && group.hide(); + handle && handle.hide(); + return; + } + group && group.show(); + handle && handle.show(); + + // Otherwise status is 'show' + var elOption = {}; + this.makeElOption(elOption, value, axisModel, axisPointerModel, api); + + // Enable change axis pointer type. + var graphicKey = elOption.graphicKey; + if (graphicKey !== this._lastGraphicKey) { + this.clear(api); + } + this._lastGraphicKey = graphicKey; + + var moveAnimation = this._moveAnimation = + this.determineAnimation(axisModel, axisPointerModel); + + if (!group) { + group = this._group = new graphic.Group(); + this.createPointerEl(group, elOption, axisModel, axisPointerModel); + this.createLabelEl(group, elOption, axisModel, axisPointerModel); + api.getZr().add(group); + } + else { + var doUpdateProps = zrUtil.curry(updateProps, axisPointerModel, moveAnimation); + this.updatePointerEl(group, elOption, doUpdateProps, axisPointerModel); + this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel); + } + + updateMandatoryProps(group, axisPointerModel, true); + + this._renderHandle(value); + }, + + /** + * @implement + */ + remove: function (api) { + this.clear(api); + }, + + /** + * @implement + */ + dispose: function (api) { + this.clear(api); + }, + + /** + * @protected + */ + determineAnimation: function (axisModel, axisPointerModel) { + var animation = axisPointerModel.get('animation'); + var axis = axisModel.axis; + var isCategoryAxis = axis.type === 'category'; + var useSnap = axisPointerModel.get('snap'); + + // Value axis without snap always do not snap. + if (!useSnap && !isCategoryAxis) { + return false; + } + + if (animation === 'auto' || animation == null) { + var animationThreshold = this.animationThreshold; + if (isCategoryAxis && axis.getBandWidth() > animationThreshold) { + return true; + } + + // It is important to auto animation when snap used. Consider if there is + // a dataZoom, animation will be disabled when too many points exist, while + // it will be enabled for better visual effect when little points exist. + if (useSnap) { + var seriesDataCount = axisPointerModelHelper.getAxisInfo(axisModel).seriesDataCount; + var axisExtent = axis.getExtent(); + // Approximate band width + return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold; + } + + return false; + } + + return animation === true; + }, + + /** + * add {pointer, label, graphicKey} to elOption + * @protected + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + // Shoule be implemenented by sub-class. + }, + + /** + * @protected + */ + createPointerEl: function (group, elOption, axisModel, axisPointerModel) { + var pointerOption = elOption.pointer; + if (pointerOption) { + var pointerEl = get(group).pointerEl = new graphic[pointerOption.type]( + clone(elOption.pointer) + ); + group.add(pointerEl); + } + }, + + /** + * @protected + */ + createLabelEl: function (group, elOption, axisModel, axisPointerModel) { + if (elOption.label) { + var labelEl = get(group).labelEl = new graphic.Rect( + clone(elOption.label) + ); + + group.add(labelEl); + updateLabelShowHide(labelEl, axisPointerModel); + } + }, + + /** + * @protected + */ + updatePointerEl: function (group, elOption, updateProps) { + var pointerEl = get(group).pointerEl; + if (pointerEl) { + pointerEl.setStyle(elOption.pointer.style); + updateProps(pointerEl, {shape: elOption.pointer.shape}); + } + }, + + /** + * @protected + */ + updateLabelEl: function (group, elOption, updateProps, axisPointerModel) { + var labelEl = get(group).labelEl; + if (labelEl) { + labelEl.setStyle(elOption.label.style); + updateProps(labelEl, { + // Consider text length change in vertical axis, animation should + // be used on shape, otherwise the effect will be weird. + shape: elOption.label.shape, + position: elOption.label.position + }); + + updateLabelShowHide(labelEl, axisPointerModel); + } + }, + + /** + * @private + */ + _renderHandle: function (value) { + if (this._dragging || !this.updateHandleTransform) { + return; + } + + var axisPointerModel = this._axisPointerModel; + var zr = this._api.getZr(); + var handle = this._handle; + var handleModel = axisPointerModel.getModel('handle'); + + var status = axisPointerModel.get('status'); + if (!handleModel.get('show') || !status || status === 'hide') { + handle && zr.remove(handle); + this._handle = null; + return; + } + + var isInit; + if (!this._handle) { + isInit = true; + handle = this._handle = createIcon(handleModel, { + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + eventTool.stop(e.event); + }, + onmousedown: bind(this._onHandleDragMove, this, 0, 0), + drift: bind(this._onHandleDragMove, this), + ondragend: bind(this._onHandleDragEnd, this) + }); + zr.add(handle); + } + + updateMandatoryProps(handle, axisPointerModel, false); + + // update style + var includeStyles = [ + 'color', 'borderColor', 'borderWidth', 'opacity', + 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY' + ]; + handle.setStyle(handleModel.getItemStyle(null, includeStyles)); + + // update position + var handleSize = handleModel.get('size'); + if (!zrUtil.isArray(handleSize)) { + handleSize = [handleSize, handleSize]; + } + handle.attr('scale', [handleSize[0] / 2, handleSize[1] / 2]); + + throttle.createOrUpdate( + this, + '_doDispatchAxisPointer', + handleModel.get('throttle') || 0, + 'fixRate' + ); + + this._moveHandleToValue(value, isInit); + }, + + /** + * @private + */ + _moveHandleToValue: function (value, isInit) { + updateProps( + this._axisPointerModel, + !isInit && this._moveAnimation, + this._handle, + getHandleTransProps(this.getHandleTransform( + value, this._axisModel, this._axisPointerModel + )) + ); + }, + + /** + * @private + */ + _onHandleDragMove: function (dx, dy) { + var handle = this._handle; + if (!handle) { + return; + } + + this._dragging = true; + + // Persistent for throttle. + var trans = this.updateHandleTransform( + getHandleTransProps(handle), + [dx, dy], + this._axisModel, + this._axisPointerModel + ); + this._payloadInfo = trans; + + handle.stopAnimation(); + handle.attr(getHandleTransProps(trans)); + get(handle).lastProp = null; + + this._doDispatchAxisPointer(); + }, + + /** + * Throttled method. + * @private + */ + _doDispatchAxisPointer: function () { + var handle = this._handle; + if (!handle) { + return; + } + + var payloadInfo = this._payloadInfo; + var axisModel = this._axisModel; + this._api.dispatchAction({ + type: 'updateAxisPointer', + x: payloadInfo.cursorPoint[0], + y: payloadInfo.cursorPoint[1], + tooltipOption: payloadInfo.tooltipOption, + axesInfo: [{ + axisDim: axisModel.axis.dim, + axisIndex: axisModel.componentIndex + }] + }); + }, + + /** + * @private + */ + _onHandleDragEnd: function (moveAnimation) { + this._dragging = false; + var handle = this._handle; + if (!handle) { + return; + } + + var value = this._axisPointerModel.get('value'); + // Consider snap or categroy axis, handle may be not consistent with + // axisPointer. So move handle to align the exact value position when + // drag ended. + this._moveHandleToValue(value); + + // For the effect: tooltip will be shown when finger holding on handle + // button, and will be hidden after finger left handle button. + this._api.dispatchAction({ + type: 'hideTip' + }); + }, + + /** + * Should be implemenented by sub-class if support `handle`. + * @protected + * @param {number} value + * @param {module:echarts/model/Model} axisModel + * @param {module:echarts/model/Model} axisPointerModel + * @return {Object} {position: [x, y], rotation: 0} + */ + getHandleTransform: null, + + /** + * * Should be implemenented by sub-class if support `handle`. + * @protected + * @param {Object} transform {position, rotation} + * @param {Array.} delta [dx, dy] + * @param {module:echarts/model/Model} axisModel + * @param {module:echarts/model/Model} axisPointerModel + * @return {Object} {position: [x, y], rotation: 0, cursorPoint: [x, y]} + */ + updateHandleTransform: null, + + /** + * @private + */ + clear: function (api) { + this._lastValue = null; + this._lastStatus = null; + + var zr = api.getZr(); + var group = this._group; + var handle = this._handle; + if (zr && group) { + this._lastGraphicKey = null; + group && zr.remove(group); + handle && zr.remove(handle); + this._group = null; + this._handle = null; + this._payloadInfo = null; + } + }, + + /** + * @protected + */ + doClear: function () { + // Implemented by sub-class if necessary. + }, + + /** + * @protected + * @param {Array.} xy + * @param {Array.} wh + * @param {number} [xDimIndex=0] or 1 + */ + buildLabel: function (xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; + } + }; + + BaseAxisPointer.prototype.constructor = BaseAxisPointer; + + + function updateProps(animationModel, moveAnimation, el, props) { + // Animation optimize. + if (!propsEqual(get(el).lastProp, props)) { + get(el).lastProp = props; + moveAnimation + ? graphic.updateProps(el, props, animationModel) + : (el.stopAnimation(), el.attr(props)); + } + } + + function propsEqual(lastProps, newProps) { + if (zrUtil.isObject(lastProps) && zrUtil.isObject(newProps)) { + var equals = true; + zrUtil.each(newProps, function (item, key) { + equals &= propsEqual(lastProps[key], item); + }); + return !!equals; + } + else { + return lastProps === newProps; + } + } + + function updateLabelShowHide(labelEl, axisPointerModel) { + labelEl[axisPointerModel.get('label.show') ? 'show' : 'hide'](); + } + + function getHandleTransProps(trans) { + return { + position: trans.position.slice(), + rotation: trans.rotation || 0 + }; + } + + function createIcon(handleModel, handlers) { + var iconStr = handleModel.get('icon'); + var style = { + x: -1, y: -1, width: 2, height: 2 + }; + var opt = zrUtil.extend({ + style: { + strokeNoScale: true + }, + rectHover: true, + cursor: 'move', + draggable: true + }, handlers); + + return iconStr.indexOf('image://') === 0 + ? ( + style.image = iconStr.slice(8), + opt.style = style, + new graphic.Image(opt) + ) + : graphic.makePath( + iconStr.replace('path://', ''), + opt, + style, + 'center' + ); + } + + function updateMandatoryProps(group, axisPointerModel, silent) { + var z = axisPointerModel.get('z'); + var zlevel = axisPointerModel.get('zlevel'); + + group && group.traverse(function (el) { + if (el.type !== 'group') { + z != null && (el.z = z); + zlevel != null && (el.zlevel = zlevel); + el.silent = silent; + } + }); + } + + clazzUtil.enableClassExtend(BaseAxisPointer); + + module.exports = BaseAxisPointer; + + +/***/ }, +/* 306 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var textContain = __webpack_require__(8); + var formatUtil = __webpack_require__(6); + var matrix = __webpack_require__(11); + var axisHelper = __webpack_require__(101); + var AxisBuilder = __webpack_require__(135); + + var helper = {}; + + /** + * @param {module:echarts/model/Model} axisPointerModel + */ + helper.buildElStyle = function (axisPointerModel) { + var axisPointerType = axisPointerModel.get('type'); + var styleModel = axisPointerModel.getModel(axisPointerType + 'Style'); + var style; + if (axisPointerType === 'line') { + style = styleModel.getLineStyle(); + style.fill = null; + } + else if (axisPointerType === 'shadow') { + style = styleModel.getAreaStyle(); + style.stroke = null; + } + return style; + }; + + /** + * @param {Function} labelPos {align, verticalAlign, position} + */ + helper.buildLabelElOption = function ( + elOption, axisModel, axisPointerModel, api, labelPos + ) { + var value = axisPointerModel.get('value'); + var text = helper.getValueLabel( + value, axisModel.axis, axisModel.ecModel, + axisPointerModel.get('seriesDataIndices'), + { + precision: axisPointerModel.get('label.precision'), + formatter: axisPointerModel.get('label.formatter') + } + ); + var labelModel = axisPointerModel.getModel('label'); + var textStyleModel = labelModel.getModel('textStyle'); + var paddings = formatUtil.normalizeCssArray(labelModel.get('padding') || 0); + + var font = textStyleModel.getFont(); + var textRect = textContain.getBoundingRect( + text, font, labelPos.textAlign, labelPos.textBaseline + ); + + var position = labelPos.position; + var width = textRect.width + paddings[1] + paddings[3]; + var height = textRect.height + paddings[0] + paddings[2]; + + // Adjust by align. + var align = labelPos.align; + align === 'right' && (position[0] -= width); + align === 'center' && (position[0] -= width / 2); + var verticalAlign = labelPos.verticalAlign; + verticalAlign === 'bottom' && (position[1] -= height); + verticalAlign === 'middle' && (position[1] -= height / 2); + + // Not overflow ec container + confineInContainer(position, width, height, api); + + var bgColor = labelModel.get('backgroundColor'); + if (!bgColor || bgColor === 'auto') { + bgColor = axisModel.get('axisLine.lineStyle.color'); + } + + elOption.label = { + shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')}, + position: position.slice(), + style: { + text: text, + textFont: font, + textFill: textStyleModel.getTextColor(), + textPosition: 'inside', + fill: bgColor, + stroke: labelModel.get('borderColor') || 'transparent', + lineWidth: labelModel.get('borderWidth') || 0, + shadowBlur: labelModel.get('shadowBlur'), + shadowColor: labelModel.get('shadowColor'), + shadowOffsetX: labelModel.get('shadowOffsetX'), + shadowOffsetY: labelModel.get('shadowOffsetY') + }, + // Lable should be over axisPointer. + z2: 10 + }; + }; + + // Do not overflow ec container + function confineInContainer(position, width, height, api) { + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + position[0] = Math.min(position[0] + width, viewWidth) - width; + position[1] = Math.min(position[1] + height, viewHeight) - height; + position[0] = Math.max(position[0], 0); + position[1] = Math.max(position[1], 0); + } + + /** + * @param {number} value + * @param {module:echarts/coord/Axis} axis + * @param {module:echarts/model/Global} ecModel + * @param {Object} opt + * @param {Array.} seriesDataIndices + * @param {number|string} opt.precision 'auto' or a number + * @param {string|Function} opt.formatter label formatter + */ + helper.getValueLabel = function (value, axis, ecModel, seriesDataIndices, opt) { + var text = axis.scale.getLabel( + // If `precision` is set, width can be fixed (like '12.00500'), which + // helps to debounce when when moving label. + value, {precision: opt.precision} + ); + var formatter = opt.formatter; + + if (formatter) { + var params = { + value: axisHelper.getAxisRawValue(axis, value), + seriesData: [] + }; + zrUtil.each(seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var dataParams = series && series.getDataParams(dataIndex); + dataParams && params.seriesData.push(dataParams); + }); + + if (zrUtil.isString(formatter)) { + text = formatter.replace('{value}', text); + } + else if (zrUtil.isFunction(formatter)) { + text = formatter(params); + } + } + + return text; + }; + + /** + * @param {module:echarts/coord/Axis} axis + * @param {number} value + * @param {Object} layoutInfo { + * rotation, position, labelOffset, labelDirection, labelMargin + * } + */ + helper.getTransformedPosition = function (axis, value, layoutInfo) { + var transform = matrix.create(); + matrix.rotate(transform, transform, layoutInfo.rotation); + matrix.translate(transform, transform, layoutInfo.position); + + return graphic.applyTransform([ + axis.dataToCoord(value), + (layoutInfo.labelOffset || 0) + + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0) + ], transform); + }; + + helper.buildCartesianSingleLabelElOption = function ( + value, elOption, layoutInfo, axisModel, axisPointerModel, api + ) { + var textLayout = AxisBuilder.innerTextLayout( + layoutInfo.rotation, 0, layoutInfo.labelDirection + ); + layoutInfo.labelMargin = axisPointerModel.get('label.margin'); + helper.buildLabelElOption(elOption, axisModel, axisPointerModel, api, { + position: helper.getTransformedPosition(axisModel.axis, value, layoutInfo), + align: textLayout.textAlign, + verticalAlign: textLayout.textVerticalAlign + }); + }; + + /** + * @param {Array.} p1 + * @param {Array.} p2 + * @param {number} [xDimIndex=0] or 1 + */ + helper.makeLineShape = function (p1, p2, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x1: p1[xDimIndex], + y1: p1[1 - xDimIndex], + x2: p2[xDimIndex], + y2: p2[1 - xDimIndex] + }; + }; + + /** + * @param {Array.} xy + * @param {Array.} wh + * @param {number} [xDimIndex=0] or 1 + */ + helper.makeRectShape = function (xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; + }; + + helper.makeSectorShape = function (cx, cy, r0, r, startAngle, endAngle) { + return { + cx: cx, + cy: cy, + r0: r0, + r: r, + startAngle: startAngle, + endAngle: endAngle, + clockwise: true + }; + }; + + module.exports = helper; + + +/***/ }, +/* 307 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var graphic = __webpack_require__(18); + var BaseAxisPointer = __webpack_require__(305); + var viewHelper = __webpack_require__(306); + var singleAxisHelper = __webpack_require__(296); + var AxisView = __webpack_require__(136); + + var XY = ['x', 'y']; + var WH = ['width', 'height']; + + var SingleAxisPointer = BaseAxisPointer.extend({ + + /** + * @override + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var otherExtent = getGlobalExtent(coordSys, 1 - getPointDimIndex(axis)); + var pixelValue = coordSys.dataToPoint(value)[0]; + + var axisPointerType = axisPointerModel.get('type'); + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = viewHelper.buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder[axisPointerType]( + axis, pixelValue, otherExtent, elStyle + ); + pointerOption.style = elStyle; + + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = singleAxisHelper.layout(axisModel); + viewHelper.buildCartesianSingleLabelElOption( + value, elOption, layoutInfo, axisModel, axisPointerModel, api + ); + }, + + /** + * @override + */ + getHandleTransform: function (value, axisModel, axisPointerModel) { + var layoutInfo = singleAxisHelper.layout(axisModel, {labelInside: false}); + layoutInfo.labelMargin = axisPointerModel.get('handle.margin'); + return { + position: viewHelper.getTransformedPosition(axisModel.axis, value, layoutInfo), + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }, + + /** + * @override + */ + updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var dimIndex = getPointDimIndex(axis); + var axisExtent = getGlobalExtent(coordSys, dimIndex); + var currPosition = transform.position; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + var otherExtent = getGlobalExtent(coordSys, 1 - dimIndex); + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; + + return { + position: currPosition, + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: { + verticalAlign: 'middle' + } + }; + } + }); + + var pointerShapeBuilder = { + + line: function (axis, pixelValue, otherExtent, elStyle) { + var targetShape = viewHelper.makeLineShape( + [pixelValue, otherExtent[0]], + [pixelValue, otherExtent[1]], + getPointDimIndex(axis) + ); + graphic.subPixelOptimizeLine({ + shape: targetShape, + style: elStyle + }); + return { + type: 'Line', + shape: targetShape + }; + }, + + shadow: function (axis, pixelValue, otherExtent, elStyle) { + var bandWidth = axis.getBandWidth(); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: viewHelper.makeRectShape( + [pixelValue - bandWidth / 2, otherExtent[0]], + [bandWidth, span], + getPointDimIndex(axis) + ) + }; + } + }; + + function getPointDimIndex(axis) { + return axis.isHorizontal() ? 0 : 1; + } + + function getGlobalExtent(coordSys, dimIndex) { + var rect = coordSys.getRect(); + return [rect[XY[dimIndex]], rect[XY[dimIndex]] + rect[WH[dimIndex]]]; + } + + AxisView.registerAxisPointerClass('SingleAxisPointer', SingleAxisPointer); + + module.exports = SingleAxisPointer; + + +/***/ }, +/* 308 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * @file Define the themeRiver view's series model + * @author Deqing Li(annong035@gmail.com) + */ + + + var completeDimensions = __webpack_require__(110); + var SeriesModel = __webpack_require__(78); + var List = __webpack_require__(98); + var zrUtil = __webpack_require__(4); + var formatUtil = __webpack_require__(6); + var encodeHTML = formatUtil.encodeHTML; + var nest = __webpack_require__(255); + + var DATA_NAME_INDEX = 2; + + var ThemeRiverSeries = SeriesModel.extend({ + + type: 'series.themeRiver', + + dependencies: ['singleAxis'], + + /** + * @readOnly + * @type {module:zrender/core/util#HashMap} + */ + nameMap: null, + + /** + * @override + */ + init: function (option) { + ThemeRiverSeries.superApply(this, 'init', arguments); + + // Put this function here is for the sake of consistency of code + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + }, + + /** + * If there is no value of a certain point in the time for some event,set it value to 0. + * + * @param {Array} data initial data in the option + * @return {Array} + */ + fixData: function (data) { + var rawDataLength = data.length; + + // grouped data by name + var dataByName = nest() + .key(function (dataItem) { + return dataItem[2]; + }) + .entries(data); + + // data group in each layer + var layData = zrUtil.map(dataByName, function (d) { + return { + name: d.key, + dataList: d.values + }; + }); + + var layerNum = layData.length; + var largestLayer = -1; + var index = -1; + for (var i = 0; i < layerNum; ++i) { + var len = layData[i].dataList.length; + if (len > largestLayer) { + largestLayer = len; + index = i; + } + } + + for (var k = 0; k < layerNum; ++k) { + if (k === index) { + continue; + } + var name = layData[k].name; + for (var j = 0; j < largestLayer; ++j) { + var timeValue = layData[index].dataList[j][0]; + var length = layData[k].dataList.length; + var keyIndex = -1; + for (var l = 0; l < length; ++l) { + var value = layData[k].dataList[l][0]; + if (value === timeValue) { + keyIndex = l; + break; + } + } + if (keyIndex === -1) { + data[rawDataLength] = []; + data[rawDataLength][0] = timeValue; + data[rawDataLength][1] = 0; + data[rawDataLength][2] = name; + rawDataLength++; + + } + } + } + return data; + }, + + /** + * @override + * @param {Object} option the initial option that user gived + * @param {module:echarts/model/Model} ecModel the model object for themeRiver option + * @return {module:echarts/data/List} + */ + getInitialData: function (option, ecModel) { + + var dimensions = []; + + var singleAxisModel = ecModel.queryComponents({ + mainType: 'singleAxis', + index: this.get('singleAxisIndex'), + id: this.get('singleAxisId') + })[0]; + + var axisType = singleAxisModel.get('type'); + + dimensions = [ + { + name: 'time', + // FIXME common? + type: axisType === 'category' + ? 'ordinal' + : axisType === 'time' + ? 'time' + : 'float' + }, + { + name: 'value', + type: 'float' + }, + { + name: 'name', + type: 'ordinal' + } + ]; + + // filter the data item with the value of label is undefined + var filterData = zrUtil.filter(option.data, function (dataItem) { + return dataItem[2] !== undefined; + }); + + var data = this.fixData(filterData || []); + var nameList = []; + var nameMap = this.nameMap = zrUtil.createHashMap(); + var count = 0; + + for (var i = 0; i < data.length; ++i) { + nameList.push(data[i][DATA_NAME_INDEX]); + if (!nameMap.get(data[i][DATA_NAME_INDEX])) { + nameMap.set(data[i][DATA_NAME_INDEX], count); + count++; + } + } + + dimensions = completeDimensions(dimensions, data); + + var list = new List(dimensions, this); + + list.initData(data, nameList); + + return list; + }, + + /** + * Used by single coordinate + * + * @param {string} axisDim the dimension for single coordinate + * @return {Array. } specified dimensions on the axis. + */ + coordDimToDataDim: function (axisDim) { + return ['time']; + }, + + /** + * The raw data is divided into multiple layers and each layer + * has same name. + * + * @return {Array.>} + */ + getLayerSeries: function () { + var data = this.getData(); + var lenCount = data.count(); + var indexArr = []; + + for (var i = 0; i < lenCount; ++i) { + indexArr[i] = i; + } + // data group by name + var dataByName = nest() + .key(function (index) { + return data.get('name', index); + }) + .entries(indexArr); + + var layerSeries = zrUtil.map(dataByName, function (d) { + return { + name: d.key, + indices: d.values + }; + }); + + for (var j = 0; j < layerSeries.length; ++j) { + layerSeries[j].indices.sort(comparer); + } + + function comparer(index1, index2) { + return data.get('time', index1) - data.get('time', index2); + } + + return layerSeries; + }, + + /** + * Get data indices for show tooltip content + * + * @param {Array.|string} dim single coordinate dimension + * @param {number} value axis value + * @param {module:echarts/coord/single/SingleAxis} baseAxis single Axis used + * the themeRiver. + * @return {Object} {dataIndices, nestestValue} + */ + getAxisTooltipData: function (dim, value, baseAxis) { + if (!zrUtil.isArray(dim)) { + dim = dim ? [dim] : []; + } + + var data = this.getData(); + var layerSeries = this.getLayerSeries(); + var indices = []; + var layerNum = layerSeries.length; + var nestestValue; + + for (var i = 0; i < layerNum; ++i) { + var minDist = Number.MAX_VALUE; + var nearestIdx = -1; + var pointNum = layerSeries[i].indices.length; + for (var j = 0; j < pointNum; ++j) { + var theValue = data.get(dim[0], layerSeries[i].indices[j]); + var dist = Math.abs(theValue - value); + if (dist <= minDist) { + nestestValue = theValue; + minDist = dist; + nearestIdx = layerSeries[i].indices[j]; + } + } + indices.push(nearestIdx); + } + + return {dataIndices: indices, nestestValue: nestestValue}; + }, + + /** + * @override + * @param {number} dataIndex index of data + */ + formatTooltip: function (dataIndex) { + var data = this.getData(); + var htmlName = data.get('name', dataIndex); + var htmlValue = data.get('value', dataIndex); + if (isNaN(htmlValue) || htmlValue == null) { + htmlValue = '-'; + } + return encodeHTML(htmlName + ' : ' + htmlValue); + }, + + defaultOption: { + zlevel: 0, + z: 2, + + coordinateSystem: 'singleAxis', + + // gap in axis's orthogonal orientation + boundaryGap: ['10%', '10%'], + + // legendHoverLink: true, + + singleAxisIndex: 0, + + animationEasing: 'linear', + + label: { + normal: { + margin: 4, + textAlign: 'right', + show: true, + position: 'left', + textStyle: { + color: '#000', + fontSize: 11 + } + }, + emphasis: { + show: true + } + } + } + }); + + module.exports = ThemeRiverSeries; + + + +/***/ }, +/* 309 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(process) {/** + * @file The file used to draw themeRiver view + * @author Deqing Li(annong035@gmail.com) + */ + + + var poly = __webpack_require__(120); + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + var DataDiffer = __webpack_require__(99); + + module.exports = __webpack_require__(1).extendChartView({ + + type: 'themeRiver', + + init: function () { + this._layers = []; + }, + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var rawData = seriesModel.getRawData(); + + if (!data.count()) { + return; + } + + var group = this.group; + + var layerSeries = seriesModel.getLayerSeries(); + + var layoutInfo = data.getLayout('layoutInfo'); + var rect = layoutInfo.rect; + var boundaryGap = layoutInfo.boundaryGap; + + group.attr('position', [0, rect.y + boundaryGap[0]]); + + function keyGetter(item) { + return item.name; + } + var dataDiffer = new DataDiffer( + this._layersSeries || [], layerSeries, + keyGetter, keyGetter + ); + + var newLayersGroups = {}; + + dataDiffer.add(zrUtil.bind(zrUtil.curry(process, 'add'), this)) + .update(zrUtil.bind(zrUtil.curry(process, 'update'), this)) + .remove(zrUtil.bind(zrUtil.curry(process, 'remove'), this)) + .execute(); + + function process(status, idx, oldIdx) { + var oldLayersGroups = this._layers; + if (status === 'remove') { + group.remove(oldLayersGroups[idx]); + return; + } + var points0 = []; + var points1 = []; + var color; + var indices = layerSeries[idx].indices; + for (var j = 0; j < indices.length; j++) { + var layout = data.getItemLayout(indices[j]); + var x = layout.x; + var y0 = layout.y0; + var y = layout.y; + + points0.push([x, y0]); + points1.push([x, y0 + y]); + + color = rawData.getItemVisual(indices[j], 'color'); + } + + var polygon; + var text; + var textLayout = data.getItemLayout(indices[0]); + var itemModel = data.getItemModel(indices[j - 1]); + var labelModel = itemModel.getModel('label.normal'); + var margin = labelModel.get('margin'); + if (status === 'add') { + var layerGroup = newLayersGroups[idx] = new graphic.Group(); + polygon = new poly.Polygon({ + shape: { + points: points0, + stackedOnPoints: points1, + smooth: 0.4, + stackedOnSmooth: 0.4, + smoothConstraint: false + }, + z2: 0 + }); + text = new graphic.Text({ + style: { + x: textLayout.x - margin, + y: textLayout.y0 + textLayout.y / 2 + } + }); + layerGroup.add(polygon); + layerGroup.add(text); + group.add(layerGroup); + + polygon.setClipPath(createGridClipShape(polygon.getBoundingRect(), seriesModel, function () { + polygon.removeClipPath(); + })); + } + else { + var layerGroup = oldLayersGroups[oldIdx]; + polygon = layerGroup.childAt(0); + text = layerGroup.childAt(1); + group.add(layerGroup); + + newLayersGroups[idx] = layerGroup; + + graphic.updateProps(polygon, { + shape: { + points: points0, + stackedOnPoints: points1 + } + }, seriesModel); + + graphic.updateProps(text, { + style: { + x: textLayout.x - margin, + y: textLayout.y0 + textLayout.y / 2 + } + }, seriesModel); + } + + var hoverItemStyleModel = itemModel.getModel('itemStyle.emphasis'); + var itemStyleModel = itemModel.getModel('itemStyle.normal'); + var textStyleModel = labelModel.getModel('textStyle'); + + text.setStyle({ + text: labelModel.get('show') + ? seriesModel.getFormattedLabel(indices[j - 1], 'normal') + || data.getName(indices[j - 1]) + : '', + textFont: textStyleModel.getFont(), + textAlign: labelModel.get('textAlign'), + textVerticalAlign: 'middle' + }); + + polygon.setStyle(zrUtil.extend({ + fill: color + }, itemStyleModel.getItemStyle(['color']))); + + graphic.setHoverStyle(polygon, hoverItemStyleModel.getItemStyle()); + } + + this._layersSeries = layerSeries; + this._layers = newLayersGroups; + }, + + dispose: function () {} + }); + + // add animation to the view + function createGridClipShape(rect, seriesModel, cb) { + var rectEl = new graphic.Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + graphic.initProps(rectEl, { + shape: { + width: rect.width + 20, + height: rect.height + 20 + } + }, seriesModel, cb); + + return rectEl; + } + + + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(310))) + +/***/ }, +/* 310 */ +/***/ function(module, exports) { + + // shim for using process in browser + var process = module.exports = {}; + + // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + } ()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { return '/' }; + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { return 0; }; + + +/***/ }, +/* 311 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Using layout algorithm transform the raw data to layout information. + * @author Deqing Li(annong035@gmail.com) + */ + + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + + + module.exports = function (ecModel, api) { + + ecModel.eachSeriesByType('themeRiver', function (seriesModel) { + + var data = seriesModel.getData(); + + var single = seriesModel.coordinateSystem; + + var layoutInfo = {}; + + // use the axis boundingRect for view + var rect = single.getRect(); + + layoutInfo.rect = rect; + + var boundaryGap = seriesModel.get('boundaryGap'); + + var axis = single.getAxis(); + + layoutInfo.boundaryGap = boundaryGap; + + if (axis.orient === 'horizontal') { + boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], rect.height); + boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], rect.height); + var height = rect.height - boundaryGap[0] - boundaryGap[1]; + themeRiverLayout(data, seriesModel, height); + } + else { + boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], rect.width); + boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], rect.width); + var width = rect.width - boundaryGap[0] - boundaryGap[1]; + themeRiverLayout(data, seriesModel, width); + } + + data.setLayout('layoutInfo', layoutInfo); + }); + }; + + /** + * The layout information about themeriver + * + * @param {module:echarts/data/List} data data in the series + * @param {module:echarts/model/Series} seriesModel the model object of themeRiver series + * @param {number} height value used to compute every series height + */ + function themeRiverLayout(data, seriesModel, height) { + if (!data.count()) { + return; + } + var coordSys = seriesModel.coordinateSystem; + // the data in each layer are organized into a series. + var layerSeries = seriesModel.getLayerSeries(); + + // the points in each layer. + var layerPoints = zrUtil.map(layerSeries, function (singleLayer) { + return zrUtil.map(singleLayer.indices, function (idx) { + var pt = coordSys.dataToPoint(data.get('time', idx)); + pt[1] = data.get('value', idx); + return pt; + }); + }); + + var base = computeBaseline(layerPoints); + var baseLine = base.y0; + var ky = height / base.max; + + // set layout information for each item. + var n = layerSeries.length; + var m = layerSeries[0].indices.length; + var baseY0; + for (var j = 0; j < m; ++j) { + baseY0 = baseLine[j] * ky; + data.setItemLayout(layerSeries[0].indices[j], { + layerIndex: 0, + x: layerPoints[0][j][0], + y0: baseY0, + y: layerPoints[0][j][1] * ky + }); + for (var i = 1; i < n; ++i) { + baseY0 += layerPoints[i - 1][j][1] * ky; + data.setItemLayout(layerSeries[i].indices[j], { + layerIndex: i, + x: layerPoints[i][j][0], + y0: baseY0, + y: layerPoints[i][j][1] * ky + }); + } + } + } + + /** + * Compute the baseLine of the rawdata + * Inspired by Lee Byron's paper Stacked Graphs - Geometry & Aesthetics + * + * @param {Array.} data the points in each layer + * @return {Array} + */ + function computeBaseline(data) { + var layerNum = data.length; + var pointNum = data[0].length; + var sums = []; + var y0 = []; + var max = 0; + var temp; + var base = {}; + + for (var i = 0; i < pointNum; ++i) { + for (var j = 0, temp = 0; j < layerNum; ++j) { + temp += data[j][i][1]; + } + if (temp > max) { + max = temp; + } + sums.push(temp); + } + + for (var k = 0; k < pointNum; ++k) { + y0[k] = (max - sums[k]) / 2; + } + max = 0; + + for (var l = 0; l < pointNum; ++l) { + var sum = sums[l] + y0[l]; + if (sum > max) { + max = sum; + } + } + base.y0 = y0; + base.max = max; + + return base; + } + + + +/***/ }, +/* 312 */ +/***/ function(module, exports) { + + /** + * @file Visual encoding for themeRiver view + * @author Deqing Li(annong035@gmail.com) + */ + + + module.exports = function (ecModel) { + ecModel.eachSeriesByType('themeRiver', function (seriesModel) { + var data = seriesModel.getData(); + var rawData = seriesModel.getRawData(); + var colorList = seriesModel.get('color'); + + data.each(function (index) { + var name = data.getName(index); + var color = colorList[(seriesModel.nameMap.get(name) - 1) % colorList.length]; + rawData.setItemVisual(index, 'color', color); + }); + }); + }; + + + +/***/ }, +/* 313 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + var graphicUtil = __webpack_require__(18); + var labelHelper = __webpack_require__(118); + var createListFromArray = __webpack_require__(109); + var barGrid = __webpack_require__(145); + + var ITEM_STYLE_NORMAL_PATH = ['itemStyle', 'normal']; + var ITEM_STYLE_EMPHASIS_PATH = ['itemStyle', 'emphasis']; + var LABEL_NORMAL = ['label', 'normal']; + var LABEL_EMPHASIS = ['label', 'emphasis']; + + /** + * To reduce total package size of each coordinate systems, the modules `prepareCustom` + * of each coordinate systems are not required by each coordinate systems directly, but + * required by the module `custom`. + * + * prepareInfoForCustomSeries {Function}: optional + * @return {Object} {coordSys: {...}, api: { + * coord: function (data, clamp) {}, // return point in global. + * size: function (dataSize, dataItem) {} // return size of each axis in coordSys. + * }} + */ + var prepareCustoms = { + cartesian2d: __webpack_require__(314), + geo: __webpack_require__(315), + singleAxis: __webpack_require__(316), + polar: __webpack_require__(317), + calendar: __webpack_require__(318) + }; + + // ------ + // Model + // ------ + + echarts.extendSeriesModel({ + + type: 'series.custom', + + dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'], + + defaultOption: { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Polar coordinate system + // polarIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + // label: {} + // itemStyle: {} + }, + + getInitialData: function (option, ecModel) { + return createListFromArray(option.data, this, ecModel); + } + }); + + // ----- + // View + // ----- + + echarts.extendChartView({ + + type: 'custom', + + /** + * @private + * @type {module:echarts/data/List} + */ + _data: null, + + /** + * @override + */ + render: function (customSeries, ecModel, api) { + var oldData = this._data; + var data = customSeries.getData(); + var group = this.group; + var renderItem = makeRenderItem(customSeries, data, ecModel, api); + + data.diff(oldData) + .add(function (newIdx) { + data.hasValue(newIdx) && createOrUpdate( + null, newIdx, renderItem(newIdx), customSeries, group, data + ); + }) + .update(function (newIdx, oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + data.hasValue(newIdx) + ? createOrUpdate( + el, newIdx, renderItem(newIdx), customSeries, group, data + ) + : (el && group.remove(el)); + }) + .remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }) + .execute(); + + this._data = data; + }, + + /** + * @override + */ + dispose: zrUtil.noop + }); + + + function createEl(elOption) { + var graphicType = elOption.type; + var el; + + if (graphicType === 'path') { + var shape = elOption.shape; + el = graphicUtil.makePath( + shape.pathData, + null, + { + x: shape.x || 0, + y: shape.y || 0, + width: shape.width || 0, + height: shape.height || 0 + }, + 'center' + ); + el.__customPathData = elOption.pathData; + } + else if (graphicType === 'image') { + el = new graphicUtil.Image({ + }); + el.__customImagePath = elOption.style.image; + } + else if (graphicType === 'text') { + el = new graphicUtil.Text({ + }); + el.__customText = elOption.style.text; + } + else { + var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)]; + + if (true) { + zrUtil.assert(Clz, 'graphic type "' + graphicType + '" can not be found.'); + } + + el = new Clz(); + } + + el.__customGraphicType = graphicType; + + return el; + } + + function updateEl(el, dataIndex, elOption, animatableModel, data, isInit) { + var targetProps = {}; + var elOptionStyle = elOption.style || {}; + + elOption.shape && (targetProps.shape = zrUtil.clone(elOption.shape)); + elOption.position && (targetProps.position = elOption.position.slice()); + elOption.scale && (targetProps.scale = elOption.scale.slice()); + elOption.origin && (targetProps.origin = elOption.origin.slice()); + elOption.rotation && (targetProps.rotation = elOption.rotation); + + if (el.type === 'image' && elOption.style) { + var targetStyle = targetProps.style = {}; + zrUtil.each(['x', 'y', 'width', 'height'], function (prop) { + prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit); + }); + } + + if (el.type === 'text' && elOption.style) { + var targetStyle = targetProps.style = {}; + zrUtil.each(['x', 'y'], function (prop) { + prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit); + }); + } + + if (el.type !== 'group') { + el.useStyle(elOptionStyle); + + // Init animation. + if (isInit) { + el.style.opacity = 0; + var targetOpacity = elOptionStyle.opacity; + targetOpacity == null && (targetOpacity = 1); + graphicUtil.initProps(el, {style: {opacity: targetOpacity}}, animatableModel, dataIndex); + } + } + + if (isInit) { + el.attr(targetProps); + } + else { + graphicUtil.updateProps(el, targetProps, animatableModel, dataIndex); + } + + // z2 must not be null/undefined, otherwise sort error may occur. + el.attr({z2: elOption.z2 || 0, silent: elOption.silent}); + + elOption.styleEmphasis !== false && graphicUtil.setHoverStyle(el, elOption.styleEmphasis); + } + + function prepareStyleTransition(prop, targetStyle, elOptionStyle, oldElStyle, isInit) { + if (elOptionStyle[prop] != null && !isInit) { + targetStyle[prop] = elOptionStyle[prop]; + elOptionStyle[prop] = oldElStyle[prop]; + } + } + + function makeRenderItem(customSeries, data, ecModel, api) { + var renderItem = customSeries.get('renderItem'); + var coordSys = customSeries.coordinateSystem; + + if (true) { + zrUtil.assert(renderItem, 'series.render is required.'); + zrUtil.assert( + coordSys.prepareCustoms || prepareCustoms[coordSys.type], + 'This coordSys does not support custom series.' + ); + } + + var prepareResult = coordSys.prepareCustoms + ? coordSys.prepareCustoms() + : prepareCustoms[coordSys.type](coordSys); + + var userAPI = zrUtil.defaults({ + getWidth: api.getWidth, + getHeight: api.getHeight, + getZr: api.getZr, + getDevicePixelRatio: api.getDevicePixelRatio, + value: value, + style: style, + styleEmphasis: styleEmphasis, + visual: visual, + barLayout: barLayout, + currentSeriesIndices: currentSeriesIndices, + font: font + }, prepareResult.api); + + var userParams = { + context: {}, + seriesId: customSeries.id, + seriesName: customSeries.name, + seriesIndex: customSeries.seriesIndex, + coordSys: prepareResult.coordSys, + dataInsideLength: data.count(), + encode: wrapEncodeDef(customSeries.getData()) + }; + + // Do not support call `api` asynchronously without dataIndexInside input. + var currDataIndexInside; + var currDirty = true; + var currItemModel; + var currLabelNormalModel; + var currLabelEmphasisModel; + var currLabelValueDim; + var currVisualColor; + + return function (dataIndexInside) { + currDataIndexInside = dataIndexInside; + currDirty = true; + return renderItem && renderItem( + zrUtil.defaults({ + dataIndexInside: dataIndexInside, + dataIndex: data.getRawIndex(dataIndexInside) + }, userParams), + userAPI + ) || {}; + }; + + // Do not update cache until api called. + function updateCache(dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + if (currDirty) { + currItemModel = data.getItemModel(dataIndexInside); + currLabelNormalModel = currItemModel.getModel(LABEL_NORMAL); + currLabelEmphasisModel = currItemModel.getModel(LABEL_EMPHASIS); + currLabelValueDim = labelHelper.findLabelValueDim(data); + currVisualColor = data.getItemVisual(dataIndexInside, 'color'); + + currDirty = false; + } + } + + /** + * @public + * @param {nubmer|string} dim + * @param {number} [dataIndexInside=currDataIndexInside] + * @return {number|string} value + */ + function value(dim, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + return data.get(data.getDimension(dim || 0), dataIndexInside); + } + + /** + * By default, `visual` is applied to style (to support visualMap). + * `visual.color` is applied at `fill`. If user want apply visual.color on `stroke`, + * it can be implemented as: + * `api.style({stroke: api.visual('color'), fill: null})`; + * @public + * @param {Object} [extra] + * @param {number} [dataIndexInside=currDataIndexInside] + */ + function style(extra, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + updateCache(dataIndexInside); + + var itemStyle = currItemModel.getModel(ITEM_STYLE_NORMAL_PATH).getItemStyle(); + + currVisualColor != null && (itemStyle.fill = currVisualColor); + var opacity = data.getItemVisual(dataIndexInside, 'opacity'); + opacity != null && (itemStyle.opacity = opacity); + + labelHelper.setTextToStyle( + data, dataIndexInside, currLabelValueDim, itemStyle, + customSeries, currLabelNormalModel, currVisualColor + ); + + extra && zrUtil.extend(itemStyle, extra); + return itemStyle; + } + + /** + * @public + * @param {Object} [extra] + * @param {number} [dataIndexInside=currDataIndexInside] + */ + function styleEmphasis(extra, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + updateCache(dataIndexInside); + + var itemStyle = currItemModel.getModel(ITEM_STYLE_EMPHASIS_PATH).getItemStyle(); + + labelHelper.setTextToStyle( + data, dataIndexInside, currLabelValueDim, itemStyle, + customSeries, currLabelEmphasisModel, currVisualColor + ); + + extra && zrUtil.extend(itemStyle, extra); + return itemStyle; + } + + /** + * @public + * @param {string} visualType + * @param {number} [dataIndexInside=currDataIndexInside] + */ + function visual(visualType, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + return data.getItemVisual(dataIndexInside, visualType); + } + + /** + * @public + * @param {number} opt.count Positive interger. + * @param {number} [opt.barWidth] + * @param {number} [opt.barMaxWidth] + * @param {number} [opt.barGap] + * @param {number} [opt.barCategoryGap] + * @return {Object} {width, offset, offsetCenter} is not support, return undefined. + */ + function barLayout(opt) { + if (coordSys.getBaseAxis) { + var baseAxis = coordSys.getBaseAxis(); + return barGrid.getLayoutOnAxis(zrUtil.defaults({axis: baseAxis}, opt), api); + } + } + + /** + * @public + * @return {Array.} + */ + function currentSeriesIndices() { + return ecModel.getCurrentSeriesIndices(); + } + + /** + * @public + * @param {Object} opt + * @param {string} [opt.fontStyle] + * @param {number} [opt.fontWeight] + * @param {number} [opt.fontSize] + * @param {string} [opt.fontFamily] + * @return {string} font string + */ + function font(opt) { + return graphicUtil.getFont(opt, ecModel); + } + } + + function wrapEncodeDef(data) { + var encodeDef = {}; + zrUtil.each(data.dimensions, function (dimName, dataDimIndex) { + var dimInfo = data.getDimensionInfo(dimName); + if (!dimInfo.isExtraCoord) { + var coordDim = dimInfo.coordDim; + var dataDims = encodeDef[coordDim] = encodeDef[coordDim] || []; + dataDims[dimInfo.coordDimIndex] = dataDimIndex; + } + }); + return encodeDef; + } + + function createOrUpdate(el, dataIndex, elOption, animatableModel, group, data) { + el = doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data); + el && data.setItemGraphicEl(dataIndex, el); + } + + function doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data) { + var elOptionType = elOption.type; + if (el + && elOptionType !== el.__customGraphicType + && (elOptionType !== 'path' || elOption.pathData !== el.__customPathData) + && (elOptionType !== 'image' || elOption.style.image !== el.__customImagePath) + && (elOptionType !== 'text' || elOption.style.text !== el.__customText) + ) { + group.remove(el); + el = null; + } + + // `elOption.type` is undefined when `renderItem` returns nothing. + if (elOptionType == null) { + return; + } + + var isInit = !el; + !el && (el = createEl(elOption)); + updateEl(el, dataIndex, elOption, animatableModel, data, isInit); + + elOptionType === 'group' && zrUtil.each(elOption.children, function (childOption, index) { + doCreateOrUpdate(el.childAt(index), dataIndex, childOption, animatableModel, el, data); + }); + + group.add(el); + + return el; + } + + + + +/***/ }, +/* 314 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + function dataToCoordSize(dataSize, dataItem) { + // dataItem is necessary in log axis. + dataItem = dataItem || [0, 0]; + return zrUtil.map(['x', 'y'], function (dim, dimIdx) { + var axis = this.getAxis(dim); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + return axis.type === 'category' + ? axis.getBandWidth() + : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + }, this); + } + + function prepareCustom(coordSys) { + var rect = coordSys.grid.getRect(); + return { + coordSys: { + // The name exposed to user is always 'cartesian2d' but not 'grid'. + type: 'cartesian2d', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: zrUtil.bind(coordSys.dataToPoint, coordSys), + size: zrUtil.bind(dataToCoordSize, coordSys) + } + }; + } + + module.exports = prepareCustom; + + +/***/ }, +/* 315 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + function dataToCoordSize(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return zrUtil.map([0, 1], function (dimIdx) { + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var p1 = []; + var p2 = []; + p1[dimIdx] = val - halfSize; + p2[dimIdx] = val + halfSize; + p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; + return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); + }, this); + } + + function prepareCustom(coordSys) { + var rect = coordSys.getBoundingRect(); + return { + coordSys: { + type: 'geo', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: zrUtil.bind(coordSys.dataToPoint, coordSys), + size: zrUtil.bind(dataToCoordSize, coordSys) + } + }; + } + + module.exports = prepareCustom; + + +/***/ }, +/* 316 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + function dataToCoordSize(dataSize, dataItem) { + // dataItem is necessary in log axis. + var axis = this.getAxis(); + var val = dataItem instanceof Array ? dataItem[0] : dataItem; + var halfSize = (dataSize instanceof Array ? dataSize[0] : dataSize) / 2; + return axis.type === 'category' + ? axis.getBandWidth() + : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + } + + function prepareCustom(coordSys) { + var rect = coordSys.getRect(); + + return { + coordSys: { + type: 'singleAxis', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: zrUtil.bind(coordSys.dataToPoint, coordSys), + size: zrUtil.bind(dataToCoordSize, coordSys) + } + }; + } + + module.exports = prepareCustom; + + +/***/ }, +/* 317 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + function dataToCoordSize(dataSize, dataItem) { + // dataItem is necessary in log axis. + return zrUtil.map(['Radius', 'Angle'], function (dim, dimIdx) { + var axis = this['get' + dim + 'Axis'](); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var method = 'dataTo' + dim; + + var result = axis.type === 'category' + ? axis.getBandWidth() + : Math.abs(axis[method](val - halfSize) - axis[method](val + halfSize)); + + if (dim === 'Angle') { + result = result * Math.PI / 180; + } + + return result; + + }, this); + } + + function prepareCustom(coordSys) { + var radiusAxis = coordSys.getRadiusAxis(); + var angleAxis = coordSys.getAngleAxis(); + var radius = radiusAxis.getExtent(); + radius[0] > radius[1] && radius.reverse(); + + return { + coordSys: { + type: 'polar', + cx: coordSys.cx, + cy: coordSys.cy, + r: radius[1], + r0: radius[0] + }, + api: { + coord: zrUtil.bind(function (data) { + var radius = radiusAxis.dataToRadius(data[0]); + var angle = angleAxis.dataToAngle(data[1]); + var coord = coordSys.coordToPoint([radius, angle]); + coord.push(radius, angle * Math.PI / 180); + return coord; + }), + size: zrUtil.bind(dataToCoordSize, coordSys) + } + }; + } + + module.exports = prepareCustom; + + +/***/ }, +/* 318 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + function prepareCustom(coordSys) { + var rect = coordSys.getRect(); + var rangeInfo = coordSys.getRangeInfo(); + + return { + coordSys: { + type: 'calendar', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height, + cellWidth: coordSys.getCellWidth(), + cellHeight: coordSys.getCellHeight(), + rangeInfo: { + start: rangeInfo.start, + end: rangeInfo.end, + weeks: rangeInfo.weeks, + dayCount: rangeInfo.allDay + } + }, + api: { + coord: zrUtil.bind(coordSys.dataToPoint, coordSys) + } + }; + } + + module.exports = prepareCustom; + + +/***/ }, +/* 319 */ +/***/ function(module, exports, __webpack_require__) { + + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + var graphicUtil = __webpack_require__(18); + var layoutUtil = __webpack_require__(71); + + // ------------- + // Preprocessor + // ------------- + + echarts.registerPreprocessor(function (option) { + var graphicOption = option.graphic; + + // Convert + // {graphic: [{left: 10, type: 'circle'}, ...]} + // or + // {graphic: {left: 10, type: 'circle'}} + // to + // {graphic: [{elements: [{left: 10, type: 'circle'}, ...]}]} + if (zrUtil.isArray(graphicOption)) { + if (!graphicOption[0] || !graphicOption[0].elements) { + option.graphic = [{elements: graphicOption}]; + } + else { + // Only one graphic instance can be instantiated. (We dont + // want that too many views are created in echarts._viewMap) + option.graphic = [option.graphic[0]]; + } + } + else if (graphicOption && !graphicOption.elements) { + option.graphic = [{elements: [graphicOption]}]; + } + }); + + // ------ + // Model + // ------ + + var GraphicModel = echarts.extendComponentModel({ + + type: 'graphic', + + defaultOption: { + + // Extra properties for each elements: + // + // left/right/top/bottom: (like 12, '22%', 'center', default undefined) + // If left/rigth is set, shape.x/shape.cx/position will not be used. + // If top/bottom is set, shape.y/shape.cy/position will not be used. + // This mechanism is useful when you want to position a group/element + // against the right side or the center of this container. + // + // width/height: (can only be pixel value, default 0) + // Only be used to specify contianer(group) size, if needed. And + // can not be percentage value (like '33%'). See the reason in the + // layout algorithm below. + // + // bounding: (enum: 'all' (default) | 'raw') + // Specify how to calculate boundingRect when locating. + // 'all': Get uioned and transformed boundingRect + // from both itself and its descendants. + // This mode simplies confining a group of elements in the bounding + // of their ancester container (e.g., using 'right: 0'). + // 'raw': Only use the boundingRect of itself and before transformed. + // This mode is similar to css behavior, which is useful when you + // want an element to be able to overflow its container. (Consider + // a rotated circle needs to be located in a corner.) + + // Note: elements is always behind its ancestors in this elements array. + elements: [], + parentId: null + }, + + /** + * Save el options for the sake of the performance (only update modified graphics). + * The order is the same as those in option. (ancesters -> descendants) + * + * @private + * @type {Array.} + */ + _elOptionsToUpdate: null, + + /** + * @override + */ + mergeOption: function (option) { + // Prevent default merge to elements + var elements = this.option.elements; + this.option.elements = null; + + GraphicModel.superApply(this, 'mergeOption', arguments); + + this.option.elements = elements; + }, + + /** + * @override + */ + optionUpdated: function (newOption, isInit) { + var thisOption = this.option; + var newList = (isInit ? thisOption : newOption).elements; + var existList = thisOption.elements = isInit ? [] : thisOption.elements; + + var flattenedList = []; + this._flatten(newList, flattenedList); + + var mappingResult = modelUtil.mappingToExists(existList, flattenedList); + modelUtil.makeIdAndName(mappingResult); + + // Clear elOptionsToUpdate + var elOptionsToUpdate = this._elOptionsToUpdate = []; + + zrUtil.each(mappingResult, function (resultItem, index) { + var newElOption = resultItem.option; + + if (true) { + zrUtil.assert( + zrUtil.isObject(newElOption) || resultItem.exist, + 'Empty graphic option definition' + ); + } + + if (!newElOption) { + return; + } + + elOptionsToUpdate.push(newElOption); + + setKeyInfoToNewElOption(resultItem, newElOption); + + mergeNewElOptionToExist(existList, index, newElOption); + + setLayoutInfoToExist(existList[index], newElOption); + + }, this); + + // Clean + for (var i = existList.length - 1; i >= 0; i--) { + if (existList[i] == null) { + existList.splice(i, 1); + } + else { + // $action should be volatile, otherwise option gotten from + // `getOption` will contain unexpected $action. + delete existList[i].$action; + } + } + }, + + /** + * Convert + * [{ + * type: 'group', + * id: 'xx', + * children: [{type: 'circle'}, {type: 'polygon'}] + * }] + * to + * [ + * {type: 'group', id: 'xx'}, + * {type: 'circle', parentId: 'xx'}, + * {type: 'polygon', parentId: 'xx'} + * ] + * + * @private + * @param {Array.} optionList option list + * @param {Array.} result result of flatten + * @param {Object} parentOption parent option + */ + _flatten: function (optionList, result, parentOption) { + zrUtil.each(optionList, function (option) { + if (!option) { + return; + } + + if (parentOption) { + option.parentOption = parentOption; + } + + result.push(option); + + var children = option.children; + if (option.type === 'group' && children) { + this._flatten(children, result, option); + } + // Deleting for JSON output, and for not affecting group creation. + delete option.children; + }, this); + }, + + // FIXME + // Pass to view using payload? setOption has a payload? + useElOptionsToUpdate: function () { + var els = this._elOptionsToUpdate; + // Clear to avoid render duplicately when zooming. + this._elOptionsToUpdate = null; + return els; + } + }); + + // ----- + // View + // ----- + + echarts.extendComponentView({ + + type: 'graphic', + + /** + * @override + */ + init: function (ecModel, api) { + + /** + * @private + * @type {module:zrender/core/util.HashMap} + */ + this._elMap = zrUtil.createHashMap(); + + /** + * @private + * @type {module:echarts/graphic/GraphicModel} + */ + this._lastGraphicModel; + }, + + /** + * @override + */ + render: function (graphicModel, ecModel, api) { + + // Having leveraged between use cases and algorithm complexity, a very + // simple layout mechanism is used: + // The size(width/height) can be determined by itself or its parent (not + // implemented yet), but can not by its children. (Top-down travel) + // The location(x/y) can be determined by the bounding rect of itself + // (can including its descendants or not) and the size of its parent. + // (Bottom-up travel) + + // When `chart.clear()` or `chart.setOption({...}, true)` with the same id, + // view will be reused. + if (graphicModel !== this._lastGraphicModel) { + this._clear(); + } + this._lastGraphicModel = graphicModel; + + this._updateElements(graphicModel, api); + this._relocate(graphicModel, api); + }, + + /** + * Update graphic elements. + * + * @private + * @param {Object} graphicModel graphic model + * @param {module:echarts/ExtensionAPI} api extension API + */ + _updateElements: function (graphicModel, api) { + var elOptionsToUpdate = graphicModel.useElOptionsToUpdate(); + + if (!elOptionsToUpdate) { + return; + } + + var elMap = this._elMap; + var rootGroup = this.group; + + // Top-down tranverse to assign graphic settings to each elements. + zrUtil.each(elOptionsToUpdate, function (elOption) { + var $action = elOption.$action; + var id = elOption.id; + var existEl = elMap.get(id); + var parentId = elOption.parentId; + var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup; + + // In top/bottom mode, textVertical should not be used. And textBaseline + // should not be 'alphabetic', which cause inaccurately locating. + if (elOption.hv && elOption.hv[1] && elOption.type === 'text') { + elOption.style = zrUtil.defaults({textBaseline: 'middle'}, elOption.style); + elOption.style.textVerticalAlign = null; + } + + // Remove unnecessary props to avoid potential problems. + var elOptionCleaned = getCleanedElOption(elOption); + + // For simple, do not support parent change, otherwise reorder is needed. + if (true) { + existEl && zrUtil.assert( + targetElParent === existEl.parent, + 'Changing parent is not supported.' + ); + } + + if (!$action || $action === 'merge') { + existEl + ? existEl.attr(elOptionCleaned) + : createEl(id, targetElParent, elOptionCleaned, elMap); + } + else if ($action === 'replace') { + removeEl(existEl, elMap); + createEl(id, targetElParent, elOptionCleaned, elMap); + } + else if ($action === 'remove') { + removeEl(existEl, elMap); + } + + var el = elMap.get(id); + if (el) { + el.__ecGraphicWidth = elOption.width; + el.__ecGraphicHeight = elOption.height; + } + }); + }, + + /** + * Locate graphic elements. + * + * @private + * @param {Object} graphicModel graphic model + * @param {module:echarts/ExtensionAPI} api extension API + */ + _relocate: function (graphicModel, api) { + var elOptions = graphicModel.option.elements; + var rootGroup = this.group; + var elMap = this._elMap; + + // Bottom-up tranvese all elements (consider ec resize) to locate elements. + for (var i = elOptions.length - 1; i >= 0; i--) { + var elOption = elOptions[i]; + var el = elMap.get(elOption.id); + + if (!el) { + continue; + } + + var parentEl = el.parent; + var containerInfo = parentEl === rootGroup + ? { + width: api.getWidth(), + height: api.getHeight() + } + : { // Like 'position:absolut' in css, default 0. + width: parentEl.__ecGraphicWidth || 0, + height: parentEl.__ecGraphicHeight || 0 + }; + + layoutUtil.positionElement( + el, elOption, containerInfo, null, + {hv: elOption.hv, boundingMode: elOption.bounding} + ); + } + }, + + /** + * Clear all elements. + * + * @private + */ + _clear: function () { + var elMap = this._elMap; + elMap.each(function (el) { + removeEl(el, elMap); + }); + this._elMap = zrUtil.createHashMap(); + }, + + /** + * @override + */ + dispose: function () { + this._clear(); + } + }); + + function createEl(id, targetElParent, elOption, elMap) { + var graphicType = elOption.type; + + if (true) { + zrUtil.assert(graphicType, 'graphic type MUST be set'); + } + + var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)]; + + if (true) { + zrUtil.assert(Clz, 'graphic type can not be found'); + } + + var el = new Clz(elOption); + targetElParent.add(el); + elMap.set(id, el); + el.__ecGraphicId = id; + } + + function removeEl(existEl, elMap) { + var existElParent = existEl && existEl.parent; + if (existElParent) { + existEl.type === 'group' && existEl.traverse(function (el) { + removeEl(el, elMap); + }); + elMap.removeKey(existEl.__ecGraphicId); + existElParent.remove(existEl); + } + } + + // Remove unnecessary props to avoid potential problems. + function getCleanedElOption(elOption) { + elOption = zrUtil.extend({}, elOption); + zrUtil.each( + ['id', 'parentId', '$action', 'hv', 'bounding'].concat(layoutUtil.LOCATION_PARAMS), + function (name) { + delete elOption[name]; + } + ); + return elOption; + } + + function isSetLoc(obj, props) { + var isSet; + zrUtil.each(props, function (prop) { + obj[prop] != null && obj[prop] !== 'auto' && (isSet = true); + }); + return isSet; + } + + function setKeyInfoToNewElOption(resultItem, newElOption) { + var existElOption = resultItem.exist; + + // Set id and type after id assigned. + newElOption.id = resultItem.keyInfo.id; + !newElOption.type && existElOption && (newElOption.type = existElOption.type); + + // Set parent id if not specified + if (newElOption.parentId == null) { + var newElParentOption = newElOption.parentOption; + if (newElParentOption) { + newElOption.parentId = newElParentOption.id; + } + else if (existElOption) { + newElOption.parentId = existElOption.parentId; + } + } + + // Clear + newElOption.parentOption = null; + } + + function mergeNewElOptionToExist(existList, index, newElOption) { + // Update existing options, for `getOption` feature. + var newElOptCopy = zrUtil.extend({}, newElOption); + var existElOption = existList[index]; + + var $action = newElOption.$action || 'merge'; + if ($action === 'merge') { + if (existElOption) { + + if (true) { + var newType = newElOption.type; + zrUtil.assert( + !newType || existElOption.type === newType, + 'Please set $action: "replace" to change `type`' + ); + } + + // We can ensure that newElOptCopy and existElOption are not + // the same object, so `merge` will not change newElOptCopy. + zrUtil.merge(existElOption, newElOptCopy, true); + // Rigid body, use ignoreSize. + layoutUtil.mergeLayoutParam(existElOption, newElOptCopy, {ignoreSize: true}); + // Will be used in render. + layoutUtil.copyLayoutParams(newElOption, existElOption); + } + else { + existList[index] = newElOptCopy; + } + } + else if ($action === 'replace') { + existList[index] = newElOptCopy; + } + else if ($action === 'remove') { + // null will be cleaned later. + existElOption && (existList[index] = null); + } + } + + function setLayoutInfoToExist(existItem, newElOption) { + if (!existItem) { + return; + } + existItem.hv = newElOption.hv = [ + // Rigid body, dont care `width`. + isSetLoc(newElOption, ['left', 'right']), + // Rigid body, dont care `height`. + isSetLoc(newElOption, ['top', 'bottom']) + ]; + // Give default group size. Otherwise layout error may occur. + if (existItem.type === 'group') { + existItem.width == null && (existItem.width = newElOption.width = 0); + existItem.height == null && (existItem.height = newElOption.height = 0); + } + } + + + +/***/ }, +/* 320 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(124); + + __webpack_require__(304); + + __webpack_require__(298); + + + +/***/ }, +/* 321 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Legend component entry file8 + */ + + + __webpack_require__(322); + __webpack_require__(323); + __webpack_require__(324); + + var echarts = __webpack_require__(1); + // Series Filter + echarts.registerProcessor(__webpack_require__(326)); + + +/***/ }, +/* 322 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var Model = __webpack_require__(12); + + var LegendModel = __webpack_require__(1).extendComponentModel({ + + type: 'legend', + + dependencies: ['series'], + + layoutMode: { + type: 'box', + ignoreSize: true + }, + + init: function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + + option.selected = option.selected || {}; + }, + + mergeOption: function (option) { + LegendModel.superCall(this, 'mergeOption', option); + }, + + optionUpdated: function () { + this._updateData(this.ecModel); + + var legendData = this._data; + + // If selectedMode is single, try to select one + if (legendData[0] && this.get('selectedMode') === 'single') { + var hasSelected = false; + // If has any selected in option.selected + for (var i = 0; i < legendData.length; i++) { + var name = legendData[i].get('name'); + if (this.isSelected(name)) { + // Force to unselect others + this.select(name); + hasSelected = true; + break; + } + } + // Try select the first if selectedMode is single + !hasSelected && this.select(legendData[0].get('name')); + } + }, + + _updateData: function (ecModel) { + var legendData = zrUtil.map(this.get('data') || [], function (dataItem) { + // Can be string or number + if (typeof dataItem === 'string' || typeof dataItem === 'number') { + dataItem = { + name: dataItem + }; + } + return new Model(dataItem, this, this.ecModel); + }, this); + this._data = legendData; + + var availableNames = zrUtil.map(ecModel.getSeries(), function (series) { + return series.name; + }); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.legendDataProvider) { + var data = seriesModel.legendDataProvider(); + availableNames = availableNames.concat(data.mapArray(data.getName)); + } + }); + /** + * @type {Array.} + * @private + */ + this._availableNames = availableNames; + }, + + /** + * @return {Array.} + */ + getData: function () { + return this._data; + }, + + /** + * @param {string} name + */ + select: function (name) { + var selected = this.option.selected; + var selectedMode = this.get('selectedMode'); + if (selectedMode === 'single') { + var data = this._data; + zrUtil.each(data, function (dataItem) { + selected[dataItem.get('name')] = false; + }); + } + selected[name] = true; + }, + + /** + * @param {string} name + */ + unSelect: function (name) { + if (this.get('selectedMode') !== 'single') { + this.option.selected[name] = false; + } + }, + + /** + * @param {string} name + */ + toggleSelected: function (name) { + var selected = this.option.selected; + // Default is true + if (!selected.hasOwnProperty(name)) { + selected[name] = true; + } + this[selected[name] ? 'unSelect' : 'select'](name); + }, + + /** + * @param {string} name + */ + isSelected: function (name) { + var selected = this.option.selected; + return !(selected.hasOwnProperty(name) && !selected[name]) + && zrUtil.indexOf(this._availableNames, name) >= 0; + }, + + defaultOption: { + // 一级层叠 + zlevel: 0, + // 二级层叠 + z: 4, + show: true, + + // 布局方式,默认为水平布局,可选为: + // 'horizontal' | 'vertical' + orient: 'horizontal', + + left: 'center', + // right: 'center', + + top: 'top', + // bottom: 'top', + + // 水平对齐 + // 'auto' | 'left' | 'right' + // 默认为 'auto', 根据 x 的位置判断是左对齐还是右对齐 + align: 'auto', + + backgroundColor: 'rgba(0,0,0,0)', + // 图例边框颜色 + borderColor: '#ccc', + // 图例边框线宽,单位px,默认为0(无边框) + borderWidth: 0, + // 图例内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + padding: 5, + // 各个item之间的间隔,单位px,默认为10, + // 横向布局时为水平间隔,纵向布局时为纵向间隔 + itemGap: 10, + // 图例图形宽度 + itemWidth: 25, + // 图例图形高度 + itemHeight: 14, + + // 图例关闭时候的颜色 + inactiveColor: '#ccc', + + textStyle: { + // 图例文字颜色 + color: '#333' + }, + // formatter: '', + // 选择模式,默认开启图例开关 + selectedMode: true, + // 配置默认选中状态,可配合LEGEND.SELECTED事件做动态数据载入 + // selected: null, + // 图例内容(详见legend.data,数组中每一项代表一个item + // data: [], + + // Tooltip 相关配置 + tooltip: { + show: false + } + } + }); + + module.exports = LegendModel; + + +/***/ }, +/* 323 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Legend action + */ + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + + function legendSelectActionHandler(methodName, payload, ecModel) { + var selectedMap = {}; + var isToggleSelect = methodName === 'toggleSelected'; + var isSelected; + // Update all legend components + ecModel.eachComponent('legend', function (legendModel) { + if (isToggleSelect && isSelected != null) { + // Force other legend has same selected status + // Or the first is toggled to true and other are toggled to false + // In the case one legend has some item unSelected in option. And if other legend + // doesn't has the item, they will assume it is selected. + legendModel[isSelected ? 'select' : 'unSelect'](payload.name); + } + else { + legendModel[methodName](payload.name); + isSelected = legendModel.isSelected(payload.name); + } + var legendData = legendModel.getData(); + zrUtil.each(legendData, function (model) { + var name = model.get('name'); + // Wrap element + if (name === '\n' || name === '') { + return; + } + var isItemSelected = legendModel.isSelected(name); + if (selectedMap.hasOwnProperty(name)) { + // Unselected if any legend is unselected + selectedMap[name] = selectedMap[name] && isItemSelected; + } + else { + selectedMap[name] = isItemSelected; + } + }); + }); + // Return the event explicitly + return { + name: payload.name, + selected: selectedMap + }; + } + /** + * @event legendToggleSelect + * @type {Object} + * @property {string} type 'legendToggleSelect' + * @property {string} [from] + * @property {string} name Series name or data item name + */ + echarts.registerAction( + 'legendToggleSelect', 'legendselectchanged', + zrUtil.curry(legendSelectActionHandler, 'toggleSelected') + ); + + /** + * @event legendSelect + * @type {Object} + * @property {string} type 'legendSelect' + * @property {string} name Series name or data item name + */ + echarts.registerAction( + 'legendSelect', 'legendselected', + zrUtil.curry(legendSelectActionHandler, 'select') + ); + + /** + * @event legendUnSelect + * @type {Object} + * @property {string} type 'legendUnSelect' + * @property {string} name Series name or data item name + */ + echarts.registerAction( + 'legendUnSelect', 'legendunselected', + zrUtil.curry(legendSelectActionHandler, 'unSelect') + ); + + +/***/ }, +/* 324 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var symbolCreator = __webpack_require__(111); + var graphic = __webpack_require__(18); + var listComponentHelper = __webpack_require__(325); + + var curry = zrUtil.curry; + + function dispatchSelectAction(name, api) { + api.dispatchAction({ + type: 'legendToggleSelect', + name: name + }); + } + + function dispatchHighlightAction(seriesModel, dataName, api) { + // If element hover will move to a hoverLayer. + var el = api.getZr().storage.getDisplayList()[0]; + if (!(el && el.useHoverLayer)) { + seriesModel.get('legendHoverLink') && api.dispatchAction({ + type: 'highlight', + seriesName: seriesModel.name, + name: dataName + }); + } + } + + function dispatchDownplayAction(seriesModel, dataName, api) { + // If element hover will move to a hoverLayer. + var el = api.getZr().storage.getDisplayList()[0]; + if (!(el && el.useHoverLayer)) { + seriesModel.get('legendHoverLink') && api.dispatchAction({ + type: 'downplay', + seriesName: seriesModel.name, + name: dataName + }); + } + } + + module.exports = __webpack_require__(1).extendComponentView({ + + type: 'legend', + + init: function () { + this._symbolTypeStore = {}; + }, + + render: function (legendModel, ecModel, api) { + var group = this.group; + group.removeAll(); + + if (!legendModel.get('show')) { + return; + } + + var selectMode = legendModel.get('selectedMode'); + var itemAlign = legendModel.get('align'); + + if (itemAlign === 'auto') { + itemAlign = (legendModel.get('left') === 'right' + && legendModel.get('orient') === 'vertical') + ? 'right' : 'left'; + } + + var legendDrawedMap = zrUtil.createHashMap(); + + zrUtil.each(legendModel.getData(), function (itemModel) { + var name = itemModel.get('name'); + + // Use empty string or \n as a newline string + if (name === '' || name === '\n') { + group.add(new graphic.Group({ + newline: true + })); + return; + } + + var seriesModel = ecModel.getSeriesByName(name)[0]; + + if (legendDrawedMap.get(name)) { + // Have been drawed + return; + } + + // Series legend + if (seriesModel) { + var data = seriesModel.getData(); + var color = data.getVisual('color'); + + // If color is a callback function + if (typeof color === 'function') { + // Use the first data + color = color(seriesModel.getDataParams(0)); + } + + // Using rect symbol defaultly + var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect'; + var symbolType = data.getVisual('symbol'); + + var itemGroup = this._createItem( + name, itemModel, legendModel, + legendSymbolType, symbolType, + itemAlign, color, + selectMode + ); + + itemGroup.on('click', curry(dispatchSelectAction, name, api)) + .on('mouseover', curry(dispatchHighlightAction, seriesModel, null, api)) + .on('mouseout', curry(dispatchDownplayAction, seriesModel, null, api)); + + legendDrawedMap.set(name, true); + } + else { + // Data legend of pie, funnel + ecModel.eachRawSeries(function (seriesModel) { + // In case multiple series has same data name + if (legendDrawedMap.get(name)) { + return; + } + if (seriesModel.legendDataProvider) { + var data = seriesModel.legendDataProvider(); + var idx = data.indexOfName(name); + if (idx < 0) { + return; + } + + var color = data.getItemVisual(idx, 'color'); + + var legendSymbolType = 'roundRect'; + + var itemGroup = this._createItem( + name, itemModel, legendModel, + legendSymbolType, null, + itemAlign, color, + selectMode + ); + + itemGroup.on('click', curry(dispatchSelectAction, name, api)) + // FIXME Should not specify the series name + .on('mouseover', curry(dispatchHighlightAction, seriesModel, name, api)) + .on('mouseout', curry(dispatchDownplayAction, seriesModel, name, api)); + + legendDrawedMap.set(name, true); + } + }, this); + } + + if (true) { + if (!legendDrawedMap.get(name)) { + console.warn(name + ' series not exists. Legend data should be same with series name or data name.'); + } + } + }, this); + + listComponentHelper.layout(group, legendModel, api); + // Render background after group is layout + // FIXME + listComponentHelper.addBackground(group, legendModel); + }, + + _createItem: function ( + name, itemModel, legendModel, + legendSymbolType, symbolType, + itemAlign, color, selectMode + ) { + var itemWidth = legendModel.get('itemWidth'); + var itemHeight = legendModel.get('itemHeight'); + var inactiveColor = legendModel.get('inactiveColor'); + + var isSelected = legendModel.isSelected(name); + var itemGroup = new graphic.Group(); + + var textStyleModel = itemModel.getModel('textStyle'); + + var itemIcon = itemModel.get('icon'); + + var tooltipModel = itemModel.getModel('tooltip'); + var legendGlobalTooltipModel = tooltipModel.parentModel; + + // Use user given icon first + legendSymbolType = itemIcon || legendSymbolType; + itemGroup.add(symbolCreator.createSymbol( + legendSymbolType, 0, 0, itemWidth, itemHeight, isSelected ? color : inactiveColor + )); + + // Compose symbols + // PENDING + if (!itemIcon && symbolType + // At least show one symbol, can't be all none + && ((symbolType !== legendSymbolType) || symbolType == 'none') + ) { + var size = itemHeight * 0.8; + if (symbolType === 'none') { + symbolType = 'circle'; + } + // Put symbol in the center + itemGroup.add(symbolCreator.createSymbol( + symbolType, (itemWidth - size) / 2, (itemHeight - size) / 2, size, size, + isSelected ? color : inactiveColor + )); + } + + // Text + var textX = itemAlign === 'left' ? itemWidth + 5 : -5; + var textAlign = itemAlign; + + var formatter = legendModel.get('formatter'); + var content = name; + if (typeof formatter === 'string' && formatter) { + content = formatter.replace('{name}', name != null ? name : ''); + } + else if (typeof formatter === 'function') { + content = formatter(name); + } + + var text = new graphic.Text({ + style: { + text: content, + x: textX, + y: itemHeight / 2, + fill: isSelected ? textStyleModel.getTextColor() : inactiveColor, + textFont: textStyleModel.getFont(), + textAlign: textAlign, + textVerticalAlign: 'middle' + } + }); + itemGroup.add(text); + + // Add a invisible rect to increase the area of mouse hover + var hitRect = new graphic.Rect({ + shape: itemGroup.getBoundingRect(), + invisible: true, + tooltip: tooltipModel.get('show') ? zrUtil.extend({ + content: name, + // Defaul formatter + formatter: legendGlobalTooltipModel.get('formatter', true) || function () { + return name; + }, + formatterParams: { + componentType: 'legend', + legendIndex: legendModel.componentIndex, + name: name, + $vars: ['name'] + } + }, tooltipModel.option) : null + }); + itemGroup.add(hitRect); + + itemGroup.eachChild(function (child) { + child.silent = true; + }); + + hitRect.silent = !selectMode; + + + + this.group.add(itemGroup); + + graphic.setHoverStyle(itemGroup); + + return itemGroup; + } + }); + + +/***/ }, +/* 325 */ +/***/ function(module, exports, __webpack_require__) { + + + // List layout + var layout = __webpack_require__(71); + var formatUtil = __webpack_require__(6); + var graphic = __webpack_require__(18); + + function positionGroup(group, model, api) { + layout.positionElement( + group, model.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + }, + model.get('padding') + ); + } + + module.exports = { + /** + * Layout list like component. + * It will box layout each items in group of component and then position the whole group in the viewport + * @param {module:zrender/group/Group} group + * @param {module:echarts/model/Component} componentModel + * @param {module:echarts/ExtensionAPI} + */ + layout: function (group, componentModel, api) { + var rect = layout.getLayoutRect(componentModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }, componentModel.get('padding')); + layout.box( + componentModel.get('orient'), + group, + componentModel.get('itemGap'), + rect.width, + rect.height + ); + + positionGroup(group, componentModel, api); + }, + + addBackground: function (group, componentModel) { + var padding = formatUtil.normalizeCssArray( + componentModel.get('padding') + ); + var boundingRect = group.getBoundingRect(); + var style = componentModel.getItemStyle(['color', 'opacity']); + style.fill = componentModel.get('backgroundColor'); + var rect = new graphic.Rect({ + shape: { + x: boundingRect.x - padding[3], + y: boundingRect.y - padding[0], + width: boundingRect.width + padding[1] + padding[3], + height: boundingRect.height + padding[0] + padding[2] + }, + style: style, + silent: true, + z2: -1 + }); + graphic.subPixelOptimizeRect(rect); + + group.add(rect); + } + }; + + +/***/ }, +/* 326 */ +/***/ function(module, exports) { + + + module.exports = function (ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + if (legendModels && legendModels.length) { + ecModel.filterSeries(function (series) { + // If in any legend component the status is not selected. + // Because in legend series is assumed selected when it is not in the legend data. + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(series.name)) { + return false; + } + } + return true; + }); + } + }; + + +/***/ }, +/* 327 */ +/***/ function(module, exports, __webpack_require__) { + + // FIXME Better way to pack data in graphic element + + + __webpack_require__(298); + + __webpack_require__(328); + + __webpack_require__(329); + + + // Show tip action + /** + * @action + * @property {string} type + * @property {number} seriesIndex + * @property {number} dataIndex + * @property {number} [x] + * @property {number} [y] + */ + __webpack_require__(1).registerAction( + { + type: 'showTip', + event: 'showTip', + update: 'tooltip:manuallyShowTip' + }, + // noop + function () {} + ); + // Hide tip action + __webpack_require__(1).registerAction( + { + type: 'hideTip', + event: 'hideTip', + update: 'tooltip:manuallyHideTip' + }, + // noop + function () {} + ); + + +/***/ }, +/* 328 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(1).extendComponentModel({ + + type: 'tooltip', + + dependencies: ['axisPointer'], + + defaultOption: { + zlevel: 0, + + z: 8, + + show: true, + + // tooltip主体内容 + showContent: true, + + // 'trigger' only works on coordinate system. + // 'item' | 'axis' | 'none' + trigger: 'item', + + // 'click' | 'mousemove' | 'none' + triggerOn: 'mousemove|click', + + alwaysShowContent: false, + + displayMode: 'single', // 'single' | 'multipleByCoordSys' + + // 位置 {Array} | {Function} + // position: null + // Consider triggered from axisPointer handle, verticalAlign should be 'middle' + // align: null, + // verticalAlign: null, + + // 是否约束 content 在 viewRect 中。默认 false 是为了兼容以前版本。 + confine: false, + + // 内容格式器:{string}(Template) ¦ {Function} + // formatter: null + + showDelay: 0, + + // 隐藏延迟,单位ms + hideDelay: 100, + + // 动画变换时间,单位s + transitionDuration: 0.4, + + enterable: false, + + // 提示背景颜色,默认为透明度为0.7的黑色 + backgroundColor: 'rgba(50,50,50,0.7)', + + // 提示边框颜色 + borderColor: '#333', + + // 提示边框圆角,单位px,默认为4 + borderRadius: 4, + + // 提示边框线宽,单位px,默认为0(无边框) + borderWidth: 0, + + // 提示内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + padding: 5, + + // Extra css text + extraCssText: '', + + // 坐标轴指示器,坐标轴触发有效 + axisPointer: { + // 默认为直线 + // 可选为:'line' | 'shadow' | 'cross' + type: 'line', + + // type 为 line 的时候有效,指定 tooltip line 所在的轴,可选 + // 可选 'x' | 'y' | 'angle' | 'radius' | 'auto' + // 默认 'auto',会选择类型为 cateogry 的轴,对于双数值轴,笛卡尔坐标系会默认选择 x 轴 + // 极坐标系会默认选择 angle 轴 + axis: 'auto', + + animation: 'auto', + animationDurationUpdate: 200, + animationEasingUpdate: 'exponentialOut', + + crossStyle: { + color: '#999', + width: 1, + type: 'dashed', + + // TODO formatter + textStyle: {} + } + + // lineStyle and shadowStyle should not be specified here, + // otherwise it will always override those styles on option.axisPointer. + }, + textStyle: { + color: '#fff', + fontSize: 14 + } + } + }); + + +/***/ }, +/* 329 */ +/***/ function(module, exports, __webpack_require__) { + + + + var TooltipContent = __webpack_require__(330); + var zrUtil = __webpack_require__(4); + var formatUtil = __webpack_require__(6); + var numberUtil = __webpack_require__(7); + var graphic = __webpack_require__(18); + var findPointFromSeries = __webpack_require__(300); + var layoutUtil = __webpack_require__(71); + var env = __webpack_require__(2); + var Model = __webpack_require__(12); + var globalListener = __webpack_require__(303); + var axisHelper = __webpack_require__(101); + var axisPointerViewHelper = __webpack_require__(306); + + var bind = zrUtil.bind; + var each = zrUtil.each; + var parsePercent = numberUtil.parsePercent; + + + var proxyRect = new graphic.Rect({ + shape: {x: -1, y: -1, width: 2, height: 2} + }); + + __webpack_require__(1).extendComponentView({ + + type: 'tooltip', + + init: function (ecModel, api) { + if (env.node) { + return; + } + var tooltipContent = new TooltipContent(api.getDom(), api); + this._tooltipContent = tooltipContent; + }, + + render: function (tooltipModel, ecModel, api) { + if (env.node) { + return; + } + + // Reset + this.group.removeAll(); + + /** + * @private + * @type {module:echarts/component/tooltip/TooltipModel} + */ + this._tooltipModel = tooltipModel; + + /** + * @private + * @type {module:echarts/model/Global} + */ + this._ecModel = ecModel; + + /** + * @private + * @type {module:echarts/ExtensionAPI} + */ + this._api = api; + + /** + * Should be cleaned when render. + * @private + * @type {Array.>} + */ + this._lastDataByCoordSys = null; + + /** + * @private + * @type {boolean} + */ + this._alwaysShowContent = tooltipModel.get('alwaysShowContent'); + + var tooltipContent = this._tooltipContent; + tooltipContent.update(); + tooltipContent.setEnterable(tooltipModel.get('enterable')); + + this._initGlobalListener(); + + this._keepShow(); + }, + + _initGlobalListener: function () { + var tooltipModel = this._tooltipModel; + var triggerOn = tooltipModel.get('triggerOn'); + + globalListener.register( + 'itemTooltip', + this._api, + bind(function (currTrigger, e, dispatchAction) { + // If 'none', it is not controlled by mouse totally. + if (triggerOn !== 'none') { + if (triggerOn.indexOf(currTrigger) >= 0) { + this._tryShow(e, dispatchAction); + } + else if (currTrigger === 'leave') { + this._hide(dispatchAction); + } + } + }, this) + ); + }, + + _keepShow: function () { + var tooltipModel = this._tooltipModel; + var ecModel = this._ecModel; + var api = this._api; + + // Try to keep the tooltip show when refreshing + if (this._lastX != null + && this._lastY != null + // When user is willing to control tooltip totally using API, + // self.manuallyShowTip({x, y}) might cause tooltip hide, + // which is not expected. + && tooltipModel.get('triggerOn') !== 'none' + ) { + var self = this; + clearTimeout(this._refreshUpdateTimeout); + this._refreshUpdateTimeout = setTimeout(function () { + // Show tip next tick after other charts are rendered + // In case highlight action has wrong result + // FIXME + self.manuallyShowTip(tooltipModel, ecModel, api, { + x: self._lastX, + y: self._lastY + }); + }); + } + }, + + /** + * Show tip manually by + * dispatchAction({ + * type: 'showTip', + * x: 10, + * y: 10 + * }); + * Or + * dispatchAction({ + * type: 'showTip', + * seriesIndex: 0, + * dataIndex or dataIndexInside or name + * }); + * + * TODO Batch + */ + manuallyShowTip: function (tooltipModel, ecModel, api, payload) { + if (payload.from === this.uid || env.node) { + return; + } + + var dispatchAction = makeDispatchAction(payload, api); + + // Reset ticket + this._ticket = ''; + + // When triggered from axisPointer. + var dataByCoordSys = payload.dataByCoordSys; + + if (payload.tooltip && payload.x != null && payload.y != null) { + var el = proxyRect; + el.position = [payload.x, payload.y]; + el.update(); + el.tooltip = payload.tooltip; + // Manually show tooltip while view is not using zrender elements. + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + target: el + }, dispatchAction); + } + else if (dataByCoordSys) { + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + event: {}, + dataByCoordSys: payload.dataByCoordSys, + tooltipOption: payload.tooltipOption + }, dispatchAction); + } + else if (payload.seriesIndex != null) { + + if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) { + return; + } + + var pointInfo = findPointFromSeries(payload, ecModel); + var cx = pointInfo.point[0]; + var cy = pointInfo.point[1]; + if (cx != null && cy != null) { + this._tryShow({ + offsetX: cx, + offsetY: cy, + position: payload.position, + target: pointInfo.el, + event: {} + }, dispatchAction); + } + } + else if (payload.x != null && payload.y != null) { + // FIXME + // should wrap dispatchAction like `axisPointer/globalListener` ? + api.dispatchAction({ + type: 'updateAxisPointer', + x: payload.x, + y: payload.y + }); + + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + target: api.getZr().findHover(payload.x, payload.y).target, + event: {} + }, dispatchAction); + } + }, + + manuallyHideTip: function (tooltipModel, ecModel, api, payload) { + var tooltipContent = this._tooltipContent; + + if (!this._alwaysShowContent) { + tooltipContent.hideLater(this._tooltipModel.get('hideDelay')); + } + + this._lastX = this._lastY = null; + + if (payload.from !== this.uid) { + this._hide(makeDispatchAction(payload, api)); + } + }, + + // Be compatible with previous design, that is, when tooltip.type is 'axis' and + // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer + // and tooltip. + _manuallyAxisShowTip: function (tooltipModel, ecModel, api, payload) { + var seriesIndex = payload.seriesIndex; + var dataIndex = payload.dataIndex; + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; + + if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) { + return; + } + + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + if (!seriesModel) { + return; + } + + var data = seriesModel.getData(); + var tooltipModel = buildTooltipModel([ + data.getItemModel(dataIndex), + seriesModel, + (seriesModel.coordinateSystem || {}).model, + tooltipModel + ]); + + if (tooltipModel.get('trigger') !== 'axis') { + return; + } + + api.dispatchAction({ + type: 'updateAxisPointer', + seriesIndex: seriesIndex, + dataIndex: dataIndex, + position: payload.position + }); + + return true; + }, + + _tryShow: function (e, dispatchAction) { + var el = e.target; + var tooltipModel = this._tooltipModel; + + if (!tooltipModel) { + return; + } + + // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed + this._lastX = e.offsetX; + this._lastY = e.offsetY; + + var dataByCoordSys = e.dataByCoordSys; + if (dataByCoordSys && dataByCoordSys.length) { + this._showAxisTooltip(dataByCoordSys, e); + } + // Always show item tooltip if mouse is on the element with dataIndex + else if (el && el.dataIndex != null) { + this._lastDataByCoordSys = null; + this._showSeriesItemTooltip(e, el, dispatchAction); + } + // Tooltip provided directly. Like legend. + else if (el && el.tooltip) { + this._lastDataByCoordSys = null; + this._showComponentItemTooltip(e, el, dispatchAction); + } + else { + this._lastDataByCoordSys = null; + this._hide(dispatchAction); + } + }, + + _showOrMove: function (tooltipModel, cb) { + // showDelay is used in this case: tooltip.enterable is set + // as true. User intent to move mouse into tooltip and click + // something. `showDelay` makes it easyer to enter the content + // but tooltip do not move immediately. + var delay = tooltipModel.get('showDelay'); + cb = zrUtil.bind(cb, this); + clearTimeout(this._showTimout); + delay > 0 + ? (this._showTimout = setTimeout(cb, delay)) + : cb(); + }, + + _showAxisTooltip: function (dataByCoordSys, e) { + var ecModel = this._ecModel; + var globalTooltipModel = this._tooltipModel; + var point = [e.offsetX, e.offsetY]; + var singleDefaultHTML = []; + var singleParamsList = []; + var singleTooltipModel = buildTooltipModel([ + e.tooltipOption, + globalTooltipModel + ]); + + each(dataByCoordSys, function (itemCoordSys) { + // var coordParamList = []; + // var coordDefaultHTML = []; + // var coordTooltipModel = buildTooltipModel([ + // e.tooltipOption, + // itemCoordSys.tooltipOption, + // ecModel.getComponent(itemCoordSys.coordSysMainType, itemCoordSys.coordSysIndex), + // globalTooltipModel + // ]); + // var displayMode = coordTooltipModel.get('displayMode'); + // var paramsList = displayMode === 'single' ? singleParamsList : []; + + each(itemCoordSys.dataByAxis, function (item) { + var axisModel = ecModel.getComponent(item.axisDim + 'Axis', item.axisIndex); + var axisValue = item.value; + var seriesDefaultHTML = []; + + if (!axisModel || axisValue == null) { + return; + } + + var valueLabel = axisPointerViewHelper.getValueLabel( + axisValue, axisModel.axis, ecModel, + item.seriesDataIndices, + item.valueLabelOpt + ); + + zrUtil.each(item.seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var dataParams = series && series.getDataParams(dataIndex); + dataParams.axisDim = item.axisDim; + dataParams.axisIndex = item.axisIndex; + dataParams.axisType = item.axisType; + dataParams.axisId = item.axisId; + dataParams.axisValue = axisHelper.getAxisRawValue(axisModel.axis, axisValue); + dataParams.axisValueLabel = valueLabel; + + if (dataParams) { + singleParamsList.push(dataParams); + seriesDefaultHTML.push(series.formatTooltip(dataIndex, true)); + } + }); + + // Default tooltip content + // FIXME + // (1) shold be the first data which has name? + // (2) themeRiver, firstDataIndex is array, and first line is unnecessary. + var firstLine = valueLabel; + singleDefaultHTML.push( + (firstLine ? formatUtil.encodeHTML(firstLine) + '
' : '') + + seriesDefaultHTML.join('
') + ); + }); + }, this); + + // In most case, the second axis is shown upper than the first one. + singleDefaultHTML.reverse(); + singleDefaultHTML = singleDefaultHTML.join('

'); + + var positionExpr = e.position; + this._showOrMove(singleTooltipModel, function () { + if (this._updateContentNotChangedOnAxis(dataByCoordSys)) { + this._updatePosition( + singleTooltipModel, + positionExpr, + point[0], point[1], + this._tooltipContent, + singleParamsList + ); + } + else { + this._showTooltipContent( + singleTooltipModel, singleDefaultHTML, singleParamsList, Math.random(), + point[0], point[1], positionExpr + ); + } + }); + + // Do not trigger events here, because this branch only be entered + // from dispatchAction. + }, + + _showSeriesItemTooltip: function (e, el, dispatchAction) { + var ecModel = this._ecModel; + // Use dataModel in element if possible + // Used when mouseover on a element like markPoint or edge + // In which case, the data is not main data in series. + var seriesIndex = el.seriesIndex; + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + + // For example, graph link. + var dataModel = el.dataModel || seriesModel; + var dataIndex = el.dataIndex; + var dataType = el.dataType; + var data = dataModel.getData(); + + var tooltipModel = buildTooltipModel([ + data.getItemModel(dataIndex), + dataModel, + seriesModel && (seriesModel.coordinateSystem || {}).model, + this._tooltipModel + ]); + + var tooltipTrigger = tooltipModel.get('trigger'); + if (tooltipTrigger != null && tooltipTrigger !== 'item') { + return; + } + + var params = dataModel.getDataParams(dataIndex, dataType); + var defaultHtml = dataModel.formatTooltip(dataIndex, false, dataType); + var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex; + + this._showOrMove(tooltipModel, function () { + this._showTooltipContent( + tooltipModel, defaultHtml, params, asyncTicket, + e.offsetX, e.offsetY, e.position, e.target + ); + }); + + // FIXME + // duplicated showtip if manuallyShowTip is called from dispatchAction. + dispatchAction({ + type: 'showTip', + dataIndexInside: dataIndex, + dataIndex: data.getRawIndex(dataIndex), + seriesIndex: seriesIndex, + from: this.uid + }); + }, + + _showComponentItemTooltip: function (e, el, dispatchAction) { + var tooltipOpt = el.tooltip; + if (typeof tooltipOpt === 'string') { + var content = tooltipOpt; + tooltipOpt = { + content: content, + // Fixed formatter + formatter: content + }; + } + var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel); + var defaultHtml = subTooltipModel.get('content'); + var asyncTicket = Math.random(); + + // Do not check whether `trigger` is 'none' here, because `trigger` + // only works on cooridinate system. In fact, we have not found case + // that requires setting `trigger` nothing on component yet. + + this._showOrMove(subTooltipModel, function () { + this._showTooltipContent( + subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {}, + asyncTicket, e.offsetX, e.offsetY, e.position, el + ); + }); + + // If not dispatch showTip, tip may be hide triggered by axis. + dispatchAction({ + type: 'showTip', + from: this.uid + }); + }, + + _showTooltipContent: function ( + tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el + ) { + // Reset ticket + this._ticket = ''; + + if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) { + return; + } + + var tooltipContent = this._tooltipContent; + + var formatter = tooltipModel.get('formatter'); + positionExpr = positionExpr || tooltipModel.get('position'); + var html = defaultHtml; + + if (formatter && typeof formatter === 'string') { + html = formatUtil.formatTpl(formatter, params, true); + } + else if (typeof formatter === 'function') { + var callback = bind(function (cbTicket, html) { + if (cbTicket === this._ticket) { + tooltipContent.setContent(html); + this._updatePosition( + tooltipModel, positionExpr, x, y, tooltipContent, params, el + ); + } + }, this); + this._ticket = asyncTicket; + html = formatter(params, asyncTicket, callback); + } + + tooltipContent.setContent(html); + tooltipContent.show(tooltipModel); + + this._updatePosition( + tooltipModel, positionExpr, x, y, tooltipContent, params, el + ); + }, + + /** + * @param {string|Function|Array.} positionExpr + * @param {number} x Mouse x + * @param {number} y Mouse y + * @param {boolean} confine Whether confine tooltip content in view rect. + * @param {Object|} params + * @param {module:zrender/Element} el target element + * @param {module:echarts/ExtensionAPI} api + * @return {Array.} + */ + _updatePosition: function (tooltipModel, positionExpr, x, y, content, params, el) { + var viewWidth = this._api.getWidth(); + var viewHeight = this._api.getHeight(); + positionExpr = positionExpr || tooltipModel.get('position'); + + var contentSize = content.getSize(); + var align = tooltipModel.get('align'); + var vAlign = tooltipModel.get('verticalAlign'); + var rect = el && el.getBoundingRect().clone(); + el && rect.applyTransform(el.transform); + + if (typeof positionExpr === 'function') { + // Callback of position can be an array or a string specify the position + positionExpr = positionExpr([x, y], params, content.el, rect, { + viewSize: [viewWidth, viewHeight], + contentSize: contentSize.slice() + }); + } + + if (zrUtil.isArray(positionExpr)) { + x = parsePercent(positionExpr[0], viewWidth); + y = parsePercent(positionExpr[1], viewHeight); + } + else if (zrUtil.isObject(positionExpr)) { + positionExpr.width = contentSize[0]; + positionExpr.height = contentSize[1]; + var layoutRect = layoutUtil.getLayoutRect( + positionExpr, {width: viewWidth, height: viewHeight} + ); + x = layoutRect.x; + y = layoutRect.y; + align = null; + // When positionExpr is left/top/right/bottom, + // align and verticalAlign will not work. + vAlign = null; + } + // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element + else if (typeof positionExpr === 'string' && el) { + var pos = calcTooltipPosition( + positionExpr, rect, contentSize + ); + x = pos[0]; + y = pos[1]; + } + else { + var pos = refixTooltipPosition( + x, y, content.el, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20 + ); + x = pos[0]; + y = pos[1]; + } + + align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0); + vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0); + + if (tooltipModel.get('confine')) { + var pos = confineTooltipPosition( + x, y, content.el, viewWidth, viewHeight + ); + x = pos[0]; + y = pos[1]; + } + + content.moveTo(x, y); + }, + + // FIXME + // Should we remove this but leave this to user? + _updateContentNotChangedOnAxis: function (dataByCoordSys) { + var lastCoordSys = this._lastDataByCoordSys; + var contentNotChanged = !!lastCoordSys + && lastCoordSys.length === dataByCoordSys.length; + + contentNotChanged && each(lastCoordSys, function (lastItemCoordSys, indexCoordSys) { + var lastDataByAxis = lastItemCoordSys.dataByAxis || {}; + var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {}; + var thisDataByAxis = thisItemCoordSys.dataByAxis || []; + contentNotChanged &= lastDataByAxis.length === thisDataByAxis.length; + + contentNotChanged && each(lastDataByAxis, function (lastItem, indexAxis) { + var thisItem = thisDataByAxis[indexAxis] || {}; + var lastIndices = lastItem.seriesDataIndices || []; + var newIndices = thisItem.seriesDataIndices || []; + + contentNotChanged &= + lastItem.value === thisItem.value + && lastItem.axisType === thisItem.axisType + && lastItem.axisId === thisItem.axisId + && lastIndices.length === newIndices.length; + + contentNotChanged && each(lastIndices, function (lastIdxItem, j) { + var newIdxItem = newIndices[j]; + contentNotChanged &= + lastIdxItem.seriesIndex === newIdxItem.seriesIndex + && lastIdxItem.dataIndex === newIdxItem.dataIndex; + }); + }); + }); + + this._lastDataByCoordSys = dataByCoordSys; + + return !!contentNotChanged; + }, + + _hide: function (dispatchAction) { + // Do not directly hideLater here, because this behavior may be prevented + // in dispatchAction when showTip is dispatched. + + // FIXME + // duplicated hideTip if manuallyHideTip is called from dispatchAction. + this._lastDataByCoordSys = null; + dispatchAction({ + type: 'hideTip', + from: this.uid + }); + }, + + dispose: function (ecModel, api) { + if (env.node) { + return; + } + this._tooltipContent.hide(); + globalListener.unregister('itemTooltip', api); + } + }); + + + /** + * @param {Array.} modelCascade + * From top to bottom. (the last one should be globalTooltipModel); + */ + function buildTooltipModel(modelCascade) { + var resultModel = modelCascade.pop(); + while (modelCascade.length) { + var tooltipOpt = modelCascade.pop(); + if (tooltipOpt) { + if (tooltipOpt instanceof Model) { + tooltipOpt = tooltipOpt.get('tooltip', true); + } + // In each data item tooltip can be simply write: + // { + // value: 10, + // tooltip: 'Something you need to know' + // } + if (typeof tooltipOpt === 'string') { + tooltipOpt = {formatter: tooltipOpt}; + } + resultModel = new Model(tooltipOpt, resultModel, resultModel.ecModel); + } + } + return resultModel; + } + + function makeDispatchAction(payload, api) { + return payload.dispatchAction || zrUtil.bind(api.dispatchAction, api); + } + + function refixTooltipPosition(x, y, el, viewWidth, viewHeight, gapH, gapV) { + var width = el.clientWidth; + var height = el.clientHeight; + + if (gapH != null) { + if (x + width + gapH > viewWidth) { + x -= width + gapH; + } + else { + x += gapH; + } + } + if (gapV != null) { + if (y + height + gapV > viewHeight) { + y -= height + gapV; + } + else { + y += gapV; + } + } + return [x, y]; + } + + function confineTooltipPosition(x, y, el, viewWidth, viewHeight) { + var width = el.clientWidth; + var height = el.clientHeight; + + x = Math.min(x + width, viewWidth) - width; + y = Math.min(y + height, viewHeight) - height; + x = Math.max(x, 0); + y = Math.max(y, 0); + + return [x, y]; + } + + function calcTooltipPosition(position, rect, contentSize) { + var domWidth = contentSize[0]; + var domHeight = contentSize[1]; + var gap = 5; + var x = 0; + var y = 0; + var rectWidth = rect.width; + var rectHeight = rect.height; + switch (position) { + case 'inside': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + case 'top': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y - domHeight - gap; + break; + case 'bottom': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight + gap; + break; + case 'left': + x = rect.x - domWidth - gap; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + case 'right': + x = rect.x + rectWidth + gap; + y = rect.y + rectHeight / 2 - domHeight / 2; + } + return [x, y]; + } + + function isCenterAlign(align) { + return align === 'center' || align === 'middle'; + } + + + +/***/ }, +/* 330 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/component/tooltip/TooltipContent + */ + + + var zrUtil = __webpack_require__(4); + var zrColor = __webpack_require__(31); + var eventUtil = __webpack_require__(88); + var formatUtil = __webpack_require__(6); + var each = zrUtil.each; + var toCamelCase = formatUtil.toCamelCase; + var env = __webpack_require__(2); + + var vendors = ['', '-webkit-', '-moz-', '-o-']; + + var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;'; + + /** + * @param {number} duration + * @return {string} + * @inner + */ + function assembleTransition(duration) { + var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)'; + var transitionText = 'left ' + duration + 's ' + transitionCurve + ',' + + 'top ' + duration + 's ' + transitionCurve; + return zrUtil.map(vendors, function (vendorPrefix) { + return vendorPrefix + 'transition:' + transitionText; + }).join(';'); + } + + /** + * @param {Object} textStyle + * @return {string} + * @inner + */ + function assembleFont(textStyleModel) { + var cssText = []; + + var fontSize = textStyleModel.get('fontSize'); + var color = textStyleModel.getTextColor(); + + color && cssText.push('color:' + color); + + cssText.push('font:' + textStyleModel.getFont()); + + fontSize && + cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px'); + + each(['decoration', 'align'], function (name) { + var val = textStyleModel.get(name); + val && cssText.push('text-' + name + ':' + val); + }); + + return cssText.join(';'); + } + + /** + * @param {Object} tooltipModel + * @return {string} + * @inner + */ + function assembleCssText(tooltipModel) { + + var cssText = []; + + var transitionDuration = tooltipModel.get('transitionDuration'); + var backgroundColor = tooltipModel.get('backgroundColor'); + var textStyleModel = tooltipModel.getModel('textStyle'); + var padding = tooltipModel.get('padding'); + + // Animation transition. Do not animate when transitionDuration is 0. + transitionDuration && + cssText.push(assembleTransition(transitionDuration)); + + if (backgroundColor) { + if (env.canvasSupported) { + cssText.push('background-Color:' + backgroundColor); + } + else { + // for ie + cssText.push( + 'background-Color:#' + zrColor.toHex(backgroundColor) + ); + cssText.push('filter:alpha(opacity=70)'); + } + } + + // Border style + each(['width', 'color', 'radius'], function (name) { + var borderName = 'border-' + name; + var camelCase = toCamelCase(borderName); + var val = tooltipModel.get(camelCase); + val != null && + cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px')); + }); + + // Text style + cssText.push(assembleFont(textStyleModel)); + + // Padding + if (padding != null) { + cssText.push('padding:' + formatUtil.normalizeCssArray(padding).join('px ') + 'px'); + } + + return cssText.join(';') + ';'; + } + + /** + * @alias module:echarts/component/tooltip/TooltipContent + * @constructor + */ + function TooltipContent(container, api) { + var el = document.createElement('div'); + var zr = this._zr = api.getZr(); + + this.el = el; + + this._x = api.getWidth() / 2; + this._y = api.getHeight() / 2; + + container.appendChild(el); + + this._container = container; + + this._show = false; + + /** + * @private + */ + this._hideTimeout; + + var self = this; + el.onmouseenter = function () { + // clear the timeout in hideLater and keep showing tooltip + if (self._enterable) { + clearTimeout(self._hideTimeout); + self._show = true; + } + self._inContent = true; + }; + el.onmousemove = function (e) { + e = e || window.event; + if (!self._enterable) { + // Try trigger zrender event to avoid mouse + // in and out shape too frequently + var handler = zr.handler; + eventUtil.normalizeEvent(container, e, true); + handler.dispatch('mousemove', e); + } + }; + el.onmouseleave = function () { + if (self._enterable) { + if (self._show) { + self.hideLater(self._hideDelay); + } + } + self._inContent = false; + }; + } + + TooltipContent.prototype = { + + constructor: TooltipContent, + + /** + * @private + * @type {boolean} + */ + _enterable: true, + + /** + * Update when tooltip is rendered + */ + update: function () { + // FIXME + // Move this logic to ec main? + var container = this._container; + var stl = container.currentStyle + || document.defaultView.getComputedStyle(container); + var domStyle = container.style; + if (domStyle.position !== 'absolute' && stl.position !== 'absolute') { + domStyle.position = 'relative'; + } + // Hide the tooltip + // PENDING + // this.hide(); + }, + + show: function (tooltipModel) { + clearTimeout(this._hideTimeout); + var el = this.el; + + el.style.cssText = gCssText + assembleCssText(tooltipModel) + // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore + + ';left:' + this._x + 'px;top:' + this._y + 'px;' + + (tooltipModel.get('extraCssText') || ''); + + el.style.display = el.innerHTML ? 'block' : 'none'; + + this._show = true; + }, + + setContent: function (content) { + this.el.innerHTML = content == null ? '' : content; + }, + + setEnterable: function (enterable) { + this._enterable = enterable; + }, + + getSize: function () { + var el = this.el; + return [el.clientWidth, el.clientHeight]; + }, + + moveTo: function (x, y) { + // xy should be based on canvas root. But tooltipContent is + // the sibling of canvas root. So padding of ec container + // should be considered here. + var zr = this._zr; + var viewportRoot; + if (zr && zr.painter && (viewportRoot = zr.painter.getViewportRoot())) { + x += viewportRoot.offsetLeft || 0; + y += viewportRoot.offsetTop || 0; + } + + var style = this.el.style; + style.left = x + 'px'; + style.top = y + 'px'; + + this._x = x; + this._y = y; + }, + + hide: function () { + this.el.style.display = 'none'; + this._show = false; + }, + + hideLater: function (time) { + if (this._show && !(this._inContent && this._enterable)) { + if (time) { + this._hideDelay = time; + // Set show false to avoid invoke hideLater mutiple times + this._show = false; + this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time); + } + else { + this.hide(); + } + } + }, + + isShow: function () { + return this._show; + } + }; + + module.exports = TooltipContent; + + +/***/ }, +/* 331 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + + __webpack_require__(332); + __webpack_require__(338); + __webpack_require__(340); + __webpack_require__(298); + + __webpack_require__(342); + + // For reducing size of echarts.min, barLayoutPolar is required by polar. + __webpack_require__(1).registerLayout(zrUtil.curry(__webpack_require__(343), 'bar')); + + // Polar view + __webpack_require__(1).extendComponentView({ + type: 'polar' + }); + + +/***/ }, +/* 332 */ +/***/ function(module, exports, __webpack_require__) { + + // TODO Axis scale + + + var Polar = __webpack_require__(333); + var numberUtil = __webpack_require__(7); + var zrUtil = __webpack_require__(4); + + var axisHelper = __webpack_require__(101); + var niceScaleExtent = axisHelper.niceScaleExtent; + + // 依赖 PolarModel 做预处理 + __webpack_require__(336); + + /** + * Resize method bound to the polar + * @param {module:echarts/coord/polar/PolarModel} polarModel + * @param {module:echarts/ExtensionAPI} api + */ + function resizePolar(polarModel, api) { + var center = polarModel.get('center'); + var radius = polarModel.get('radius'); + var width = api.getWidth(); + var height = api.getHeight(); + var parsePercent = numberUtil.parsePercent; + + this.cx = parsePercent(center[0], width); + this.cy = parsePercent(center[1], height); + + var radiusAxis = this.getRadiusAxis(); + var size = Math.min(width, height) / 2; + // var idx = radiusAxis.inverse ? 1 : 0; + radiusAxis.setExtent(0, parsePercent(radius, size)); + } + + /** + * Update polar + */ + function updatePolarScale(ecModel, api) { + var polar = this; + var angleAxis = polar.getAngleAxis(); + var radiusAxis = polar.getRadiusAxis(); + // Reset scale + angleAxis.scale.setExtent(Infinity, -Infinity); + radiusAxis.scale.setExtent(Infinity, -Infinity); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === polar) { + var data = seriesModel.getData(); + radiusAxis.scale.unionExtentFromData(data, 'radius'); + angleAxis.scale.unionExtentFromData(data, 'angle'); + } + }); + + niceScaleExtent(angleAxis.scale, angleAxis.model); + niceScaleExtent(radiusAxis.scale, radiusAxis.model); + + // Fix extent of category angle axis + if (angleAxis.type === 'category' && !angleAxis.onBand) { + var extent = angleAxis.getExtent(); + var diff = 360 / angleAxis.scale.count(); + angleAxis.inverse ? (extent[1] += diff) : (extent[1] -= diff); + angleAxis.setExtent(extent[0], extent[1]); + } + } + + /** + * Set common axis properties + * @param {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + * @param {module:echarts/coord/polar/AxisModel} + * @inner + */ + function setAxis(axis, axisModel) { + axis.type = axisModel.get('type'); + axis.scale = axisHelper.createScaleByModel(axisModel); + axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category'; + + // FIXME Radius axis not support inverse axis + if (axisModel.mainType === 'angleAxis') { + var startAngle = axisModel.get('startAngle'); + axis.inverse = axisModel.get('inverse') ^ axisModel.get('clockwise'); + axis.setExtent(startAngle, startAngle + (axis.inverse ? -360 : 360)); + } + + // Inject axis instance + axisModel.axis = axis; + axis.model = axisModel; + } + + + var polarCreator = { + + dimensions: Polar.prototype.dimensions, + + create: function (ecModel, api) { + var polarList = []; + ecModel.eachComponent('polar', function (polarModel, idx) { + var polar = new Polar(idx); + // Inject resize and update method + polar.resize = resizePolar; + polar.update = updatePolarScale; + + var radiusAxis = polar.getRadiusAxis(); + var angleAxis = polar.getAngleAxis(); + + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + + setAxis(radiusAxis, radiusAxisModel); + setAxis(angleAxis, angleAxisModel); + + polar.resize(polarModel, api); + polarList.push(polar); + + polarModel.coordinateSystem = polar; + polar.model = polarModel; + }); + // Inject coordinateSystem to series + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'polar') { + var polarModel = ecModel.queryComponents({ + mainType: 'polar', + index: seriesModel.get('polarIndex'), + id: seriesModel.get('polarId') + })[0]; + + if (true) { + if (!polarModel) { + throw new Error( + 'Polar "' + zrUtil.retrieve( + seriesModel.get('polarIndex'), + seriesModel.get('polarId'), + 0 + ) + '" not found' + ); + } + } + seriesModel.coordinateSystem = polarModel.coordinateSystem; + } + }); + + return polarList; + } + }; + + __webpack_require__(76).register('polar', polarCreator); + + +/***/ }, +/* 333 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * @module echarts/coord/polar/Polar + */ + + + var RadiusAxis = __webpack_require__(334); + var AngleAxis = __webpack_require__(335); + + /** + * @alias {module:echarts/coord/polar/Polar} + * @constructor + * @param {string} name + */ + var Polar = function (name) { + + /** + * @type {string} + */ + this.name = name || ''; + + /** + * x of polar center + * @type {number} + */ + this.cx = 0; + + /** + * y of polar center + * @type {number} + */ + this.cy = 0; + + /** + * @type {module:echarts/coord/polar/RadiusAxis} + * @private + */ + this._radiusAxis = new RadiusAxis(); + + /** + * @type {module:echarts/coord/polar/AngleAxis} + * @private + */ + this._angleAxis = new AngleAxis(); + + this._radiusAxis.polar = this._angleAxis.polar = this; + }; + + Polar.prototype = { + + type: 'polar', + + axisPointerEnabled: true, + + constructor: Polar, + + /** + * @param {Array.} + * @readOnly + */ + dimensions: ['radius', 'angle'], + + /** + * @type {module:echarts/coord/PolarModel} + */ + model: null, + + /** + * If contain coord + * @param {Array.} point + * @return {boolean} + */ + containPoint: function (point) { + var coord = this.pointToCoord(point); + return this._radiusAxis.contain(coord[0]) + && this._angleAxis.contain(coord[1]); + }, + + /** + * If contain data + * @param {Array.} data + * @return {boolean} + */ + containData: function (data) { + return this._radiusAxis.containData(data[0]) + && this._angleAxis.containData(data[1]); + }, + + /** + * @param {string} dim + * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + */ + getAxis: function (dim) { + return this['_' + dim + 'Axis']; + }, + + /** + * @return {Array.} + */ + getAxes: function () { + return [this._radiusAxis, this._angleAxis]; + }, + + /** + * Get axes by type of scale + * @param {string} scaleType + * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + */ + getAxesByScale: function (scaleType) { + var axes = []; + var angleAxis = this._angleAxis; + var radiusAxis = this._radiusAxis; + angleAxis.scale.type === scaleType && axes.push(angleAxis); + radiusAxis.scale.type === scaleType && axes.push(radiusAxis); + + return axes; + }, + + /** + * @return {module:echarts/coord/polar/AngleAxis} + */ + getAngleAxis: function () { + return this._angleAxis; + }, + + /** + * @return {module:echarts/coord/polar/RadiusAxis} + */ + getRadiusAxis: function () { + return this._radiusAxis; + }, + + /** + * @param {module:echarts/coord/polar/Axis} + * @return {module:echarts/coord/polar/Axis} + */ + getOtherAxis: function (axis) { + var angleAxis = this._angleAxis; + return axis === angleAxis ? this._radiusAxis : angleAxis; + }, + + /** + * Base axis will be used on stacking. + * + * @return {module:echarts/coord/polar/Axis} + */ + getBaseAxis: function () { + return this.getAxesByScale('ordinal')[0] + || this.getAxesByScale('time')[0] + || this.getAngleAxis(); + }, + + /** + * @param {string} [dim] 'radius' or 'angle' or 'auto' or null/undefined + * @return {Object} {baseAxes: [], otherAxes: []} + */ + getTooltipAxes: function (dim) { + var baseAxis = (dim != null && dim !== 'auto') + ? this.getAxis(dim) : this.getBaseAxis(); + return { + baseAxes: [baseAxis], + otherAxes: [this.getOtherAxis(baseAxis)] + }; + }, + + /** + * Convert series data to a list of (x, y) points + * @param {module:echarts/data/List} data + * @return {Array} + * Return list of coordinates. For example: + * `[[10, 10], [20, 20], [30, 30]]` + */ + dataToPoints: function (data) { + return data.mapArray(this.dimensions, function (radius, angle) { + return this.dataToPoint([radius, angle]); + }, true, this); + }, + + /** + * Convert a single data item to (x, y) point. + * Parameter data is an array which the first element is radius and the second is angle + * @param {Array.} data + * @param {boolean} [clamp=false] + * @return {Array.} + */ + dataToPoint: function (data, clamp) { + return this.coordToPoint([ + this._radiusAxis.dataToRadius(data[0], clamp), + this._angleAxis.dataToAngle(data[1], clamp) + ]); + }, + + /** + * Convert a (x, y) point to data + * @param {Array.} point + * @param {boolean} [clamp=false] + * @return {Array.} + */ + pointToData: function (point, clamp) { + var coord = this.pointToCoord(point); + return [ + this._radiusAxis.radiusToData(coord[0], clamp), + this._angleAxis.angleToData(coord[1], clamp) + ]; + }, + + /** + * Convert a (x, y) point to (radius, angle) coord + * @param {Array.} point + * @return {Array.} + */ + pointToCoord: function (point) { + var dx = point[0] - this.cx; + var dy = point[1] - this.cy; + var angleAxis = this.getAngleAxis(); + var extent = angleAxis.getExtent(); + var minAngle = Math.min(extent[0], extent[1]); + var maxAngle = Math.max(extent[0], extent[1]); + // Fix fixed extent in polarCreator + // FIXME + angleAxis.inverse + ? (minAngle = maxAngle - 360) + : (maxAngle = minAngle + 360); + + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + + var radian = Math.atan2(-dy, dx) / Math.PI * 180; + + // move to angleExtent + var dir = radian < minAngle ? 1 : -1; + while (radian < minAngle || radian > maxAngle) { + radian += dir * 360; + } + + return [radius, radian]; + }, + + /** + * Convert a (radius, angle) coord to (x, y) point + * @param {Array.} coord + * @return {Array.} + */ + coordToPoint: function (coord) { + var radius = coord[0]; + var radian = coord[1] / 180 * Math.PI; + var x = Math.cos(radian) * radius + this.cx; + // Inverse the y + var y = -Math.sin(radian) * radius + this.cy; + + return [x, y]; + } + + }; + + module.exports = Polar; + + +/***/ }, +/* 334 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var Axis = __webpack_require__(100); + + function RadiusAxis(scale, radiusExtent) { + + Axis.call(this, 'radius', scale, radiusExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = 'category'; + } + + RadiusAxis.prototype = { + + constructor: RadiusAxis, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }, + + dataToRadius: Axis.prototype.dataToCoord, + + radiusToData: Axis.prototype.coordToData + }; + + zrUtil.inherits(RadiusAxis, Axis); + + module.exports = RadiusAxis; + + +/***/ }, +/* 335 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var Axis = __webpack_require__(100); + + function AngleAxis(scale, angleExtent) { + + angleExtent = angleExtent || [0, 360]; + + Axis.call(this, 'angle', scale, angleExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = 'category'; + } + + AngleAxis.prototype = { + + constructor: AngleAxis, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }, + + dataToAngle: Axis.prototype.dataToCoord, + + angleToData: Axis.prototype.coordToData + }; + + zrUtil.inherits(AngleAxis, Axis); + + module.exports = AngleAxis; + + +/***/ }, +/* 336 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + __webpack_require__(337); + + __webpack_require__(1).extendComponentModel({ + + type: 'polar', + + dependencies: ['polarAxis', 'angleAxis'], + + /** + * @type {module:echarts/coord/polar/Polar} + */ + coordinateSystem: null, + + /** + * @param {string} axisType + * @return {module:echarts/coord/polar/AxisModel} + */ + findAxisModel: function (axisType) { + var foundAxisModel; + var ecModel = this.ecModel; + + ecModel.eachComponent(axisType, function (axisModel) { + if (axisModel.getCoordSysModel() === this) { + foundAxisModel = axisModel; + } + }, this); + return foundAxisModel; + }, + + defaultOption: { + + zlevel: 0, + + z: 0, + + center: ['50%', '50%'], + + radius: '80%' + } + }); + + +/***/ }, +/* 337 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var ComponentModel = __webpack_require__(69); + var axisModelCreator = __webpack_require__(131); + + var PolarAxisModel = ComponentModel.extend({ + + type: 'polarAxis', + + /** + * @type {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + */ + axis: null, + + /** + * @override + */ + getCoordSysModel: function () { + return this.ecModel.queryComponents({ + mainType: 'polar', + index: this.option.polarIndex, + id: this.option.polarId + })[0]; + } + + }); + + zrUtil.merge(PolarAxisModel.prototype, __webpack_require__(112)); + + var polarAxisDefaultExtendedOption = { + angle: { + // polarIndex: 0, + // polarId: '', + + startAngle: 90, + + clockwise: true, + + splitNumber: 12, + + axisLabel: { + rotate: false + } + }, + radius: { + // polarIndex: 0, + // polarId: '', + + splitNumber: 5 + } + }; + + function getAxisType(axisDim, option) { + // Default axis with data is category axis + return option.type || (option.data ? 'category' : 'value'); + } + + axisModelCreator('angle', PolarAxisModel, getAxisType, polarAxisDefaultExtendedOption.angle); + axisModelCreator('radius', PolarAxisModel, getAxisType, polarAxisDefaultExtendedOption.radius); + + + +/***/ }, +/* 338 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + __webpack_require__(332); + + __webpack_require__(339); + + +/***/ }, +/* 339 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var Model = __webpack_require__(12); + + var elementList = ['axisLine', 'axisLabel', 'axisTick', 'splitLine', 'splitArea']; + + function getAxisLineShape(polar, r0, r, angle) { + var start = polar.coordToPoint([r0, angle]); + var end = polar.coordToPoint([r, angle]); + + return { + x1: start[0], + y1: start[1], + x2: end[0], + y2: end[1] + }; + } + + __webpack_require__(136).extend({ + + type: 'angleAxis', + + axisPointerClass: 'PolarAxisPointer', + + render: function (angleAxisModel, ecModel) { + this.group.removeAll(); + if (!angleAxisModel.get('show')) { + return; + } + + var angleAxis = angleAxisModel.axis; + var polar = angleAxis.polar; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var ticksAngles = angleAxis.getTicksCoords(); + + if (angleAxis.type !== 'category') { + // Remove the last tick which will overlap the first tick + ticksAngles.pop(); + } + + zrUtil.each(elementList, function (name) { + if (angleAxisModel.get(name +'.show') + && (!angleAxis.scale.isBlank() || name === 'axisLine') + ) { + this['_' + name](angleAxisModel, polar, ticksAngles, radiusExtent); + } + }, this); + }, + + /** + * @private + */ + _axisLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle'); + + var circle = new graphic.Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: radiusExtent[1] + }, + style: lineStyleModel.getLineStyle(), + z2: 1, + silent: true + }); + circle.style.fill = null; + + this.group.add(circle); + }, + + /** + * @private + */ + _axisTick: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + var tickModel = angleAxisModel.getModel('axisTick'); + + var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length'); + + var lines = zrUtil.map(ticksAngles, function (tickAngle) { + return new graphic.Line({ + shape: getAxisLineShape(polar, radiusExtent[1], radiusExtent[1] + tickLen, tickAngle) + }); + }); + this.group.add(graphic.mergePath( + lines, { + style: zrUtil.defaults( + tickModel.getModel('lineStyle').getLineStyle(), + { + stroke: angleAxisModel.get('axisLine.lineStyle.color') + } + ) + } + )); + }, + + /** + * @private + */ + _axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + var axis = angleAxisModel.axis; + + var categoryData = angleAxisModel.get('data'); + + var labelModel = angleAxisModel.getModel('axisLabel'); + var axisTextStyleModel = labelModel.getModel('textStyle'); + + var labels = angleAxisModel.getFormattedLabels(); + + var labelMargin = labelModel.get('margin'); + var labelsAngles = axis.getLabelsCoords(); + + // Use length of ticksAngles because it may remove the last tick to avoid overlapping + for (var i = 0; i < ticksAngles.length; i++) { + var r = radiusExtent[1]; + var p = polar.coordToPoint([r + labelMargin, labelsAngles[i]]); + var cx = polar.cx; + var cy = polar.cy; + + var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3 + ? 'center' : (p[0] > cx ? 'left' : 'right'); + var labelTextBaseline = Math.abs(p[1] - cy) / r < 0.3 + ? 'middle' : (p[1] > cy ? 'top' : 'bottom'); + + var textStyleModel = axisTextStyleModel; + if (categoryData && categoryData[i] && categoryData[i].textStyle) { + textStyleModel = new Model( + categoryData[i].textStyle, axisTextStyleModel + ); + } + this.group.add(new graphic.Text({ + style: { + x: p[0], + y: p[1], + fill: textStyleModel.getTextColor() || angleAxisModel.get('axisLine.lineStyle.color'), + text: labels[i], + textAlign: labelTextAlign, + textVerticalAlign: labelTextBaseline, + textFont: textStyleModel.getFont() + }, + silent: true + })); + } + }, + + /** + * @private + */ + _splitLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + var splitLineModel = angleAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + + var splitLines = []; + + for (var i = 0; i < ticksAngles.length; i++) { + var colorIndex = (lineCount++) % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new graphic.Line({ + shape: getAxisLineShape(polar, radiusExtent[0], radiusExtent[1], ticksAngles[i]) + })); + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitLines.length; i++) { + this.group.add(graphic.mergePath(splitLines[i], { + style: zrUtil.defaults({ + stroke: lineColors[i % lineColors.length] + }, lineStyleModel.getLineStyle()), + silent: true, + z: angleAxisModel.get('z') + })); + } + }, + + /** + * @private + */ + _splitArea: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + + var splitAreaModel = angleAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + + var splitAreas = []; + + var RADIAN = Math.PI / 180; + var prevAngle = -ticksAngles[0] * RADIAN; + var r0 = Math.min(radiusExtent[0], radiusExtent[1]); + var r1 = Math.max(radiusExtent[0], radiusExtent[1]); + + var clockwise = angleAxisModel.get('clockwise'); + + for (var i = 1; i < ticksAngles.length; i++) { + var colorIndex = (lineCount++) % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new graphic.Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: r0, + r: r1, + startAngle: prevAngle, + endAngle: -ticksAngles[i] * RADIAN, + clockwise: clockwise + }, + silent: true + })); + prevAngle = -ticksAngles[i] * RADIAN; + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitAreas.length; i++) { + this.group.add(graphic.mergePath(splitAreas[i], { + style: zrUtil.defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } + }); + + +/***/ }, +/* 340 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(332); + + __webpack_require__(341); + + +/***/ }, +/* 341 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var AxisBuilder = __webpack_require__(135); + + var axisBuilderAttrs = [ + 'axisLine', 'axisLabel', 'axisTick', 'axisName' + ]; + var selfBuilderAttrs = [ + 'splitLine', 'splitArea' + ]; + + __webpack_require__(136).extend({ + + type: 'radiusAxis', + + axisPointerClass: 'PolarAxisPointer', + + render: function (radiusAxisModel, ecModel) { + this.group.removeAll(); + if (!radiusAxisModel.get('show')) { + return; + } + var radiusAxis = radiusAxisModel.axis; + var polar = radiusAxis.polar; + var angleAxis = polar.getAngleAxis(); + var ticksCoords = radiusAxis.getTicksCoords(); + var axisAngle = angleAxis.getExtent()[0]; + var radiusExtent = radiusAxis.getExtent(); + + var layout = layoutAxis(polar, radiusAxisModel, axisAngle); + var axisBuilder = new AxisBuilder(radiusAxisModel, layout); + zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder); + this.group.add(axisBuilder.getGroup()); + + zrUtil.each(selfBuilderAttrs, function (name) { + if (radiusAxisModel.get(name +'.show') && !radiusAxis.scale.isBlank()) { + this['_' + name](radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords); + } + }, this); + }, + + /** + * @private + */ + _splitLine: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + var splitLineModel = radiusAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + + var splitLines = []; + + for (var i = 0; i < ticksCoords.length; i++) { + var colorIndex = (lineCount++) % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new graphic.Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: ticksCoords[i] + }, + silent: true + })); + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitLines.length; i++) { + this.group.add(graphic.mergePath(splitLines[i], { + style: zrUtil.defaults({ + stroke: lineColors[i % lineColors.length], + fill: null + }, lineStyleModel.getLineStyle()), + silent: true + })); + } + }, + + /** + * @private + */ + _splitArea: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + + var splitAreaModel = radiusAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + + var splitAreas = []; + + var prevRadius = ticksCoords[0]; + for (var i = 1; i < ticksCoords.length; i++) { + var colorIndex = (lineCount++) % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new graphic.Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: prevRadius, + r: ticksCoords[i], + startAngle: 0, + endAngle: Math.PI * 2 + }, + silent: true + })); + prevRadius = ticksCoords[i]; + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitAreas.length; i++) { + this.group.add(graphic.mergePath(splitAreas[i], { + style: zrUtil.defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } + }); + + /** + * @inner + */ + function layoutAxis(polar, radiusAxisModel, axisAngle) { + return { + position: [polar.cx, polar.cy], + rotation: axisAngle / 180 * Math.PI, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1, + labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'), + // Over splitLine and splitArea + z2: 1 + }; + } + + +/***/ }, +/* 342 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var formatUtil = __webpack_require__(6); + var BaseAxisPointer = __webpack_require__(305); + var graphic = __webpack_require__(18); + var viewHelper = __webpack_require__(306); + var matrix = __webpack_require__(11); + var AxisBuilder = __webpack_require__(135); + var AxisView = __webpack_require__(136); + + var PolarAxisPointer = BaseAxisPointer.extend({ + + /** + * @override + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + + if (axis.dim === 'angle') { + this.animationThreshold = Math.PI / 18; + } + + var polar = axis.polar; + var otherAxis = polar.getOtherAxis(axis); + var otherExtent = otherAxis.getExtent(); + + var coordValue; + coordValue = axis['dataTo' + formatUtil.capitalFirst(axis.dim)](value); + + var axisPointerType = axisPointerModel.get('type'); + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = viewHelper.buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder[axisPointerType]( + axis, polar, coordValue, otherExtent, elStyle + ); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var labelMargin = axisPointerModel.get('label.margin'); + var labelPos = getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin); + viewHelper.buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos); + } + + // Do not support handle, utill any user requires it. + + }); + + function getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin) { + var axis = axisModel.axis; + var coord = axis.dataToCoord(value); + var axisAngle = polar.getAngleAxis().getExtent()[0]; + axisAngle = axisAngle / 180 * Math.PI; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var position; + var align; + var verticalAlign; + + if (axis.dim === 'radius') { + var transform = matrix.create(); + matrix.rotate(transform, transform, axisAngle); + matrix.translate(transform, transform, [polar.cx, polar.cy]); + position = graphic.applyTransform([coord, -labelMargin], transform); + + var labelRotation = axisModel.getModel('axisLabel').get('rotate') || 0; + var labelLayout = AxisBuilder.innerTextLayout( + axisAngle, labelRotation * Math.PI / 180, -1 + ); + align = labelLayout.textAlign; + verticalAlign = labelLayout.textVerticalAlign; + } + else { // angle axis + var r = radiusExtent[1]; + position = polar.coordToPoint([r + labelMargin, coord]); + var cx = polar.cx; + var cy = polar.cy; + align = Math.abs(position[0] - cx) / r < 0.3 + ? 'center' : (position[0] > cx ? 'left' : 'right'); + verticalAlign = Math.abs(position[1] - cy) / r < 0.3 + ? 'middle' : (position[1] > cy ? 'top' : 'bottom'); + } + + return { + position: position, + align: align, + verticalAlign: verticalAlign + }; + } + + + var pointerShapeBuilder = { + + line: function (axis, polar, coordValue, otherExtent, elStyle) { + return axis.dim === 'angle' + ? { + type: 'Line', + shape: viewHelper.makeLineShape( + polar.coordToPoint([otherExtent[0], coordValue]), + polar.coordToPoint([otherExtent[1], coordValue]) + ) + } + : { + type: 'Circle', + shape: { + cx: polar.cx, + cy: polar.cy, + r: coordValue + } + }; + }, + + shadow: function (axis, polar, coordValue, otherExtent, elStyle) { + var bandWidth = axis.getBandWidth(); + var radian = Math.PI / 180; + + return axis.dim === 'angle' + ? { + type: 'Sector', + shape: viewHelper.makeSectorShape( + polar.cx, polar.cy, + otherExtent[0], otherExtent[1], + // In ECharts y is negative if angle is positive + (-coordValue - bandWidth / 2) * radian, + (-coordValue + bandWidth / 2) * radian + ) + } + : { + type: 'Sector', + shape: viewHelper.makeSectorShape( + polar.cx, polar.cy, + coordValue - bandWidth / 2, + coordValue + bandWidth / 2, + 0, Math.PI * 2 + ) + }; + } + }; + + AxisView.registerAxisPointerClass('PolarAxisPointer', PolarAxisPointer); + + module.exports = PolarAxisPointer; + + +/***/ }, +/* 343 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var parsePercent = __webpack_require__(7).parsePercent; + + function getSeriesStackId(seriesModel) { + return seriesModel.get('stack') + || '__ec_stack_' + seriesModel.seriesIndex; + } + + function getAxisKey(axis) { + return axis.dim; + } + + /** + * @param {string} seriesType + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + function barLayoutPolar(seriesType, ecModel, api) { + + var width = api.getWidth(); + var height = api.getHeight(); + + var lastStackCoords = {}; + var lastStackCoordsOrigin = {}; + + var barWidthAndOffset = calRadialBar( + zrUtil.filter( + ecModel.getSeriesByType(seriesType), + function (seriesModel) { + return !ecModel.isSeriesFiltered(seriesModel) + && seriesModel.coordinateSystem + && seriesModel.coordinateSystem.type === 'polar'; + } + ) + ); + + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + // Check series coordinate, do layout for polar only + if (seriesModel.coordinateSystem.type !== 'polar') { + return; + } + + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + var angleAxis = polar.getAngleAxis(); + var baseAxis = polar.getBaseAxis(); + + var stackId = getSeriesStackId(seriesModel); + var columnLayoutInfo + = barWidthAndOffset[getAxisKey(baseAxis)][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + var valueAxis = polar.getOtherAxis(baseAxis); + + var center = seriesModel.get('center') || ['50%', '50%']; + var cx = parsePercent(center[0], width); + var cy = parsePercent(center[1], height); + + var barMinHeight = seriesModel.get('barMinHeight') || 0; + var barMinAngle = seriesModel.get('barMinAngle') || 0; + + var valueAxisStart = valueAxis.getExtent()[0]; + var valueMax = valueAxis.model.get('max'); + var valueMin = valueAxis.model.get('min'); + + var coords = polar.dataToPoints(data); + lastStackCoords[stackId] = lastStackCoords[stackId] || []; + lastStackCoordsOrigin[stackId] = lastStackCoordsOrigin[stackId] || []; // Fix #4243 + + data.each(valueAxis.dim, function (value, idx) { + if (isNaN(value)) { + return; + } + + if (!lastStackCoords[stackId][idx]) { + lastStackCoords[stackId][idx] = { + p: valueAxisStart, // Positive stack + n: valueAxisStart // Negative stack + }; + lastStackCoordsOrigin[stackId][idx] = { + p: valueAxisStart, // Positive stack + n: valueAxisStart // Negative stack + }; + } + var sign = value >= 0 ? 'p' : 'n'; + var coord = polar.pointToCoord(coords[idx]); + + var lastCoordOrigin = lastStackCoordsOrigin[stackId][idx][sign]; + var r0; + var r; + var startAngle; + var endAngle; + + if (valueAxis.dim === 'radius') { + // radial sector + r0 = lastCoordOrigin; + r = coord[0]; + startAngle = (-coord[1] + columnOffset) * Math.PI / 180; + endAngle = startAngle + columnWidth * Math.PI / 180; + + if (Math.abs(r) < barMinHeight) { + r = r0 + (r < 0 ? -1 : 1) * barMinHeight; + } + + lastStackCoordsOrigin[stackId][idx][sign] = r; + } + else { + // tangential sector + r0 = coord[0] + columnOffset; + r = r0 + columnWidth; + + // clamp data if min or max is defined for valueAxis + if (valueMax != null) { + value = Math.min(value, valueMax); + } + if (valueMin != null) { + value = Math.max(value, valueMin); + } + + var angle = angleAxis.dataToAngle(value); + if (Math.abs(angle - lastCoordOrigin) < barMinAngle) { + angle = lastCoordOrigin - (value < 0 ? -1 : 1) + * barMinAngle; + } + + startAngle = -lastCoordOrigin * Math.PI / 180; + endAngle = -angle * Math.PI / 180; + + // if the previous stack is at the end of the ring, + // add a round to differentiate it from origin + var extent = angleAxis.getExtent(); + var stackCoord = angle; + if (stackCoord === extent[0] && value > 0) { + stackCoord = extent[1]; + } + else if (stackCoord === extent[1] && value < 0) { + stackCoord = extent[0]; + } + lastStackCoordsOrigin[stackId][idx][sign] = stackCoord; + } + + data.setItemLayout(idx, { + cx: cx, + cy: cy, + r0: r0, + r: r, + startAngle: startAngle, + endAngle: endAngle + }); + + }, true); + + }, this); + + } + + /** + * Calculate bar width and offset for radial bar charts + */ + function calRadialBar(barSeries, api) { + // Columns info on each category axis. Key is polar name + var columnsMap = {}; + + zrUtil.each(barSeries, function (seriesModel, idx) { + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + + var baseAxis = polar.getBaseAxis(); + + var axisExtent = baseAxis.getExtent(); + var bandWidth = baseAxis.type === 'category' + ? baseAxis.getBandWidth() + : (Math.abs(axisExtent[1] - axisExtent[0]) / data.count()); + + var columnsOnAxis = columnsMap[getAxisKey(baseAxis)] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: '20%', + gap: '30%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[getAxisKey(baseAxis)] = columnsOnAxis; + + var stackId = getSeriesStackId(seriesModel); + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; + + var barWidth = parsePercent( + seriesModel.get('barWidth'), + bandWidth + ); + var barMaxWidth = parsePercent( + seriesModel.get('barMaxWidth'), + bandWidth + ); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + + if (barWidth && !stacks[stackId].width) { + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + stacks[stackId].width = barWidth; + columnsOnAxis.remainedWidth -= barWidth; + } + + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + (barGap != null) && (columnsOnAxis.gap = barGap); + (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap); + }); + + + var result = {}; + + zrUtil.each(columnsMap, function (columnsOnAxis, coordSysName) { + + result[coordSysName] = {}; + + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGap = parsePercent(columnsOnAxis.categoryGap, bandWidth); + var barGapPercent = parsePercent(columnsOnAxis.gap, 1); + + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + // Find if any auto calculated bar exceeded maxBarWidth + zrUtil.each(stacks, function (column, stack) { + var maxWidth = column.maxWidth; + if (maxWidth && maxWidth < autoWidth) { + maxWidth = Math.min(maxWidth, remainedWidth); + if (column.width) { + maxWidth = Math.min(maxWidth, column.width); + } + remainedWidth -= maxWidth; + column.width = maxWidth; + autoWidthCount--; + } + }); + + // Recalculate width again + autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + var widthSum = 0; + var lastColumn; + zrUtil.each(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + zrUtil.each(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + offset: offset, + width: column.width + }; + + offset += column.width * (1 + barGapPercent); + }); + }); + + return result; + } + + module.exports = barLayoutPolar; + + + +/***/ }, +/* 344 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(345); + + __webpack_require__(171); + + __webpack_require__(346); + + __webpack_require__(187); + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + + function makeAction(method, actionInfo) { + actionInfo.update = 'updateView'; + echarts.registerAction(actionInfo, function (payload, ecModel) { + var selected = {}; + + ecModel.eachComponent( + { mainType: 'geo', query: payload}, + function (geoModel) { + geoModel[method](payload.name); + var geo = geoModel.coordinateSystem; + zrUtil.each(geo.regions, function (region) { + selected[region.name] = geoModel.isSelected(region.name) || false; + }); + } + ); + + return { + selected: selected, + name: payload.name + }; + }); + } + + makeAction('toggleSelected', { + type: 'geoToggleSelect', + event: 'geoselectchanged' + }); + makeAction('select', { + type: 'geoSelect', + event: 'geoselected' + }); + makeAction('unSelect', { + type: 'geoUnSelect', + event: 'geounselected' + }); + + +/***/ }, +/* 345 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var modelUtil = __webpack_require__(5); + var ComponentModel = __webpack_require__(69); + var Model = __webpack_require__(12); + var zrUtil = __webpack_require__(4); + + var selectableMixin = __webpack_require__(148); + + var geoCreator = __webpack_require__(171); + + var GeoModel = ComponentModel.extend({ + + type: 'geo', + + /** + * @type {module:echarts/coord/geo/Geo} + */ + coordinateSystem: null, + + layoutMode: 'box', + + init: function (option) { + ComponentModel.prototype.init.apply(this, arguments); + + // Default label emphasis `position` and `show` + modelUtil.defaultEmphasis( + option.label, ['position', 'show', 'textStyle', 'distance', 'formatter'] + ); + }, + + optionUpdated: function () { + var option = this.option; + var self = this; + + option.regions = geoCreator.getFilledRegions(option.regions, option.map); + + this._optionModelMap = zrUtil.reduce(option.regions || [], function (optionModelMap, regionOpt) { + if (regionOpt.name) { + optionModelMap.set(regionOpt.name, new Model(regionOpt, self)); + } + return optionModelMap; + }, zrUtil.createHashMap()); + + this.updateSelectedMap(option.regions); + }, + + defaultOption: { + + zlevel: 0, + + z: 0, + + show: true, + + left: 'center', + + top: 'center', + + + // width:, + // height:, + // right + // bottom + + // Aspect is width / height. Inited to be geoJson bbox aspect + // This parameter is used for scale this aspect + aspectScale: 0.75, + + ///// Layout with center and size + // If you wan't to put map in a fixed size box with right aspect ratio + // This two properties may more conveninet + // layoutCenter: [50%, 50%] + // layoutSize: 100 + + + silent: false, + + // Map type + map: '', + + // Define left-top, right-bottom coords to control view + // For example, [ [180, 90], [-180, -90] ] + boundingCoords: null, + + // Default on center of map + center: null, + + zoom: 1, + + scaleLimit: null, + + // selectedMode: false + + label: { + normal: { + show: false, + textStyle: { + color: '#000' + } + }, + emphasis: { + show: true, + textStyle: { + color: 'rgb(100,0,0)' + } + } + }, + + itemStyle: { + normal: { + // color: 各异, + borderWidth: 0.5, + borderColor: '#444', + color: '#eee' + }, + emphasis: { // 也是选中样式 + color: 'rgba(255,215,0,0.8)' + } + }, + + regions: [] + }, + + /** + * Get model of region + * @param {string} name + * @return {module:echarts/model/Model} + */ + getRegionModel: function (name) { + return this._optionModelMap.get(name) || new Model(null, this, this.ecModel); + }, + + /** + * Format label + * @param {string} name Region name + * @param {string} [status='normal'] 'normal' or 'emphasis' + * @return {string} + */ + getFormattedLabel: function (name, status) { + var regionModel = this.getRegionModel(name); + var formatter = regionModel.get('label.' + status + '.formatter'); + var params = { + name: name + }; + if (typeof formatter === 'function') { + params.status = status; + return formatter(params); + } + else if (typeof formatter === 'string') { + var serName = params.seriesName; + return formatter.replace('{a}', serName != null ? serName : ''); + } + }, + + setZoom: function (zoom) { + this.option.zoom = zoom; + }, + + setCenter: function (center) { + this.option.center = center; + } + }); + + zrUtil.mixin(GeoModel, selectableMixin); + + module.exports = GeoModel; + + +/***/ }, +/* 346 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var MapDraw = __webpack_require__(182); + + module.exports = __webpack_require__(1).extendComponentView({ + + type: 'geo', + + init: function (ecModel, api) { + var mapDraw = new MapDraw(api, true); + this._mapDraw = mapDraw; + + this.group.add(mapDraw.group); + }, + + render: function (geoModel, ecModel, api, payload) { + // Not render if it is an toggleSelect action from self + if (payload && payload.type === 'geoToggleSelect' + && payload.from === this.uid + ) { + return; + } + + var mapDraw = this._mapDraw; + if (geoModel.get('show')) { + mapDraw.draw(geoModel, ecModel, api, this, payload); + } + else { + this._mapDraw.group.removeAll(); + } + + this.group.silent = geoModel.get('silent'); + }, + + dispose: function () { + this._mapDraw && this._mapDraw.remove(); + } + + }); + + +/***/ }, +/* 347 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Brush component entry + */ + + + __webpack_require__(1).registerPreprocessor( + __webpack_require__(348) + ); + + __webpack_require__(349); + __webpack_require__(353); + __webpack_require__(354); + __webpack_require__(355); + + __webpack_require__(356); + + + +/***/ }, +/* 348 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file brush preprocessor + */ + + + var zrUtil = __webpack_require__(4); + + var DEFAULT_TOOLBOX_BTNS = ['rect', 'polygon', 'keep', 'clear']; + + module.exports = function (option, isNew) { + var brushComponents = option && option.brush; + if (!zrUtil.isArray(brushComponents)) { + brushComponents = brushComponents ? [brushComponents] : []; + } + + if (!brushComponents.length) { + return; + } + + var brushComponentSpecifiedBtns = []; + + zrUtil.each(brushComponents, function (brushOpt) { + var tbs = brushOpt.hasOwnProperty('toolbox') + ? brushOpt.toolbox : []; + + if (tbs instanceof Array) { + brushComponentSpecifiedBtns = brushComponentSpecifiedBtns.concat(tbs); + } + }); + + var toolbox = option && option.toolbox; + + if (zrUtil.isArray(toolbox)) { + toolbox = toolbox[0]; + } + if (!toolbox) { + toolbox = {feature: {}}; + option.toolbox = [toolbox]; + } + + var toolboxFeature = (toolbox.feature || (toolbox.feature = {})); + var toolboxBrush = toolboxFeature.brush || (toolboxFeature.brush = {}); + var brushTypes = toolboxBrush.type || (toolboxBrush.type = []); + + brushTypes.push.apply(brushTypes, brushComponentSpecifiedBtns); + + removeDuplicate(brushTypes); + + if (isNew && !brushTypes.length) { + brushTypes.push.apply(brushTypes, DEFAULT_TOOLBOX_BTNS); + } + }; + + function removeDuplicate(arr) { + var map = {}; + zrUtil.each(arr, function (val) { + map[val] = 1; + }); + arr.length = 0; + zrUtil.each(map, function (flag, val) { + arr.push(val); + }); + } + + + +/***/ }, +/* 349 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Brush visual coding. + */ + + + var echarts = __webpack_require__(1); + var visualSolution = __webpack_require__(350); + var zrUtil = __webpack_require__(4); + var BoundingRect = __webpack_require__(9); + var selector = __webpack_require__(351); + var throttle = __webpack_require__(81); + var BrushTargetManager = __webpack_require__(352); + + var STATE_LIST = ['inBrush', 'outOfBrush']; + var DISPATCH_METHOD = '__ecBrushSelect'; + var DISPATCH_FLAG = '__ecInBrushSelectEvent'; + var PRIORITY_BRUSH = echarts.PRIORITY.VISUAL.BRUSH; + + /** + * Layout for visual, the priority higher than other layout, and before brush visual. + */ + echarts.registerLayout(PRIORITY_BRUSH, function (ecModel, api, payload) { + ecModel.eachComponent({mainType: 'brush'}, function (brushModel) { + + payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption( + payload.key === 'brush' ? payload.brushOption : {brushType: false} + ); + + var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel); + + brushTargetManager.setInputRanges(brushModel.areas, ecModel); + }); + }); + + /** + * Register the visual encoding if this modules required. + */ + echarts.registerVisual(PRIORITY_BRUSH, function (ecModel, api, payload) { + + var brushSelected = []; + var throttleType; + var throttleDelay; + + ecModel.eachComponent({mainType: 'brush'}, function (brushModel, brushIndex) { + + var thisBrushSelected = { + brushId: brushModel.id, + brushIndex: brushIndex, + brushName: brushModel.name, + areas: zrUtil.clone(brushModel.areas), + selected: [] + }; + // Every brush component exists in event params, convenient + // for user to find by index. + brushSelected.push(thisBrushSelected); + + var brushOption = brushModel.option; + var brushLink = brushOption.brushLink; + var linkedSeriesMap = []; + var selectedDataIndexForLink = []; + var rangeInfoBySeries = []; + var hasBrushExists = 0; + + if (!brushIndex) { // Only the first throttle setting works. + throttleType = brushOption.throttleType; + throttleDelay = brushOption.throttleDelay; + } + + // Add boundingRect and selectors to range. + var areas = zrUtil.map(brushModel.areas, function (area) { + return bindSelector( + zrUtil.defaults( + {boundingRect: boundingRectBuilders[area.brushType](area)}, + area + ) + ); + }); + + var visualMappings = visualSolution.createVisualMappings( + brushModel.option, STATE_LIST, function (mappingOption) { + mappingOption.mappingMethod = 'fixed'; + } + ); + + zrUtil.isArray(brushLink) && zrUtil.each(brushLink, function (seriesIndex) { + linkedSeriesMap[seriesIndex] = 1; + }); + + function linkOthers(seriesIndex) { + return brushLink === 'all' || linkedSeriesMap[seriesIndex]; + } + + // If no supported brush or no brush on the series, + // all visuals should be in original state. + function brushed(rangeInfoList) { + return !!rangeInfoList.length; + } + + /** + * Logic for each series: (If the logic has to be modified one day, do it carefully!) + * + * ( brushed ┬ && ┬hasBrushExist ┬ && linkOthers ) => StepA: ┬record, ┬ StepB: ┬visualByRecord. + * !brushed┘ ├hasBrushExist ┤ └nothing,┘ ├visualByRecord. + * └!hasBrushExist┘ └nothing. + * ( !brushed && ┬hasBrushExist ┬ && linkOthers ) => StepA: nothing, StepB: ┬visualByRecord. + * └!hasBrushExist┘ └nothing. + * ( brushed ┬ && !linkOthers ) => StepA: nothing, StepB: ┬visualByCheck. + * !brushed┘ └nothing. + * ( !brushed && !linkOthers ) => StepA: nothing, StepB: nothing. + */ + + // Step A + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var rangeInfoList = rangeInfoBySeries[seriesIndex] = []; + + seriesModel.subType === 'parallel' + ? stepAParallel(seriesModel, seriesIndex, rangeInfoList) + : stepAOthers(seriesModel, seriesIndex, rangeInfoList); + }); + + function stepAParallel(seriesModel, seriesIndex) { + var coordSys = seriesModel.coordinateSystem; + hasBrushExists |= coordSys.hasAxisBrushed(); + + linkOthers(seriesIndex) && coordSys.eachActiveState( + seriesModel.getData(), + function (activeState, dataIndex) { + activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1); + } + ); + } + + function stepAOthers(seriesModel, seriesIndex, rangeInfoList) { + var selectorsByBrushType = getSelectorsByBrushType(seriesModel); + if (!selectorsByBrushType || brushModelNotControll(brushModel, seriesIndex)) { + return; + } + + zrUtil.each(areas, function (area) { + selectorsByBrushType[area.brushType] + && brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel) + && rangeInfoList.push(area); + hasBrushExists |= brushed(rangeInfoList); + }); + + if (linkOthers(seriesIndex) && brushed(rangeInfoList)) { + var data = seriesModel.getData(); + data.each(function (dataIndex) { + if (checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex)) { + selectedDataIndexForLink[dataIndex] = 1; + } + }); + } + } + + // Step B + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var seriesBrushSelected = { + seriesId: seriesModel.id, + seriesIndex: seriesIndex, + seriesName: seriesModel.name, + dataIndex: [] + }; + // Every series exists in event params, convenient + // for user to find series by seriesIndex. + thisBrushSelected.selected.push(seriesBrushSelected); + + var selectorsByBrushType = getSelectorsByBrushType(seriesModel); + var rangeInfoList = rangeInfoBySeries[seriesIndex]; + + var data = seriesModel.getData(); + var getValueState = linkOthers(seriesIndex) + ? function (dataIndex) { + return selectedDataIndexForLink[dataIndex] + ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') + : 'outOfBrush'; + } + : function (dataIndex) { + return checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex) + ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') + : 'outOfBrush'; + }; + + // If no supported brush or no brush, all visuals are in original state. + (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList)) + && visualSolution.applyVisual( + STATE_LIST, visualMappings, data, getValueState + ); + }); + + }); + + dispatchAction(api, throttleType, throttleDelay, brushSelected, payload); + }); + + function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) { + // This event will not be triggered when `setOpion`, otherwise dead lock may + // triggered when do `setOption` in event listener, which we do not find + // satisfactory way to solve yet. Some considered resolutions: + // (a) Diff with prevoius selected data ant only trigger event when changed. + // But store previous data and diff precisely (i.e., not only by dataIndex, but + // also detect value changes in selected data) might bring complexity or fragility. + // (b) Use spectial param like `silent` to suppress event triggering. + // But such kind of volatile param may be weird in `setOption`. + if (!payload) { + return; + } + + var zr = api.getZr(); + if (zr[DISPATCH_FLAG]) { + return; + } + + if (!zr[DISPATCH_METHOD]) { + zr[DISPATCH_METHOD] = doDispatch; + } + + var fn = throttle.createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType); + + fn(api, brushSelected); + } + + function doDispatch(api, brushSelected) { + if (!api.isDisposed()) { + var zr = api.getZr(); + zr[DISPATCH_FLAG] = true; + api.dispatchAction({ + type: 'brushSelect', + batch: brushSelected + }); + zr[DISPATCH_FLAG] = false; + } + } + + function checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex) { + for (var i = 0, len = rangeInfoList.length; i < len; i++) { + var area = rangeInfoList[i]; + if (selectorsByBrushType[area.brushType]( + dataIndex, data, area.selectors, area + )) { + return true; + } + } + } + + function getSelectorsByBrushType(seriesModel) { + var brushSelector = seriesModel.brushSelector; + if (zrUtil.isString(brushSelector)) { + var sels = []; + zrUtil.each(selector, function (selectorsByElementType, brushType) { + sels[brushType] = function (dataIndex, data, selectors, area) { + var itemLayout = data.getItemLayout(dataIndex); + return selectorsByElementType[brushSelector](itemLayout, selectors, area); + }; + }); + return sels; + } + else if (zrUtil.isFunction(brushSelector)) { + var bSelector = {}; + zrUtil.each(selector, function (sel, brushType) { + bSelector[brushType] = brushSelector; + }); + return bSelector; + } + return brushSelector; + } + + function brushModelNotControll(brushModel, seriesIndex) { + var seriesIndices = brushModel.option.seriesIndex; + return seriesIndices != null + && seriesIndices !== 'all' + && ( + zrUtil.isArray(seriesIndices) + ? zrUtil.indexOf(seriesIndices, seriesIndex) < 0 + : seriesIndex !== seriesIndices + ); + } + + function bindSelector(area) { + var selectors = area.selectors = {}; + zrUtil.each(selector[area.brushType], function (selFn, elType) { + // Do not use function binding or curry for performance. + selectors[elType] = function (itemLayout) { + return selFn(itemLayout, selectors, area); + }; + }); + return area; + } + + var boundingRectBuilders = { + + lineX: zrUtil.noop, + + lineY: zrUtil.noop, + + rect: function (area) { + return getBoundingRectFromMinMax(area.range); + }, + + polygon: function (area) { + var minMax; + var range = area.range; + + for (var i = 0, len = range.length; i < len; i++) { + minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]]; + var rg = range[i]; + rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]); + rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]); + rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]); + rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]); + } + + return minMax && getBoundingRectFromMinMax(minMax); + } + }; + + function getBoundingRectFromMinMax(minMax) { + return new BoundingRect( + minMax[0][0], + minMax[1][0], + minMax[0][1] - minMax[0][0], + minMax[1][1] - minMax[1][0] + ); + } + + + +/***/ }, +/* 350 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Visual solution, for consistent option specification. + */ + + + var zrUtil = __webpack_require__(4); + var VisualMapping = __webpack_require__(203); + var each = zrUtil.each; + + function hasKeys(obj) { + if (obj) { + for (var name in obj){ + if (obj.hasOwnProperty(name)) { + return true; + } + } + } + } + + var visualSolution = { + + /** + * @param {Object} option + * @param {Array.} stateList + * @param {Function} [supplementVisualOption] + * @return {Object} visualMappings > + */ + createVisualMappings: function (option, stateList, supplementVisualOption) { + var visualMappings = {}; + + each(stateList, function (state) { + var mappings = visualMappings[state] = createMappings(); + + each(option[state], function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + var mappingOption = { + type: visualType, + visual: visualData + }; + supplementVisualOption && supplementVisualOption(mappingOption, state); + mappings[visualType] = new VisualMapping(mappingOption); + + // Prepare a alpha for opacity, for some case that opacity + // is not supported, such as rendering using gradient color. + if (visualType === 'opacity') { + mappingOption = zrUtil.clone(mappingOption); + mappingOption.type = 'colorAlpha'; + mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption); + } + }); + }); + + return visualMappings; + + function createMappings() { + var Creater = function () {}; + // Make sure hidden fields will not be visited by + // object iteration (with hasOwnProperty checking). + Creater.prototype.__hidden = Creater.prototype; + var obj = new Creater(); + return obj; + } + }, + + /** + * @param {Object} thisOption + * @param {Object} newOption + * @param {Array.} keys + */ + replaceVisualOption: function (thisOption, newOption, keys) { + // Visual attributes merge is not supported, otherwise it + // brings overcomplicated merge logic. See #2853. So if + // newOption has anyone of these keys, all of these keys + // will be reset. Otherwise, all keys remain. + var has; + zrUtil.each(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + has = true; + } + }); + has && zrUtil.each(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + thisOption[key] = zrUtil.clone(newOption[key]); + } + else { + delete thisOption[key]; + } + }); + }, + + /** + * @param {Array.} stateList + * @param {Object} visualMappings > + * @param {module:echarts/data/List} list + * @param {Function} getValueState param: valueOrIndex, return: state. + * @param {object} [scope] Scope for getValueState + * @param {string} [dimension] Concrete dimension, if used. + */ + applyVisual: function (stateList, visualMappings, data, getValueState, scope, dimension) { + var visualTypesMap = {}; + zrUtil.each(stateList, function (state) { + var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]); + visualTypesMap[state] = visualTypes; + }); + + var dataIndex; + + function getVisual(key) { + return data.getItemVisual(dataIndex, key); + } + + function setVisual(key, value) { + data.setItemVisual(dataIndex, key, value); + } + + if (dimension == null) { + data.each(eachItem, true); + } + else { + data.each([dimension], eachItem, true); + } + + function eachItem(valueOrIndex, index) { + dataIndex = dimension == null ? valueOrIndex : index; + + var rawDataItem = data.getRawDataItem(dataIndex); + // Consider performance + if (rawDataItem && rawDataItem.visualMap === false) { + return; + } + + var valueState = getValueState.call(scope, valueOrIndex); + var mappings = visualMappings[valueState]; + var visualTypes = visualTypesMap[valueState]; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + mappings[type] && mappings[type].applyVisual( + valueOrIndex, getVisual, setVisual + ); + } + } + } + }; + + module.exports = visualSolution; + + + +/***/ }, +/* 351 */ +/***/ function(module, exports, __webpack_require__) { + + + + var polygonContain = __webpack_require__(175).contain; + var BoundingRect = __webpack_require__(9); + + // Key of the first level is brushType: `line`, `rect`, `polygon`. + // Key of the second level is chart element type: `point`, `rect`. + // See moudule:echarts/component/helper/BrushController + // function param: + // {Object} itemLayout fetch from data.getItemLayout(dataIndex) + // {Object} selectors {point: selector, rect: selector, ...} + // {Object} area {range: [[], [], ..], boudingRect} + // function return: + // {boolean} Whether in the given brush. + var selector = { + lineX: getLineSelectors(0), + lineY: getLineSelectors(1), + rect: { + point: function (itemLayout, selectors, area) { + return area.boundingRect.contain(itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + return area.boundingRect.intersect(itemLayout); + } + }, + polygon: { + point: function (itemLayout, selectors, area) { + return area.boundingRect.contain(itemLayout[0], itemLayout[1]) + && polygonContain(area.range, itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + var points = area.range; + + if (points.length <= 1) { + return false; + } + + var x = itemLayout.x; + var y = itemLayout.y; + var width = itemLayout.width; + var height = itemLayout.height; + var p = points[0]; + + if (polygonContain(points, x, y) + || polygonContain(points, x + width, y) + || polygonContain(points, x, y + height) + || polygonContain(points, x + width, y + height) + || BoundingRect.create(itemLayout).contain(p[0], p[1]) + || lineIntersectPolygon(x, y, x + width, y, points) + || lineIntersectPolygon(x, y, x, y + height, points) + || lineIntersectPolygon(x + width, y, x + width, y + height, points) + || lineIntersectPolygon(x, y + height, x + width, y + height, points) + ) { + return true; + } + } + } + }; + + function getLineSelectors(xyIndex) { + var xy = ['x', 'y']; + var wh = ['width', 'height']; + + return { + point: function (itemLayout, selectors, area) { + var range = area.range; + var p = itemLayout[xyIndex]; + return inLineRange(p, range); + }, + rect: function (itemLayout, selectors, area) { + var range = area.range; + var layoutRange = [ + itemLayout[xy[xyIndex]], + itemLayout[xy[xyIndex]] + itemLayout[wh[xyIndex]] + ]; + layoutRange[1] < layoutRange[0] && layoutRange.reverse(); + return inLineRange(layoutRange[0], range) + || inLineRange(layoutRange[1], range) + || inLineRange(range[0], layoutRange) + || inLineRange(range[1], layoutRange); + } + }; + } + + function inLineRange(p, range) { + return range[0] <= p && p <= range[1]; + } + + function lineIntersectPolygon(lx, ly, l2x, l2y, points) { + for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) { + var p = points[i]; + if (lineIntersect(lx, ly, l2x, l2y, p[0], p[1], p2[0], p2[1])) { + return true; + } + p2 = p; + } + } + + // Code from with some fix. + // See + function lineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) { + var delta = determinant(a2x - a1x, b1x - b2x, a2y - a1y, b1y - b2y); + if (nearZero(delta)) { // parallel + return false; + } + var namenda = determinant(b1x - a1x, b1x - b2x, b1y - a1y, b1y - b2y) / delta; + if (namenda < 0 || namenda > 1) { + return false; + } + var miu = determinant(a2x - a1x, b1x - a1x, a2y - a1y, b1y - a1y) / delta; + if (miu < 0 || miu > 1) { + return false; + } + return true; + } + + function nearZero(val) { + return val <= (1e-6) && val >= -(1e-6); + } + + function determinant(v1, v2, v3, v4) { + return v1 * v4 - v2 * v3; + } + + module.exports = selector; + + + +/***/ }, +/* 352 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var modelUtil = __webpack_require__(5); + var brushHelper = __webpack_require__(246); + + var each = zrUtil.each; + var indexOf = zrUtil.indexOf; + var curry = zrUtil.curry; + + var COORD_CONVERTS = ['dataToPoint', 'pointToData']; + + // FIXME + // how to genarialize to more coordinate systems. + var INCLUDE_FINDER_MAIN_TYPES = [ + 'grid', 'xAxis', 'yAxis', 'geo', 'graph', + 'polar', 'radiusAxis', 'angleAxis', 'bmap' + ]; + + /** + * [option in constructor]: + * { + * Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder. + * } + * + * + * [targetInfo]: + * + * There can be multiple axes in a single targetInfo. Consider the case + * of `grid` component, a targetInfo represents a grid which contains one or more + * cartesian and one or more axes. And consider the case of parallel system, + * which has multiple axes in a coordinate system. + * Can be { + * panelId: ..., + * coordSys: , + * coordSyses: all cartesians. + * gridModel: + * xAxes: correspond to coordSyses on index + * yAxes: correspond to coordSyses on index + * } + * or { + * panelId: ..., + * coordSys: + * coordSyses: [] + * geoModel: + * } + * + * + * [panelOpt]: + * + * Make from targetInfo. Input to BrushController. + * { + * panelId: ..., + * rect: ... + * } + * + * + * [area]: + * + * Generated by BrushController or user input. + * { + * panelId: Used to locate coordInfo directly. If user inpput, no panelId. + * brushType: determine how to convert to/from coord('rect' or 'polygon' or 'lineX/Y'). + * Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder. + * range: pixel range. + * coordRange: representitive coord range (the first one of coordRanges). + * coordRanges: coord ranges, used in multiple cartesian in one grid. + * } + */ + + /** + * @param {Object} option contains Index/Id/Name of xAxis/yAxis/geo/grid + * Each can be {number|Array.}. like: {xAxisIndex: [3, 4]} + * @param {module:echarts/model/Global} ecModel + * @param {Object} [opt] + * @param {Array.} [opt.include] include coordinate system types. + */ + function BrushTargetManager(option, ecModel, opt) { + /** + * @private + * @type {Array.} + */ + var targetInfoList = this._targetInfoList = []; + var info = {}; + var foundCpts = parseFinder(ecModel, option); + + each(targetInfoBuilders, function (builder, type) { + if (!opt || !opt.include || indexOf(opt.include, type) >= 0) { + builder(foundCpts, targetInfoList, info); + } + }); + } + + var proto = BrushTargetManager.prototype; + + proto.setOutputRanges = function (areas, ecModel) { + this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + (area.coordRanges || (area.coordRanges = [])).push(coordRange); + // area.coordRange is the first of area.coordRanges + if (!area.coordRange) { + area.coordRange = coordRange; + // In 'category' axis, coord to pixel is not reversible, so we can not + // rebuild range by coordRange accrately, which may bring trouble when + // brushing only one item. So we use __rangeOffset to rebuilding range + // by coordRange. And this it only used in brush component so it is no + // need to be adapted to coordRanges. + var result = coordConvert[area.brushType](0, coordSys, coordRange); + area.__rangeOffset = { + offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]), + xyMinMax: result.xyMinMax + }; + } + }); + }; + + proto.matchOutputRanges = function (areas, ecModel, cb) { + each(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if (targetInfo && targetInfo !== true) { + zrUtil.each( + targetInfo.coordSyses, + function (coordSys) { + var result = coordConvert[area.brushType](1, coordSys, area.range); + cb(area, result.values, coordSys, ecModel); + } + ); + } + }, this); + }; + + proto.setInputRanges = function (areas, ecModel) { + each(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if (true) { + zrUtil.assert( + !targetInfo || targetInfo === true || area.coordRange, + 'coordRange must be specified when coord index specified.' + ); + zrUtil.assert( + !targetInfo || targetInfo !== true || area.range, + 'range must be specified in global brush.' + ); + } + + area.range = area.range || []; + + // convert coordRange to global range and set panelId. + if (targetInfo && targetInfo !== true) { + area.panelId = targetInfo.panelId; + // (1) area.range shoule always be calculate from coordRange but does + // not keep its original value, for the sake of the dataZoom scenario, + // where area.coordRange remains unchanged but area.range may be changed. + // (2) Only support converting one coordRange to pixel range in brush + // component. So do not consider `coordRanges`. + // (3) About __rangeOffset, see comment above. + var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange); + var rangeOffset = area.__rangeOffset; + area.range = rangeOffset + ? diffProcessor[area.brushType]( + result.values, + rangeOffset.offset, + getScales(result.xyMinMax, rangeOffset.xyMinMax) + ) + : result.values; + } + }, this); + }; + + proto.makePanelOpts = function (api, getDefaultBrushType) { + return zrUtil.map(this._targetInfoList, function (targetInfo) { + var rect = targetInfo.getPanelRect(); + return { + panelId: targetInfo.panelId, + defaultBrushType: getDefaultBrushType && getDefaultBrushType(targetInfo), + clipPath: brushHelper.makeRectPanelClipPath(rect), + isTargetByCursor: brushHelper.makeRectIsTargetByCursor( + rect, api, targetInfo.coordSysModel + ), + getLinearBrushOtherExtent: brushHelper.makeLinearBrushOtherExtent(rect) + }; + }); + }; + + proto.controlSeries = function (area, seriesModel, ecModel) { + // Check whether area is bound in coord, and series do not belong to that coord. + // If do not do this check, some brush (like lineX) will controll all axes. + var targetInfo = this.findTargetInfo(area, ecModel); + return targetInfo === true || ( + targetInfo && indexOf(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0 + ); + }; + + /** + * If return Object, a coord found. + * If reutrn true, global found. + * Otherwise nothing found. + * + * @param {Object} area + * @param {Array} targetInfoList + * @return {Obejct|boolean} + */ + proto.findTargetInfo = function (area, ecModel) { + var targetInfoList = this._targetInfoList; + var foundCpts = parseFinder(ecModel, area); + + for (var i = 0; i < targetInfoList.length; i++) { + var targetInfo = targetInfoList[i]; + var areaPanelId = area.panelId; + if (areaPanelId) { + if (targetInfo.panelId === areaPanelId) { + return targetInfo; + } + } + else { + for (var i = 0; i < targetInfoMatchers.length; i++) { + if (targetInfoMatchers[i](foundCpts, targetInfo)) { + return targetInfo; + } + } + } + } + + return true; + }; + + function formatMinMax(minMax) { + minMax[0] > minMax[1] && minMax.reverse(); + return minMax; + } + + function parseFinder(ecModel, option) { + return modelUtil.parseFinder( + ecModel, option, {includeMainTypes: INCLUDE_FINDER_MAIN_TYPES} + ); + } + + var targetInfoBuilders = { + + grid: function (foundCpts, targetInfoList) { + var xAxisModels = foundCpts.xAxisModels; + var yAxisModels = foundCpts.yAxisModels; + var gridModels = foundCpts.gridModels; + // Remove duplicated. + var gridModelMap = zrUtil.createHashMap(); + var xAxesHas = {}; + var yAxesHas = {}; + + if (!xAxisModels && !yAxisModels && !gridModels) { + return; + } + + each(xAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + }); + each(yAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + yAxesHas[gridModel.id] = true; + }); + each(gridModels, function (gridModel) { + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + yAxesHas[gridModel.id] = true; + }); + + gridModelMap.each(function (gridModel) { + var grid = gridModel.coordinateSystem; + var cartesians = []; + + each(grid.getCartesians(), function (cartesian, index) { + if (indexOf(xAxisModels, cartesian.getAxis('x').model) >= 0 + || indexOf(yAxisModels, cartesian.getAxis('y').model) >= 0 + ) { + cartesians.push(cartesian); + } + }); + targetInfoList.push({ + panelId: 'grid--' + gridModel.id, + gridModel: gridModel, + coordSysModel: gridModel, + // Use the first one as the representitive coordSys. + coordSys: cartesians[0], + coordSyses: cartesians, + getPanelRect: panelRectBuilder.grid, + xAxisDeclared: xAxesHas[gridModel.id], + yAxisDeclared: yAxesHas[gridModel.id] + }); + }); + }, + + geo: function (foundCpts, targetInfoList) { + each(foundCpts.geoModels, function (geoModel) { + var coordSys = geoModel.coordinateSystem; + targetInfoList.push({ + panelId: 'geo--' + geoModel.id, + geoModel: geoModel, + coordSysModel: geoModel, + coordSys: coordSys, + coordSyses: [coordSys], + getPanelRect: panelRectBuilder.geo + }); + }); + } + }; + + var targetInfoMatchers = [ + + // grid + function (foundCpts, targetInfo) { + var xAxisModel = foundCpts.xAxisModel; + var yAxisModel = foundCpts.yAxisModel; + var gridModel = foundCpts.gridModel; + + !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model); + !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model); + + return gridModel && gridModel === targetInfo.gridModel; + }, + + // geo + function (foundCpts, targetInfo) { + var geoModel = foundCpts.geoModel; + return geoModel && geoModel === targetInfo.geoModel; + } + ]; + + var panelRectBuilder = { + + grid: function () { + // grid is not Transformable. + return this.coordSys.grid.getRect().clone(); + }, + + geo: function () { + var coordSys = this.coordSys; + var rect = coordSys.getBoundingRect().clone(); + // geo roam and zoom transform + rect.applyTransform(graphic.getTransform(coordSys)); + return rect; + } + }; + + var coordConvert = { + + lineX: curry(axisConvert, 0), + + lineY: curry(axisConvert, 1), + + rect: function (to, coordSys, rangeOrCoordRange) { + var xminymin = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]]); + var xmaxymax = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]]); + var values = [ + formatMinMax([xminymin[0], xmaxymax[0]]), + formatMinMax([xminymin[1], xmaxymax[1]]) + ]; + return {values: values, xyMinMax: values}; + }, + + polygon: function (to, coordSys, rangeOrCoordRange) { + var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]]; + var values = zrUtil.map(rangeOrCoordRange, function (item) { + var p = coordSys[COORD_CONVERTS[to]](item); + xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]); + xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]); + xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]); + xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]); + return p; + }); + return {values: values, xyMinMax: xyMinMax}; + } + }; + + function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) { + if (true) { + zrUtil.assert( + coordSys.type === 'cartesian2d', + 'lineX/lineY brush is available only in cartesian2d.' + ); + } + + var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]); + var values = formatMinMax(zrUtil.map([0, 1], function (i) { + return to + ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i])) + : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i])); + })); + var xyMinMax = []; + xyMinMax[axisNameIndex] = values; + xyMinMax[1 - axisNameIndex] = [NaN, NaN]; + + return {values: values, xyMinMax: xyMinMax}; + } + + var diffProcessor = { + lineX: curry(axisDiffProcessor, 0), + + lineY: curry(axisDiffProcessor, 1), + + rect: function (values, refer, scales) { + return [ + [values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]], + [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]] + ]; + }, + + polygon: function (values, refer, scales) { + return zrUtil.map(values, function (item, idx) { + return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]]; + }); + } + }; + + function axisDiffProcessor(axisNameIndex, values, refer, scales) { + return [ + values[0] - scales[axisNameIndex] * refer[0], + values[1] - scales[axisNameIndex] * refer[1] + ]; + } + + // We have to process scale caused by dataZoom manually, + // although it might be not accurate. + function getScales(xyMinMaxCurr, xyMinMaxOrigin) { + var sizeCurr = getSize(xyMinMaxCurr); + var sizeOrigin = getSize(xyMinMaxOrigin); + var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]]; + isNaN(scales[0]) && (scales[0] = 1); + isNaN(scales[1]) && (scales[1] = 1); + return scales; + } + + function getSize(xyMinMax) { + return xyMinMax + ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]] + : [NaN, NaN]; + } + + module.exports = BrushTargetManager; + + +/***/ }, +/* 353 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Brush model + */ + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + var visualSolution = __webpack_require__(350); + var Model = __webpack_require__(12); + + var DEFAULT_OUT_OF_BRUSH_COLOR = ['#ddd']; + + var BrushModel = echarts.extendComponentModel({ + + type: 'brush', + + dependencies: ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series'], + + /** + * @protected + */ + defaultOption: { + // inBrush: null, + // outOfBrush: null, + toolbox: null, // Default value see preprocessor. + brushLink: null, // Series indices array, broadcast using dataIndex. + // or 'all', which means all series. 'none' or null means no series. + seriesIndex: 'all', // seriesIndex array, specify series controlled by this brush component. + geoIndex: null, // + xAxisIndex: null, + yAxisIndex: null, + + brushType: 'rect', // Default brushType, see BrushController. + brushMode: 'single', // Default brushMode, 'single' or 'multiple' + transformable: true, // Default transformable. + brushStyle: { // Default brushStyle + borderWidth: 1, + color: 'rgba(120,140,180,0.3)', + borderColor: 'rgba(120,140,180,0.8)' + }, + + throttleType: 'fixRate',// Throttle in brushSelected event. 'fixRate' or 'debounce'. + // If null, no throttle. Valid only in the first brush component + throttleDelay: 0, // Unit: ms, 0 means every event will be triggered. + + // FIXME + // 试验效果 + removeOnClick: true, + + z: 10000 + }, + + /** + * @readOnly + * @type {Array.} + */ + areas: [], + + /** + * Current activated brush type. + * If null, brush is inactived. + * see module:echarts/component/helper/BrushController + * @readOnly + * @type {string} + */ + brushType: null, + + /** + * Current brush opt. + * see module:echarts/component/helper/BrushController + * @readOnly + * @type {Object} + */ + brushOption: {}, + + /** + * @readOnly + * @type {Array.} + */ + coordInfoList: [], + + optionUpdated: function (newOption, isInit) { + var thisOption = this.option; + + !isInit && visualSolution.replaceVisualOption( + thisOption, newOption, ['inBrush', 'outOfBrush'] + ); + + thisOption.inBrush = thisOption.inBrush || {}; + // Always give default visual, consider setOption at the second time. + thisOption.outOfBrush = thisOption.outOfBrush || {color: DEFAULT_OUT_OF_BRUSH_COLOR}; + }, + + /** + * If ranges is null/undefined, range state remain. + * + * @param {Array.} [ranges] + */ + setAreas: function (areas) { + if (true) { + zrUtil.assert(zrUtil.isArray(areas)); + zrUtil.each(areas, function (area) { + zrUtil.assert(area.brushType, 'Illegal areas'); + }); + } + + // If ranges is null/undefined, range state remain. + // This helps user to dispatchAction({type: 'brush'}) with no areas + // set but just want to get the current brush select info from a `brush` event. + if (!areas) { + return; + } + + this.areas = zrUtil.map(areas, function (area) { + return generateBrushOption(this.option, area); + }, this); + }, + + /** + * see module:echarts/component/helper/BrushController + * @param {Object} brushOption + */ + setBrushOption: function (brushOption) { + this.brushOption = generateBrushOption(this.option, brushOption); + this.brushType = this.brushOption.brushType; + } + + }); + + function generateBrushOption(option, brushOption) { + return zrUtil.merge( + { + brushType: option.brushType, + brushMode: option.brushMode, + transformable: option.transformable, + brushStyle: new Model(option.brushStyle).getItemStyle(), + removeOnClick: option.removeOnClick, + z: option.z + }, + brushOption, + true + ); + } + + module.exports = BrushModel; + + + +/***/ }, +/* 354 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var BrushController = __webpack_require__(245); + var echarts = __webpack_require__(1); + + module.exports = echarts.extendComponentView({ + + type: 'brush', + + init: function (ecModel, api) { + + /** + * @readOnly + * @type {module:echarts/model/Global} + */ + this.ecModel = ecModel; + + /** + * @readOnly + * @type {module:echarts/ExtensionAPI} + */ + this.api = api; + + /** + * @readOnly + * @type {module:echarts/component/brush/BrushModel} + */ + this.model; + + /** + * @private + * @type {module:echarts/component/helper/BrushController} + */ + (this._brushController = new BrushController(api.getZr())) + .on('brush', zrUtil.bind(this._onBrush, this)) + .mount(); + }, + + /** + * @override + */ + render: function (brushModel) { + this.model = brushModel; + return updateController.apply(this, arguments); + }, + + /** + * @override + */ + updateView: updateController, + + /** + * @override + */ + updateLayout: updateController, + + /** + * @override + */ + updateVisual: updateController, + + /** + * @override + */ + dispose: function () { + this._brushController.dispose(); + }, + + /** + * @private + */ + _onBrush: function (areas, opt) { + var modelId = this.model.id; + + this.model.brushTargetManager.setOutputRanges(areas, this.ecModel); + + // Action is not dispatched on drag end, because the drag end + // emits the same params with the last drag move event, and + // may have some delay when using touch pad, which makes + // animation not smooth (when using debounce). + (!opt.isEnd || opt.removeOnClick) && this.api.dispatchAction({ + type: 'brush', + brushId: modelId, + areas: zrUtil.clone(areas), + $from: modelId + }); + } + + }); + + function updateController(brushModel, ecModel, api, payload) { + // Do not update controller when drawing. + (!payload || payload.$from !== brushModel.id) && this._brushController + .setPanels(brushModel.brushTargetManager.makePanelOpts(api)) + .enableBrush(brushModel.brushOption) + .updateCovers(brushModel.areas.slice()); + } + + + +/***/ }, +/* 355 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Brush action + */ + + + var echarts = __webpack_require__(1); + + /** + * payload: { + * brushIndex: number, or, + * brushId: string, or, + * brushName: string, + * globalRanges: Array + * } + */ + echarts.registerAction( + {type: 'brush', event: 'brush', update: 'updateView'}, + function (payload, ecModel) { + ecModel.eachComponent({mainType: 'brush', query: payload}, function (brushModel) { + brushModel.setAreas(payload.areas); + }); + } + ); + + /** + * payload: { + * brushComponents: [ + * { + * brushId, + * brushIndex, + * brushName, + * series: [ + * { + * seriesId, + * seriesIndex, + * seriesName, + * rawIndices: [21, 34, ...] + * }, + * ... + * ] + * }, + * ... + * ] + * } + */ + echarts.registerAction( + {type: 'brushSelect', event: 'brushSelected', update: 'none'}, + function () {} + ); + + +/***/ }, +/* 356 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var featureManager = __webpack_require__(357); + var zrUtil = __webpack_require__(4); + + function Brush(model, ecModel, api) { + this.model = model; + this.ecModel = ecModel; + this.api = api; + + /** + * @private + * @type {string} + */ + this._brushType; + + /** + * @private + * @type {string} + */ + this._brushMode; + } + + Brush.defaultOption = { + show: true, + type: ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'], + icon: { + rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', // jshint ignore:line + polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', // jshint ignore:line + lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', // jshint ignore:line + lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', // jshint ignore:line + keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', // jshint ignore:line + clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' // jshint ignore:line + }, + title: { + rect: '矩形选择', + polygon: '圈选', + lineX: '横向选择', + lineY: '纵向选择', + keep: '保持选择', + clear: '清除选择' + } + }; + + var proto = Brush.prototype; + + proto.render = + proto.updateView = + proto.updateLayout = function (featureModel, ecModel, api) { + var brushType; + var brushMode; + var isBrushed; + + ecModel.eachComponent({mainType: 'brush'}, function (brushModel) { + brushType = brushModel.brushType; + brushMode = brushModel.brushOption.brushMode || 'single'; + isBrushed |= brushModel.areas.length; + }); + this._brushType = brushType; + this._brushMode = brushMode; + + zrUtil.each(featureModel.get('type', true), function (type) { + featureModel.setIconStatus( + type, + ( + type === 'keep' + ? brushMode === 'multiple' + : type === 'clear' + ? isBrushed + : type === brushType + ) ? 'emphasis' : 'normal' + ); + }); + }; + + proto.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon', true); + var icons = {}; + zrUtil.each(model.get('type', true), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; + }; + + proto.onclick = function (ecModel, api, type) { + var api = this.api; + var brushType = this._brushType; + var brushMode = this._brushMode; + + if (type === 'clear') { + // Trigger parallel action firstly + api.dispatchAction({ + type: 'axisAreaSelect', + intervals: [] + }); + + api.dispatchAction({ + type: 'brush', + command: 'clear', + // Clear all areas of all brush components. + areas: [] + }); + } + else { + api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'brush', + brushOption: { + brushType: type === 'keep' + ? brushType + : (brushType === type ? false : type), + brushMode: type === 'keep' + ? (brushMode === 'multiple' ? 'single' : 'multiple') + : brushMode + } + }); + } + }; + + featureManager.register('brush', Brush); + + module.exports = Brush; + + +/***/ }, +/* 357 */ +/***/ function(module, exports) { + + 'use strict'; + + + var features = {}; + + module.exports = { + register: function (name, ctor) { + features[name] = ctor; + }, + + get: function (name) { + return features[name]; + } + }; + + +/***/ }, +/* 358 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + /** + * @file calendar.js + * @author dxh + */ + + + + __webpack_require__(359); + __webpack_require__(360); + __webpack_require__(361); + + + + +/***/ }, +/* 359 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var layout = __webpack_require__(71); + var numberUtil = __webpack_require__(7); + var zrUtil = __webpack_require__(4); + + // (24*60*60*1000) + var ONE_DAY = 86400000; + + /** + * Calendar + * + * @constructor + * + * @param {Object} calendarModel calendarModel + * @param {Object} ecModel ecModel + * @param {Object} api api + */ + function Calendar(calendarModel, ecModel, api) { + this._model = calendarModel; + } + + Calendar.prototype = { + + constructor: Calendar, + + type: 'calendar', + + dimensions: ['time', 'value'], + + // Required in createListFromData + getDimensionsInfo: function () { + return [{name: 'time', type: 'time'}]; + }, + + getRangeInfo: function () { + return this._rangeInfo; + }, + + getModel: function () { + return this._model; + }, + + getRect: function () { + return this._rect; + }, + + getCellWidth: function () { + return this._sw; + }, + + getCellHeight: function () { + return this._sh; + }, + + getOrient: function () { + return this._orient; + }, + + /** + * getFirstDayOfWeek + * + * @example + * 0 : start at Sunday + * 1 : start at Monday + * + * @return {number} + */ + getFirstDayOfWeek: function () { + return this._firstDayOfWeek; + }, + + /** + * get date info + * + * @param {string|number} date date + * @return {Object} info + */ + getDateInfo: function (date) { + + date = numberUtil.parseDate(date); + + var y = date.getFullYear(); + + var m = date.getMonth() + 1; + m = m < 10 ? '0' + m : m; + + var d = date.getDate(); + d = d < 10 ? '0' + d : d; + + var day = date.getDay(); + + day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7); + + return { + y: y, + m: m, + d: d, + day: day, + time: date.getTime(), + formatedDate: y + '-' + m + '-' + d, + date: date + }; + }, + + getNextNDay: function (date, n) { + n = n || 0; + if (n === 0) { + return this.getDateInfo(date); + } + + var time = this.getDateInfo(date).time; + + return this.getDateInfo(time + ONE_DAY * n); + }, + + update: function (ecModel, api) { + + this._firstDayOfWeek = this._model.getModel('dayLabel').get('firstDay'); + this._orient = this._model.get('orient'); + this._lineWidth = this._model.getModel('itemStyle.normal').getItemStyle().lineWidth || 0; + + + this._rangeInfo = this._getRangeInfo(this._initRangeOption()); + var weeks = this._rangeInfo.weeks || 1; + var whNames = ['width', 'height']; + var cellSize = this._model.get('cellSize').slice(); + var layoutParams = this._model.getBoxLayoutParams(); + var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks]; + + zrUtil.each([0, 1], function (idx) { + if (cellSizeSpecified(cellSize, idx)) { + layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx]; + } + }); + + var whGlobal = { + width: api.getWidth(), + height: api.getHeight() + }; + var calendarRect = this._rect = layout.getLayoutRect(layoutParams, whGlobal); + + zrUtil.each([0, 1], function (idx) { + if (!cellSizeSpecified(cellSize, idx)) { + cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx]; + } + }); + + function cellSizeSpecified(cellSize, idx) { + return cellSize[idx] != null && cellSize[idx] !== 'auto'; + } + + this._sw = cellSize[0]; + this._sh = cellSize[1]; + }, + + + /** + * Convert a time data(time, value) item to (x, y) point. + * + * @override + * @param {Array|number} data data + * @param {boolean} [clamp=true] out of range + * @return {Array} point + */ + dataToPoint: function (data, clamp) { + zrUtil.isArray(data) && (data = data[0]); + clamp == null && (clamp = true); + + var dayInfo = this.getDateInfo(data); + var range = this._rangeInfo; + var date = dayInfo.formatedDate; + + // if not in range return [NaN, NaN] + if (clamp && !(dayInfo.time >= range.start.time && dayInfo.time <= range.end.time)) { + return [NaN, NaN]; + } + + var week = dayInfo.day; + var nthWeek = this._getRangeInfo([range.start.time, date]).weeks; + + if (this._orient === 'vertical') { + return [ + this._rect.x + week * this._sw + this._sw / 2, + this._rect.y + (nthWeek - 1) * this._sh + this._sh / 2 + ]; + + } + + return [ + this._rect.x + (nthWeek - 1) * this._sw + this._sw / 2, + this._rect.y + week * this._sh + this._sh / 2 + ]; + + }, + + /** + * Convert a (x, y) point to time data + * + * @override + * @param {string} point point + * @return {string} data + */ + pointToData: function (point) { + + var date = this.pointToDate(point); + + return date && date.time; + }, + + /** + * Convert a time date item to (x, y) four point. + * + * @param {Array} data date[0] is date + * @param {boolean} [clamp=true] out of range + * @return {Object} point + */ + dataToRect: function (data, clamp) { + var point = this.dataToPoint(data, clamp); + + return { + contentShape: { + x: point[0] - (this._sw - this._lineWidth) / 2, + y: point[1] - (this._sh - this._lineWidth) / 2, + width: this._sw - this._lineWidth, + height: this._sh - this._lineWidth + }, + + center: point, + + tl: [ + point[0] - this._sw / 2, + point[1] - this._sh / 2 + ], + + tr: [ + point[0] + this._sw / 2, + point[1] - this._sh / 2 + ], + + br: [ + point[0] + this._sw / 2, + point[1] + this._sh / 2 + ], + + bl: [ + point[0] - this._sw / 2, + point[1] + this._sh / 2 + ] + + }; + }, + + /** + * Convert a (x, y) point to time date + * + * @param {string} point point + * @return {Object} date + */ + pointToDate: function (point) { + var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1; + var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1; + var range = this._rangeInfo.range; + + if (this._orient === 'vertical') { + return this._getDateByWeeksAndDay(nthY, nthX - 1, range); + } + + return this._getDateByWeeksAndDay(nthX, nthY - 1, range); + }, + + /** + * @inheritDoc + */ + convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'), + + /** + * @inheritDoc + */ + convertFromPixel: zrUtil.curry(doConvert, 'pointToData'), + + /** + * initRange + * + * @private + * @return {Array} [start, end] + */ + _initRangeOption: function () { + var range = this._model.get('range'); + + var rg = range; + + if (zrUtil.isArray(rg) && rg.length === 1) { + rg = rg[0]; + } + + if (/^\d{4}$/.test(rg)) { + range = [rg + '-01-01', rg + '-12-31']; + } + + if (/^\d{4}[\/|-]\d{1,2}$/.test(rg)) { + + var start = this.getDateInfo(rg); + var firstDay = start.date; + firstDay.setMonth(firstDay.getMonth() + 1); + + var end = this.getNextNDay(firstDay, -1); + range = [start.formatedDate, end.formatedDate]; + } + + if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rg)) { + range = [rg, rg]; + } + + var tmp = this._getRangeInfo(range); + + if (tmp.start.time > tmp.end.time) { + range.reverse(); + } + + return range; + }, + + /** + * range info + * + * @private + * @param {Array} range range ['2017-01-01', '2017-07-08'] + * @return {Object} obj + */ + _getRangeInfo: function (range) { + + var start = this.getDateInfo(range[0]); + var end = this.getDateInfo(range[1]); + + var allDay = Math.floor(end.time / ONE_DAY) - Math.floor(start.time / ONE_DAY) + 1; + + var weeks = Math.floor((allDay + start.day + 6) / 7); + + return { + range: [start.formatedDate, end.formatedDate], + start: start, + end: end, + allDay: allDay, + weeks: weeks, + fweek: start.day, + lweek: end.day + }; + }, + + /** + * get date by nthWeeks and week day in range + * + * @private + * @param {number} nthWeek the week + * @param {number} day the week day + * @param {Array} range [d1, d2] + * @return {Object} + */ + _getDateByWeeksAndDay: function (nthWeek, day, range) { + var rangeInfo = this._getRangeInfo(range); + + if (nthWeek > rangeInfo.weeks + || (nthWeek === 0 && day < rangeInfo.fweek) + || (nthWeek === rangeInfo.weeks && day > rangeInfo.lweek) + ) { + return false; + } + + var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day; + + var time = rangeInfo.start.time + nthDay * ONE_DAY; + + return this.getDateInfo(time); + + } + }; + + Calendar.dimensions = Calendar.prototype.dimensions; + + Calendar.getDimensionsInfo = Calendar.prototype.getDimensionsInfo; + + Calendar.create = function (ecModel, api) { + var calendarList = []; + + ecModel.eachComponent('calendar', function (calendarModel) { + var calendar = new Calendar(calendarModel, ecModel, api); + calendarList.push(calendar); + calendarModel.coordinateSystem = calendar; + }); + + ecModel.eachSeries(function (calendarSeries) { + if (calendarSeries.get('coordinateSystem') === 'calendar') { + // Inject coordinate system + calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0]; + } + }); + return calendarList; + }; + + function doConvert(methodName, ecModel, finder, value) { + var calendarModel = finder.calendarModel; + var seriesModel = finder.seriesModel; + + var coordSys = calendarModel + ? calendarModel.coordinateSystem + : seriesModel + ? seriesModel.coordinateSystem + : null; + + return coordSys === this ? coordSys[methodName](value) : null; + } + + __webpack_require__(76).register('calendar', Calendar); + + module.exports = Calendar; + + + +/***/ }, +/* 360 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var ComponentModel = __webpack_require__(69); + var zrUtil = __webpack_require__(4); + var layout = __webpack_require__(71); + + var CalendarModel = ComponentModel.extend({ + + type: 'calendar', + + /** + * @type {module:echarts/coord/calendar/Calendar} + */ + coordinateSystem: null, + + defaultOption: { + zlevel: 0, + z: 2, + left: 80, + top: 60, + + cellSize: 20, + + // horizontal vertical + orient: 'horizontal', + + // month separate line style + splitLine: { + show: true, + lineStyle: { + color: '#000', + width: 1, + type: 'solid' + } + }, + + // rect style temporarily unused emphasis + itemStyle: { + normal: { + color: '#fff', + borderWidth: 1, + borderColor: '#ccc' + } + }, + + // week text style + dayLabel: { + show: true, + + // a week first day + firstDay: 0, + + // start end + position: 'start', + margin: '50%', // 50% of cellSize + nameMap: 'en', + textStyle: { + color: '#000' + } + }, + + // month text style + monthLabel: { + show: true, + + // start end + position: 'start', + margin: 5, + + // center or left + align: 'center', + + // cn en [] + nameMap: 'en', + formatter: null, + textStyle: { + color: '#000' + } + }, + + // year text style + yearLabel: { + show: true, + + // top bottom left right + position: null, + margin: 30, + formatter: null, + textStyle: { + color: '#ccc', + fontFamily: 'sans-serif', + fontWeight: 'bolder', + fontSize: 20 + } + } + }, + + /** + * @override + */ + init: function (option, parentModel, ecModel, extraOpt) { + var inputPositionParams = layout.getLayoutParams(option); + + CalendarModel.superApply(this, 'init', arguments); + + mergeAndNormalizeLayoutParams(option, inputPositionParams); + }, + + /** + * @override + */ + mergeOption: function (option, extraOpt) { + CalendarModel.superApply(this, 'mergeOption', arguments); + + mergeAndNormalizeLayoutParams(this.option, option); + } + }); + + function mergeAndNormalizeLayoutParams(target, raw) { + // Normalize cellSize + var cellSize = target.cellSize; + + if (!zrUtil.isArray(cellSize)) { + cellSize = target.cellSize = [cellSize, cellSize]; + } + else if (cellSize.length === 1) { + cellSize[1] = cellSize[0]; + } + + var ignoreSize = zrUtil.map([0, 1], function (hvIdx) { + // If user have set `width` or both `left` and `right`, cellSize + // will be automatically set to 'auto', otherwise the default + // setting of cellSize will make `width` setting not work. + if (layout.sizeCalculable(raw, hvIdx)) { + cellSize[hvIdx] = 'auto'; + } + return cellSize[hvIdx] != null && cellSize[hvIdx] !== 'auto'; + }); + + layout.mergeLayoutParam(target, raw, { + type: 'box', ignoreSize: ignoreSize + }); + } + + module.exports = CalendarModel; + + + + +/***/ }, +/* 361 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var formatUtil = __webpack_require__(6); + var numberUtil = __webpack_require__(7); + + var MONTH_TEXT = { + EN: [ + 'Jan', 'Feb', 'Mar', + 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec' + ], + CN: [ + '一月', '二月', '三月', + '四月', '五月', '六月', + '七月', '八月', '九月', + '十月', '十一月', '十二月' + ] + }; + + var WEEK_TEXT = { + EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], + CN: ['日', '一', '二', '三', '四', '五', '六'] + }; + + module.exports = __webpack_require__(1).extendComponentView({ + + type: 'calendar', + + /** + * top/left line points + * @private + */ + _tlpoints: null, + + /** + * bottom/right line points + * @private + */ + _blpoints: null, + + /** + * first day of month + * @private + */ + _firstDayOfMonth: null, + + /** + * first day point of month + * @private + */ + _firstDayPoints: null, + + render: function (calendarModel, ecModel, api) { + + var group = this.group; + + group.removeAll(); + + var coordSys = calendarModel.coordinateSystem; + + // range info + var rangeData = coordSys.getRangeInfo(); + var orient = coordSys.getOrient(); + + this._renderDayRect(calendarModel, rangeData, group); + + // _renderLines must be called prior to following function + this._renderLines(calendarModel, rangeData, orient, group); + + this._renderYearText(calendarModel, rangeData, orient, group); + + this._renderMonthText(calendarModel, orient, group); + + this._renderWeekText(calendarModel, rangeData, orient, group); + }, + + // render day rect + _renderDayRect: function (calendarModel, rangeData, group) { + var coordSys = calendarModel.coordinateSystem; + var itemRectStyleModel = calendarModel.getModel('itemStyle.normal').getItemStyle(); + var sw = coordSys.getCellWidth(); + var sh = coordSys.getCellHeight(); + + for (var i = rangeData.start.time; + i <= rangeData.end.time; + i = coordSys.getNextNDay(i, 1).time + ) { + + var point = coordSys.dataToRect([i], false).tl; + + // every rect + var rect = new graphic.Rect({ + shape: { + x: point[0], + y: point[1], + width: sw, + height: sh + }, + cursor: 'default', + style: itemRectStyleModel + }); + + group.add(rect); + } + + }, + + // render separate line + _renderLines: function (calendarModel, rangeData, orient, group) { + + var self = this; + + var coordSys = calendarModel.coordinateSystem; + + var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle(); + var show = calendarModel.get('splitLine.show'); + + var lineWidth = lineStyleModel.lineWidth; + + this._tlpoints = []; + this._blpoints = []; + this._firstDayOfMonth = []; + this._firstDayPoints = []; + + + var firstDay = rangeData.start; + + for (var i = 0; firstDay.time <= rangeData.end.time; i++) { + addPoints(firstDay.formatedDate); + + if (i === 0) { + firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m); + } + + var date = firstDay.date; + date.setMonth(date.getMonth() + 1); + firstDay = coordSys.getDateInfo(date); + } + + addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate); + + function addPoints(date) { + + self._firstDayOfMonth.push(coordSys.getDateInfo(date)); + self._firstDayPoints.push(coordSys.dataToRect([date], false).tl); + + var points = self._getLinePointsOfOneWeek(calendarModel, date, orient); + + self._tlpoints.push(points[0]); + self._blpoints.push(points[points.length - 1]); + + show && self._drawSplitline(points, lineStyleModel, group); + } + + + // render top/left line + show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group); + + // render bottom/right line + show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group); + + }, + + // get points at both ends + _getEdgesPoints: function (points, lineWidth, orient) { + var rs = [points[0].slice(), points[points.length - 1].slice()]; + var idx = orient === 'horizontal' ? 0 : 1; + + // both ends of the line are extend half lineWidth + rs[0][idx] = rs[0][idx] - lineWidth / 2; + rs[1][idx] = rs[1][idx] + lineWidth / 2; + + return rs; + }, + + // render split line + _drawSplitline: function (points, lineStyleModel, group) { + + var poyline = new graphic.Polyline({ + z2: 20, + shape: { + points: points + }, + style: lineStyleModel + }); + + group.add(poyline); + }, + + // render month line of one week points + _getLinePointsOfOneWeek: function (calendarModel, date, orient) { + + var coordSys = calendarModel.coordinateSystem; + date = coordSys.getDateInfo(date); + + var points = []; + + for (var i = 0; i < 7; i++) { + + var tmpD = coordSys.getNextNDay(date.time, i); + var point = coordSys.dataToRect([tmpD.time], false); + + points[2 * tmpD.day] = point.tl; + points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr']; + } + + return points; + + }, + + _formatterLabel: function (formatter, params) { + + if (typeof formatter === 'string' && formatter) { + return formatUtil.formatTplSimple(formatter, params); + } + + if (typeof formatter === 'function') { + return formatter(params); + } + + return params.nameMap; + + }, + + _yearTextPositionControl: function (point, orient, position, margin) { + + point = point.slice(); + var aligns = ['center', 'bottom']; + + if (position === 'top') { + point[1] -= margin; + } + if (position === 'bottom') { + point[1] += margin; + aligns = ['center', 'top']; + } + if (position === 'left') { + point[0] -= margin; + } + if (position === 'right') { + point[0] += margin; + aligns = ['center', 'top']; + } + + var rotate = 0; + if (position === 'left' || position === 'right') { + rotate = Math.PI / 2; + } + + return { + rotation: rotate, + origin: point, + style: { + x: point[0], + y: point[1], + textAlign: aligns[0], + textVerticalAlign: aligns[1] + } + }; + }, + + // render year + _renderYearText: function (calendarModel, rangeData, orient, group) { + var yearLabel = calendarModel.getModel('yearLabel'); + + if (!yearLabel.get('show')) { + return; + } + + var yearLabelStyleModel = calendarModel.getModel('yearLabel.textStyle'); + var margin = yearLabel.get('margin'); + var pos = yearLabel.get('position'); + + if (!pos) { + pos = orient !== 'horizontal' ? 'top' : 'left'; + } + + var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]]; + var xc = (points[0][0] + points[1][0]) / 2; + var yc = (points[0][1] + points[1][1]) / 2; + + var idx = orient === 'horizontal' ? 0 : 1; + + + var posPoints = { + top: [xc, points[idx][1]], + bottom: [xc, points[1 - idx][1]], + left: [points[1 - idx][0], yc], + right: [points[idx][0], yc] + }; + + var name = rangeData.start.y; + + if (+rangeData.end.y > +rangeData.start.y) { + name = name + '-' + rangeData.end.y; + } + + var formatter = yearLabel.get('formatter'); + + var params = { + start: rangeData.start.y, + end: rangeData.end.y, + nameMap: name + }; + + var content = this._formatterLabel(formatter, params); + + var yearText = new graphic.Text( + zrUtil.merge({ + z2: 30, + style: { + text: content, + font: yearLabelStyleModel.getFont(), + fill: yearLabelStyleModel.getTextColor() + } + }, this._yearTextPositionControl(posPoints[pos], orient, pos, margin)) + ); + + group.add(yearText); + }, + + _monthTextPositionControl: function (point, isCenter, orient, position, margin) { + var align = 'left'; + var vAlign = 'top'; + var x = point[0]; + var y = point[1]; + + if (orient === 'horizontal') { + y = y + margin; + + if (isCenter) { + align = 'center'; + } + + if (position === 'start') { + vAlign = 'bottom'; + } + } + else { + x = x + margin; + + if (isCenter) { + vAlign = 'middle'; + } + + if (position === 'start') { + align = 'right'; + } + } + + return { + x: x, + y: y, + textAlign: align, + textVerticalAlign: vAlign + }; + }, + + // render month and year text + _renderMonthText: function (calendarModel, orient, group) { + var monthLabel = calendarModel.getModel('monthLabel'); + + if (!monthLabel.get('show')) { + return; + } + + var monthLabelStyleModel = calendarModel.getModel('monthLabel.textStyle'); + var nameMap = monthLabel.get('nameMap'); + var margin = monthLabel.get('margin'); + var pos = monthLabel.get('position'); + var align = monthLabel.get('align'); + + var termPoints = [this._tlpoints, this._blpoints]; + + if (zrUtil.isString(nameMap)) { + nameMap = MONTH_TEXT[nameMap.toUpperCase()] || []; + } + + var idx = pos === 'start' ? 0 : 1; + var axis = orient === 'horizontal' ? 0 : 1; + margin = pos === 'start' ? -margin : margin; + var isCenter = (align === 'center'); + + for (var i = 0; i < termPoints[idx].length - 1; i++) { + + var tmp = termPoints[idx][i].slice(); + var firstDay = this._firstDayOfMonth[i]; + + if (isCenter) { + var firstDayPoints = this._firstDayPoints[i]; + tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2; + } + + var formatter = monthLabel.get('formatter'); + var name = nameMap[+firstDay.m - 1]; + var params = { + yyyy: firstDay.y, + yy: (firstDay.y + '').slice(2), + MM: firstDay.m, + M: +firstDay.m, + nameMap: name + }; + + var content = this._formatterLabel(formatter, params); + + var monthText = new graphic.Text({ + z2: 30, + style: zrUtil.extend({ + text: content, + font: monthLabelStyleModel.getFont(), + fill: monthLabelStyleModel.getTextColor() + }, this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)) + }); + + group.add(monthText); + } + }, + + _weekTextPositionControl: function (point, orient, position, margin, cellSize) { + var align = 'center'; + var vAlign = 'middle'; + var x = point[0]; + var y = point[1]; + var isStart = position === 'start'; + + if (orient === 'horizontal') { + x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2; + align = isStart ? 'right' : 'left'; + } + else { + y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2; + vAlign = isStart ? 'bottom' : 'top'; + } + + return { + x: x, + y: y, + textAlign: align, + textVerticalAlign: vAlign + }; + }, + + // render weeks + _renderWeekText: function (calendarModel, rangeData, orient, group) { + var dayLabel = calendarModel.getModel('dayLabel'); + + if (!dayLabel.get('show')) { + return; + } + + var coordSys = calendarModel.coordinateSystem; + var dayLabelStyleModel = calendarModel.getModel('dayLabel.textStyle'); + var pos = dayLabel.get('position'); + var nameMap = dayLabel.get('nameMap'); + var margin = dayLabel.get('margin'); + var firstDayOfWeek = coordSys.getFirstDayOfWeek(); + + if (zrUtil.isString(nameMap)) { + nameMap = WEEK_TEXT[nameMap.toUpperCase()] || []; + } + + var start = coordSys.getNextNDay( + rangeData.end.time, (7 - rangeData.lweek) + ).time; + + var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()]; + margin = numberUtil.parsePercent(margin, cellSize[orient === 'horizontal' ? 0 : 1]); + + if (pos === 'start') { + start = coordSys.getNextNDay( + rangeData.start.time, -(7 + rangeData.fweek) + ).time; + margin = -margin; + } + + for (var i = 0; i < 7; i++) { + + var tmpD = coordSys.getNextNDay(start, i); + var point = coordSys.dataToRect([tmpD.time], false).center; + var day = i; + day = Math.abs((i + firstDayOfWeek) % 7); + var weekText = new graphic.Text({ + z2: 30, + style: zrUtil.extend({ + text: nameMap[day], + font: dayLabelStyleModel.getFont(), + fill: dayLabelStyleModel.getTextColor() + }, this._weekTextPositionControl(point, orient, pos, margin, cellSize)) + }); + group.add(weekText); + } + } + }); + + + +/***/ }, +/* 362 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var echarts = __webpack_require__(1); + var graphic = __webpack_require__(18); + var layout = __webpack_require__(71); + + // Model + echarts.extendComponentModel({ + + type: 'title', + + layoutMode: {type: 'box', ignoreSize: true}, + + defaultOption: { + // 一级层叠 + zlevel: 0, + // 二级层叠 + z: 6, + show: true, + + text: '', + // 超链接跳转 + // link: null, + // 仅支持self | blank + target: 'blank', + subtext: '', + + // 超链接跳转 + // sublink: null, + // 仅支持self | blank + subtarget: 'blank', + + // 'center' ¦ 'left' ¦ 'right' + // ¦ {number}(x坐标,单位px) + left: 0, + // 'top' ¦ 'bottom' ¦ 'center' + // ¦ {number}(y坐标,单位px) + top: 0, + + // 水平对齐 + // 'auto' | 'left' | 'right' | 'center' + // 默认根据 left 的位置判断是左对齐还是右对齐 + // textAlign: null + // + // 垂直对齐 + // 'auto' | 'top' | 'bottom' | 'middle' + // 默认根据 top 位置判断是上对齐还是下对齐 + // textBaseline: null + + backgroundColor: 'rgba(0,0,0,0)', + + // 标题边框颜色 + borderColor: '#ccc', + + // 标题边框线宽,单位px,默认为0(无边框) + borderWidth: 0, + + // 标题内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + padding: 5, + + // 主副标题纵向间隔,单位px,默认为10, + itemGap: 10, + textStyle: { + fontSize: 18, + fontWeight: 'bolder', + color: '#333' + }, + subtextStyle: { + color: '#aaa' + } + } + }); + + // View + echarts.extendComponentView({ + + type: 'title', + + render: function (titleModel, ecModel, api) { + this.group.removeAll(); + + if (!titleModel.get('show')) { + return; + } + + var group = this.group; + + var textStyleModel = titleModel.getModel('textStyle'); + var subtextStyleModel = titleModel.getModel('subtextStyle'); + + var textAlign = titleModel.get('textAlign'); + var textBaseline = titleModel.get('textBaseline'); + + var textEl = new graphic.Text({ + style: { + text: titleModel.get('text'), + textFont: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + }, + z2: 10 + }); + + var textRect = textEl.getBoundingRect(); + + var subText = titleModel.get('subtext'); + var subTextEl = new graphic.Text({ + style: { + text: subText, + textFont: subtextStyleModel.getFont(), + fill: subtextStyleModel.getTextColor(), + y: textRect.height + titleModel.get('itemGap'), + textBaseline: 'top' + }, + z2: 10 + }); + + var link = titleModel.get('link'); + var sublink = titleModel.get('sublink'); + + textEl.silent = !link; + subTextEl.silent = !sublink; + + if (link) { + textEl.on('click', function () { + window.open(link, '_' + titleModel.get('target')); + }); + } + if (sublink) { + subTextEl.on('click', function () { + window.open(sublink, '_' + titleModel.get('subtarget')); + }); + } + + group.add(textEl); + subText && group.add(subTextEl); + // If no subText, but add subTextEl, there will be an empty line. + + var groupRect = group.getBoundingRect(); + var layoutOption = titleModel.getBoxLayoutParams(); + layoutOption.width = groupRect.width; + layoutOption.height = groupRect.height; + var layoutRect = layout.getLayoutRect( + layoutOption, { + width: api.getWidth(), + height: api.getHeight() + }, titleModel.get('padding') + ); + // Adjust text align based on position + if (!textAlign) { + // Align left if title is on the left. center and right is same + textAlign = titleModel.get('left') || titleModel.get('right'); + if (textAlign === 'middle') { + textAlign = 'center'; + } + // Adjust layout by text align + if (textAlign === 'right') { + layoutRect.x += layoutRect.width; + } + else if (textAlign === 'center') { + layoutRect.x += layoutRect.width / 2; + } + } + if (!textBaseline) { + textBaseline = titleModel.get('top') || titleModel.get('bottom'); + if (textBaseline === 'center') { + textBaseline = 'middle'; + } + if (textBaseline === 'bottom') { + layoutRect.y += layoutRect.height; + } + else if (textBaseline === 'middle') { + layoutRect.y += layoutRect.height / 2; + } + + textBaseline = textBaseline || 'top'; + } + + group.attr('position', [layoutRect.x, layoutRect.y]); + var alignStyle = { + textAlign: textAlign, + textVerticalAlign: textBaseline + }; + textEl.setStyle(alignStyle); + subTextEl.setStyle(alignStyle); + + // Render background + // Get groupRect again because textAlign has been changed + groupRect = group.getBoundingRect(); + var padding = layoutRect.margin; + var style = titleModel.getItemStyle(['color', 'opacity']); + style.fill = titleModel.get('backgroundColor'); + var rect = new graphic.Rect({ + shape: { + x: groupRect.x - padding[3], + y: groupRect.y - padding[0], + width: groupRect.width + padding[1] + padding[3], + height: groupRect.height + padding[0] + padding[2] + }, + style: style, + silent: true + }); + graphic.subPixelOptimizeRect(rect); + + group.add(rect); + } + }); + + +/***/ }, +/* 363 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * DataZoom component entry + */ + + + __webpack_require__(364); + + __webpack_require__(365); + __webpack_require__(368); + + __webpack_require__(369); + __webpack_require__(370); + + __webpack_require__(371); + __webpack_require__(372); + + __webpack_require__(374); + __webpack_require__(375); + + + +/***/ }, +/* 364 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(69).registerSubTypeDefaulter('dataZoom', function (option) { + // Default 'slider' when no type specified. + return 'slider'; + }); + + + +/***/ }, +/* 365 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data zoom model + */ + + + var zrUtil = __webpack_require__(4); + var env = __webpack_require__(2); + var echarts = __webpack_require__(1); + var modelUtil = __webpack_require__(5); + var helper = __webpack_require__(366); + var AxisProxy = __webpack_require__(367); + var each = zrUtil.each; + var eachAxisDim = helper.eachAxisDim; + + var DataZoomModel = echarts.extendComponentModel({ + + type: 'dataZoom', + + dependencies: [ + 'xAxis', 'yAxis', 'zAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series' + ], + + /** + * @protected + */ + defaultOption: { + zlevel: 0, + z: 4, // Higher than normal component (z: 2). + orient: null, // Default auto by axisIndex. Possible value: 'horizontal', 'vertical'. + xAxisIndex: null, // Default the first horizontal category axis. + yAxisIndex: null, // Default the first vertical category axis. + + filterMode: 'filter', // Possible values: 'filter' or 'empty' or 'weakFilter'. + // 'filter': data items which are out of window will be removed. This option is + // applicable when filtering outliers. For each data item, it will be + // filtered if one of the relevant dimensions is out of the window. + // 'weakFilter': data items which are out of window will be removed. This option + // is applicable when filtering outliers. For each data item, it will be + // filtered only if all of the relevant dimensions are out of the same + // side of the window. + // 'empty': data items which are out of window will be set to empty. + // This option is applicable when user should not neglect + // that there are some data items out of window. + // 'none': Do not filter. + // Taking line chart as an example, line will be broken in + // the filtered points when filterModel is set to 'empty', but + // be connected when set to 'filter'. + + throttle: null, // Dispatch action by the fixed rate, avoid frequency. + // default 100. Do not throttle when use null/undefined. + // If animation === true and animationDurationUpdate > 0, + // default value is 100, otherwise 20. + start: 0, // Start percent. 0 ~ 100 + end: 100, // End percent. 0 ~ 100 + startValue: null, // Start value. If startValue specified, start is ignored. + endValue: null, // End value. If endValue specified, end is ignored. + minSpan: null, // 0 ~ 100 + maxSpan: null, // 0 ~ 100 + minValueSpan: null, // The range of dataZoom can not be smaller than that. + maxValueSpan: null // The range of dataZoom can not be larger than that. + }, + + /** + * @override + */ + init: function (option, parentModel, ecModel) { + + /** + * key like x_0, y_1 + * @private + * @type {Object} + */ + this._dataIntervalByAxis = {}; + + /** + * @private + */ + this._dataInfo = {}; + + /** + * key like x_0, y_1 + * @private + */ + this._axisProxies = {}; + + /** + * @readOnly + */ + this.textStyleModel; + + /** + * @private + */ + this._autoThrottle = true; + + /** + * 'percent' or 'value' + * @private + */ + this._rangePropMode = ['percent', 'percent']; + + var rawOption = retrieveRaw(option); + + this.mergeDefaultAndTheme(option, ecModel); + + this.doInit(rawOption); + }, + + /** + * @override + */ + mergeOption: function (newOption) { + var rawOption = retrieveRaw(newOption); + + //FIX #2591 + zrUtil.merge(this.option, newOption, true); + + this.doInit(rawOption); + }, + + /** + * @protected + */ + doInit: function (rawOption) { + var thisOption = this.option; + + // Disable realtime view update if canvas is not supported. + if (!env.canvasSupported) { + thisOption.realtime = false; + } + + this._setDefaultThrottle(rawOption); + + updateRangeUse(this, rawOption); + + each([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + // start/end has higher priority over startValue/endValue if they + // both set, but we should make chart.setOption({endValue: 1000}) + // effective, rather than chart.setOption({endValue: 1000, end: null}). + if (this._rangePropMode[index] === 'value') { + thisOption[names[0]] = null; + } + // Otherwise do nothing and use the merge result. + }, this); + + this.textStyleModel = this.getModel('textStyle'); + + this._resetTarget(); + + this._giveAxisProxies(); + }, + + /** + * @private + */ + _giveAxisProxies: function () { + var axisProxies = this._axisProxies; + + this.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel, ecModel) { + var axisModel = this.dependentModels[dimNames.axis][axisIndex]; + + // If exists, share axisProxy with other dataZoomModels. + var axisProxy = axisModel.__dzAxisProxy || ( + // Use the first dataZoomModel as the main model of axisProxy. + axisModel.__dzAxisProxy = new AxisProxy( + dimNames.name, axisIndex, this, ecModel + ) + ); + // FIXME + // dispose __dzAxisProxy + + axisProxies[dimNames.name + '_' + axisIndex] = axisProxy; + }, this); + }, + + /** + * @private + */ + _resetTarget: function () { + var thisOption = this.option; + + var autoMode = this._judgeAutoMode(); + + eachAxisDim(function (dimNames) { + var axisIndexName = dimNames.axisIndex; + thisOption[axisIndexName] = modelUtil.normalizeToArray( + thisOption[axisIndexName] + ); + }, this); + + if (autoMode === 'axisIndex') { + this._autoSetAxisIndex(); + } + else if (autoMode === 'orient') { + this._autoSetOrient(); + } + }, + + /** + * @private + */ + _judgeAutoMode: function () { + // Auto set only works for setOption at the first time. + // The following is user's reponsibility. So using merged + // option is OK. + var thisOption = this.option; + + var hasIndexSpecified = false; + eachAxisDim(function (dimNames) { + // When user set axisIndex as a empty array, we think that user specify axisIndex + // but do not want use auto mode. Because empty array may be encountered when + // some error occured. + if (thisOption[dimNames.axisIndex] != null) { + hasIndexSpecified = true; + } + }, this); + + var orient = thisOption.orient; + + if (orient == null && hasIndexSpecified) { + return 'orient'; + } + else if (!hasIndexSpecified) { + if (orient == null) { + thisOption.orient = 'horizontal'; + } + return 'axisIndex'; + } + }, + + /** + * @private + */ + _autoSetAxisIndex: function () { + var autoAxisIndex = true; + var orient = this.get('orient', true); + var thisOption = this.option; + var dependentModels = this.dependentModels; + + if (autoAxisIndex) { + // Find axis that parallel to dataZoom as default. + var dimName = orient === 'vertical' ? 'y' : 'x'; + + if (dependentModels[dimName + 'Axis'].length) { + thisOption[dimName + 'AxisIndex'] = [0]; + autoAxisIndex = false; + } + else { + each(dependentModels.singleAxis, function (singleAxisModel) { + if (autoAxisIndex && singleAxisModel.get('orient', true) === orient) { + thisOption.singleAxisIndex = [singleAxisModel.componentIndex]; + autoAxisIndex = false; + } + }); + } + } + + if (autoAxisIndex) { + // Find the first category axis as default. (consider polar) + eachAxisDim(function (dimNames) { + if (!autoAxisIndex) { + return; + } + var axisIndices = []; + var axisModels = this.dependentModels[dimNames.axis]; + if (axisModels.length && !axisIndices.length) { + for (var i = 0, len = axisModels.length; i < len; i++) { + if (axisModels[i].get('type') === 'category') { + axisIndices.push(i); + } + } + } + thisOption[dimNames.axisIndex] = axisIndices; + if (axisIndices.length) { + autoAxisIndex = false; + } + }, this); + } + + if (autoAxisIndex) { + // FIXME + // 这里是兼容ec2的写法(没指定xAxisIndex和yAxisIndex时把scatter和双数值轴折柱纳入dataZoom控制), + // 但是实际是否需要Grid.js#getScaleByOption来判断(考虑time,log等axis type)? + + // If both dataZoom.xAxisIndex and dataZoom.yAxisIndex is not specified, + // dataZoom component auto adopts series that reference to + // both xAxis and yAxis which type is 'value'. + this.ecModel.eachSeries(function (seriesModel) { + if (this._isSeriesHasAllAxesTypeOf(seriesModel, 'value')) { + eachAxisDim(function (dimNames) { + var axisIndices = thisOption[dimNames.axisIndex]; + + var axisIndex = seriesModel.get(dimNames.axisIndex); + var axisId = seriesModel.get(dimNames.axisId); + + var axisModel = seriesModel.ecModel.queryComponents({ + mainType: dimNames.axis, + index: axisIndex, + id: axisId + })[0]; + + if (true) { + if (!axisModel) { + throw new Error( + dimNames.axis + ' "' + zrUtil.retrieve( + axisIndex, + axisId, + 0 + ) + '" not found' + ); + } + } + axisIndex = axisModel.componentIndex; + + if (zrUtil.indexOf(axisIndices, axisIndex) < 0) { + axisIndices.push(axisIndex); + } + }); + } + }, this); + } + }, + + /** + * @private + */ + _autoSetOrient: function () { + var dim; + + // Find the first axis + this.eachTargetAxis(function (dimNames) { + !dim && (dim = dimNames.name); + }, this); + + this.option.orient = dim === 'y' ? 'vertical' : 'horizontal'; + }, + + /** + * @private + */ + _isSeriesHasAllAxesTypeOf: function (seriesModel, axisType) { + // FIXME + // 需要series的xAxisIndex和yAxisIndex都首先自动设置上。 + // 例如series.type === scatter时。 + + var is = true; + eachAxisDim(function (dimNames) { + var seriesAxisIndex = seriesModel.get(dimNames.axisIndex); + var axisModel = this.dependentModels[dimNames.axis][seriesAxisIndex]; + + if (!axisModel || axisModel.get('type') !== axisType) { + is = false; + } + }, this); + return is; + }, + + /** + * @private + */ + _setDefaultThrottle: function (rawOption) { + // When first time user set throttle, auto throttle ends. + if (rawOption.hasOwnProperty('throttle')) { + this._autoThrottle = false; + } + if (this._autoThrottle) { + var globalOption = this.ecModel.option; + this.option.throttle = + (globalOption.animation && globalOption.animationDurationUpdate > 0) + ? 100 : 20; + } + }, + + /** + * @public + */ + getFirstTargetAxisModel: function () { + var firstAxisModel; + eachAxisDim(function (dimNames) { + if (firstAxisModel == null) { + var indices = this.get(dimNames.axisIndex); + if (indices.length) { + firstAxisModel = this.dependentModels[dimNames.axis][indices[0]]; + } + } + }, this); + + return firstAxisModel; + }, + + /** + * @public + * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel + */ + eachTargetAxis: function (callback, context) { + var ecModel = this.ecModel; + eachAxisDim(function (dimNames) { + each( + this.get(dimNames.axisIndex), + function (axisIndex) { + callback.call(context, dimNames, axisIndex, this, ecModel); + }, + this + ); + }, this); + }, + + /** + * @param {string} dimName + * @param {number} axisIndex + * @return {module:echarts/component/dataZoom/AxisProxy} If not found, return null/undefined. + */ + getAxisProxy: function (dimName, axisIndex) { + return this._axisProxies[dimName + '_' + axisIndex]; + }, + + /** + * @param {string} dimName + * @param {number} axisIndex + * @return {module:echarts/model/Model} If not found, return null/undefined. + */ + getAxisModel: function (dimName, axisIndex) { + var axisProxy = this.getAxisProxy(dimName, axisIndex); + return axisProxy && axisProxy.getAxisModel(); + }, + + /** + * If not specified, set to undefined. + * + * @public + * @param {Object} opt + * @param {number} [opt.start] + * @param {number} [opt.end] + * @param {number} [opt.startValue] + * @param {number} [opt.endValue] + * @param {boolean} [ignoreUpdateRangeUsg=false] + */ + setRawRange: function (opt, ignoreUpdateRangeUsg) { + each(['start', 'end', 'startValue', 'endValue'], function (name) { + // If any of those prop is null/undefined, we should alos set + // them, because only one pair between start/end and + // startValue/endValue can work. + this.option[name] = opt[name]; + }, this); + + !ignoreUpdateRangeUsg && updateRangeUse(this, opt); + }, + + /** + * @public + * @return {Array.} [startPercent, endPercent] + */ + getPercentRange: function () { + var axisProxy = this.findRepresentativeAxisProxy(); + if (axisProxy) { + return axisProxy.getDataPercentWindow(); + } + }, + + /** + * @public + * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0); + * + * @param {string} [axisDimName] + * @param {number} [axisIndex] + * @return {Array.} [startValue, endValue] value can only be '-' or finite number. + */ + getValueRange: function (axisDimName, axisIndex) { + if (axisDimName == null && axisIndex == null) { + var axisProxy = this.findRepresentativeAxisProxy(); + if (axisProxy) { + return axisProxy.getDataValueWindow(); + } + } + else { + return this.getAxisProxy(axisDimName, axisIndex).getDataValueWindow(); + } + }, + + /** + * @public + * @param {module:echarts/model/Model} [axisModel] If axisModel given, find axisProxy + * corresponding to the axisModel + * @return {module:echarts/component/dataZoom/AxisProxy} + */ + findRepresentativeAxisProxy: function (axisModel) { + if (axisModel) { + return axisModel.__dzAxisProxy; + } + + // Find the first hosted axisProxy + var axisProxies = this._axisProxies; + for (var key in axisProxies) { + if (axisProxies.hasOwnProperty(key) && axisProxies[key].hostedBy(this)) { + return axisProxies[key]; + } + } + + // If no hosted axis find not hosted axisProxy. + // Consider this case: dataZoomModel1 and dataZoomModel2 control the same axis, + // and the option.start or option.end settings are different. The percentRange + // should follow axisProxy. + // (We encounter this problem in toolbox data zoom.) + for (var key in axisProxies) { + if (axisProxies.hasOwnProperty(key) && !axisProxies[key].hostedBy(this)) { + return axisProxies[key]; + } + } + }, + + /** + * @return {Array.} + */ + getRangePropMode: function () { + return this._rangePropMode.slice(); + } + }); + + function retrieveRaw(option) { + var ret = {}; + each( + ['start', 'end', 'startValue', 'endValue', 'throttle'], + function (name) { + option.hasOwnProperty(name) && (ret[name] = option[name]); + } + ); + return ret; + } + + function updateRangeUse(dataZoomModel, rawOption) { + each([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + var rangePropMode = dataZoomModel._rangePropMode; + if (rawOption[names[0]] != null) { + rangePropMode[index] = 'percent'; + } + else if (rawOption[names[1]] != null) { + rangePropMode[index] = 'value'; + } + // else remain its original setting. + }); + } + + module.exports = DataZoomModel; + + + +/***/ }, +/* 366 */ +/***/ function(module, exports, __webpack_require__) { + + + var formatUtil = __webpack_require__(6); + var zrUtil = __webpack_require__(4); + + var helper = {}; + + var AXIS_DIMS = ['x', 'y', 'z', 'radius', 'angle', 'single']; + // Supported coords. + var COORDS = ['cartesian2d', 'polar', 'singleAxis']; + + /** + * @param {string} coordType + * @return {boolean} + */ + helper.isCoordSupported = function (coordType) { + return zrUtil.indexOf(COORDS, coordType) >= 0; + }; + + /** + * Create "each" method to iterate names. + * + * @pubilc + * @param {Array.} names + * @param {Array.=} attrs + * @return {Function} + */ + helper.createNameEach = function (names, attrs) { + names = names.slice(); + var capitalNames = zrUtil.map(names, formatUtil.capitalFirst); + attrs = (attrs || []).slice(); + var capitalAttrs = zrUtil.map(attrs, formatUtil.capitalFirst); + + return function (callback, context) { + zrUtil.each(names, function (name, index) { + var nameObj = {name: name, capital: capitalNames[index]}; + + for (var j = 0; j < attrs.length; j++) { + nameObj[attrs[j]] = name + capitalAttrs[j]; + } + + callback.call(context, nameObj); + }); + }; + }; + + /** + * Iterate each dimension name. + * + * @public + * @param {Function} callback The parameter is like: + * { + * name: 'angle', + * capital: 'Angle', + * axis: 'angleAxis', + * axisIndex: 'angleAixs', + * index: 'angleIndex' + * } + * @param {Object} context + */ + helper.eachAxisDim = helper.createNameEach(AXIS_DIMS, ['axisIndex', 'axis', 'index', 'id']); + + /** + * If tow dataZoomModels has the same axis controlled, we say that they are 'linked'. + * dataZoomModels and 'links' make up one or more graphics. + * This function finds the graphic where the source dataZoomModel is in. + * + * @public + * @param {Function} forEachNode Node iterator. + * @param {Function} forEachEdgeType edgeType iterator + * @param {Function} edgeIdGetter Giving node and edgeType, return an array of edge id. + * @return {Function} Input: sourceNode, Output: Like {nodes: [], dims: {}} + */ + helper.createLinkedNodesFinder = function (forEachNode, forEachEdgeType, edgeIdGetter) { + + return function (sourceNode) { + var result = { + nodes: [], + records: {} // key: edgeType.name, value: Object (key: edge id, value: boolean). + }; + + forEachEdgeType(function (edgeType) { + result.records[edgeType.name] = {}; + }); + + if (!sourceNode) { + return result; + } + + absorb(sourceNode, result); + + var existsLink; + do { + existsLink = false; + forEachNode(processSingleNode); + } + while (existsLink); + + function processSingleNode(node) { + if (!isNodeAbsorded(node, result) && isLinked(node, result)) { + absorb(node, result); + existsLink = true; + } + } + + return result; + }; + + function isNodeAbsorded(node, result) { + return zrUtil.indexOf(result.nodes, node) >= 0; + } + + function isLinked(node, result) { + var hasLink = false; + forEachEdgeType(function (edgeType) { + zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) { + result.records[edgeType.name][edgeId] && (hasLink = true); + }); + }); + return hasLink; + } + + function absorb(node, result) { + result.nodes.push(node); + forEachEdgeType(function (edgeType) { + zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) { + result.records[edgeType.name][edgeId] = true; + }); + }); + } + }; + + module.exports = helper; + + +/***/ }, +/* 367 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Axis operator + */ + + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var helper = __webpack_require__(366); + var each = zrUtil.each; + var asc = numberUtil.asc; + + /** + * Operate single axis. + * One axis can only operated by one axis operator. + * Different dataZoomModels may be defined to operate the same axis. + * (i.e. 'inside' data zoom and 'slider' data zoom components) + * So dataZoomModels share one axisProxy in that case. + * + * @class + */ + var AxisProxy = function (dimName, axisIndex, dataZoomModel, ecModel) { + + /** + * @private + * @type {string} + */ + this._dimName = dimName; + + /** + * @private + */ + this._axisIndex = axisIndex; + + /** + * @private + * @type {Array.} + */ + this._valueWindow; + + /** + * @private + * @type {Array.} + */ + this._percentWindow; + + /** + * @private + * @type {Array.} + */ + this._dataExtent; + + /** + * {minSpan, maxSpan, minValueSpan, maxValueSpan} + * @private + * @type {Object} + */ + this._minMaxSpan; + + /** + * @readOnly + * @type {module: echarts/model/Global} + */ + this.ecModel = ecModel; + + /** + * @private + * @type {module: echarts/component/dataZoom/DataZoomModel} + */ + this._dataZoomModel = dataZoomModel; + }; + + AxisProxy.prototype = { + + constructor: AxisProxy, + + /** + * Whether the axisProxy is hosted by dataZoomModel. + * + * @public + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + * @return {boolean} + */ + hostedBy: function (dataZoomModel) { + return this._dataZoomModel === dataZoomModel; + }, + + /** + * @return {Array.} Value can only be NaN or finite value. + */ + getDataValueWindow: function () { + return this._valueWindow.slice(); + }, + + /** + * @return {Array.} + */ + getDataPercentWindow: function () { + return this._percentWindow.slice(); + }, + + /** + * @public + * @param {number} axisIndex + * @return {Array} seriesModels + */ + getTargetSeriesModels: function () { + var seriesModels = []; + var ecModel = this.ecModel; + + ecModel.eachSeries(function (seriesModel) { + if (helper.isCoordSupported(seriesModel.get('coordinateSystem'))) { + var dimName = this._dimName; + var axisModel = ecModel.queryComponents({ + mainType: dimName + 'Axis', + index: seriesModel.get(dimName + 'AxisIndex'), + id: seriesModel.get(dimName + 'AxisId') + })[0]; + if (this._axisIndex === (axisModel && axisModel.componentIndex)) { + seriesModels.push(seriesModel); + } + } + }, this); + + return seriesModels; + }, + + getAxisModel: function () { + return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex); + }, + + getOtherAxisModel: function () { + var axisDim = this._dimName; + var ecModel = this.ecModel; + var axisModel = this.getAxisModel(); + var isCartesian = axisDim === 'x' || axisDim === 'y'; + var otherAxisDim; + var coordSysIndexName; + if (isCartesian) { + coordSysIndexName = 'gridIndex'; + otherAxisDim = axisDim === 'x' ? 'y' : 'x'; + } + else { + coordSysIndexName = 'polarIndex'; + otherAxisDim = axisDim === 'angle' ? 'radius' : 'angle'; + } + var foundOtherAxisModel; + ecModel.eachComponent(otherAxisDim + 'Axis', function (otherAxisModel) { + if ((otherAxisModel.get(coordSysIndexName) || 0) + === (axisModel.get(coordSysIndexName) || 0) + ) { + foundOtherAxisModel = otherAxisModel; + } + }); + return foundOtherAxisModel; + }, + + getMinMaxSpan: function () { + return zrUtil.clone(this._minMaxSpan); + }, + + /** + * Only calculate by given range and this._dataExtent, do not change anything. + * + * @param {Object} opt + * @param {number} [opt.start] + * @param {number} [opt.end] + * @param {number} [opt.startValue] + * @param {number} [opt.endValue] + */ + calculateDataWindow: function (opt) { + var dataExtent = this._dataExtent; + var axisModel = this.getAxisModel(); + var scale = axisModel.axis.scale; + var rangePropMode = this._dataZoomModel.getRangePropMode(); + var percentExtent = [0, 100]; + var percentWindow = [ + opt.start, + opt.end + ]; + var valueWindow = []; + + each(['startValue', 'endValue'], function (prop) { + valueWindow.push(opt[prop] != null ? scale.parse(opt[prop]) : null); + }); + + // Normalize bound. + each([0, 1], function (idx) { + var boundValue = valueWindow[idx]; + var boundPercent = percentWindow[idx]; + + // Notice: dataZoom is based either on `percentProp` ('start', 'end') or + // on `valueProp` ('startValue', 'endValue'). The former one is suitable + // for cases that a dataZoom component controls multiple axes with different + // unit or extent, and the latter one is suitable for accurate zoom by pixel + // (e.g., in dataZoomSelect). `valueProp` can be calculated from `percentProp`, + // but it is awkward that `percentProp` can not be obtained from `valueProp` + // accurately (because all of values that are overflow the `dataExtent` will + // be calculated to percent '100%'). So we have to use + // `dataZoom.getRangePropMode()` to mark which prop is used. + // `rangePropMode` is updated only when setOption or dispatchAction, otherwise + // it remains its original value. + + if (rangePropMode[idx] === 'percent') { + if (boundPercent == null) { + boundPercent = percentExtent[idx]; + } + // Use scale.parse to math round for category or time axis. + boundValue = scale.parse(numberUtil.linearMap( + boundPercent, percentExtent, dataExtent, true + )); + } + else { + // Calculating `percent` from `value` may be not accurate, because + // This calculation can not be inversed, because all of values that + // are overflow the `dataExtent` will be calculated to percent '100%' + boundPercent = numberUtil.linearMap( + boundValue, dataExtent, percentExtent, true + ); + } + + // valueWindow[idx] = round(boundValue); + // percentWindow[idx] = round(boundPercent); + valueWindow[idx] = boundValue; + percentWindow[idx] = boundPercent; + }); + + return { + valueWindow: asc(valueWindow), + percentWindow: asc(percentWindow) + }; + }, + + /** + * Notice: reset should not be called before series.restoreData() called, + * so it is recommanded to be called in "process stage" but not "model init + * stage". + * + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + */ + reset: function (dataZoomModel) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + // Culculate data window and data extent, and record them. + this._dataExtent = calculateDataExtent( + this, this._dimName, this.getTargetSeriesModels() + ); + + var dataWindow = this.calculateDataWindow(dataZoomModel.option); + + this._valueWindow = dataWindow.valueWindow; + this._percentWindow = dataWindow.percentWindow; + + setMinMaxSpan(this); + + // Update axis setting then. + setAxisModel(this); + }, + + /** + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + */ + restore: function (dataZoomModel) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + this._valueWindow = this._percentWindow = null; + setAxisModel(this, true); + }, + + /** + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + */ + filterData: function (dataZoomModel) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + var axisDim = this._dimName; + var seriesModels = this.getTargetSeriesModels(); + var filterMode = dataZoomModel.get('filterMode'); + var valueWindow = this._valueWindow; + + if (filterMode === 'none') { + return; + } + + // FIXME + // Toolbox may has dataZoom injected. And if there are stacked bar chart + // with NaN data, NaN will be filtered and stack will be wrong. + // So we need to force the mode to be set empty. + // In fect, it is not a big deal that do not support filterMode-'filter' + // when using toolbox#dataZoom, utill tooltip#dataZoom support "single axis + // selection" some day, which might need "adapt to data extent on the + // otherAxis", which is disabled by filterMode-'empty'. + var otherAxisModel = this.getOtherAxisModel(); + if (dataZoomModel.get('$fromToolbox') + && otherAxisModel + && otherAxisModel.get('type') === 'category' + ) { + filterMode = 'empty'; + } + + // Process series data + each(seriesModels, function (seriesModel) { + var seriesData = seriesModel.getData(); + var dataDims = seriesModel.coordDimToDataDim(axisDim); + + if (filterMode === 'weakFilter') { + seriesData && seriesData.filterSelf(function (dataIndex) { + var leftOut; + var rightOut; + var hasValue; + for (var i = 0; i < dataDims.length; i++) { + var value = seriesData.get(dataDims[i], dataIndex); + var thisHasValue = !isNaN(value); + var thisLeftOut = value < valueWindow[0]; + var thisRightOut = value > valueWindow[1]; + if (thisHasValue && !thisLeftOut && !thisRightOut) { + return true; + } + thisHasValue && (hasValue = true); + thisLeftOut && (leftOut = true); + thisRightOut && (rightOut = true); + } + // If both left out and right out, do not filter. + return hasValue && leftOut && rightOut; + }); + } + else { + seriesData && each(dataDims, function (dim) { + if (filterMode === 'empty') { + seriesModel.setData( + seriesData.map(dim, function (value) { + return !isInWindow(value) ? NaN : value; + }) + ); + } + else { + seriesData.filterSelf(dim, isInWindow); + } + }); + } + }); + + function isInWindow(value) { + return value >= valueWindow[0] && value <= valueWindow[1]; + } + } + }; + + function calculateDataExtent(axisProxy, axisDim, seriesModels) { + var dataExtent = [Infinity, -Infinity]; + + each(seriesModels, function (seriesModel) { + var seriesData = seriesModel.getData(); + if (seriesData) { + each(seriesModel.coordDimToDataDim(axisDim), function (dim) { + var seriesExtent = seriesData.getDataExtent(dim); + seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]); + seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]); + }); + } + }); + + if (dataExtent[1] < dataExtent[0]) { + dataExtent = [NaN, NaN]; + } + + // It is important to get "consistent" extent when more then one axes is + // controlled by a `dataZoom`, otherwise those axes will not be synchronized + // when zooming. But it is difficult to know what is "consistent", considering + // axes have different type or even different meanings (For example, two + // time axes are used to compare data of the same date in different years). + // So basically dataZoom just obtains extent by series.data (in category axis + // extent can be obtained from axis.data). + // Nevertheless, user can set min/max/scale on axes to make extent of axes + // consistent. + fixExtentByAxis(axisProxy, dataExtent); + + return dataExtent; + } + + function fixExtentByAxis(axisProxy, dataExtent) { + var axisModel = axisProxy.getAxisModel(); + var min = axisModel.getMin(true); + + // For category axis, if min/max/scale are not set, extent is determined + // by axis.data by default. + var isCategoryAxis = axisModel.get('type') === 'category'; + var axisDataLen = isCategoryAxis && (axisModel.get('data') || []).length; + + if (min != null && min !== 'dataMin') { + dataExtent[0] = min; + } + else if (isCategoryAxis) { + dataExtent[0] = axisDataLen > 0 ? 0 : NaN; + } + + var max = axisModel.getMax(true); + if (max != null && max !== 'dataMax') { + dataExtent[1] = max; + } + else if (isCategoryAxis) { + dataExtent[1] = axisDataLen > 0 ? axisDataLen - 1 : NaN; + } + + if (!axisModel.get('scale', true)) { + dataExtent[0] > 0 && (dataExtent[0] = 0); + dataExtent[1] < 0 && (dataExtent[1] = 0); + } + + // For value axis, if min/max/scale are not set, we just use the extent obtained + // by series data, which may be a little different from the extent calculated by + // `axisHelper.getScaleExtent`. But the different just affects the experience a + // little when zooming. So it will not be fixed until some users require it strongly. + + return dataExtent; + } + + function setAxisModel(axisProxy, isRestore) { + var axisModel = axisProxy.getAxisModel(); + + var percentWindow = axisProxy._percentWindow; + var valueWindow = axisProxy._valueWindow; + + if (!percentWindow) { + return; + } + + // [0, 500]: arbitrary value, guess axis extent. + var precision = numberUtil.getPixelPrecision(valueWindow, [0, 500]); + // isRestore or isFull + var useOrigin = isRestore || (percentWindow[0] === 0 && percentWindow[1] === 100); + + axisModel.setRange( + useOrigin ? null : +valueWindow[0].toFixed(precision), + useOrigin ? null : +valueWindow[1].toFixed(precision) + ); + } + + function setMinMaxSpan(axisProxy) { + var minMaxSpan = axisProxy._minMaxSpan = {}; + var dataZoomModel = axisProxy._dataZoomModel; + + each(['min', 'max'], function (minMax) { + minMaxSpan[minMax + 'Span'] = dataZoomModel.get(minMax + 'Span'); + + // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan + var valueSpan = dataZoomModel.get(minMax + 'ValueSpan'); + if (valueSpan != null) { + minMaxSpan[minMax + 'ValueSpan'] = valueSpan; + + valueSpan = axisProxy.getAxisModel().axis.scale.parse(valueSpan); + if (valueSpan != null) { + minMaxSpan[minMax + 'Span'] = numberUtil.linearMap( + valueSpan, axisProxy._dataExtent, [0, 100], true + ); + } + } + }); + } + + module.exports = AxisProxy; + + + +/***/ }, +/* 368 */ +/***/ function(module, exports, __webpack_require__) { + + + + var ComponentView = __webpack_require__(79); + + module.exports = ComponentView.extend({ + + type: 'dataZoom', + + render: function (dataZoomModel, ecModel, api, payload) { + this.dataZoomModel = dataZoomModel; + this.ecModel = ecModel; + this.api = api; + }, + + /** + * Find the first target coordinate system. + * + * @protected + * @return {Object} { + * grid: [ + * {model: coord0, axisModels: [axis1, axis3], coordIndex: 1}, + * {model: coord1, axisModels: [axis0, axis2], coordIndex: 0}, + * ... + * ], // cartesians must not be null/undefined. + * polar: [ + * {model: coord0, axisModels: [axis4], coordIndex: 0}, + * ... + * ], // polars must not be null/undefined. + * singleAxis: [ + * {model: coord0, axisModels: [], coordIndex: 0} + * ] + */ + getTargetCoordInfo: function () { + var dataZoomModel = this.dataZoomModel; + var ecModel = this.ecModel; + var coordSysLists = {}; + + dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) { + var axisModel = ecModel.getComponent(dimNames.axis, axisIndex); + if (axisModel) { + var coordModel = axisModel.getCoordSysModel(); + coordModel && save( + coordModel, + axisModel, + coordSysLists[coordModel.mainType] || (coordSysLists[coordModel.mainType] = []), + coordModel.componentIndex + ); + } + }, this); + + function save(coordModel, axisModel, store, coordIndex) { + var item; + for (var i = 0; i < store.length; i++) { + if (store[i].model === coordModel) { + item = store[i]; + break; + } + } + if (!item) { + store.push(item = { + model: coordModel, axisModels: [], coordIndex: coordIndex + }); + } + item.axisModels.push(axisModel); + } + + return coordSysLists; + } + + }); + + + +/***/ }, +/* 369 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data zoom model + */ + + + var DataZoomModel = __webpack_require__(365); + + var SliderZoomModel = DataZoomModel.extend({ + + type: 'dataZoom.slider', + + layoutMode: 'box', + + /** + * @protected + */ + defaultOption: { + show: true, + + // ph => placeholder. Using placehoder here because + // deault value can only be drived in view stage. + right: 'ph', // Default align to grid rect. + top: 'ph', // Default align to grid rect. + width: 'ph', // Default align to grid rect. + height: 'ph', // Default align to grid rect. + left: null, // Default align to grid rect. + bottom: null, // Default align to grid rect. + + backgroundColor: 'rgba(47,69,84,0)', // Background of slider zoom component. + // dataBackgroundColor: '#ddd', // Background coor of data shadow and border of box, + // highest priority, remain for compatibility of + // previous version, but not recommended any more. + dataBackground: { + lineStyle: { + color: '#2f4554', + width: 0.5, + opacity: 0.3 + }, + areaStyle: { + color: 'rgba(47,69,84,0.3)', + opacity: 0.3 + } + }, + borderColor: '#ddd', // border color of the box. For compatibility, + // if dataBackgroundColor is set, borderColor + // is ignored. + + fillerColor: 'rgba(167,183,204,0.4)', // Color of selected area. + // handleColor: 'rgba(89,170,216,0.95)', // Color of handle. + // handleIcon: 'path://M4.9,17.8c0-1.4,4.5-10.5,5.5-12.4c0-0.1,0.6-1.1,0.9-1.1c0.4,0,0.9,1,0.9,1.1c1.1,2.2,5.4,11,5.4,12.4v17.8c0,1.5-0.6,2.1-1.3,2.1H6.1c-0.7,0-1.3-0.6-1.3-2.1V17.8z', + handleIcon: 'M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z', + // Percent of the slider height + handleSize: '100%', + + handleStyle: { + color: '#a7b7cc' + }, + + labelPrecision: null, + labelFormatter: null, + showDetail: true, + showDataShadow: 'auto', // Default auto decision. + realtime: true, + zoomLock: false, // Whether disable zoom. + textStyle: { + color: '#333' + } + } + + }); + + module.exports = SliderZoomModel; + + + +/***/ }, +/* 370 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var throttle = __webpack_require__(81); + var DataZoomView = __webpack_require__(368); + var Rect = graphic.Rect; + var numberUtil = __webpack_require__(7); + var linearMap = numberUtil.linearMap; + var layout = __webpack_require__(71); + var sliderMove = __webpack_require__(239); + var eventTool = __webpack_require__(88); + + var asc = numberUtil.asc; + var bind = zrUtil.bind; + // var mathMax = Math.max; + var each = zrUtil.each; + + // Constants + var DEFAULT_LOCATION_EDGE_GAP = 7; + var DEFAULT_FRAME_BORDER_WIDTH = 1; + var DEFAULT_FILLER_SIZE = 30; + var HORIZONTAL = 'horizontal'; + var VERTICAL = 'vertical'; + var LABEL_GAP = 5; + var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter']; + + var SliderZoomView = DataZoomView.extend({ + + type: 'dataZoom.slider', + + init: function (ecModel, api) { + + /** + * @private + * @type {Object} + */ + this._displayables = {}; + + /** + * @private + * @type {string} + */ + this._orient; + + /** + * [0, 100] + * @private + */ + this._range; + + /** + * [coord of the first handle, coord of the second handle] + * @private + */ + this._handleEnds; + + /** + * [length, thick] + * @private + * @type {Array.} + */ + this._size; + + /** + * @private + * @type {number} + */ + this._handleWidth; + + /** + * @private + * @type {number} + */ + this._handleHeight; + + /** + * @private + */ + this._location; + + /** + * @private + */ + this._dragging; + + /** + * @private + */ + this._dataShadowInfo; + + this.api = api; + }, + + /** + * @override + */ + render: function (dataZoomModel, ecModel, api, payload) { + SliderZoomView.superApply(this, 'render', arguments); + + throttle.createOrUpdate( + this, + '_dispatchZoomAction', + this.dataZoomModel.get('throttle'), + 'fixRate' + ); + + this._orient = dataZoomModel.get('orient'); + + if (this.dataZoomModel.get('show') === false) { + this.group.removeAll(); + return; + } + + // Notice: this._resetInterval() should not be executed when payload.type + // is 'dataZoom', origin this._range should be maintained, otherwise 'pan' + // or 'zoom' info will be missed because of 'throttle' of this.dispatchAction, + if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) { + this._buildView(); + } + + this._updateView(); + }, + + /** + * @override + */ + remove: function () { + SliderZoomView.superApply(this, 'remove', arguments); + throttle.clear(this, '_dispatchZoomAction'); + }, + + /** + * @override + */ + dispose: function () { + SliderZoomView.superApply(this, 'dispose', arguments); + throttle.clear(this, '_dispatchZoomAction'); + }, + + _buildView: function () { + var thisGroup = this.group; + + thisGroup.removeAll(); + + this._resetLocation(); + this._resetInterval(); + + var barGroup = this._displayables.barGroup = new graphic.Group(); + + this._renderBackground(); + + this._renderHandle(); + + this._renderDataShadow(); + + thisGroup.add(barGroup); + + this._positionGroup(); + }, + + /** + * @private + */ + _resetLocation: function () { + var dataZoomModel = this.dataZoomModel; + var api = this.api; + + // If some of x/y/width/height are not specified, + // auto-adapt according to target grid. + var coordRect = this._findCoordRect(); + var ecSize = {width: api.getWidth(), height: api.getHeight()}; + // Default align by coordinate system rect. + var positionInfo = this._orient === HORIZONTAL + ? { + // Why using 'right', because right should be used in vertical, + // and it is better to be consistent for dealing with position param merge. + right: ecSize.width - coordRect.x - coordRect.width, + top: (ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP), + width: coordRect.width, + height: DEFAULT_FILLER_SIZE + } + : { // vertical + right: DEFAULT_LOCATION_EDGE_GAP, + top: coordRect.y, + width: DEFAULT_FILLER_SIZE, + height: coordRect.height + }; + + // Do not write back to option and replace value 'ph', because + // the 'ph' value should be recalculated when resize. + var layoutParams = layout.getLayoutParams(dataZoomModel.option); + + // Replace the placeholder value. + zrUtil.each(['right', 'top', 'width', 'height'], function (name) { + if (layoutParams[name] === 'ph') { + layoutParams[name] = positionInfo[name]; + } + }); + + var layoutRect = layout.getLayoutRect( + layoutParams, + ecSize, + dataZoomModel.padding + ); + + this._location = {x: layoutRect.x, y: layoutRect.y}; + this._size = [layoutRect.width, layoutRect.height]; + this._orient === VERTICAL && this._size.reverse(); + }, + + /** + * @private + */ + _positionGroup: function () { + var thisGroup = this.group; + var location = this._location; + var orient = this._orient; + + // Just use the first axis to determine mapping. + var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel(); + var inverse = targetAxisModel && targetAxisModel.get('inverse'); + + var barGroup = this._displayables.barGroup; + var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse; + + // Transform barGroup. + barGroup.attr( + (orient === HORIZONTAL && !inverse) + ? {scale: otherAxisInverse ? [1, 1] : [1, -1]} + : (orient === HORIZONTAL && inverse) + ? {scale: otherAxisInverse ? [-1, 1] : [-1, -1]} + : (orient === VERTICAL && !inverse) + ? {scale: otherAxisInverse ? [1, -1] : [1, 1], rotation: Math.PI / 2} + // Dont use Math.PI, considering shadow direction. + : {scale: otherAxisInverse ? [-1, -1] : [-1, 1], rotation: Math.PI / 2} + ); + + // Position barGroup + var rect = thisGroup.getBoundingRect([barGroup]); + thisGroup.attr('position', [location.x - rect.x, location.y - rect.y]); + }, + + /** + * @private + */ + _getViewExtent: function () { + return [0, this._size[0]]; + }, + + _renderBackground: function () { + var dataZoomModel = this.dataZoomModel; + var size = this._size; + var barGroup = this._displayables.barGroup; + + barGroup.add(new Rect({ + silent: true, + shape: { + x: 0, y: 0, width: size[0], height: size[1] + }, + style: { + fill: dataZoomModel.get('backgroundColor') + }, + z2: -40 + })); + + // Click panel, over shadow, below handles. + barGroup.add(new Rect({ + shape: { + x: 0, y: 0, width: size[0], height: size[1] + }, + style: { + fill: 'transparent' + }, + z2: 0, + onclick: zrUtil.bind(this._onClickPanelClick, this) + })); + }, + + _renderDataShadow: function () { + var info = this._dataShadowInfo = this._prepareDataShadowInfo(); + + if (!info) { + return; + } + + var size = this._size; + var seriesModel = info.series; + var data = seriesModel.getRawData(); + var otherDim = seriesModel.getShadowDim + ? seriesModel.getShadowDim() // @see candlestick + : info.otherDim; + + if (otherDim == null) { + return; + } + + var otherDataExtent = data.getDataExtent(otherDim); + // Nice extent. + var otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3; + otherDataExtent = [ + otherDataExtent[0] - otherOffset, + otherDataExtent[1] + otherOffset + ]; + var otherShadowExtent = [0, size[1]]; + + var thisShadowExtent = [0, size[0]]; + + var areaPoints = [[size[0], 0], [0, 0]]; + var linePoints = []; + var step = thisShadowExtent[1] / (data.count() - 1); + var thisCoord = 0; + + // Optimize for large data shadow + var stride = Math.round(data.count() / size[0]); + var lastIsEmpty; + data.each([otherDim], function (value, index) { + if (stride > 0 && (index % stride)) { + thisCoord += step; + return; + } + + // FIXME + // Should consider axis.min/axis.max when drawing dataShadow. + + // FIXME + // 应该使用统一的空判断?还是在list里进行空判断? + var isEmpty = value == null || isNaN(value) || value === ''; + // See #4235. + var otherCoord = isEmpty + ? 0 : linearMap(value, otherDataExtent, otherShadowExtent, true); + + // Attempt to draw data shadow precisely when there are empty value. + if (isEmpty && !lastIsEmpty && index) { + areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]); + linePoints.push([linePoints[linePoints.length - 1][0], 0]); + } + else if (!isEmpty && lastIsEmpty) { + areaPoints.push([thisCoord, 0]); + linePoints.push([thisCoord, 0]); + } + + areaPoints.push([thisCoord, otherCoord]); + linePoints.push([thisCoord, otherCoord]); + + thisCoord += step; + lastIsEmpty = isEmpty; + }); + + var dataZoomModel = this.dataZoomModel; + // var dataBackgroundModel = dataZoomModel.getModel('dataBackground'); + this._displayables.barGroup.add(new graphic.Polygon({ + shape: {points: areaPoints}, + style: zrUtil.defaults( + {fill: dataZoomModel.get('dataBackgroundColor')}, + dataZoomModel.getModel('dataBackground.areaStyle').getAreaStyle() + ), + silent: true, + z2: -20 + })); + this._displayables.barGroup.add(new graphic.Polyline({ + shape: {points: linePoints}, + style: dataZoomModel.getModel('dataBackground.lineStyle').getLineStyle(), + silent: true, + z2: -19 + })); + }, + + _prepareDataShadowInfo: function () { + var dataZoomModel = this.dataZoomModel; + var showDataShadow = dataZoomModel.get('showDataShadow'); + + if (showDataShadow === false) { + return; + } + + // Find a representative series. + var result; + var ecModel = this.ecModel; + + dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) { + var seriesModels = dataZoomModel + .getAxisProxy(dimNames.name, axisIndex) + .getTargetSeriesModels(); + + zrUtil.each(seriesModels, function (seriesModel) { + if (result) { + return; + } + + if (showDataShadow !== true && zrUtil.indexOf( + SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type') + ) < 0 + ) { + return; + } + + var thisAxis = ecModel.getComponent(dimNames.axis, axisIndex).axis; + var otherDim = getOtherDim(dimNames.name); + var otherAxisInverse; + var coordSys = seriesModel.coordinateSystem; + if (otherDim != null && coordSys.getOtherAxis) { + otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; + } + + result = { + thisAxis: thisAxis, + series: seriesModel, + thisDim: dimNames.name, + otherDim: otherDim, + otherAxisInverse: otherAxisInverse + }; + + }, this); + + }, this); + + return result; + }, + + _renderHandle: function () { + var displaybles = this._displayables; + var handles = displaybles.handles = []; + var handleLabels = displaybles.handleLabels = []; + var barGroup = this._displayables.barGroup; + var size = this._size; + var dataZoomModel = this.dataZoomModel; + + barGroup.add(displaybles.filler = new Rect({ + draggable: true, + cursor: 'move', + drift: bind(this._onDragMove, this, 'all'), + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + eventTool.stop(e.event); + }, + ondragstart: bind(this._showDataInfo, this, true), + ondragend: bind(this._onDragEnd, this), + onmouseover: bind(this._showDataInfo, this, true), + onmouseout: bind(this._showDataInfo, this, false), + style: { + fill: dataZoomModel.get('fillerColor'), + textPosition : 'inside' + } + })); + + // Frame border. + barGroup.add(new Rect(graphic.subPixelOptimizeRect({ + silent: true, + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1] + }, + style: { + stroke: dataZoomModel.get('dataBackgroundColor') + || dataZoomModel.get('borderColor'), + lineWidth: DEFAULT_FRAME_BORDER_WIDTH, + fill: 'rgba(0,0,0,0)' + } + }))); + + var iconStr = dataZoomModel.get('handleIcon'); + each([0, 1], function (handleIndex) { + var iconOpt = { + style: { + strokeNoScale: true + }, + rectHover: true, + cursor: this._orient === 'vertical' ? 'ns-resize' : 'ew-resize', + draggable: true, + drift: bind(this._onDragMove, this, handleIndex), + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + eventTool.stop(e.event); + }, + ondragend: bind(this._onDragEnd, this), + onmouseover: bind(this._showDataInfo, this, true), + onmouseout: bind(this._showDataInfo, this, false) + }; + var iconStyle = {x: -1, y: 0, width: 2, height: 2}; + + var path = iconStr.indexOf('image://') === 0 + ? ( + iconStyle.image = iconStr.slice(8), + iconOpt.style = iconStyle, + new graphic.Image(iconOpt) + ) + : graphic.makePath( + iconStr.replace('path://', ''), + iconOpt, + iconStyle, + 'center' + ); + + var bRect = path.getBoundingRect(); + this._handleHeight = numberUtil.parsePercent(dataZoomModel.get('handleSize'), this._size[1]); + this._handleWidth = bRect.width / bRect.height * this._handleHeight; + + path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle()); + var handleColor = dataZoomModel.get('handleColor'); + // Compatitable with previous version + if (handleColor != null) { + path.style.fill = handleColor; + } + + barGroup.add(handles[handleIndex] = path); + + var textStyleModel = dataZoomModel.textStyleModel; + + this.group.add( + handleLabels[handleIndex] = new graphic.Text({ + silent: true, + invisible: true, + style: { + x: 0, y: 0, text: '', + textVerticalAlign: 'middle', + textAlign: 'center', + fill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont() + }, + z2: 10 + })); + + }, this); + }, + + /** + * @private + */ + _resetInterval: function () { + var range = this._range = this.dataZoomModel.getPercentRange(); + var viewExtent = this._getViewExtent(); + + this._handleEnds = [ + linearMap(range[0], [0, 100], viewExtent, true), + linearMap(range[1], [0, 100], viewExtent, true) + ]; + }, + + /** + * @private + * @param {(number|string)} handleIndex 0 or 1 or 'all' + * @param {number} delta + */ + _updateInterval: function (handleIndex, delta) { + var dataZoomModel = this.dataZoomModel; + var handleEnds = this._handleEnds; + var viewExtend = this._getViewExtent(); + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + var percentExtent = [0, 100]; + + sliderMove( + delta, + handleEnds, + viewExtend, + dataZoomModel.get('zoomLock') ? 'all' : handleIndex, + minMaxSpan.minSpan != null + ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, + minMaxSpan.maxSpan != null + ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null + ); + + this._range = asc([ + linearMap(handleEnds[0], viewExtend, percentExtent, true), + linearMap(handleEnds[1], viewExtend, percentExtent, true) + ]); + }, + + /** + * @private + */ + _updateView: function (nonRealtime) { + var displaybles = this._displayables; + var handleEnds = this._handleEnds; + var handleInterval = asc(handleEnds.slice()); + var size = this._size; + + each([0, 1], function (handleIndex) { + // Handles + var handle = displaybles.handles[handleIndex]; + var handleHeight = this._handleHeight; + handle.attr({ + scale: [handleHeight / 2, handleHeight / 2], + position: [handleEnds[handleIndex], size[1] / 2 - handleHeight / 2] + }); + }, this); + + // Filler + displaybles.filler.setShape({ + x: handleInterval[0], + y: 0, + width: handleInterval[1] - handleInterval[0], + height: size[1] + }); + + this._updateDataInfo(nonRealtime); + }, + + /** + * @private + */ + _updateDataInfo: function (nonRealtime) { + var dataZoomModel = this.dataZoomModel; + var displaybles = this._displayables; + var handleLabels = displaybles.handleLabels; + var orient = this._orient; + var labelTexts = ['', '']; + + // FIXME + // date型,支持formatter,autoformatter(ec2 date.getAutoFormatter) + if (dataZoomModel.get('showDetail')) { + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + + if (axisProxy) { + var axis = axisProxy.getAxisModel().axis; + var range = this._range; + + var dataInterval = nonRealtime + // See #4434, data and axis are not processed and reset yet in non-realtime mode. + ? axisProxy.calculateDataWindow({ + start: range[0], end: range[1] + }).valueWindow + : axisProxy.getDataValueWindow(); + + labelTexts = [ + this._formatLabel(dataInterval[0], axis), + this._formatLabel(dataInterval[1], axis) + ]; + } + } + + var orderedHandleEnds = asc(this._handleEnds.slice()); + + setLabel.call(this, 0); + setLabel.call(this, 1); + + function setLabel(handleIndex) { + // Label + // Text should not transform by barGroup. + // Ignore handlers transform + var barTransform = graphic.getTransform( + displaybles.handles[handleIndex].parent, this.group + ); + var direction = graphic.transformDirection( + handleIndex === 0 ? 'right' : 'left', barTransform + ); + var offset = this._handleWidth / 2 + LABEL_GAP; + var textPoint = graphic.applyTransform( + [ + orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset), + this._size[1] / 2 + ], + barTransform + ); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + textVerticalAlign: orient === HORIZONTAL ? 'middle' : direction, + textAlign: orient === HORIZONTAL ? direction : 'center', + text: labelTexts[handleIndex] + }); + } + }, + + /** + * @private + */ + _formatLabel: function (value, axis) { + var dataZoomModel = this.dataZoomModel; + var labelFormatter = dataZoomModel.get('labelFormatter'); + + var labelPrecision = dataZoomModel.get('labelPrecision'); + if (labelPrecision == null || labelPrecision === 'auto') { + labelPrecision = axis.getPixelPrecision(); + } + + var valueStr = (value == null || isNaN(value)) + ? '' + // FIXME Glue code + : (axis.type === 'category' || axis.type === 'time') + ? axis.scale.getLabel(Math.round(value)) + // param of toFixed should less then 20. + : value.toFixed(Math.min(labelPrecision, 20)); + + return zrUtil.isFunction(labelFormatter) + ? labelFormatter(value, valueStr) + : zrUtil.isString(labelFormatter) + ? labelFormatter.replace('{value}', valueStr) + : valueStr; + }, + + /** + * @private + * @param {boolean} showOrHide true: show, false: hide + */ + _showDataInfo: function (showOrHide) { + // Always show when drgging. + showOrHide = this._dragging || showOrHide; + + var handleLabels = this._displayables.handleLabels; + handleLabels[0].attr('invisible', !showOrHide); + handleLabels[1].attr('invisible', !showOrHide); + }, + + _onDragMove: function (handleIndex, dx, dy) { + this._dragging = true; + + // Transform dx, dy to bar coordination. + var barTransform = this._displayables.barGroup.getLocalTransform(); + var vertex = graphic.applyTransform([dx, dy], barTransform, true); + + this._updateInterval(handleIndex, vertex[0]); + + var realtime = this.dataZoomModel.get('realtime'); + + this._updateView(!realtime); + + if (realtime) { + realtime && this._dispatchZoomAction(); + } + }, + + _onDragEnd: function () { + this._dragging = false; + this._showDataInfo(false); + this._dispatchZoomAction(); + }, + + _onClickPanelClick: function (e) { + var size = this._size; + var localPoint = this._displayables.barGroup.transformCoordToLocal(e.offsetX, e.offsetY); + + if (localPoint[0] < 0 || localPoint[0] > size[0] + || localPoint[1] < 0 || localPoint[1] > size[1] + ) { + return; + } + + var handleEnds = this._handleEnds; + var center = (handleEnds[0] + handleEnds[1]) / 2; + + this._updateInterval('all', localPoint[0] - center); + this._updateView(); + this._dispatchZoomAction(); + }, + + /** + * This action will be throttled. + * @private + */ + _dispatchZoomAction: function () { + var range = this._range; + + this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + dataZoomId: this.dataZoomModel.id, + start: range[0], + end: range[1] + }); + }, + + /** + * @private + */ + _findCoordRect: function () { + // Find the grid coresponding to the first axis referred by dataZoom. + var rect; + each(this.getTargetCoordInfo(), function (coordInfoList) { + if (!rect && coordInfoList.length) { + var coordSys = coordInfoList[0].model.coordinateSystem; + rect = coordSys.getRect && coordSys.getRect(); + } + }); + if (!rect) { + var width = this.api.getWidth(); + var height = this.api.getHeight(); + rect = { + x: width * 0.2, + y: height * 0.2, + width: width * 0.6, + height: height * 0.6 + }; + } + + return rect; + } + + }); + + function getOtherDim(thisDim) { + // FIXME + // 这个逻辑和getOtherAxis里一致,但是写在这里是否不好 + var map = {x: 'y', y: 'x', radius: 'angle', angle: 'radius'}; + return map[thisDim]; + } + + module.exports = SliderZoomView; + + + +/***/ }, +/* 371 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data zoom model + */ + + + module.exports = __webpack_require__(365).extend({ + + type: 'dataZoom.inside', + + /** + * @protected + */ + defaultOption: { + disabled: false, // Whether disable this inside zoom. + zoomLock: false, // Whether disable zoom but only pan. + zoomOnMouseWheel: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'. + moveOnMouseMove: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'. + preventDefaultMouseMove: true + } + }); + + +/***/ }, +/* 372 */ +/***/ function(module, exports, __webpack_require__) { + + + + var DataZoomView = __webpack_require__(368); + var zrUtil = __webpack_require__(4); + var sliderMove = __webpack_require__(239); + var roams = __webpack_require__(373); + var bind = zrUtil.bind; + + var InsideZoomView = DataZoomView.extend({ + + type: 'dataZoom.inside', + + /** + * @override + */ + init: function (ecModel, api) { + /** + * 'throttle' is used in this.dispatchAction, so we save range + * to avoid missing some 'pan' info. + * @private + * @type {Array.} + */ + this._range; + }, + + /** + * @override + */ + render: function (dataZoomModel, ecModel, api, payload) { + InsideZoomView.superApply(this, 'render', arguments); + + // Notice: origin this._range should be maintained, and should not be re-fetched + // from dataZoomModel when payload.type is 'dataZoom', otherwise 'pan' or 'zoom' + // info will be missed because of 'throttle' of this.dispatchAction. + if (roams.shouldRecordRange(payload, dataZoomModel.id)) { + this._range = dataZoomModel.getPercentRange(); + } + + // Reset controllers. + zrUtil.each(this.getTargetCoordInfo(), function (coordInfoList, coordSysName) { + + var allCoordIds = zrUtil.map(coordInfoList, function (coordInfo) { + return roams.generateCoordId(coordInfo.model); + }); + + zrUtil.each(coordInfoList, function (coordInfo) { + var coordModel = coordInfo.model; + var dataZoomOption = dataZoomModel.option; + + roams.register( + api, + { + coordId: roams.generateCoordId(coordModel), + allCoordIds: allCoordIds, + containsPoint: function (e, x, y) { + return coordModel.coordinateSystem.containPoint([x, y]); + }, + dataZoomId: dataZoomModel.id, + throttleRate: dataZoomModel.get('throttle', true), + panGetRange: bind(this._onPan, this, coordInfo, coordSysName), + zoomGetRange: bind(this._onZoom, this, coordInfo, coordSysName), + zoomLock: dataZoomOption.zoomLock, + disabled: dataZoomOption.disabled, + roamControllerOpt: { + zoomOnMouseWheel: dataZoomOption.zoomOnMouseWheel, + moveOnMouseMove: dataZoomOption.moveOnMouseMove, + preventDefaultMouseMove: dataZoomOption.preventDefaultMouseMove + } + } + ); + }, this); + + }, this); + }, + + /** + * @override + */ + dispose: function () { + roams.unregister(this.api, this.dataZoomModel.id); + InsideZoomView.superApply(this, 'dispose', arguments); + this._range = null; + }, + + /** + * @private + */ + _onPan: function (coordInfo, coordSysName, controller, dx, dy, oldX, oldY, newX, newY) { + var range = this._range.slice(); + + // Calculate transform by the first axis. + var axisModel = coordInfo.axisModels[0]; + if (!axisModel) { + return; + } + + var directionInfo = getDirectionInfo[coordSysName]( + [oldX, oldY], [newX, newY], axisModel, controller, coordInfo + ); + + var percentDelta = directionInfo.signal + * (range[1] - range[0]) + * directionInfo.pixel / directionInfo.pixelLength; + + sliderMove(percentDelta, range, [0, 100], 'all'); + + return (this._range = range); + }, + + /** + * @private + */ + _onZoom: function (coordInfo, coordSysName, controller, scale, mouseX, mouseY) { + var range = this._range.slice(); + + // Calculate transform by the first axis. + var axisModel = coordInfo.axisModels[0]; + if (!axisModel) { + return; + } + + var directionInfo = getDirectionInfo[coordSysName]( + null, [mouseX, mouseY], axisModel, controller, coordInfo + ); + var percentPoint = ( + directionInfo.signal > 0 + ? (directionInfo.pixelStart + directionInfo.pixelLength - directionInfo.pixel) + : (directionInfo.pixel - directionInfo.pixelStart) + ) / directionInfo.pixelLength * (range[1] - range[0]) + range[0]; + + scale = Math.max(1 / scale, 0); + range[0] = (range[0] - percentPoint) * scale + percentPoint; + range[1] = (range[1] - percentPoint) * scale + percentPoint; + + // Restrict range. + var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); + + return (this._range = range); + } + + }); + + var getDirectionInfo = { + + grid: function (oldPoint, newPoint, axisModel, controller, coordInfo) { + var axis = axisModel.axis; + var ret = {}; + var rect = coordInfo.model.coordinateSystem.getRect(); + oldPoint = oldPoint || [0, 0]; + + if (axis.dim === 'x') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } + else { // axis.dim === 'y' + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + + polar: function (oldPoint, newPoint, axisModel, controller, coordInfo) { + var axis = axisModel.axis; + var ret = {}; + var polar = coordInfo.model.coordinateSystem; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var angleExtent = polar.getAngleAxis().getExtent(); + + oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0]; + newPoint = polar.pointToCoord(newPoint); + + if (axisModel.mainType === 'radiusAxis') { + ret.pixel = newPoint[0] - oldPoint[0]; + // ret.pixelLength = Math.abs(radiusExtent[1] - radiusExtent[0]); + // ret.pixelStart = Math.min(radiusExtent[0], radiusExtent[1]); + ret.pixelLength = radiusExtent[1] - radiusExtent[0]; + ret.pixelStart = radiusExtent[0]; + ret.signal = axis.inverse ? 1 : -1; + } + else { // 'angleAxis' + ret.pixel = newPoint[1] - oldPoint[1]; + // ret.pixelLength = Math.abs(angleExtent[1] - angleExtent[0]); + // ret.pixelStart = Math.min(angleExtent[0], angleExtent[1]); + ret.pixelLength = angleExtent[1] - angleExtent[0]; + ret.pixelStart = angleExtent[0]; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + + singleAxis: function (oldPoint, newPoint, axisModel, controller, coordInfo) { + var axis = axisModel.axis; + var rect = coordInfo.model.coordinateSystem.getRect(); + var ret = {}; + + oldPoint = oldPoint || [0, 0]; + + if (axis.orient === 'horizontal') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } + else { // 'vertical' + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + } + }; + + module.exports = InsideZoomView; + + +/***/ }, +/* 373 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Roam controller manager. + */ + + + // Only create one roam controller for each coordinate system. + // one roam controller might be refered by two inside data zoom + // components (for example, one for x and one for y). When user + // pan or zoom, only dispatch one action for those data zoom + // components. + + var zrUtil = __webpack_require__(4); + var RoamController = __webpack_require__(183); + var throttle = __webpack_require__(81); + var curry = zrUtil.curry; + + var ATTR = '\0_ec_dataZoom_roams'; + + var roams = { + + /** + * @public + * @param {module:echarts/ExtensionAPI} api + * @param {Object} dataZoomInfo + * @param {string} dataZoomInfo.coordId + * @param {Function} dataZoomInfo.containsPoint + * @param {Array.} dataZoomInfo.allCoordIds + * @param {string} dataZoomInfo.dataZoomId + * @param {number} dataZoomInfo.throttleRate + * @param {Function} dataZoomInfo.panGetRange + * @param {Function} dataZoomInfo.zoomGetRange + * @param {boolean} [dataZoomInfo.zoomLock] + * @param {boolean} [dataZoomInfo.disabled] + */ + register: function (api, dataZoomInfo) { + var store = giveStore(api); + var theDataZoomId = dataZoomInfo.dataZoomId; + var theCoordId = dataZoomInfo.coordId; + + // Do clean when a dataZoom changes its target coordnate system. + // Avoid memory leak, dispose all not-used-registered. + zrUtil.each(store, function (record, coordId) { + var dataZoomInfos = record.dataZoomInfos; + if (dataZoomInfos[theDataZoomId] + && zrUtil.indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0 + ) { + delete dataZoomInfos[theDataZoomId]; + record.count--; + } + }); + + cleanStore(store); + + var record = store[theCoordId]; + // Create if needed. + if (!record) { + record = store[theCoordId] = { + coordId: theCoordId, + dataZoomInfos: {}, + count: 0 + }; + record.controller = createController(api, record); + record.dispatchAction = zrUtil.curry(dispatchAction, api); + } + + // Update reference of dataZoom. + !(record.dataZoomInfos[theDataZoomId]) && record.count++; + record.dataZoomInfos[theDataZoomId] = dataZoomInfo; + + var controllerParams = mergeControllerParams(record.dataZoomInfos); + record.controller.enable(controllerParams.controlType, controllerParams.opt); + + // Consider resize, area should be always updated. + record.controller.setPointerChecker(dataZoomInfo.containsPoint); + + // Update throttle. + throttle.createOrUpdate( + record, + 'dispatchAction', + dataZoomInfo.throttleRate, + 'fixRate' + ); + }, + + /** + * @public + * @param {module:echarts/ExtensionAPI} api + * @param {string} dataZoomId + */ + unregister: function (api, dataZoomId) { + var store = giveStore(api); + + zrUtil.each(store, function (record) { + record.controller.dispose(); + var dataZoomInfos = record.dataZoomInfos; + if (dataZoomInfos[dataZoomId]) { + delete dataZoomInfos[dataZoomId]; + record.count--; + } + }); + + cleanStore(store); + }, + + /** + * @public + */ + shouldRecordRange: function (payload, dataZoomId) { + if (payload && payload.type === 'dataZoom' && payload.batch) { + for (var i = 0, len = payload.batch.length; i < len; i++) { + if (payload.batch[i].dataZoomId === dataZoomId) { + return false; + } + } + } + return true; + }, + + /** + * @public + */ + generateCoordId: function (coordModel) { + return coordModel.type + '\0_' + coordModel.id; + } + }; + + /** + * Key: coordId, value: {dataZoomInfos: [], count, controller} + * @type {Array.} + */ + function giveStore(api) { + // Mount store on zrender instance, so that we do not + // need to worry about dispose. + var zr = api.getZr(); + return zr[ATTR] || (zr[ATTR] = {}); + } + + function createController(api, newRecord) { + var controller = new RoamController(api.getZr()); + controller.on('pan', curry(onPan, newRecord)); + controller.on('zoom', curry(onZoom, newRecord)); + + return controller; + } + + function cleanStore(store) { + zrUtil.each(store, function (record, coordId) { + if (!record.count) { + record.controller.dispose(); + delete store[coordId]; + } + }); + } + + function onPan(record, dx, dy, oldX, oldY, newX, newY) { + wrapAndDispatch(record, function (info) { + return info.panGetRange(record.controller, dx, dy, oldX, oldY, newX, newY); + }); + } + + function onZoom(record, scale, mouseX, mouseY) { + wrapAndDispatch(record, function (info) { + return info.zoomGetRange(record.controller, scale, mouseX, mouseY); + }); + } + + function wrapAndDispatch(record, getRange) { + var batch = []; + + zrUtil.each(record.dataZoomInfos, function (info) { + var range = getRange(info); + !info.disabled && range && batch.push({ + dataZoomId: info.dataZoomId, + start: range[0], + end: range[1] + }); + }); + + record.dispatchAction(batch); + } + + /** + * This action will be throttled. + */ + function dispatchAction(api, batch) { + api.dispatchAction({ + type: 'dataZoom', + batch: batch + }); + } + + /** + * Merge roamController settings when multiple dataZooms share one roamController. + */ + function mergeControllerParams(dataZoomInfos) { + var controlType; + var opt = {}; + var typePriority = { + 'true': 2, + 'move': 1, + 'false': 0, + 'undefined': -1 + }; + zrUtil.each(dataZoomInfos, function (dataZoomInfo) { + var oneType = dataZoomInfo.disabled ? false : dataZoomInfo.zoomLock ? 'move' : true; + typePriority[oneType] > typePriority[controlType] && (controlType = oneType); + // Do not support that different 'shift'/'ctrl'/'alt' setting used in one coord sys. + zrUtil.extend(opt, dataZoomInfo.roamControllerOpt); + }); + + return { + controlType: controlType, + opt: opt + }; + } + + module.exports = roams; + + + +/***/ }, +/* 374 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data zoom processor + */ + + + var echarts = __webpack_require__(1); + + echarts.registerProcessor(function (ecModel, api) { + + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + // We calculate window and reset axis here but not in model + // init stage and not after action dispatch handler, because + // reset should be called after seriesData.restoreData. + dataZoomModel.eachTargetAxis(resetSingleAxis); + + // Caution: data zoom filtering is order sensitive when using + // percent range and no min/max/scale set on axis. + // For example, we have dataZoom definition: + // [ + // {xAxisIndex: 0, start: 30, end: 70}, + // {yAxisIndex: 0, start: 20, end: 80} + // ] + // In this case, [20, 80] of y-dataZoom should be based on data + // that have filtered by x-dataZoom using range of [30, 70], + // but should not be based on full raw data. Thus sliding + // x-dataZoom will change both ranges of xAxis and yAxis, + // while sliding y-dataZoom will only change the range of yAxis. + // So we should filter x-axis after reset x-axis immediately, + // and then reset y-axis and filter y-axis. + dataZoomModel.eachTargetAxis(filterSingleAxis); + }); + + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + // Fullfill all of the range props so that user + // is able to get them from chart.getOption(). + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + var percentRange = axisProxy.getDataPercentWindow(); + var valueRange = axisProxy.getDataValueWindow(); + + dataZoomModel.setRawRange({ + start: percentRange[0], + end: percentRange[1], + startValue: valueRange[0], + endValue: valueRange[1] + }, true); + }); + }); + + function resetSingleAxis(dimNames, axisIndex, dataZoomModel) { + dataZoomModel.getAxisProxy(dimNames.name, axisIndex).reset(dataZoomModel); + } + + function filterSingleAxis(dimNames, axisIndex, dataZoomModel) { + dataZoomModel.getAxisProxy(dimNames.name, axisIndex).filterData(dataZoomModel); + } + + + + +/***/ }, +/* 375 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data zoom action + */ + + + var zrUtil = __webpack_require__(4); + var helper = __webpack_require__(366); + var echarts = __webpack_require__(1); + + + echarts.registerAction('dataZoom', function (payload, ecModel) { + + var linkedNodesFinder = helper.createLinkedNodesFinder( + zrUtil.bind(ecModel.eachComponent, ecModel, 'dataZoom'), + helper.eachAxisDim, + function (model, dimNames) { + return model.get(dimNames.axisIndex); + } + ); + + var effectedModels = []; + + ecModel.eachComponent( + {mainType: 'dataZoom', query: payload}, + function (model, index) { + effectedModels.push.apply( + effectedModels, linkedNodesFinder(model).nodes + ); + } + ); + + zrUtil.each(effectedModels, function (dataZoomModel, index) { + dataZoomModel.setRawRange({ + start: payload.start, + end: payload.end, + startValue: payload.startValue, + endValue: payload.endValue + }); + }); + + }); + + + +/***/ }, +/* 376 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * visualMap component entry + */ + + + __webpack_require__(377); + __webpack_require__(388); + + + +/***/ }, +/* 377 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * DataZoom component entry + */ + + + __webpack_require__(1).registerPreprocessor( + __webpack_require__(378) + ); + + __webpack_require__(379); + __webpack_require__(380); + __webpack_require__(381); + __webpack_require__(384); + __webpack_require__(387); + + + +/***/ }, +/* 378 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file VisualMap preprocessor + */ + + + var zrUtil = __webpack_require__(4); + var each = zrUtil.each; + + module.exports = function (option) { + var visualMap = option && option.visualMap; + + if (!zrUtil.isArray(visualMap)) { + visualMap = visualMap ? [visualMap] : []; + } + + each(visualMap, function (opt) { + if (!opt) { + return; + } + + // rename splitList to pieces + if (has(opt, 'splitList') && !has(opt, 'pieces')) { + opt.pieces = opt.splitList; + delete opt.splitList; + } + + var pieces = opt.pieces; + if (pieces && zrUtil.isArray(pieces)) { + each(pieces, function (piece) { + if (zrUtil.isObject(piece)) { + if (has(piece, 'start') && !has(piece, 'min')) { + piece.min = piece.start; + } + if (has(piece, 'end') && !has(piece, 'max')) { + piece.max = piece.end; + } + } + }); + } + }); + }; + + function has(obj, name) { + return obj && obj.hasOwnProperty && obj.hasOwnProperty(name); + } + + + +/***/ }, +/* 379 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(69).registerSubTypeDefaulter('visualMap', function (option) { + // Compatible with ec2, when splitNumber === 0, continuous visualMap will be used. + return ( + !option.categories + && ( + !( + option.pieces + ? option.pieces.length > 0 + : option.splitNumber > 0 + ) + || option.calculable + ) + ) + ? 'continuous' : 'piecewise'; + }); + + + +/***/ }, +/* 380 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data range visual coding. + */ + + + var echarts = __webpack_require__(1); + var visualSolution = __webpack_require__(350); + var VisualMapping = __webpack_require__(203); + var zrUtil = __webpack_require__(4); + + echarts.registerVisual(echarts.PRIORITY.VISUAL.COMPONENT, function (ecModel) { + ecModel.eachComponent('visualMap', function (visualMapModel) { + processSingleVisualMap(visualMapModel, ecModel); + }); + + prepareVisualMeta(ecModel); + }); + + function processSingleVisualMap(visualMapModel, ecModel) { + visualMapModel.eachTargetSeries(function (seriesModel) { + var data = seriesModel.getData(); + + visualSolution.applyVisual( + visualMapModel.stateList, + visualMapModel.targetVisuals, + data, + visualMapModel.getValueState, + visualMapModel, + visualMapModel.getDataDimension(data) + ); + }); + } + + // Only support color. + function prepareVisualMeta(ecModel) { + ecModel.eachSeries(function (seriesModel) { + var data = seriesModel.getData(); + var visualMetaList = []; + + ecModel.eachComponent('visualMap', function (visualMapModel) { + if (visualMapModel.isTargetSeries(seriesModel)) { + var visualMeta = visualMapModel.getVisualMeta( + zrUtil.bind(getColorVisual, null, seriesModel, visualMapModel) + ) || {stops: [], outerColors: []}; + visualMeta.dimension = visualMapModel.getDataDimension(data); + visualMetaList.push(visualMeta); + } + }); + + // console.log(JSON.stringify(visualMetaList.map(a => a.stops))); + seriesModel.getData().setVisual('visualMeta', visualMetaList); + }); + } + + // FIXME + // performance and export for heatmap? + // value can be Infinity or -Infinity + function getColorVisual(seriesModel, visualMapModel, value, valueState) { + var mappings = visualMapModel.targetVisuals[valueState]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + var resultVisual = { + color: seriesModel.getData().getVisual('color') // default color. + }; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + var mapping = mappings[ + type === 'opacity' ? '__alphaForOpacity' : type + ]; + mapping && mapping.applyVisual(value, getVisual, setVisual); + } + + return resultVisual.color; + + function getVisual(key) { + return resultVisual[key]; + } + + function setVisual(key, value) { + resultVisual[key] = value; + } + } + + + + +/***/ }, +/* 381 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data zoom model + */ + + + var VisualMapModel = __webpack_require__(382); + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + + // Constant + var DEFAULT_BAR_BOUND = [20, 140]; + + var ContinuousModel = VisualMapModel.extend({ + + type: 'visualMap.continuous', + + /** + * @protected + */ + defaultOption: { + align: 'auto', // 'auto', 'left', 'right', 'top', 'bottom' + calculable: false, // This prop effect default component type determine, + // See echarts/component/visualMap/typeDefaulter. + range: null, // selected range. In default case `range` is [min, max] + // and can auto change along with modification of min max, + // util use specifid a range. + realtime: true, // Whether realtime update. + itemHeight: null, // The length of the range control edge. + itemWidth: null, // The length of the other side. + hoverLink: true, // Enable hover highlight. + hoverLinkDataSize: null,// The size of hovered data. + hoverLinkOnHandle: true // Whether trigger hoverLink when hover handle. + }, + + /** + * @override + */ + optionUpdated: function (newOption, isInit) { + ContinuousModel.superApply(this, 'optionUpdated', arguments); + + this.resetTargetSeries(); + this.resetExtent(); + + this.resetVisual(function (mappingOption) { + mappingOption.mappingMethod = 'linear'; + mappingOption.dataExtent = this.getExtent(); + }); + + this._resetRange(); + }, + + /** + * @protected + * @override + */ + resetItemSize: function () { + ContinuousModel.superApply(this, 'resetItemSize', arguments); + + var itemSize = this.itemSize; + + this._orient === 'horizontal' && itemSize.reverse(); + + (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]); + (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]); + }, + + /** + * @private + */ + _resetRange: function () { + var dataExtent = this.getExtent(); + var range = this.option.range; + + if (!range || range.auto) { + // `range` should always be array (so we dont use other + // value like 'auto') for user-friend. (consider getOption). + dataExtent.auto = 1; + this.option.range = dataExtent; + } + else if (zrUtil.isArray(range)) { + if (range[0] > range[1]) { + range.reverse(); + } + range[0] = Math.max(range[0], dataExtent[0]); + range[1] = Math.min(range[1], dataExtent[1]); + } + }, + + /** + * @protected + * @override + */ + completeVisualOption: function () { + VisualMapModel.prototype.completeVisualOption.apply(this, arguments); + + zrUtil.each(this.stateList, function (state) { + var symbolSize = this.option.controller[state].symbolSize; + if (symbolSize && symbolSize[0] !== symbolSize[1]) { + symbolSize[0] = 0; // For good looking. + } + }, this); + }, + + /** + * @override + */ + setSelected: function (selected) { + this.option.range = selected.slice(); + this._resetRange(); + }, + + /** + * @public + */ + getSelected: function () { + var dataExtent = this.getExtent(); + + var dataInterval = numberUtil.asc( + (this.get('range') || []).slice() + ); + + // Clamp + dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]); + dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]); + dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]); + dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]); + + return dataInterval; + }, + + /** + * @override + */ + getValueState: function (value) { + var range = this.option.range; + var dataExtent = this.getExtent(); + + // When range[0] === dataExtent[0], any value larger than dataExtent[0] maps to 'inRange'. + // range[1] is processed likewise. + return ( + (range[0] <= dataExtent[0] || range[0] <= value) + && (range[1] >= dataExtent[1] || value <= range[1]) + ) ? 'inRange' : 'outOfRange'; + }, + + /** + * @params {Array.} range target value: range[0] <= value && value <= range[1] + * @return {Array.} [{seriesId, dataIndices: >}, ...] + */ + findTargetDataIndices: function (range) { + var result = []; + + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + + data.each(this.getDataDimension(data), function (value, dataIndex) { + range[0] <= value && value <= range[1] && dataIndices.push(dataIndex); + }, true, this); + + result.push({seriesId: seriesModel.id, dataIndex: dataIndices}); + }, this); + + return result; + }, + + /** + * @implement + */ + getVisualMeta: function (getColorVisual) { + var oVals = getColorStopValues(this, 'outOfRange', this.getExtent()); + var iVals = getColorStopValues(this, 'inRange', this.option.range.slice()); + var stops = []; + + function setStop(value, valueState) { + stops.push({ + value: value, + color: getColorVisual(value, valueState) + }); + } + + // Format to: outOfRange -- inRange -- outOfRange. + var iIdx = 0; + var oIdx = 0; + var iLen = iVals.length; + var oLen = oVals.length; + + for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) { + // If oVal[oIdx] === iVals[iIdx], oVal[oIdx] should be ignored. + if (oVals[oIdx] < iVals[iIdx]) { + setStop(oVals[oIdx], 'outOfRange'); + } + } + for (var first = 1; iIdx < iLen; iIdx++, first = 0) { + // If range is full, value beyond min, max will be clamped. + // make a singularity + first && stops.length && setStop(iVals[iIdx], 'outOfRange'); + setStop(iVals[iIdx], 'inRange'); + } + for (var first = 1; oIdx < oLen; oIdx++) { + if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) { + // make a singularity + if (first) { + stops.length && setStop(stops[stops.length - 1].value, 'outOfRange'); + first = 0; + } + setStop(oVals[oIdx], 'outOfRange'); + } + } + + var stopsLen = stops.length; + + return { + stops: stops, + outerColors: [ + stopsLen ? stops[0].color : 'transparent', + stopsLen ? stops[stopsLen - 1].color : 'transparent' + ] + }; + } + + }); + + function getColorStopValues(visualMapModel, valueState, dataExtent) { + if (dataExtent[0] === dataExtent[1]) { + return dataExtent.slice(); + } + + // When using colorHue mapping, it is not linear color any more. + // Moreover, canvas gradient seems not to be accurate linear. + // FIXME + // Should be arbitrary value 100? or based on pixel size? + var count = 200; + var step = (dataExtent[1] - dataExtent[0]) / count; + + var value = dataExtent[0]; + var stopValues = []; + for (var i = 0; i <= count && value < dataExtent[1]; i++) { + stopValues.push(value); + value += step; + } + stopValues.push(dataExtent[1]); + + return stopValues; + } + + module.exports = ContinuousModel; + + + +/***/ }, +/* 382 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Controller visual map model + */ + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + var env = __webpack_require__(2); + var visualDefault = __webpack_require__(383); + var VisualMapping = __webpack_require__(203); + var visualSolution = __webpack_require__(350); + var mapVisual = VisualMapping.mapVisual; + var modelUtil = __webpack_require__(5); + var eachVisual = VisualMapping.eachVisual; + var numberUtil = __webpack_require__(7); + var isArray = zrUtil.isArray; + var each = zrUtil.each; + var asc = numberUtil.asc; + var linearMap = numberUtil.linearMap; + var noop = zrUtil.noop; + + var DEFAULT_COLOR = ['#f6efa6', '#d88273', '#bf444c']; + + var VisualMapModel = echarts.extendComponentModel({ + + type: 'visualMap', + + dependencies: ['series'], + + /** + * @readOnly + * @type {Array.} + */ + stateList: ['inRange', 'outOfRange'], + + /** + * @readOnly + * @type {Array.} + */ + replacableOptionKeys: [ + 'inRange', 'outOfRange', 'target', 'controller', 'color' + ], + + /** + * [lowerBound, upperBound] + * + * @readOnly + * @type {Array.} + */ + dataBound: [-Infinity, Infinity], + + /** + * @readOnly + * @type {string|Object} + */ + layoutMode: {type: 'box', ignoreSize: true}, + + /** + * @protected + */ + defaultOption: { + show: true, + + zlevel: 0, + z: 4, + + seriesIndex: null, // 所控制的series indices,默认所有有value的series. + + // set min: 0, max: 200, only for campatible with ec2. + // In fact min max should not have default value. + min: 0, // min value, must specified if pieces is not specified. + max: 200, // max value, must specified if pieces is not specified. + + dimension: null, + inRange: null, // 'color', 'colorHue', 'colorSaturation', 'colorLightness', 'colorAlpha', + // 'symbol', 'symbolSize' + outOfRange: null, // 'color', 'colorHue', 'colorSaturation', + // 'colorLightness', 'colorAlpha', + // 'symbol', 'symbolSize' + + left: 0, // 'center' ¦ 'left' ¦ 'right' ¦ {number} (px) + right: null, // The same as left. + top: null, // 'top' ¦ 'bottom' ¦ 'center' ¦ {number} (px) + bottom: 0, // The same as top. + + itemWidth: null, + itemHeight: null, + inverse: false, + orient: 'vertical', // 'horizontal' ¦ 'vertical' + + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', // 值域边框颜色 + contentColor: '#5793f3', + inactiveColor: '#aaa', + borderWidth: 0, // 值域边框线宽,单位px,默认为0(无边框) + padding: 5, // 值域内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + textGap: 10, // + precision: 0, // 小数精度,默认为0,无小数点 + color: null, //颜色(deprecated,兼容ec2,顺序同pieces,不同于inRange/outOfRange) + + formatter: null, + text: null, // 文本,如['高', '低'],兼容ec2,text[0]对应高值,text[1]对应低值 + textStyle: { + color: '#333' // 值域文字颜色 + } + }, + + /** + * @protected + */ + init: function (option, parentModel, ecModel) { + + /** + * @private + * @type {Array.} + */ + this._dataExtent; + + /** + * @readOnly + */ + this.targetVisuals = {}; + + /** + * @readOnly + */ + this.controllerVisuals = {}; + + /** + * @readOnly + */ + this.textStyleModel; + + /** + * [width, height] + * @readOnly + * @type {Array.} + */ + this.itemSize; + + this.mergeDefaultAndTheme(option, ecModel); + }, + + /** + * @protected + */ + optionUpdated: function (newOption, isInit) { + var thisOption = this.option; + + // FIXME + // necessary? + // Disable realtime view update if canvas is not supported. + if (!env.canvasSupported) { + thisOption.realtime = false; + } + + !isInit && visualSolution.replaceVisualOption( + thisOption, newOption, this.replacableOptionKeys + ); + + this.textStyleModel = this.getModel('textStyle'); + + this.resetItemSize(); + + this.completeVisualOption(); + }, + + /** + * @protected + */ + resetVisual: function (supplementVisualOption) { + var stateList = this.stateList; + supplementVisualOption = zrUtil.bind(supplementVisualOption, this); + + this.controllerVisuals = visualSolution.createVisualMappings( + this.option.controller, stateList, supplementVisualOption + ); + this.targetVisuals = visualSolution.createVisualMappings( + this.option.target, stateList, supplementVisualOption + ); + }, + + + /** + * @protected + */ + resetTargetSeries: function () { + var thisOption = this.option; + var allSeriesIndex = thisOption.seriesIndex == null; + thisOption.seriesIndex = allSeriesIndex + ? [] : modelUtil.normalizeToArray(thisOption.seriesIndex); + + allSeriesIndex && this.ecModel.eachSeries(function (seriesModel, index) { + thisOption.seriesIndex.push(index); + }); + }, + + /** + * @public + */ + eachTargetSeries: function (callback, context) { + zrUtil.each(this.option.seriesIndex, function (seriesIndex) { + callback.call(context, this.ecModel.getSeriesByIndex(seriesIndex)); + }, this); + }, + + /** + * @pubilc + */ + isTargetSeries: function (seriesModel) { + var is = false; + this.eachTargetSeries(function (model) { + model === seriesModel && (is = true); + }); + return is; + }, + + /** + * @example + * this.formatValueText(someVal); // format single numeric value to text. + * this.formatValueText(someVal, true); // format single category value to text. + * this.formatValueText([min, max]); // format numeric min-max to text. + * this.formatValueText([this.dataBound[0], max]); // using data lower bound. + * this.formatValueText([min, this.dataBound[1]]); // using data upper bound. + * + * @param {number|Array.} value Real value, or this.dataBound[0 or 1]. + * @param {boolean} [isCategory=false] Only available when value is number. + * @param {Array.} edgeSymbols Open-close symbol when value is interval. + * @return {string} + * @protected + */ + formatValueText: function(value, isCategory, edgeSymbols) { + var option = this.option; + var precision = option.precision; + var dataBound = this.dataBound; + var formatter = option.formatter; + var isMinMax; + var textValue; + edgeSymbols = edgeSymbols || ['<', '>']; + + if (zrUtil.isArray(value)) { + value = value.slice(); + isMinMax = true; + } + + textValue = isCategory + ? value + : (isMinMax + ? [toFixed(value[0]), toFixed(value[1])] + : toFixed(value) + ); + + if (zrUtil.isString(formatter)) { + return formatter + .replace('{value}', isMinMax ? textValue[0] : textValue) + .replace('{value2}', isMinMax ? textValue[1] : textValue); + } + else if (zrUtil.isFunction(formatter)) { + return isMinMax + ? formatter(value[0], value[1]) + : formatter(value); + } + + if (isMinMax) { + if (value[0] === dataBound[0]) { + return edgeSymbols[0] + ' ' + textValue[1]; + } + else if (value[1] === dataBound[1]) { + return edgeSymbols[1] + ' ' + textValue[0]; + } + else { + return textValue[0] + ' - ' + textValue[1]; + } + } + else { // Format single value (includes category case). + return textValue; + } + + function toFixed(val) { + return val === dataBound[0] + ? 'min' + : val === dataBound[1] + ? 'max' + : (+val).toFixed(precision); + } + }, + + /** + * @protected + */ + resetExtent: function () { + var thisOption = this.option; + + // Can not calculate data extent by data here. + // Because series and data may be modified in processing stage. + // So we do not support the feature "auto min/max". + + var extent = asc([thisOption.min, thisOption.max]); + + this._dataExtent = extent; + }, + + /** + * @public + * @param {module:echarts/data/List} list + * @return {string} Concrete dimention. If return null/undefined, + * no dimension used. + */ + getDataDimension: function (list) { + var optDim = this.option.dimension; + return optDim != null + ? optDim : list.dimensions.length - 1; + }, + + /** + * @public + * @override + */ + getExtent: function () { + return this._dataExtent.slice(); + }, + + /** + * @protected + */ + completeVisualOption: function () { + var thisOption = this.option; + var base = {inRange: thisOption.inRange, outOfRange: thisOption.outOfRange}; + + var target = thisOption.target || (thisOption.target = {}); + var controller = thisOption.controller || (thisOption.controller = {}); + + zrUtil.merge(target, base); // Do not override + zrUtil.merge(controller, base); // Do not override + + var isCategory = this.isCategory(); + + completeSingle.call(this, target); + completeSingle.call(this, controller); + completeInactive.call(this, target, 'inRange', 'outOfRange'); + // completeInactive.call(this, target, 'outOfRange', 'inRange'); + completeController.call(this, controller); + + function completeSingle(base) { + // Compatible with ec2 dataRange.color. + // The mapping order of dataRange.color is: [high value, ..., low value] + // whereas inRange.color and outOfRange.color is [low value, ..., high value] + // Notice: ec2 has no inverse. + if (isArray(thisOption.color) + // If there has been inRange: {symbol: ...}, adding color is a mistake. + // So adding color only when no inRange defined. + && !base.inRange + ) { + base.inRange = {color: thisOption.color.slice().reverse()}; + } + + // Compatible with previous logic, always give a defautl color, otherwise + // simple config with no inRange and outOfRange will not work. + // Originally we use visualMap.color as the default color, but setOption at + // the second time the default color will be erased. So we change to use + // constant DEFAULT_COLOR. + // If user do not want the defualt color, set inRange: {color: null}. + base.inRange = base.inRange || {color: DEFAULT_COLOR}; + + // If using shortcut like: {inRange: 'symbol'}, complete default value. + each(this.stateList, function (state) { + var visualType = base[state]; + + if (zrUtil.isString(visualType)) { + var defa = visualDefault.get(visualType, 'active', isCategory); + if (defa) { + base[state] = {}; + base[state][visualType] = defa; + } + else { + // Mark as not specified. + delete base[state]; + } + } + }, this); + } + + function completeInactive(base, stateExist, stateAbsent) { + var optExist = base[stateExist]; + var optAbsent = base[stateAbsent]; + + if (optExist && !optAbsent) { + optAbsent = base[stateAbsent] = {}; + each(optExist, function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + + var defa = visualDefault.get(visualType, 'inactive', isCategory); + + if (defa != null) { + optAbsent[visualType] = defa; + + // Compatibable with ec2: + // Only inactive color to rgba(0,0,0,0) can not + // make label transparent, so use opacity also. + if (visualType === 'color' + && !optAbsent.hasOwnProperty('opacity') + && !optAbsent.hasOwnProperty('colorAlpha') + ) { + optAbsent.opacity = [0, 0]; + } + } + }); + } + } + + function completeController(controller) { + var symbolExists = (controller.inRange || {}).symbol + || (controller.outOfRange || {}).symbol; + var symbolSizeExists = (controller.inRange || {}).symbolSize + || (controller.outOfRange || {}).symbolSize; + var inactiveColor = this.get('inactiveColor'); + + each(this.stateList, function (state) { + + var itemSize = this.itemSize; + var visuals = controller[state]; + + // Set inactive color for controller if no other color + // attr (like colorAlpha) specified. + if (!visuals) { + visuals = controller[state] = { + color: isCategory ? inactiveColor : [inactiveColor] + }; + } + + // Consistent symbol and symbolSize if not specified. + if (visuals.symbol == null) { + visuals.symbol = symbolExists + && zrUtil.clone(symbolExists) + || (isCategory ? 'roundRect' : ['roundRect']); + } + if (visuals.symbolSize == null) { + visuals.symbolSize = symbolSizeExists + && zrUtil.clone(symbolSizeExists) + || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]); + } + + // Filter square and none. + visuals.symbol = mapVisual(visuals.symbol, function (symbol) { + return (symbol === 'none' || symbol === 'square') ? 'roundRect' : symbol; + }); + + // Normalize symbolSize + var symbolSize = visuals.symbolSize; + + if (symbolSize != null) { + var max = -Infinity; + // symbolSize can be object when categories defined. + eachVisual(symbolSize, function (value) { + value > max && (max = value); + }); + visuals.symbolSize = mapVisual(symbolSize, function (value) { + return linearMap(value, [0, max], [0, itemSize[0]], true); + }); + } + + }, this); + } + }, + + /** + * @protected + */ + resetItemSize: function () { + this.itemSize = [ + parseFloat(this.get('itemWidth')), + parseFloat(this.get('itemHeight')) + ]; + }, + + /** + * @public + */ + isCategory: function () { + return !!this.option.categories; + }, + + /** + * @public + * @abstract + */ + setSelected: noop, + + /** + * @public + * @abstract + * @param {*|module:echarts/data/List} valueOrData + * @param {number} dataIndex + * @return {string} state See this.stateList + */ + getValueState: noop, + + /** + * FIXME + * Do not publish to thirt-part-dev temporarily + * util the interface is stable. (Should it return + * a function but not visual meta?) + * + * @pubilc + * @abstract + * @param {Function} getColorVisual + * params: value, valueState + * return: color + * @return {Object} visualMeta + * should includes {stops, outerColors} + * outerColor means [colorBeyondMinValue, colorBeyondMaxValue] + */ + getVisualMeta: noop + + }); + + module.exports = VisualMapModel; + + + +/***/ }, +/* 383 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Visual mapping. + */ + + + var zrUtil = __webpack_require__(4); + + var visualDefault = { + + /** + * @public + */ + get: function (visualType, key, isCategory) { + var value = zrUtil.clone( + (defaultOption[visualType] || {})[key] + ); + + return isCategory + ? (zrUtil.isArray(value) ? value[value.length - 1] : value) + : value; + } + + }; + + var defaultOption = { + + color: { + active: ['#006edd', '#e0ffff'], + inactive: ['rgba(0,0,0,0)'] + }, + + colorHue: { + active: [0, 360], + inactive: [0, 0] + }, + + colorSaturation: { + active: [0.3, 1], + inactive: [0, 0] + }, + + colorLightness: { + active: [0.9, 0.5], + inactive: [0, 0] + }, + + colorAlpha: { + active: [0.3, 1], + inactive: [0, 0] + }, + + opacity: { + active: [0.3, 1], + inactive: [0, 0] + }, + + symbol: { + active: ['circle', 'roundRect', 'diamond'], + inactive: ['none'] + }, + + symbolSize: { + active: [10, 50], + inactive: [0, 0] + } + }; + + module.exports = visualDefault; + + + + +/***/ }, +/* 384 */ +/***/ function(module, exports, __webpack_require__) { + + + + var VisualMapView = __webpack_require__(385); + var graphic = __webpack_require__(18); + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var sliderMove = __webpack_require__(239); + var LinearGradient = __webpack_require__(65); + var helper = __webpack_require__(386); + var modelUtil = __webpack_require__(5); + var eventTool = __webpack_require__(88); + + var linearMap = numberUtil.linearMap; + var each = zrUtil.each; + var mathMin = Math.min; + var mathMax = Math.max; + + // Arbitrary value + var HOVER_LINK_SIZE = 12; + var HOVER_LINK_OUT = 6; + + // Notice: + // Any "interval" should be by the order of [low, high]. + // "handle0" (handleIndex === 0) maps to + // low data value: this._dataInterval[0] and has low coord. + // "handle1" (handleIndex === 1) maps to + // high data value: this._dataInterval[1] and has high coord. + // The logic of transform is implemented in this._createBarGroup. + + var ContinuousView = VisualMapView.extend({ + + type: 'visualMap.continuous', + + /** + * @override + */ + init: function () { + + ContinuousView.superApply(this, 'init', arguments); + + /** + * @private + */ + this._shapes = {}; + + /** + * @private + */ + this._dataInterval = []; + + /** + * @private + */ + this._handleEnds = []; + + /** + * @private + */ + this._orient; + + /** + * @private + */ + this._useHandle; + + /** + * @private + */ + this._hoverLinkDataIndices = []; + + /** + * @private + */ + this._dragging; + + /** + * @private + */ + this._hovering; + }, + + /** + * @protected + * @override + */ + doRender: function (visualMapModel, ecModel, api, payload) { + if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) { + this._buildView(); + } + }, + + /** + * @private + */ + _buildView: function () { + this.group.removeAll(); + + var visualMapModel = this.visualMapModel; + var thisGroup = this.group; + + this._orient = visualMapModel.get('orient'); + this._useHandle = visualMapModel.get('calculable'); + + this._resetInterval(); + + this._renderBar(thisGroup); + + var dataRangeText = visualMapModel.get('text'); + this._renderEndsText(thisGroup, dataRangeText, 0); + this._renderEndsText(thisGroup, dataRangeText, 1); + + // Do this for background size calculation. + this._updateView(true); + + // After updating view, inner shapes is built completely, + // and then background can be rendered. + this.renderBackground(thisGroup); + + // Real update view + this._updateView(); + + this._enableHoverLinkToSeries(); + this._enableHoverLinkFromSeries(); + + this.positionGroup(thisGroup); + }, + + /** + * @private + */ + _renderEndsText: function (group, dataRangeText, endsIndex) { + if (!dataRangeText) { + return; + } + + // Compatible with ec2, text[0] map to high value, text[1] map low value. + var text = dataRangeText[1 - endsIndex]; + text = text != null ? text + '' : ''; + + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var itemSize = visualMapModel.itemSize; + + var barGroup = this._shapes.barGroup; + var position = this._applyTransform( + [ + itemSize[0] / 2, + endsIndex === 0 ? -textGap : itemSize[1] + textGap + ], + barGroup + ); + var align = this._applyTransform( + endsIndex === 0 ? 'bottom' : 'top', + barGroup + ); + var orient = this._orient; + var textStyleModel = this.visualMapModel.textStyleModel; + + this.group.add(new graphic.Text({ + style: { + x: position[0], + y: position[1], + textVerticalAlign: orient === 'horizontal' ? 'middle' : align, + textAlign: orient === 'horizontal' ? align : 'center', + text: text, + textFont: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + })); + }, + + /** + * @private + */ + _renderBar: function (targetGroup) { + var visualMapModel = this.visualMapModel; + var shapes = this._shapes; + var itemSize = visualMapModel.itemSize; + var orient = this._orient; + var useHandle = this._useHandle; + var itemAlign = helper.getItemAlign(visualMapModel, this.api, itemSize); + var barGroup = shapes.barGroup = this._createBarGroup(itemAlign); + + // Bar + barGroup.add(shapes.outOfRange = createPolygon()); + barGroup.add(shapes.inRange = createPolygon( + null, + useHandle ? 'move' : null, + zrUtil.bind(this._dragHandle, this, 'all', false), + zrUtil.bind(this._dragHandle, this, 'all', true) + )); + + var textRect = visualMapModel.textStyleModel.getTextRect('国'); + var textSize = mathMax(textRect.width, textRect.height); + + // Handle + if (useHandle) { + shapes.handleThumbs = []; + shapes.handleLabels = []; + shapes.handleLabelPoints = []; + + this._createHandle(barGroup, 0, itemSize, textSize, orient, itemAlign); + this._createHandle(barGroup, 1, itemSize, textSize, orient, itemAlign); + } + + this._createIndicator(barGroup, itemSize, textSize, orient); + + targetGroup.add(barGroup); + }, + + /** + * @private + */ + _createHandle: function (barGroup, handleIndex, itemSize, textSize, orient) { + var onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false); + var onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true); + var handleThumb = createPolygon( + createHandlePoints(handleIndex, textSize), + 'move', + onDrift, + onDragEnd + ); + handleThumb.position[0] = itemSize[0]; + barGroup.add(handleThumb); + + // Text is always horizontal layout but should not be effected by + // transform (orient/inverse). So label is built separately but not + // use zrender/graphic/helper/RectText, and is located based on view + // group (according to handleLabelPoint) but not barGroup. + var textStyleModel = this.visualMapModel.textStyleModel; + var handleLabel = new graphic.Text({ + draggable: true, + drift: onDrift, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + eventTool.stop(e.event); + }, + ondragend: onDragEnd, + style: { + x: 0, y: 0, text: '', + textFont: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + }); + this.group.add(handleLabel); + + var handleLabelPoint = [ + orient === 'horizontal' + ? textSize / 2 + : textSize * 1.5, + orient === 'horizontal' + ? (handleIndex === 0 ? -(textSize * 1.5) : (textSize * 1.5)) + : (handleIndex === 0 ? -textSize / 2 : textSize / 2) + ]; + + var shapes = this._shapes; + shapes.handleThumbs[handleIndex] = handleThumb; + shapes.handleLabelPoints[handleIndex] = handleLabelPoint; + shapes.handleLabels[handleIndex] = handleLabel; + }, + + /** + * @private + */ + _createIndicator: function (barGroup, itemSize, textSize, orient) { + var indicator = createPolygon([[0, 0]], 'move'); + indicator.position[0] = itemSize[0]; + indicator.attr({invisible: true, silent: true}); + barGroup.add(indicator); + + var textStyleModel = this.visualMapModel.textStyleModel; + var indicatorLabel = new graphic.Text({ + silent: true, + invisible: true, + style: { + x: 0, y: 0, text: '', + textFont: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + }); + this.group.add(indicatorLabel); + + var indicatorLabelPoint = [ + orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT + 3, + 0 + ]; + + var shapes = this._shapes; + shapes.indicator = indicator; + shapes.indicatorLabel = indicatorLabel; + shapes.indicatorLabelPoint = indicatorLabelPoint; + }, + + /** + * @private + */ + _dragHandle: function (handleIndex, isEnd, dx, dy) { + if (!this._useHandle) { + return; + } + + this._dragging = !isEnd; + + if (!isEnd) { + // Transform dx, dy to bar coordination. + var vertex = this._applyTransform([dx, dy], this._shapes.barGroup, true); + this._updateInterval(handleIndex, vertex[1]); + + // Considering realtime, update view should be executed + // before dispatch action. + this._updateView(); + } + + // dragEnd do not dispatch action when realtime. + if (isEnd === !this.visualMapModel.get('realtime')) { // jshint ignore:line + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: this._dataInterval.slice() + }); + } + + if (isEnd) { + !this._hovering && this._clearHoverLinkToSeries(); + } + else if (useHoverLinkOnHandle(this.visualMapModel)) { + this._doHoverLinkToSeries(this._handleEnds[handleIndex], false); + } + }, + + /** + * @private + */ + _resetInterval: function () { + var visualMapModel = this.visualMapModel; + + var dataInterval = this._dataInterval = visualMapModel.getSelected(); + var dataExtent = visualMapModel.getExtent(); + var sizeExtent = [0, visualMapModel.itemSize[1]]; + + this._handleEnds = [ + linearMap(dataInterval[0], dataExtent, sizeExtent, true), + linearMap(dataInterval[1], dataExtent, sizeExtent, true) + ]; + }, + + /** + * @private + * @param {(number|string)} handleIndex 0 or 1 or 'all' + * @param {number} dx + * @param {number} dy + */ + _updateInterval: function (handleIndex, delta) { + delta = delta || 0; + var visualMapModel = this.visualMapModel; + var handleEnds = this._handleEnds; + var sizeExtent = [0, visualMapModel.itemSize[1]]; + + sliderMove( + delta, + handleEnds, + sizeExtent, + handleIndex, + // cross is forbiden + 0 + ); + + var dataExtent = visualMapModel.getExtent(); + // Update data interval. + this._dataInterval = [ + linearMap(handleEnds[0], sizeExtent, dataExtent, true), + linearMap(handleEnds[1], sizeExtent, dataExtent, true) + ]; + }, + + /** + * @private + */ + _updateView: function (forSketch) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var shapes = this._shapes; + + var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]]; + var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds; + + var visualInRange = this._createBarVisual( + this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange' + ); + var visualOutOfRange = this._createBarVisual( + dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange' + ); + + shapes.inRange + .setStyle({ + fill: visualInRange.barColor, + opacity: visualInRange.opacity + }) + .setShape('points', visualInRange.barPoints); + shapes.outOfRange + .setStyle({ + fill: visualOutOfRange.barColor, + opacity: visualOutOfRange.opacity + }) + .setShape('points', visualOutOfRange.barPoints); + + this._updateHandle(inRangeHandleEnds, visualInRange); + }, + + /** + * @private + */ + _createBarVisual: function (dataInterval, dataExtent, handleEnds, forceState) { + var opts = { + forceState: forceState, + convertOpacityToAlpha: true + }; + var colorStops = this._makeColorGradient(dataInterval, opts); + + var symbolSizes = [ + this.getControllerVisual(dataInterval[0], 'symbolSize', opts), + this.getControllerVisual(dataInterval[1], 'symbolSize', opts) + ]; + var barPoints = this._createBarPoints(handleEnds, symbolSizes); + + return { + barColor: new LinearGradient(0, 0, 0, 1, colorStops), + barPoints: barPoints, + handlesColor: [ + colorStops[0].color, + colorStops[colorStops.length - 1].color + ] + }; + }, + + /** + * @private + */ + _makeColorGradient: function (dataInterval, opts) { + // Considering colorHue, which is not linear, so we have to sample + // to calculate gradient color stops, but not only caculate head + // and tail. + var sampleNumber = 100; // Arbitrary value. + var colorStops = []; + var step = (dataInterval[1] - dataInterval[0]) / sampleNumber; + + colorStops.push({ + color: this.getControllerVisual(dataInterval[0], 'color', opts), + offset: 0 + }); + + for (var i = 1; i < sampleNumber; i++) { + var currValue = dataInterval[0] + step * i; + if (currValue > dataInterval[1]) { + break; + } + colorStops.push({ + color: this.getControllerVisual(currValue, 'color', opts), + offset: i / sampleNumber + }); + } + + colorStops.push({ + color: this.getControllerVisual(dataInterval[1], 'color', opts), + offset: 1 + }); + + return colorStops; + }, + + /** + * @private + */ + _createBarPoints: function (handleEnds, symbolSizes) { + var itemSize = this.visualMapModel.itemSize; + + return [ + [itemSize[0] - symbolSizes[0], handleEnds[0]], + [itemSize[0], handleEnds[0]], + [itemSize[0], handleEnds[1]], + [itemSize[0] - symbolSizes[1], handleEnds[1]] + ]; + }, + + /** + * @private + */ + _createBarGroup: function (itemAlign) { + var orient = this._orient; + var inverse = this.visualMapModel.get('inverse'); + + return new graphic.Group( + (orient === 'horizontal' && !inverse) + ? {scale: itemAlign === 'bottom' ? [1, 1] : [-1, 1], rotation: Math.PI / 2} + : (orient === 'horizontal' && inverse) + ? {scale: itemAlign === 'bottom' ? [-1, 1] : [1, 1], rotation: -Math.PI / 2} + : (orient === 'vertical' && !inverse) + ? {scale: itemAlign === 'left' ? [1, -1] : [-1, -1]} + : {scale: itemAlign === 'left' ? [1, 1] : [-1, 1]} + ); + }, + + /** + * @private + */ + _updateHandle: function (handleEnds, visualInRange) { + if (!this._useHandle) { + return; + } + + var shapes = this._shapes; + var visualMapModel = this.visualMapModel; + var handleThumbs = shapes.handleThumbs; + var handleLabels = shapes.handleLabels; + + each([0, 1], function (handleIndex) { + var handleThumb = handleThumbs[handleIndex]; + handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]); + handleThumb.position[1] = handleEnds[handleIndex]; + + // Update handle label position. + var textPoint = graphic.applyTransform( + shapes.handleLabelPoints[handleIndex], + graphic.getTransform(handleThumb, this.group) + ); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + text: visualMapModel.formatValueText(this._dataInterval[handleIndex]), + textVerticalAlign: 'middle', + textAlign: this._applyTransform( + this._orient === 'horizontal' + ? (handleIndex === 0 ? 'bottom' : 'top') + : 'left', + shapes.barGroup + ) + }); + }, this); + }, + + /** + * @private + * @param {number} cursorValue + * @param {number} textValue + * @param {string} [rangeSymbol] + * @param {number} [halfHoverLinkSize] + */ + _showIndicator: function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var itemSize = visualMapModel.itemSize; + var sizeExtent = [0, itemSize[1]]; + var pos = linearMap(cursorValue, dataExtent, sizeExtent, true); + + var shapes = this._shapes; + var indicator = shapes.indicator; + if (!indicator) { + return; + } + + indicator.position[1] = pos; + indicator.attr('invisible', false); + indicator.setShape('points', createIndicatorPoints( + !!rangeSymbol, halfHoverLinkSize, pos, itemSize[1] + )); + + var opts = {convertOpacityToAlpha: true}; + var color = this.getControllerVisual(cursorValue, 'color', opts); + indicator.setStyle('fill', color); + + // Update handle label position. + var textPoint = graphic.applyTransform( + shapes.indicatorLabelPoint, + graphic.getTransform(indicator, this.group) + ); + + var indicatorLabel = shapes.indicatorLabel; + indicatorLabel.attr('invisible', false); + var align = this._applyTransform('left', shapes.barGroup); + var orient = this._orient; + indicatorLabel.setStyle({ + text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue), + textVerticalAlign: orient === 'horizontal' ? align : 'middle', + textAlign: orient === 'horizontal' ? 'center' : align, + x: textPoint[0], + y: textPoint[1] + }); + }, + + /** + * @private + */ + _enableHoverLinkToSeries: function () { + var self = this; + this._shapes.barGroup + + .on('mousemove', function (e) { + self._hovering = true; + + if (!self._dragging) { + var itemSize = self.visualMapModel.itemSize; + var pos = self._applyTransform( + [e.offsetX, e.offsetY], self._shapes.barGroup, true, true + ); + // For hover link show when hover handle, which might be + // below or upper than sizeExtent. + pos[1] = mathMin(mathMax(0, pos[1]), itemSize[1]); + + self._doHoverLinkToSeries( + pos[1], + 0 <= pos[0] && pos[0] <= itemSize[0] + ); + } + }) + + .on('mouseout', function () { + // When mouse is out of handle, hoverLink still need + // to be displayed when realtime is set as false. + self._hovering = false; + !self._dragging && self._clearHoverLinkToSeries(); + }); + }, + + /** + * @private + */ + _enableHoverLinkFromSeries: function () { + var zr = this.api.getZr(); + + if (this.visualMapModel.option.hoverLink) { + zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this); + zr.on('mouseout', this._hideIndicator, this); + } + else { + this._clearHoverLinkFromSeries(); + } + }, + + /** + * @private + */ + _doHoverLinkToSeries: function (cursorPos, hoverOnBar) { + var visualMapModel = this.visualMapModel; + var itemSize = visualMapModel.itemSize; + + if (!visualMapModel.option.hoverLink) { + return; + } + + var sizeExtent = [0, itemSize[1]]; + var dataExtent = visualMapModel.getExtent(); + + // For hover link show when hover handle, which might be below or upper than sizeExtent. + cursorPos = mathMin(mathMax(sizeExtent[0], cursorPos), sizeExtent[1]); + + var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent); + var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize]; + var cursorValue = linearMap(cursorPos, sizeExtent, dataExtent, true); + var valueRange = [ + linearMap(hoverRange[0], sizeExtent, dataExtent, true), + linearMap(hoverRange[1], sizeExtent, dataExtent, true) + ]; + // Consider data range is out of visualMap range, see test/visualMap-continuous.html, + // where china and india has very large population. + hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity); + hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity); + + // Do not show indicator when mouse is over handle, + // otherwise labels overlap, especially when dragging. + if (hoverOnBar) { + if (valueRange[0] === -Infinity) { + this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize); + } + else if (valueRange[1] === Infinity) { + this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize); + } + else { + this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize); + } + } + + // When realtime is set as false, handles, which are in barGroup, + // also trigger hoverLink, which help user to realize where they + // focus on when dragging. (see test/heatmap-large.html) + // When realtime is set as true, highlight will not show when hover + // handle, because the label on handle, which displays a exact value + // but not range, might mislead users. + var oldBatch = this._hoverLinkDataIndices; + var newBatch = []; + if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) { + newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange); + } + + var resultBatches = modelUtil.compressBatches(oldBatch, newBatch); + this._dispatchHighDown('downplay', helper.convertDataIndex(resultBatches[0])); + this._dispatchHighDown('highlight', helper.convertDataIndex(resultBatches[1])); + }, + + /** + * @private + */ + _hoverLinkFromSeriesMouseOver: function (e) { + var el = e.target; + var visualMapModel = this.visualMapModel; + + if (!el || el.dataIndex == null) { + return; + } + + var dataModel = this.ecModel.getSeriesByIndex(el.seriesIndex); + + if (!visualMapModel.isTargetSeries(dataModel)) { + return; + } + + var data = dataModel.getData(el.dataType); + var dim = data.getDimension(visualMapModel.getDataDimension(data)); + var value = data.get(dim, el.dataIndex, true); + + if (!isNaN(value)) { + this._showIndicator(value, value); + } + }, + + /** + * @private + */ + _hideIndicator: function () { + var shapes = this._shapes; + shapes.indicator && shapes.indicator.attr('invisible', true); + shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true); + }, + + /** + * @private + */ + _clearHoverLinkToSeries: function () { + this._hideIndicator(); + + var indices = this._hoverLinkDataIndices; + + this._dispatchHighDown('downplay', helper.convertDataIndex(indices)); + + indices.length = 0; + }, + + /** + * @private + */ + _clearHoverLinkFromSeries: function () { + this._hideIndicator(); + + var zr = this.api.getZr(); + zr.off('mouseover', this._hoverLinkFromSeriesMouseOver); + zr.off('mouseout', this._hideIndicator); + }, + + /** + * @private + */ + _applyTransform: function (vertex, element, inverse, global) { + var transform = graphic.getTransform(element, global ? null : this.group); + + return graphic[ + zrUtil.isArray(vertex) ? 'applyTransform' : 'transformDirection' + ](vertex, transform, inverse); + }, + + /** + * @private + */ + _dispatchHighDown: function (type, batch) { + batch && batch.length && this.api.dispatchAction({ + type: type, + batch: batch + }); + }, + + /** + * @override + */ + dispose: function () { + this._clearHoverLinkFromSeries(); + this._clearHoverLinkToSeries(); + }, + + /** + * @override + */ + remove: function () { + this._clearHoverLinkFromSeries(); + this._clearHoverLinkToSeries(); + } + + }); + + function createPolygon(points, cursor, onDrift, onDragEnd) { + return new graphic.Polygon({ + shape: {points: points}, + draggable: !!onDrift, + cursor: cursor, + drift: onDrift, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + eventTool.stop(e.event); + }, + ondragend: onDragEnd + }); + } + + function createHandlePoints(handleIndex, textSize) { + return handleIndex === 0 + ? [[0, 0], [textSize, 0], [textSize, -textSize]] + : [[0, 0], [textSize, 0], [textSize, textSize]]; + } + + function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) { + return isRange + ? [ // indicate range + [0, -mathMin(halfHoverLinkSize, mathMax(pos, 0))], + [HOVER_LINK_OUT, 0], + [0, mathMin(halfHoverLinkSize, mathMax(extentMax - pos, 0))] + ] + : [ // indicate single value + [0, 0], [5, -5], [5, 5] + ]; + } + + function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) { + var halfHoverLinkSize = HOVER_LINK_SIZE / 2; + var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize'); + if (hoverLinkDataSize) { + halfHoverLinkSize = linearMap(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2; + } + return halfHoverLinkSize; + } + + function useHoverLinkOnHandle(visualMapModel) { + return !visualMapModel.get('realtime') && visualMapModel.get('hoverLinkOnHandle'); + } + + module.exports = ContinuousView; + + + +/***/ }, +/* 385 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var formatUtil = __webpack_require__(6); + var layout = __webpack_require__(71); + var echarts = __webpack_require__(1); + var VisualMapping = __webpack_require__(203); + + module.exports = echarts.extendComponentView({ + + type: 'visualMap', + + /** + * @readOnly + * @type {Object} + */ + autoPositionValues: {left: 1, right: 1, top: 1, bottom: 1}, + + init: function (ecModel, api) { + /** + * @readOnly + * @type {module:echarts/model/Global} + */ + this.ecModel = ecModel; + + /** + * @readOnly + * @type {module:echarts/ExtensionAPI} + */ + this.api = api; + + /** + * @readOnly + * @type {module:echarts/component/visualMap/visualMapModel} + */ + this.visualMapModel; + }, + + /** + * @protected + */ + render: function (visualMapModel, ecModel, api, payload) { + this.visualMapModel = visualMapModel; + + if (visualMapModel.get('show') === false) { + this.group.removeAll(); + return; + } + + this.doRender.apply(this, arguments); + }, + + /** + * @protected + */ + renderBackground: function (group) { + var visualMapModel = this.visualMapModel; + var padding = formatUtil.normalizeCssArray(visualMapModel.get('padding') || 0); + var rect = group.getBoundingRect(); + + group.add(new graphic.Rect({ + z2: -1, // Lay background rect on the lowest layer. + silent: true, + shape: { + x: rect.x - padding[3], + y: rect.y - padding[0], + width: rect.width + padding[3] + padding[1], + height: rect.height + padding[0] + padding[2] + }, + style: { + fill: visualMapModel.get('backgroundColor'), + stroke: visualMapModel.get('borderColor'), + lineWidth: visualMapModel.get('borderWidth') + } + })); + }, + + /** + * @protected + * @param {number} targetValue can be Infinity or -Infinity + * @param {string=} visualCluster Only can be 'color' 'opacity' 'symbol' 'symbolSize' + * @param {Object} [opts] + * @param {string=} [opts.forceState] Specify state, instead of using getValueState method. + * @param {string=} [opts.convertOpacityToAlpha=false] For color gradient in controller widget. + * @return {*} Visual value. + */ + getControllerVisual: function (targetValue, visualCluster, opts) { + opts = opts || {}; + + var forceState = opts.forceState; + var visualMapModel = this.visualMapModel; + var visualObj = {}; + + // Default values. + if (visualCluster === 'symbol') { + visualObj.symbol = visualMapModel.get('itemSymbol'); + } + if (visualCluster === 'color') { + var defaultColor = visualMapModel.get('contentColor'); + visualObj.color = defaultColor; + } + + function getter(key) { + return visualObj[key]; + } + + function setter(key, value) { + visualObj[key] = value; + } + + var mappings = visualMapModel.controllerVisuals[ + forceState || visualMapModel.getValueState(targetValue) + ]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + + zrUtil.each(visualTypes, function (type) { + var visualMapping = mappings[type]; + if (opts.convertOpacityToAlpha && type === 'opacity') { + type = 'colorAlpha'; + visualMapping = mappings.__alphaForOpacity; + } + if (VisualMapping.dependsOn(type, visualCluster)) { + visualMapping && visualMapping.applyVisual( + targetValue, getter, setter + ); + } + }); + + return visualObj[visualCluster]; + }, + + /** + * @protected + */ + positionGroup: function (group) { + var model = this.visualMapModel; + var api = this.api; + + layout.positionElement( + group, + model.getBoxLayoutParams(), + {width: api.getWidth(), height: api.getHeight()} + ); + }, + + /** + * @protected + * @abstract + */ + doRender: zrUtil.noop + + }); + + + +/***/ }, +/* 386 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var layout = __webpack_require__(71); + + var helper = { + + /** + * @param {module:echarts/component/visualMap/VisualMapModel} visualMapModel\ + * @param {module:echarts/ExtensionAPI} api + * @param {Array.} itemSize always [short, long] + * @return {string} 'left' or 'right' or 'top' or 'bottom' + */ + getItemAlign: function (visualMapModel, api, itemSize) { + var modelOption = visualMapModel.option; + var itemAlign = modelOption.align; + + if (itemAlign != null && itemAlign !== 'auto') { + return itemAlign; + } + + // Auto decision align. + var ecSize = {width: api.getWidth(), height: api.getHeight()}; + var realIndex = modelOption.orient === 'horizontal' ? 1 : 0; + + var paramsSet = [ + ['left', 'right', 'width'], + ['top', 'bottom', 'height'] + ]; + var reals = paramsSet[realIndex]; + var fakeValue = [0, null, 10]; + + var layoutInput = {}; + for (var i = 0; i < 3; i++) { + layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i]; + layoutInput[reals[i]] = i === 2 ? itemSize[0] : modelOption[reals[i]]; + } + + var rParam = [['x', 'width', 3], ['y', 'height', 0]][realIndex]; + var rect = layout.getLayoutRect(layoutInput, ecSize, modelOption.padding); + + return reals[ + (rect.margin[rParam[2]] || 0) + rect[rParam[0]] + rect[rParam[1]] * 0.5 + < ecSize[rParam[1]] * 0.5 ? 0 : 1 + ]; + }, + + /** + * Prepare dataIndex for outside usage, where dataIndex means rawIndex, and + * dataIndexInside means filtered index. + */ + convertDataIndex: function (batch) { + zrUtil.each(batch || [], function (batchItem) { + if (batch.dataIndex != null) { + batch.dataIndexInside = batch.dataIndex; + batch.dataIndex = null; + } + }); + return batch; + } + + }; + + + module.exports = helper; + + + +/***/ }, +/* 387 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data range action + */ + + + var echarts = __webpack_require__(1); + + var actionInfo = { + type: 'selectDataRange', + event: 'dataRangeSelected', + // FIXME use updateView appears wrong + update: 'update' + }; + + echarts.registerAction(actionInfo, function (payload, ecModel) { + + ecModel.eachComponent({mainType: 'visualMap', query: payload}, function (model) { + model.setSelected(payload.selected); + }); + + }); + + + +/***/ }, +/* 388 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * DataZoom component entry + */ + + + __webpack_require__(1).registerPreprocessor( + __webpack_require__(378) + ); + + __webpack_require__(379); + __webpack_require__(380); + __webpack_require__(389); + __webpack_require__(390); + __webpack_require__(387); + + + +/***/ }, +/* 389 */ +/***/ function(module, exports, __webpack_require__) { + + + + var VisualMapModel = __webpack_require__(382); + var zrUtil = __webpack_require__(4); + var VisualMapping = __webpack_require__(203); + var visualDefault = __webpack_require__(383); + var reformIntervals = __webpack_require__(7).reformIntervals; + + var PiecewiseModel = VisualMapModel.extend({ + + type: 'visualMap.piecewise', + + /** + * Order Rule: + * + * option.categories / option.pieces / option.text / option.selected: + * If !option.inverse, + * Order when vertical: ['top', ..., 'bottom']. + * Order when horizontal: ['left', ..., 'right']. + * If option.inverse, the meaning of + * the order should be reversed. + * + * this._pieceList: + * The order is always [low, ..., high]. + * + * Mapping from location to low-high: + * If !option.inverse + * When vertical, top is high. + * When horizontal, right is high. + * If option.inverse, reverse. + */ + + /** + * @protected + */ + defaultOption: { + selected: null, // Object. If not specified, means selected. + // When pieces and splitNumber: {'0': true, '5': true} + // When categories: {'cate1': false, 'cate3': true} + // When selected === false, means all unselected. + + minOpen: false, // Whether include values that smaller than `min`. + maxOpen: false, // Whether include values that bigger than `max`. + + align: 'auto', // 'auto', 'left', 'right' + itemWidth: 20, // When put the controller vertically, it is the length of + // horizontal side of each item. Otherwise, vertical side. + itemHeight: 14, // When put the controller vertically, it is the length of + // vertical side of each item. Otherwise, horizontal side. + itemSymbol: 'roundRect', + pieceList: null, // Each item is Object, with some of those attrs: + // {min, max, lt, gt, lte, gte, value, + // color, colorSaturation, colorAlpha, opacity, + // symbol, symbolSize}, which customize the range or visual + // coding of the certain piece. Besides, see "Order Rule". + categories: null, // category names, like: ['some1', 'some2', 'some3']. + // Attr min/max are ignored when categories set. See "Order Rule" + splitNumber: 5, // If set to 5, auto split five pieces equally. + // If set to 0 and component type not set, component type will be + // determined as "continuous". (It is less reasonable but for ec2 + // compatibility, see echarts/component/visualMap/typeDefaulter) + selectedMode: 'multiple', // Can be 'multiple' or 'single'. + itemGap: 10, // The gap between two items, in px. + hoverLink: true, // Enable hover highlight. + + showLabel: null // By default, when text is used, label will hide (the logic + // is remained for compatibility reason) + }, + + /** + * @override + */ + optionUpdated: function (newOption, isInit) { + PiecewiseModel.superApply(this, 'optionUpdated', arguments); + + /** + * The order is always [low, ..., high]. + * [{text: string, interval: Array.}, ...] + * @private + * @type {Array.} + */ + this._pieceList = []; + + this.resetTargetSeries(); + this.resetExtent(); + + /** + * 'pieces', 'categories', 'splitNumber' + * @type {string} + */ + var mode = this._mode = this._determineMode(); + + resetMethods[this._mode].call(this); + + this._resetSelected(newOption, isInit); + + var categories = this.option.categories; + + this.resetVisual(function (mappingOption, state) { + if (mode === 'categories') { + mappingOption.mappingMethod = 'category'; + mappingOption.categories = zrUtil.clone(categories); + } + else { + mappingOption.dataExtent = this.getExtent(); + mappingOption.mappingMethod = 'piecewise'; + mappingOption.pieceList = zrUtil.map(this._pieceList, function (piece) { + var piece = zrUtil.clone(piece); + if (state !== 'inRange') { + // FIXME + // outOfRange do not support special visual in pieces. + piece.visual = null; + } + return piece; + }); + } + }); + }, + + /** + * @protected + * @override + */ + completeVisualOption: function () { + // Consider this case: + // visualMap: { + // pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}] + // } + // where no inRange/outOfRange set but only pieces. So we should make + // default inRange/outOfRange for this case, otherwise visuals that only + // appear in `pieces` will not be taken into account in visual encoding. + + var option = this.option; + var visualTypesInPieces = {}; + var visualTypes = VisualMapping.listVisualTypes(); + var isCategory = this.isCategory(); + + zrUtil.each(option.pieces, function (piece) { + zrUtil.each(visualTypes, function (visualType) { + if (piece.hasOwnProperty(visualType)) { + visualTypesInPieces[visualType] = 1; + } + }); + }); + + zrUtil.each(visualTypesInPieces, function (v, visualType) { + var exists = 0; + zrUtil.each(this.stateList, function (state) { + exists |= has(option, state, visualType) + || has(option.target, state, visualType); + }, this); + + !exists && zrUtil.each(this.stateList, function (state) { + (option[state] || (option[state] = {}))[visualType] = visualDefault.get( + visualType, state === 'inRange' ? 'active' : 'inactive', isCategory + ); + }); + }, this); + + function has(obj, state, visualType) { + return obj && obj[state] && ( + zrUtil.isObject(obj[state]) + ? obj[state].hasOwnProperty(visualType) + : obj[state] === visualType // e.g., inRange: 'symbol' + ); + } + + VisualMapModel.prototype.completeVisualOption.apply(this, arguments); + }, + + _resetSelected: function (newOption, isInit) { + var thisOption = this.option; + var pieceList = this._pieceList; + + // Selected do not merge but all override. + var selected = (isInit ? thisOption : newOption).selected || {}; + thisOption.selected = selected; + + // Consider 'not specified' means true. + zrUtil.each(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + if (!selected.hasOwnProperty(key)) { + selected[key] = true; + } + }, this); + + if (thisOption.selectedMode === 'single') { + // Ensure there is only one selected. + var hasSel = false; + + zrUtil.each(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + if (selected[key]) { + hasSel + ? (selected[key] = false) + : (hasSel = true); + } + }, this); + } + // thisOption.selectedMode === 'multiple', default: all selected. + }, + + /** + * @public + */ + getSelectedMapKey: function (piece) { + return this._mode === 'categories' + ? piece.value + '' : piece.index + ''; + }, + + /** + * @public + */ + getPieceList: function () { + return this._pieceList; + }, + + /** + * @private + * @return {string} + */ + _determineMode: function () { + var option = this.option; + + return option.pieces && option.pieces.length > 0 + ? 'pieces' + : this.option.categories + ? 'categories' + : 'splitNumber'; + }, + + /** + * @public + * @override + */ + setSelected: function (selected) { + this.option.selected = zrUtil.clone(selected); + }, + + /** + * @public + * @override + */ + getValueState: function (value) { + var index = VisualMapping.findPieceIndex(value, this._pieceList); + + return index != null + ? (this.option.selected[this.getSelectedMapKey(this._pieceList[index])] + ? 'inRange' : 'outOfRange' + ) + : 'outOfRange'; + }, + + /** + * @public + * @params {number} pieceIndex piece index in visualMapModel.getPieceList() + * @return {Array.} [{seriesId, dataIndices: >}, ...] + */ + findTargetDataIndices: function (pieceIndex) { + var result = []; + + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + + data.each(this.getDataDimension(data), function (value, dataIndex) { + // Should always base on model pieceList, because it is order sensitive. + var pIdx = VisualMapping.findPieceIndex(value, this._pieceList); + pIdx === pieceIndex && dataIndices.push(dataIndex); + }, true, this); + + result.push({seriesId: seriesModel.id, dataIndex: dataIndices}); + }, this); + + return result; + }, + + /** + * @private + * @param {Object} piece piece.value or piece.interval is required. + * @return {number} Can be Infinity or -Infinity + */ + getRepresentValue: function (piece) { + var representValue; + if (this.isCategory()) { + representValue = piece.value; + } + else { + if (piece.value != null) { + representValue = piece.value; + } + else { + var pieceInterval = piece.interval || []; + representValue = (pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity) + ? 0 + : (pieceInterval[0] + pieceInterval[1]) / 2; + } + } + return representValue; + }, + + getVisualMeta: function (getColorVisual) { + // Do not support category. (category axis is ordinal, numerical) + if (this.isCategory()) { + return; + } + + var stops = []; + var outerColors = []; + var visualMapModel = this; + + function setStop(interval, valueState) { + var representValue = visualMapModel.getRepresentValue({interval: interval}); + if (!valueState) { + valueState = visualMapModel.getValueState(representValue); + } + var color = getColorVisual(representValue, valueState); + if (interval[0] === -Infinity) { + outerColors[0] = color; + } + else if (interval[1] === Infinity) { + outerColors[1] = color; + } + else { + stops.push( + {value: interval[0], color: color}, + {value: interval[1], color: color} + ); + } + } + + // Suplement + var pieceList = this._pieceList.slice(); + if (!pieceList.length) { + pieceList.push({interval: [-Infinity, Infinity]}); + } + else { + var edge = pieceList[0].interval[0]; + edge !== -Infinity && pieceList.unshift({interval: [-Infinity, edge]}); + edge = pieceList[pieceList.length - 1].interval[1]; + edge !== Infinity && pieceList.push({interval: [edge, Infinity]}); + } + + var curr = -Infinity; + zrUtil.each(pieceList, function (piece) { + var interval = piece.interval; + if (interval) { + // Fulfill gap. + interval[0] > curr && setStop([curr, interval[0]], 'outOfRange'); + setStop(interval.slice()); + curr = interval[1]; + } + }, this); + + return {stops: stops, outerColors: outerColors}; + } + + }); + + /** + * Key is this._mode + * @type {Object} + * @this {module:echarts/component/viusalMap/PiecewiseMode} + */ + var resetMethods = { + + splitNumber: function () { + var thisOption = this.option; + var pieceList = this._pieceList; + var precision = thisOption.precision; + var dataExtent = this.getExtent(); + var splitNumber = thisOption.splitNumber; + splitNumber = Math.max(parseInt(splitNumber, 10), 1); + thisOption.splitNumber = splitNumber; + + var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber; + // Precision auto-adaption + while (+splitStep.toFixed(precision) !== splitStep && precision < 5) { + precision++; + } + thisOption.precision = precision; + splitStep = +splitStep.toFixed(precision); + + var index = 0; + + if (thisOption.minOpen) { + pieceList.push({ + index: index++, + interval: [-Infinity, dataExtent[0]], + close: [0, 0] + }); + } + + for ( + var curr = dataExtent[0], len = index + splitNumber; + index < len; + curr += splitStep + ) { + var max = index === splitNumber - 1 ? dataExtent[1] : (curr + splitStep); + + pieceList.push({ + index: index++, + interval: [curr, max], + close: [1, 1] + }); + } + + if (thisOption.maxOpen) { + pieceList.push({ + index: index++, + interval: [dataExtent[1], Infinity], + close: [0, 0] + }); + } + + reformIntervals(pieceList); + + zrUtil.each(pieceList, function (piece) { + piece.text = this.formatValueText(piece.interval); + }, this); + }, + + categories: function () { + var thisOption = this.option; + zrUtil.each(thisOption.categories, function (cate) { + // FIXME category模式也使用pieceList,但在visualMapping中不是使用pieceList。 + // 是否改一致。 + this._pieceList.push({ + text: this.formatValueText(cate, true), + value: cate + }); + }, this); + + // See "Order Rule". + normalizeReverse(thisOption, this._pieceList); + }, + + pieces: function () { + var thisOption = this.option; + var pieceList = this._pieceList; + + zrUtil.each(thisOption.pieces, function (pieceListItem, index) { + + if (!zrUtil.isObject(pieceListItem)) { + pieceListItem = {value: pieceListItem}; + } + + var item = {text: '', index: index}; + + if (pieceListItem.label != null) { + item.text = pieceListItem.label; + } + + if (pieceListItem.hasOwnProperty('value')) { + var value = item.value = pieceListItem.value; + item.interval = [value, value]; + item.close = [1, 1]; + } + else { + // `min` `max` is legacy option. + // `lt` `gt` `lte` `gte` is recommanded. + var interval = item.interval = []; + var close = item.close = [0, 0]; + + var closeList = [1, 0, 1]; + var infinityList = [-Infinity, Infinity]; + + var useMinMax = []; + for (var lg = 0; lg < 2; lg++) { + var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg]; + for (var i = 0; i < 3 && interval[lg] == null; i++) { + interval[lg] = pieceListItem[names[i]]; + close[lg] = closeList[i]; + useMinMax[lg] = i === 2; + } + interval[lg] == null && (interval[lg] = infinityList[lg]); + } + useMinMax[0] && interval[1] === Infinity && (close[0] = 0); + useMinMax[1] && interval[0] === -Infinity && (close[1] = 0); + + if (true) { + if (interval[0] > interval[1]) { + console.warn( + 'Piece ' + index + 'is illegal: ' + interval + + ' lower bound should not greater then uppper bound.' + ); + } + } + + if (interval[0] === interval[1] && close[0] && close[1]) { + // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}], + // we use value to lift the priority when min === max + item.value = interval[0]; + } + } + + item.visual = VisualMapping.retrieveVisuals(pieceListItem); + + pieceList.push(item); + + }, this); + + // See "Order Rule". + normalizeReverse(thisOption, pieceList); + // Only pieces + reformIntervals(pieceList); + + zrUtil.each(pieceList, function (piece) { + var close = piece.close; + var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]]; + piece.text = piece.text || this.formatValueText( + piece.value != null ? piece.value : piece.interval, + false, + edgeSymbols + ); + }, this); + } + }; + + function normalizeReverse(thisOption, pieceList) { + var inverse = thisOption.inverse; + if (thisOption.orient === 'vertical' ? !inverse : inverse) { + pieceList.reverse(); + } + } + + module.exports = PiecewiseModel; + + +/***/ }, +/* 390 */ +/***/ function(module, exports, __webpack_require__) { + + + + var VisualMapView = __webpack_require__(385); + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var symbolCreators = __webpack_require__(111); + var layout = __webpack_require__(71); + var helper = __webpack_require__(386); + + var PiecewiseVisualMapView = VisualMapView.extend({ + + type: 'visualMap.piecewise', + + /** + * @protected + * @override + */ + doRender: function () { + var thisGroup = this.group; + + thisGroup.removeAll(); + + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var textStyleModel = visualMapModel.textStyleModel; + var textFont = textStyleModel.getFont(); + var textFill = textStyleModel.getTextColor(); + var itemAlign = this._getItemAlign(); + var itemSize = visualMapModel.itemSize; + var viewData = this._getViewData(); + var endsText = viewData.endsText; + var showLabel = zrUtil.retrieve(visualMapModel.get('showLabel', true), !endsText); + + endsText && this._renderEndsText( + thisGroup, endsText[0], itemSize, showLabel, itemAlign + ); + + zrUtil.each(viewData.viewPieceList, renderItem, this); + + endsText && this._renderEndsText( + thisGroup, endsText[1], itemSize, showLabel, itemAlign + ); + + layout.box( + visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap') + ); + + this.renderBackground(thisGroup); + + this.positionGroup(thisGroup); + + function renderItem(item) { + var piece = item.piece; + + var itemGroup = new graphic.Group(); + itemGroup.onclick = zrUtil.bind(this._onItemClick, this, piece); + + this._enableHoverLink(itemGroup, item.indexInModelPieceList); + + var representValue = visualMapModel.getRepresentValue(piece); + + this._createItemSymbol( + itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]] + ); + + if (showLabel) { + var visualState = this.visualMapModel.getValueState(representValue); + + itemGroup.add(new graphic.Text({ + style: { + x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap, + y: itemSize[1] / 2, + text: piece.text, + textVerticalAlign: 'middle', + textAlign: itemAlign, + textFont: textFont, + fill: textFill, + opacity: visualState === 'outOfRange' ? 0.5 : 1 + } + })); + } + + thisGroup.add(itemGroup); + } + }, + + /** + * @private + */ + _enableHoverLink: function (itemGroup, pieceIndex) { + itemGroup + .on('mouseover', zrUtil.bind(onHoverLink, this, 'highlight')) + .on('mouseout', zrUtil.bind(onHoverLink, this, 'downplay')); + + function onHoverLink(method) { + var visualMapModel = this.visualMapModel; + + visualMapModel.option.hoverLink && this.api.dispatchAction({ + type: method, + batch: helper.convertDataIndex( + visualMapModel.findTargetDataIndices(pieceIndex) + ) + }); + } + }, + + /** + * @private + */ + _getItemAlign: function () { + var visualMapModel = this.visualMapModel; + var modelOption = visualMapModel.option; + + if (modelOption.orient === 'vertical') { + return helper.getItemAlign( + visualMapModel, this.api, visualMapModel.itemSize + ); + } + else { // horizontal, most case left unless specifying right. + var align = modelOption.align; + if (!align || align === 'auto') { + align = 'left'; + } + return align; + } + }, + + /** + * @private + */ + _renderEndsText: function (group, text, itemSize, showLabel, itemAlign) { + if (!text) { + return; + } + + var itemGroup = new graphic.Group(); + var textStyleModel = this.visualMapModel.textStyleModel; + + itemGroup.add(new graphic.Text({ + style: { + x: showLabel ? (itemAlign === 'right' ? itemSize[0] : 0) : itemSize[0] / 2, + y: itemSize[1] / 2, + textVerticalAlign: 'middle', + textAlign: showLabel ? itemAlign : 'center', + text: text, + textFont: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + })); + + group.add(itemGroup); + }, + + /** + * @private + * @return {Object} {peiceList, endsText} The order is the same as screen pixel order. + */ + _getViewData: function () { + var visualMapModel = this.visualMapModel; + + var viewPieceList = zrUtil.map(visualMapModel.getPieceList(), function (piece, index) { + return {piece: piece, indexInModelPieceList: index}; + }); + var endsText = visualMapModel.get('text'); + + // Consider orient and inverse. + var orient = visualMapModel.get('orient'); + var inverse = visualMapModel.get('inverse'); + + // Order of model pieceList is always [low, ..., high] + if (orient === 'horizontal' ? inverse : !inverse) { + viewPieceList.reverse(); + } + // Origin order of endsText is [high, low] + else if (endsText) { + endsText = endsText.slice().reverse(); + } + + return {viewPieceList: viewPieceList, endsText: endsText}; + }, + + /** + * @private + */ + _createItemSymbol: function (group, representValue, shapeParam) { + group.add(symbolCreators.createSymbol( + this.getControllerVisual(representValue, 'symbol'), + shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3], + this.getControllerVisual(representValue, 'color') + )); + }, + + /** + * @private + */ + _onItemClick: function (piece) { + var visualMapModel = this.visualMapModel; + var option = visualMapModel.option; + var selected = zrUtil.clone(option.selected); + var newKey = visualMapModel.getSelectedMapKey(piece); + + if (option.selectedMode === 'single') { + selected[newKey] = true; + zrUtil.each(selected, function (o, key) { + selected[key] = key === newKey; + }); + } + else { + selected[newKey] = !selected[newKey]; + } + + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: selected + }); + } + }); + + module.exports = PiecewiseVisualMapView; + + + +/***/ }, +/* 391 */ +/***/ function(module, exports, __webpack_require__) { + + // HINT Markpoint can't be used too much + + + __webpack_require__(392); + __webpack_require__(394); + + __webpack_require__(1).registerPreprocessor(function (opt) { + // Make sure markPoint component is enabled + opt.markPoint = opt.markPoint || {}; + }); + + +/***/ }, +/* 392 */ +/***/ function(module, exports, __webpack_require__) { + + + + module.exports = __webpack_require__(393).extend({ + + type: 'markPoint', + + defaultOption: { + zlevel: 0, + z: 5, + symbol: 'pin', + symbolSize: 50, + //symbolRotate: 0, + //symbolOffset: [0, 0] + tooltip: { + trigger: 'item' + }, + label: { + normal: { + show: true, + position: 'inside' + }, + emphasis: { + show: true + } + }, + itemStyle: { + normal: { + borderWidth: 2 + } + } + } + }); + + +/***/ }, +/* 393 */ +/***/ function(module, exports, __webpack_require__) { + + + + var modelUtil = __webpack_require__(5); + var zrUtil = __webpack_require__(4); + var env = __webpack_require__(2); + + var formatUtil = __webpack_require__(6); + var addCommas = formatUtil.addCommas; + var encodeHTML = formatUtil.encodeHTML; + + function fillLabel(opt) { + modelUtil.defaultEmphasis( + opt.label, + modelUtil.LABEL_OPTIONS + ); + } + var MarkerModel = __webpack_require__(1).extendComponentModel({ + + type: 'marker', + + dependencies: ['series', 'grid', 'polar', 'geo'], + /** + * @overrite + */ + init: function (option, parentModel, ecModel, extraOpt) { + + if (true) { + if (this.type === 'marker') { + throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.'); + } + } + this.mergeDefaultAndTheme(option, ecModel); + this.mergeOption(option, ecModel, extraOpt.createdBySelf, true); + }, + + /** + * @return {boolean} + */ + isAnimationEnabled: function () { + if (env.node) { + return false; + } + + var hostSeries = this.__hostSeries; + return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled(); + }, + + mergeOption: function (newOpt, ecModel, createdBySelf, isInit) { + var MarkerModel = this.constructor; + var modelPropName = this.mainType + 'Model'; + if (!createdBySelf) { + ecModel.eachSeries(function (seriesModel) { + + var markerOpt = seriesModel.get(this.mainType); + + var markerModel = seriesModel[modelPropName]; + if (!markerOpt || !markerOpt.data) { + seriesModel[modelPropName] = null; + return; + } + if (!markerModel) { + if (isInit) { + // Default label emphasis `position` and `show` + fillLabel(markerOpt); + } + zrUtil.each(markerOpt.data, function (item) { + // FIXME Overwrite fillLabel method ? + if (item instanceof Array) { + fillLabel(item[0]); + fillLabel(item[1]); + } + else { + fillLabel(item); + } + }); + + markerModel = new MarkerModel( + markerOpt, this, ecModel + ); + + zrUtil.extend(markerModel, { + mainType: this.mainType, + // Use the same series index and name + seriesIndex: seriesModel.seriesIndex, + name: seriesModel.name, + createdBySelf: true + }); + + markerModel.__hostSeries = seriesModel; + } + else { + markerModel.mergeOption(markerOpt, ecModel, true); + } + seriesModel[modelPropName] = markerModel; + }, this); + } + }, + + formatTooltip: function (dataIndex) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var formattedValue = zrUtil.isArray(value) + ? zrUtil.map(value, addCommas).join(', ') : addCommas(value); + var name = data.getName(dataIndex); + var html = encodeHTML(this.name); + if (value != null || name) { + html += '
'; + } + if (name) { + html += encodeHTML(name); + if (value != null) { + html += ' : '; + } + } + if (value != null) { + html += encodeHTML(formattedValue); + } + return html; + }, + + getData: function () { + return this._data; + }, + + setData: function (data) { + this._data = data; + } + }); + + zrUtil.mixin(MarkerModel, modelUtil.dataFormatMixin); + + module.exports = MarkerModel; + + +/***/ }, +/* 394 */ +/***/ function(module, exports, __webpack_require__) { + + + + var SymbolDraw = __webpack_require__(116); + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + + var List = __webpack_require__(98); + + var markerHelper = __webpack_require__(395); + + function updateMarkerLayout(mpData, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var point; + var xPx = numberUtil.parsePercent(itemModel.get('x'), api.getWidth()); + var yPx = numberUtil.parsePercent(itemModel.get('y'), api.getHeight()); + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } + // Chart like bar may have there own marker positioning logic + else if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition( + mpData.getValues(mpData.dimensions, idx) + ); + } + else if (coordSys) { + var x = mpData.get(coordSys.dimensions[0], idx); + var y = mpData.get(coordSys.dimensions[1], idx); + point = coordSys.dataToPoint([x, y]); + + } + + // Use x, y if has any + if (!isNaN(xPx)) { + point[0] = xPx; + } + if (!isNaN(yPx)) { + point[1] = yPx; + } + + mpData.setItemLayout(idx, point); + }); + } + + __webpack_require__(396).extend({ + + type: 'markPoint', + + updateLayout: function (markPointModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mpModel = seriesModel.markPointModel; + if (mpModel) { + updateMarkerLayout(mpModel.getData(), seriesModel, api); + this.markerGroupMap.get(seriesModel.id).updateLayout(mpModel); + } + }, this); + }, + + renderSeries: function (seriesModel, mpModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + + var symbolDrawMap = this.markerGroupMap; + var symbolDraw = symbolDrawMap.get(seriesId) + || symbolDrawMap.set(seriesId, new SymbolDraw()); + + var mpData = createList(coordSys, seriesModel, mpModel); + + // FIXME + mpModel.setData(mpData); + + updateMarkerLayout(mpModel.getData(), seriesModel, api); + + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var symbolSize = itemModel.getShallow('symbolSize'); + if (typeof symbolSize === 'function') { + // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据? + symbolSize = symbolSize( + mpModel.getRawValue(idx), mpModel.getDataParams(idx) + ); + } + mpData.setItemVisual(idx, { + symbolSize: symbolSize, + color: itemModel.get('itemStyle.normal.color') + || seriesData.getVisual('color'), + symbol: itemModel.getShallow('symbol') + }); + }); + + // TODO Text are wrong + symbolDraw.updateData(mpData); + this.group.add(symbolDraw.group); + + // Set host model for tooltip + // FIXME + mpData.eachItemGraphicEl(function (el) { + el.traverse(function (child) { + child.dataModel = mpModel; + }); + }); + + symbolDraw.__keep = true; + + symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent'); + } + }); + + /** + * @inner + * @param {module:echarts/coord/*} [coordSys] + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Model} mpModel + */ + function createList(coordSys, seriesModel, mpModel) { + var coordDimsInfos; + if (coordSys) { + coordDimsInfos = zrUtil.map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo( + seriesModel.coordDimToDataDim(coordDim)[0] + ) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys + info.name = coordDim; + return info; + }); + } + else { + coordDimsInfos =[{ + name: 'value', + type: 'float' + }]; + } + + var mpData = new List(coordDimsInfos, mpModel); + var dataOpt = zrUtil.map(mpModel.get('data'), zrUtil.curry( + markerHelper.dataTransform, seriesModel + )); + if (coordSys) { + dataOpt = zrUtil.filter( + dataOpt, zrUtil.curry(markerHelper.dataFilter, coordSys) + ); + } + + mpData.initData(dataOpt, null, + coordSys ? markerHelper.dimValueGetter : function (item) { + return item.value; + } + ); + return mpData; + } + + + +/***/ }, +/* 395 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var numberUtil = __webpack_require__(7); + var indexOf = zrUtil.indexOf; + + function hasXOrY(item) { + return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y))); + } + + function hasXAndY(item) { + return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y)); + } + + function getPrecision(data, valueAxisDim, dataIndex) { + var precision = -1; + do { + precision = Math.max( + numberUtil.getPrecision(data.get( + valueAxisDim, dataIndex + )), + precision + ); + data = data.stackedOn; + } while (data); + + return precision; + } + + function markerTypeCalculatorWithExtent( + mlType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex + ) { + var coordArr = []; + var value = numCalculate(data, targetDataDim, mlType); + + var dataIndex = data.indicesOfNearest(targetDataDim, value, true)[0]; + coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex, true); + coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex, true); + + var precision = getPrecision(data, targetDataDim, dataIndex); + if (precision >= 0) { + coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision); + } + + return coordArr; + } + + var curry = zrUtil.curry; + // TODO Specified percent + var markerTypeCalculator = { + /** + * @method + * @param {module:echarts/data/List} data + * @param {string} baseAxisDim + * @param {string} valueAxisDim + */ + min: curry(markerTypeCalculatorWithExtent, 'min'), + /** + * @method + * @param {module:echarts/data/List} data + * @param {string} baseAxisDim + * @param {string} valueAxisDim + */ + max: curry(markerTypeCalculatorWithExtent, 'max'), + + /** + * @method + * @param {module:echarts/data/List} data + * @param {string} baseAxisDim + * @param {string} valueAxisDim + */ + average: curry(markerTypeCalculatorWithExtent, 'average') + }; + + /** + * Transform markPoint data item to format used in List by do the following + * 1. Calculate statistic like `max`, `min`, `average` + * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/coord/*} [coordSys] + * @param {Object} item + * @return {Object} + */ + var dataTransform = function (seriesModel, item) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + + // 1. If not specify the position with pixel directly + // 2. If `coord` is not a data array. Which uses `xAxis`, + // `yAxis` to specify the coord on each dimension + + // parseFloat first because item.x and item.y can be percent string like '20%' + if (item && !hasXAndY(item) && !zrUtil.isArray(item.coord) && coordSys) { + var dims = coordSys.dimensions; + var axisInfo = getAxisInfo(item, data, coordSys, seriesModel); + + // Clone the option + // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value + item = zrUtil.clone(item); + + if (item.type + && markerTypeCalculator[item.type] + && axisInfo.baseAxis && axisInfo.valueAxis + ) { + var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim); + var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim); + + item.coord = markerTypeCalculator[item.type]( + data, axisInfo.baseDataDim, axisInfo.valueDataDim, + otherCoordIndex, targetCoordIndex + ); + // Force to use the value of calculated value. + item.value = item.coord[targetCoordIndex]; + } + else { + // FIXME Only has one of xAxis and yAxis. + var coord = [ + item.xAxis != null ? item.xAxis : item.radiusAxis, + item.yAxis != null ? item.yAxis : item.angleAxis + ]; + // Each coord support max, min, average + for (var i = 0; i < 2; i++) { + if (markerTypeCalculator[coord[i]]) { + var dataDim = seriesModel.coordDimToDataDim(dims[i])[0]; + coord[i] = numCalculate(data, dataDim, coord[i]); + } + } + item.coord = coord; + } + } + return item; + }; + + var getAxisInfo = function (item, data, coordSys, seriesModel) { + var ret = {}; + + if (item.valueIndex != null || item.valueDim != null) { + ret.valueDataDim = item.valueIndex != null + ? data.getDimension(item.valueIndex) : item.valueDim; + ret.valueAxis = coordSys.getAxis(seriesModel.dataDimToCoordDim(ret.valueDataDim)); + ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis); + ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0]; + } + else { + ret.baseAxis = seriesModel.getBaseAxis(); + ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis); + ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0]; + ret.valueDataDim = seriesModel.coordDimToDataDim(ret.valueAxis.dim)[0]; + } + + return ret; + }; + + /** + * Filter data which is out of coordinateSystem range + * [dataFilter description] + * @param {module:echarts/coord/*} [coordSys] + * @param {Object} item + * @return {boolean} + */ + var dataFilter = function (coordSys, item) { + // Alwalys return true if there is no coordSys + return (coordSys && coordSys.containData && item.coord && !hasXOrY(item)) + ? coordSys.containData(item.coord) : true; + }; + + var dimValueGetter = function (item, dimName, dataIndex, dimIndex) { + // x, y, radius, angle + if (dimIndex < 2) { + return item.coord && item.coord[dimIndex]; + } + return item.value; + }; + + var numCalculate = function (data, valueDataDim, type) { + if (type === 'average') { + var sum = 0; + var count = 0; + data.each(valueDataDim, function (val, idx) { + if (!isNaN(val)) { + sum += val; + count++; + } + }, true); + return sum / count; + } + else { + return data.getDataExtent(valueDataDim, true)[type === 'max' ? 1 : 0]; + } + }; + + module.exports = { + dataTransform: dataTransform, + dataFilter: dataFilter, + dimValueGetter: dimValueGetter, + getAxisInfo: getAxisInfo, + numCalculate: numCalculate + }; + + +/***/ }, +/* 396 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + + module.exports = __webpack_require__(1).extendComponentView({ + + type: 'marker', + + init: function () { + /** + * Markline grouped by series + * @private + * @type {module:zrender/core/util.HashMap} + */ + this.markerGroupMap = zrUtil.createHashMap(); + }, + + render: function (markerModel, ecModel, api) { + var markerGroupMap = this.markerGroupMap; + markerGroupMap.each(function (item) { + item.__keep = false; + }); + + var markerModelKey = this.type + 'Model'; + ecModel.eachSeries(function (seriesModel) { + var markerModel = seriesModel[markerModelKey]; + markerModel && this.renderSeries(seriesModel, markerModel, ecModel, api); + }, this); + + markerGroupMap.each(function (item) { + !item.__keep && this.group.remove(item.group); + }, this); + }, + + renderSeries: function () {} + }); + + +/***/ }, +/* 397 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(398); + __webpack_require__(399); + + __webpack_require__(1).registerPreprocessor(function (opt) { + // Make sure markLine component is enabled + opt.markLine = opt.markLine || {}; + }); + + +/***/ }, +/* 398 */ +/***/ function(module, exports, __webpack_require__) { + + + + module.exports = __webpack_require__(393).extend({ + + type: 'markLine', + + defaultOption: { + zlevel: 0, + z: 5, + + symbol: ['circle', 'arrow'], + symbolSize: [8, 16], + + //symbolRotate: 0, + + precision: 2, + tooltip: { + trigger: 'item' + }, + label: { + normal: { + show: true, + position: 'end' + }, + emphasis: { + show: true + } + }, + lineStyle: { + normal: { + type: 'dashed' + }, + emphasis: { + width: 3 + } + }, + animationEasing: 'linear' + } + }); + + +/***/ }, +/* 399 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var List = __webpack_require__(98); + var numberUtil = __webpack_require__(7); + + var markerHelper = __webpack_require__(395); + + var LineDraw = __webpack_require__(210); + + var markLineTransform = function (seriesModel, coordSys, mlModel, item) { + var data = seriesModel.getData(); + // Special type markLine like 'min', 'max', 'average' + var mlType = item.type; + + if (!zrUtil.isArray(item) + && ( + mlType === 'min' || mlType === 'max' || mlType === 'average' + // In case + // data: [{ + // yAxis: 10 + // }] + || (item.xAxis != null || item.yAxis != null) + ) + ) { + var valueAxis; + var valueDataDim; + var value; + + if (item.yAxis != null || item.xAxis != null) { + valueDataDim = item.yAxis != null ? 'y' : 'x'; + valueAxis = coordSys.getAxis(valueDataDim); + + value = zrUtil.retrieve(item.yAxis, item.xAxis); + } + else { + var axisInfo = markerHelper.getAxisInfo(item, data, coordSys, seriesModel); + valueDataDim = axisInfo.valueDataDim; + valueAxis = axisInfo.valueAxis; + value = markerHelper.numCalculate(data, valueDataDim, mlType); + } + var valueIndex = valueDataDim === 'x' ? 0 : 1; + var baseIndex = 1 - valueIndex; + + var mlFrom = zrUtil.clone(item); + var mlTo = {}; + + mlFrom.type = null; + + mlFrom.coord = []; + mlTo.coord = []; + mlFrom.coord[baseIndex] = -Infinity; + mlTo.coord[baseIndex] = Infinity; + + var precision = mlModel.get('precision'); + if (precision >= 0 && typeof value === 'number') { + value = +value.toFixed(precision); + } + + mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value; + + item = [mlFrom, mlTo, { // Extra option for tooltip and label + type: mlType, + valueIndex: item.valueIndex, + // Force to use the value of calculated value. + value: value + }]; + } + + item = [ + markerHelper.dataTransform(seriesModel, item[0]), + markerHelper.dataTransform(seriesModel, item[1]), + zrUtil.extend({}, item[2]) + ]; + + // Avoid line data type is extended by from(to) data type + item[2].type = item[2].type || ''; + + // Merge from option and to option into line option + zrUtil.merge(item[2], item[0]); + zrUtil.merge(item[2], item[1]); + + return item; + }; + + function isInifinity(val) { + return !isNaN(val) && !isFinite(val); + } + + // If a markLine has one dim + function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + var dimName = coordSys.dimensions[dimIndex]; + return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]) + && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]); + } + + function markLineFilter(coordSys, item) { + if (coordSys.type === 'cartesian2d') { + var fromCoord = item[0].coord; + var toCoord = item[1].coord; + // In case + // { + // markLine: { + // data: [{ yAxis: 2 }] + // } + // } + if ( + fromCoord && toCoord && + (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys) + || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys)) + ) { + return true; + } + } + return markerHelper.dataFilter(coordSys, item[0]) + && markerHelper.dataFilter(coordSys, item[1]); + } + + function updateSingleMarkerEndLayout( + data, idx, isFrom, seriesModel, api + ) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + + var point; + var xPx = numberUtil.parsePercent(itemModel.get('x'), api.getWidth()); + var yPx = numberUtil.parsePercent(itemModel.get('y'), api.getHeight()); + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } + else { + // Chart like bar may have there own marker positioning logic + if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition( + data.getValues(data.dimensions, idx) + ); + } + else { + var dims = coordSys.dimensions; + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + point = coordSys.dataToPoint([x, y]); + } + // Expand line to the edge of grid if value on one axis is Inifnity + // In case + // markLine: { + // data: [{ + // yAxis: 2 + // // or + // type: 'average' + // }] + // } + if (coordSys.type === 'cartesian2d') { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var dims = coordSys.dimensions; + if (isInifinity(data.get(dims[0], idx))) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]); + } + else if (isInifinity(data.get(dims[1], idx))) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]); + } + } + + // Use x, y if has any + if (!isNaN(xPx)) { + point[0] = xPx; + } + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + data.setItemLayout(idx, point); + } + + __webpack_require__(396).extend({ + + type: 'markLine', + + updateLayout: function (markLineModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mlModel = seriesModel.markLineModel; + if (mlModel) { + var mlData = mlModel.getData(); + var fromData = mlModel.__from; + var toData = mlModel.__to; + // Update visual and layout of from symbol and to symbol + fromData.each(function (idx) { + updateSingleMarkerEndLayout(fromData, idx, true, seriesModel, api); + updateSingleMarkerEndLayout(toData, idx, false, seriesModel, api); + }); + // Update layout of line + mlData.each(function (idx) { + mlData.setItemLayout(idx, [ + fromData.getItemLayout(idx), + toData.getItemLayout(idx) + ]); + }); + + this.markerGroupMap.get(seriesModel.id).updateLayout(); + + } + }, this); + }, + + renderSeries: function (seriesModel, mlModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + + var lineDrawMap = this.markerGroupMap; + var lineDraw = lineDrawMap.get(seriesId) + || lineDrawMap.set(seriesId, new LineDraw()); + this.group.add(lineDraw.group); + + var mlData = createList(coordSys, seriesModel, mlModel); + + var fromData = mlData.from; + var toData = mlData.to; + var lineData = mlData.line; + + mlModel.__from = fromData; + mlModel.__to = toData; + // Line data for tooltip and formatter + mlModel.setData(lineData); + + var symbolType = mlModel.get('symbol'); + var symbolSize = mlModel.get('symbolSize'); + if (!zrUtil.isArray(symbolType)) { + symbolType = [symbolType, symbolType]; + } + if (typeof symbolSize === 'number') { + symbolSize = [symbolSize, symbolSize]; + } + + // Update visual and layout of from symbol and to symbol + mlData.from.each(function (idx) { + updateDataVisualAndLayout(fromData, idx, true); + updateDataVisualAndLayout(toData, idx, false); + }); + + // Update visual and layout of line + lineData.each(function (idx) { + var lineColor = lineData.getItemModel(idx).get('lineStyle.normal.color'); + lineData.setItemVisual(idx, { + color: lineColor || fromData.getItemVisual(idx, 'color') + }); + lineData.setItemLayout(idx, [ + fromData.getItemLayout(idx), + toData.getItemLayout(idx) + ]); + + lineData.setItemVisual(idx, { + 'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'), + 'fromSymbol': fromData.getItemVisual(idx, 'symbol'), + 'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'), + 'toSymbol': toData.getItemVisual(idx, 'symbol') + }); + }); + + lineDraw.updateData(lineData); + + // Set host model for tooltip + // FIXME + mlData.line.eachItemGraphicEl(function (el, idx) { + el.traverse(function (child) { + child.dataModel = mlModel; + }); + }); + + function updateDataVisualAndLayout(data, idx, isFrom) { + var itemModel = data.getItemModel(idx); + + updateSingleMarkerEndLayout( + data, idx, isFrom, seriesModel, api + ); + + data.setItemVisual(idx, { + symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1], + symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1], + color: itemModel.get('itemStyle.normal.color') || seriesData.getVisual('color') + }); + } + + lineDraw.__keep = true; + + lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent'); + } + }); + + /** + * @inner + * @param {module:echarts/coord/*} coordSys + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Model} mpModel + */ + function createList(coordSys, seriesModel, mlModel) { + + var coordDimsInfos; + if (coordSys) { + coordDimsInfos = zrUtil.map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo( + seriesModel.coordDimToDataDim(coordDim)[0] + ) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys + info.name = coordDim; + return info; + }); + } + else { + coordDimsInfos =[{ + name: 'value', + type: 'float' + }]; + } + + var fromData = new List(coordDimsInfos, mlModel); + var toData = new List(coordDimsInfos, mlModel); + // No dimensions + var lineData = new List([], mlModel); + + var optData = zrUtil.map(mlModel.get('data'), zrUtil.curry( + markLineTransform, seriesModel, coordSys, mlModel + )); + if (coordSys) { + optData = zrUtil.filter( + optData, zrUtil.curry(markLineFilter, coordSys) + ); + } + var dimValueGetter = coordSys ? markerHelper.dimValueGetter : function (item) { + return item.value; + }; + fromData.initData( + zrUtil.map(optData, function (item) { return item[0]; }), + null, dimValueGetter + ); + toData.initData( + zrUtil.map(optData, function (item) { return item[1]; }), + null, dimValueGetter + ); + lineData.initData( + zrUtil.map(optData, function (item) { return item[2]; }) + ); + lineData.hasItemOption = true; + return { + from: fromData, + to: toData, + line: lineData + }; + } + + +/***/ }, +/* 400 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(401); + __webpack_require__(402); + + __webpack_require__(1).registerPreprocessor(function (opt) { + // Make sure markArea component is enabled + opt.markArea = opt.markArea || {}; + }); + + +/***/ }, +/* 401 */ +/***/ function(module, exports, __webpack_require__) { + + + + module.exports = __webpack_require__(393).extend({ + + type: 'markArea', + + defaultOption: { + zlevel: 0, + // PENDING + z: 1, + tooltip: { + trigger: 'item' + }, + // markArea should fixed on the coordinate system + animation: false, + label: { + normal: { + show: true, + position: 'top' + }, + emphasis: { + show: true, + position: 'top' + } + }, + itemStyle: { + normal: { + // color and borderColor default to use color from series + // color: 'auto' + // borderColor: 'auto' + borderWidth: 0 + } + } + } + }); + + +/***/ }, +/* 402 */ +/***/ function(module, exports, __webpack_require__) { + + // TODO Better on polar + + + var zrUtil = __webpack_require__(4); + var List = __webpack_require__(98); + var numberUtil = __webpack_require__(7); + var graphic = __webpack_require__(18); + var colorUtil = __webpack_require__(31); + + var markerHelper = __webpack_require__(395); + + var markAreaTransform = function (seriesModel, coordSys, maModel, item) { + var lt = markerHelper.dataTransform(seriesModel, item[0]); + var rb = markerHelper.dataTransform(seriesModel, item[1]); + var retrieve = zrUtil.retrieve; + + // FIXME make sure lt is less than rb + var ltCoord = lt.coord; + var rbCoord = rb.coord; + ltCoord[0] = retrieve(ltCoord[0], -Infinity); + ltCoord[1] = retrieve(ltCoord[1], -Infinity); + + rbCoord[0] = retrieve(rbCoord[0], Infinity); + rbCoord[1] = retrieve(rbCoord[1], Infinity); + + // Merge option into one + var result = zrUtil.mergeAll([{}, lt, rb]); + + result.coord = [ + lt.coord, rb.coord + ]; + result.x0 = lt.x; + result.y0 = lt.y; + result.x1 = rb.x; + result.y1 = rb.y; + return result; + }; + + function isInifinity(val) { + return !isNaN(val) && !isFinite(val); + } + + // If a markArea has one dim + function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]); + } + + function markAreaFilter(coordSys, item) { + var fromCoord = item.coord[0]; + var toCoord = item.coord[1]; + if (coordSys.type === 'cartesian2d') { + // In case + // { + // markArea: { + // data: [{ yAxis: 2 }] + // } + // } + if ( + fromCoord && toCoord && + (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys) + || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys)) + ) { + return true; + } + } + return markerHelper.dataFilter(coordSys, { + coord: fromCoord, + x: item.x0, + y: item.y0 + }) + || markerHelper.dataFilter(coordSys, { + coord: toCoord, + x: item.x1, + y: item.y1 + }); + } + + // dims can be ['x0', 'y0'], ['x1', 'y1'], ['x0', 'y1'], ['x1', 'y0'] + function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + + var point; + var xPx = numberUtil.parsePercent(itemModel.get(dims[0]), api.getWidth()); + var yPx = numberUtil.parsePercent(itemModel.get(dims[1]), api.getHeight()); + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } + else { + // Chart like bar may have there own marker positioning logic + if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition( + data.getValues(dims, idx) + ); + } + else { + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + point = coordSys.dataToPoint([x, y], true); + } + if (coordSys.type === 'cartesian2d') { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + if (isInifinity(x)) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]); + } + else if (isInifinity(y)) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]); + } + } + + // Use x, y if has any + if (!isNaN(xPx)) { + point[0] = xPx; + } + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + return point; + } + + var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']]; + + __webpack_require__(396).extend({ + + type: 'markArea', + + updateLayout: function (markAreaModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var maModel = seriesModel.markAreaModel; + if (maModel) { + var areaData = maModel.getData(); + areaData.each(function (idx) { + var points = zrUtil.map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api); + }); + // Layout + areaData.setItemLayout(idx, points); + var el = areaData.getItemGraphicEl(idx); + el.setShape('points', points); + }); + } + }, this); + }, + + renderSeries: function (seriesModel, maModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesName = seriesModel.name; + var seriesData = seriesModel.getData(); + + var areaGroupMap = this.markerGroupMap; + var polygonGroup = areaGroupMap.get(seriesName) + || areaGroupMap.set(seriesName, {group: new graphic.Group()}); + + this.group.add(polygonGroup.group); + polygonGroup.__keep = true; + + var areaData = createList(coordSys, seriesModel, maModel); + + // Line data for tooltip and formatter + maModel.setData(areaData); + + // Update visual and layout of line + areaData.each(function (idx) { + // Layout + areaData.setItemLayout(idx, zrUtil.map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api); + })); + + // Visual + areaData.setItemVisual(idx, { + color: seriesData.getVisual('color') + }); + }); + + + areaData.diff(polygonGroup.__data) + .add(function (idx) { + var polygon = new graphic.Polygon({ + shape: { + points: areaData.getItemLayout(idx) + } + }); + areaData.setItemGraphicEl(idx, polygon); + polygonGroup.group.add(polygon); + }) + .update(function (newIdx, oldIdx) { + var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx); + graphic.updateProps(polygon, { + shape: { + points: areaData.getItemLayout(newIdx) + } + }, maModel, newIdx); + polygonGroup.group.add(polygon); + areaData.setItemGraphicEl(newIdx, polygon); + }) + .remove(function (idx) { + var polygon = polygonGroup.__data.getItemGraphicEl(idx); + polygonGroup.group.remove(polygon); + }) + .execute(); + + areaData.eachItemGraphicEl(function (polygon, idx) { + var itemModel = areaData.getItemModel(idx); + var labelModel = itemModel.getModel('label.normal'); + var labelHoverModel = itemModel.getModel('label.emphasis'); + var color = areaData.getItemVisual(idx, 'color'); + polygon.useStyle( + zrUtil.defaults( + itemModel.getModel('itemStyle.normal').getItemStyle(), + { + fill: colorUtil.modifyAlpha(color, 0.4), + stroke: color + } + ) + ); + + polygon.hoverStyle = itemModel.getModel('itemStyle.normal').getItemStyle(); + + var defaultValue = areaData.getName(idx) || ''; + var textColor = color || polygon.style.fill; + + if (labelModel.getShallow('show')) { + graphic.setText(polygon.style, labelModel, textColor); + polygon.style.text = zrUtil.retrieve( + maModel.getFormattedLabel(idx, 'normal'), + defaultValue + ); + } + else { + polygon.style.text = ''; + } + + if (labelHoverModel.getShallow('show')) { + graphic.setText(polygon.hoverStyle, labelHoverModel, textColor); + polygon.hoverStyle.text = zrUtil.retrieve( + maModel.getFormattedLabel(idx, 'emphasis'), + defaultValue + ); + } + else { + polygon.hoverStyle.text = ''; + } + + graphic.setHoverStyle(polygon, {}); + + polygon.dataModel = maModel; + }); + + polygonGroup.__data = areaData; + + polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent'); + } + }); + + /** + * @inner + * @param {module:echarts/coord/*} coordSys + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Model} mpModel + */ + function createList(coordSys, seriesModel, maModel) { + + var coordDimsInfos; + var areaData; + var dims = ['x0', 'y0', 'x1', 'y1']; + if (coordSys) { + coordDimsInfos = zrUtil.map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo( + seriesModel.coordDimToDataDim(coordDim)[0] + ) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys + info.name = coordDim; + return info; + }); + areaData = new List(zrUtil.map(dims, function (dim, idx) { + return { + name: dim, + type: coordDimsInfos[idx % 2].type + }; + }), maModel); + } + else { + coordDimsInfos =[{ + name: 'value', + type: 'float' + }]; + areaData = new List(coordDimsInfos, maModel); + } + + var optData = zrUtil.map(maModel.get('data'), zrUtil.curry( + markAreaTransform, seriesModel, coordSys, maModel + )); + if (coordSys) { + optData = zrUtil.filter( + optData, zrUtil.curry(markAreaFilter, coordSys) + ); + } + + var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) { + return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2]; + } : function (item) { + return item.value; + }; + areaData.initData(optData, null, dimValueGetter); + areaData.hasItemOption = true; + return areaData; + } + + +/***/ }, +/* 403 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * DataZoom component entry + */ + + + var echarts = __webpack_require__(1); + + echarts.registerPreprocessor(__webpack_require__(404)); + + __webpack_require__(405); + __webpack_require__(406); + __webpack_require__(407); + __webpack_require__(409); + + + +/***/ }, +/* 404 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Timeline preprocessor + */ + + + var zrUtil = __webpack_require__(4); + + module.exports = function (option) { + var timelineOpt = option && option.timeline; + + if (!zrUtil.isArray(timelineOpt)) { + timelineOpt = timelineOpt ? [timelineOpt] : []; + } + + zrUtil.each(timelineOpt, function (opt) { + if (!opt) { + return; + } + + compatibleEC2(opt); + }); + }; + + function compatibleEC2(opt) { + var type = opt.type; + + var ec2Types = {'number': 'value', 'time': 'time'}; + + // Compatible with ec2 + if (ec2Types[type]) { + opt.axisType = ec2Types[type]; + delete opt.type; + } + + transferItem(opt); + + if (has(opt, 'controlPosition')) { + var controlStyle = opt.controlStyle || (opt.controlStyle = {}); + if (!has(controlStyle, 'position')) { + controlStyle.position = opt.controlPosition; + } + if (controlStyle.position === 'none' && !has(controlStyle, 'show')) { + controlStyle.show = false; + delete controlStyle.position; + } + delete opt.controlPosition; + } + + zrUtil.each(opt.data || [], function (dataItem) { + if (zrUtil.isObject(dataItem) && !zrUtil.isArray(dataItem)) { + if (!has(dataItem, 'value') && has(dataItem, 'name')) { + // In ec2, using name as value. + dataItem.value = dataItem.name; + } + transferItem(dataItem); + } + }); + } + + function transferItem(opt) { + var itemStyle = opt.itemStyle || (opt.itemStyle = {}); + + var itemStyleEmphasis = itemStyle.emphasis || (itemStyle.emphasis = {}); + + // Transfer label out + var label = opt.label || (opt.label || {}); + var labelNormal = label.normal || (label.normal = {}); + var excludeLabelAttr = {normal: 1, emphasis: 1}; + + zrUtil.each(label, function (value, name) { + if (!excludeLabelAttr[name] && !has(labelNormal, name)) { + labelNormal[name] = value; + } + }); + + if (itemStyleEmphasis.label && !has(label, 'emphasis')) { + label.emphasis = itemStyleEmphasis.label; + delete itemStyleEmphasis.label; + } + } + + function has(obj, attr) { + return obj.hasOwnProperty(attr); + } + + + +/***/ }, +/* 405 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(69).registerSubTypeDefaulter('timeline', function () { + // Only slider now. + return 'slider'; + }); + + + +/***/ }, +/* 406 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Timeilne action + */ + + + var echarts = __webpack_require__(1); + var zrUtil = __webpack_require__(4); + + echarts.registerAction( + + {type: 'timelineChange', event: 'timelineChanged', update: 'prepareAndUpdate'}, + + function (payload, ecModel) { + + var timelineModel = ecModel.getComponent('timeline'); + if (timelineModel && payload.currentIndex != null) { + timelineModel.setCurrentIndex(payload.currentIndex); + + if (!timelineModel.get('loop', true) && timelineModel.isIndexMax()) { + timelineModel.setPlayState(false); + } + } + + // Set normalized currentIndex to payload. + ecModel.resetOption('timeline'); + + return zrUtil.defaults({ + currentIndex: timelineModel.option.currentIndex + }, payload); + } + ); + + echarts.registerAction( + + {type: 'timelinePlayChange', event: 'timelinePlayChanged', update: 'update'}, + + function (payload, ecModel) { + var timelineModel = ecModel.getComponent('timeline'); + if (timelineModel && payload.playState != null) { + timelineModel.setPlayState(payload.playState); + } + } + ); + + + +/***/ }, +/* 407 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Silder timeline model + */ + + + var TimelineModel = __webpack_require__(408); + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + + var SliderTimelineModel = TimelineModel.extend({ + + type: 'timeline.slider', + + /** + * @protected + */ + defaultOption: { + + backgroundColor: 'rgba(0,0,0,0)', // 时间轴背景颜色 + borderColor: '#ccc', // 时间轴边框颜色 + borderWidth: 0, // 时间轴边框线宽,单位px,默认为0(无边框) + + orient: 'horizontal', // 'vertical' + inverse: false, + + tooltip: { // boolean or Object + trigger: 'item' // data item may also have tootip attr. + }, + + symbol: 'emptyCircle', + symbolSize: 10, + + lineStyle: { + show: true, + width: 2, + color: '#304654' + }, + label: { // 文本标签 + position: 'auto', // auto left right top bottom + // When using number, label position is not + // restricted by viewRect. + // positive: right/bottom, negative: left/top + normal: { + show: true, + interval: 'auto', + rotate: 0, + // formatter: null, + textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#304654' + } + }, + emphasis: { + show: true, + textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#c23531' + } + } + }, + itemStyle: { + normal: { + color: '#304654', + borderWidth: 1 + }, + emphasis: { + color: '#c23531' + } + }, + + checkpointStyle: { + symbol: 'circle', + symbolSize: 13, + color: '#c23531', + borderWidth: 5, + borderColor: 'rgba(194,53,49, 0.5)', + animation: true, + animationDuration: 300, + animationEasing: 'quinticInOut' + }, + + controlStyle: { + show: true, + showPlayBtn: true, + showPrevBtn: true, + showNextBtn: true, + itemSize: 22, + itemGap: 12, + position: 'left', // 'left' 'right' 'top' 'bottom' + playIcon: 'path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z', // jshint ignore:line + stopIcon: 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z', // jshint ignore:line + nextIcon: 'path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z', // jshint ignore:line + prevIcon: 'path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z', // jshint ignore:line + normal: { + color: '#304654', + borderColor: '#304654', + borderWidth: 1 + }, + emphasis: { + color: '#c23531', + borderColor: '#c23531', + borderWidth: 2 + } + }, + data: [] + } + + }); + + zrUtil.mixin(SliderTimelineModel, modelUtil.dataFormatMixin); + + module.exports = SliderTimelineModel; + + +/***/ }, +/* 408 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Timeline model + */ + + + var ComponentModel = __webpack_require__(69); + var List = __webpack_require__(98); + var zrUtil = __webpack_require__(4); + var modelUtil = __webpack_require__(5); + + var TimelineModel = ComponentModel.extend({ + + type: 'timeline', + + layoutMode: 'box', + + /** + * @protected + */ + defaultOption: { + + zlevel: 0, // 一级层叠 + z: 4, // 二级层叠 + show: true, + + axisType: 'time', // 模式是时间类型,支持 value, category + + realtime: true, + + left: '20%', + top: null, + right: '20%', + bottom: 0, + width: null, + height: 40, + padding: 5, + + controlPosition: 'left', // 'left' 'right' 'top' 'bottom' 'none' + autoPlay: false, + rewind: false, // 反向播放 + loop: true, + playInterval: 2000, // 播放时间间隔,单位ms + + currentIndex: 0, + + itemStyle: { + normal: {}, + emphasis: {} + }, + label: { + normal: { + textStyle: { + color: '#000' + } + }, + emphasis: {} + }, + + data: [] + }, + + /** + * @override + */ + init: function (option, parentModel, ecModel) { + + /** + * @private + * @type {module:echarts/data/List} + */ + this._data; + + /** + * @private + * @type {Array.} + */ + this._names; + + this.mergeDefaultAndTheme(option, ecModel); + this._initData(); + }, + + /** + * @override + */ + mergeOption: function (option) { + TimelineModel.superApply(this, 'mergeOption', arguments); + this._initData(); + }, + + /** + * @param {number} [currentIndex] + */ + setCurrentIndex: function (currentIndex) { + if (currentIndex == null) { + currentIndex = this.option.currentIndex; + } + var count = this._data.count(); + + if (this.option.loop) { + currentIndex = (currentIndex % count + count) % count; + } + else { + currentIndex >= count && (currentIndex = count - 1); + currentIndex < 0 && (currentIndex = 0); + } + + this.option.currentIndex = currentIndex; + }, + + /** + * @return {number} currentIndex + */ + getCurrentIndex: function () { + return this.option.currentIndex; + }, + + /** + * @return {boolean} + */ + isIndexMax: function () { + return this.getCurrentIndex() >= this._data.count() - 1; + }, + + /** + * @param {boolean} state true: play, false: stop + */ + setPlayState: function (state) { + this.option.autoPlay = !!state; + }, + + /** + * @return {boolean} true: play, false: stop + */ + getPlayState: function () { + return !!this.option.autoPlay; + }, + + /** + * @private + */ + _initData: function () { + var thisOption = this.option; + var dataArr = thisOption.data || []; + var axisType = thisOption.axisType; + var names = this._names = []; + + if (axisType === 'category') { + var idxArr = []; + zrUtil.each(dataArr, function (item, index) { + var value = modelUtil.getDataItemValue(item); + var newItem; + + if (zrUtil.isObject(item)) { + newItem = zrUtil.clone(item); + newItem.value = index; + } + else { + newItem = index; + } + + idxArr.push(newItem); + + if (!zrUtil.isString(value) && (value == null || isNaN(value))) { + value = ''; + } + + names.push(value + ''); + }); + dataArr = idxArr; + } + + var dimType = ({category: 'ordinal', time: 'time'})[axisType] || 'number'; + + var data = this._data = new List([{name: 'value', type: dimType}], this); + + data.initData(dataArr, names); + }, + + getData: function () { + return this._data; + }, + + /** + * @public + * @return {Array.} categoreis + */ + getCategories: function () { + if (this.get('axisType') === 'category') { + return this._names.slice(); + } + } + + }); + + module.exports = TimelineModel; + + +/***/ }, +/* 409 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Silder timeline view + */ + + + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var layout = __webpack_require__(71); + var TimelineView = __webpack_require__(410); + var TimelineAxis = __webpack_require__(411); + var symbolUtil = __webpack_require__(111); + var axisHelper = __webpack_require__(101); + var BoundingRect = __webpack_require__(9); + var matrix = __webpack_require__(11); + var numberUtil = __webpack_require__(7); + var formatUtil = __webpack_require__(6); + var encodeHTML = formatUtil.encodeHTML; + + var bind = zrUtil.bind; + var each = zrUtil.each; + + var PI = Math.PI; + + module.exports = TimelineView.extend({ + + type: 'timeline.slider', + + init: function (ecModel, api) { + + this.api = api; + + /** + * @private + * @type {module:echarts/component/timeline/TimelineAxis} + */ + this._axis; + + /** + * @private + * @type {module:zrender/core/BoundingRect} + */ + this._viewRect; + + /** + * @type {number} + */ + this._timer; + + /** + * @type {module:zrender/Element} + */ + this._currentPointer; + + /** + * @type {module:zrender/container/Group} + */ + this._mainGroup; + + /** + * @type {module:zrender/container/Group} + */ + this._labelGroup; + }, + + /** + * @override + */ + render: function (timelineModel, ecModel, api, payload) { + this.model = timelineModel; + this.api = api; + this.ecModel = ecModel; + + this.group.removeAll(); + + if (timelineModel.get('show', true)) { + + var layoutInfo = this._layout(timelineModel, api); + var mainGroup = this._createGroup('mainGroup'); + var labelGroup = this._createGroup('labelGroup'); + + /** + * @private + * @type {module:echarts/component/timeline/TimelineAxis} + */ + var axis = this._axis = this._createAxis(layoutInfo, timelineModel); + + timelineModel.formatTooltip = function (dataIndex) { + return encodeHTML(axis.scale.getLabel(dataIndex)); + }; + + each( + ['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'], + function (name) { + this['_render' + name](layoutInfo, mainGroup, axis, timelineModel); + }, + this + ); + + this._renderAxisLabel(layoutInfo, labelGroup, axis, timelineModel); + this._position(layoutInfo, timelineModel); + } + + this._doPlayStop(); + }, + + /** + * @override + */ + remove: function () { + this._clearTimer(); + this.group.removeAll(); + }, + + /** + * @override + */ + dispose: function () { + this._clearTimer(); + }, + + _layout: function (timelineModel, api) { + var labelPosOpt = timelineModel.get('label.normal.position'); + var orient = timelineModel.get('orient'); + var viewRect = getViewRect(timelineModel, api); + // Auto label offset. + if (labelPosOpt == null || labelPosOpt === 'auto') { + labelPosOpt = orient === 'horizontal' + ? ((viewRect.y + viewRect.height / 2) < api.getHeight() / 2 ? '-' : '+') + : ((viewRect.x + viewRect.width / 2) < api.getWidth() / 2 ? '+' : '-'); + } + else if (isNaN(labelPosOpt)) { + labelPosOpt = ({ + horizontal: {top: '-', bottom: '+'}, + vertical: {left: '-', right: '+'} + })[orient][labelPosOpt]; + } + + var labelAlignMap = { + horizontal: 'center', + vertical: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'left' : 'right' + }; + + var labelBaselineMap = { + horizontal: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'top' : 'bottom', + vertical: 'middle' + }; + var rotationMap = { + horizontal: 0, + vertical: PI / 2 + }; + + // Position + var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width; + + var controlModel = timelineModel.getModel('controlStyle'); + var showControl = controlModel.get('show'); + var controlSize = showControl ? controlModel.get('itemSize') : 0; + var controlGap = showControl ? controlModel.get('itemGap') : 0; + var sizePlusGap = controlSize + controlGap; + + // Special label rotate. + var labelRotation = timelineModel.get('label.normal.rotate') || 0; + labelRotation = labelRotation * PI / 180; // To radian. + + var playPosition; + var prevBtnPosition; + var nextBtnPosition; + var axisExtent; + var controlPosition = controlModel.get('position', true); + var showControl = controlModel.get('show', true); + var showPlayBtn = showControl && controlModel.get('showPlayBtn', true); + var showPrevBtn = showControl && controlModel.get('showPrevBtn', true); + var showNextBtn = showControl && controlModel.get('showNextBtn', true); + var xLeft = 0; + var xRight = mainLength; + + // position[0] means left, position[1] means middle. + if (controlPosition === 'left' || controlPosition === 'bottom') { + showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap); + showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } + else { // 'top' 'right' + showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } + axisExtent = [xLeft, xRight]; + + if (timelineModel.get('inverse')) { + axisExtent.reverse(); + } + + return { + viewRect: viewRect, + mainLength: mainLength, + orient: orient, + + rotation: rotationMap[orient], + labelRotation: labelRotation, + labelPosOpt: labelPosOpt, + labelAlign: timelineModel.get('label.normal.textStyle.align') || labelAlignMap[orient], + labelBaseline: timelineModel.get('label.normal.textStyle.baseline') || labelBaselineMap[orient], + + // Based on mainGroup. + playPosition: playPosition, + prevBtnPosition: prevBtnPosition, + nextBtnPosition: nextBtnPosition, + axisExtent: axisExtent, + + controlSize: controlSize, + controlGap: controlGap + }; + }, + + _position: function (layoutInfo, timelineModel) { + // Position is be called finally, because bounding rect is needed for + // adapt content to fill viewRect (auto adapt offset). + + // Timeline may be not all in the viewRect when 'offset' is specified + // as a number, because it is more appropriate that label aligns at + // 'offset' but not the other edge defined by viewRect. + + var mainGroup = this._mainGroup; + var labelGroup = this._labelGroup; + + var viewRect = layoutInfo.viewRect; + if (layoutInfo.orient === 'vertical') { + // transfrom to horizontal, inverse rotate by left-top point. + var m = matrix.create(); + var rotateOriginX = viewRect.x; + var rotateOriginY = viewRect.y + viewRect.height; + matrix.translate(m, m, [-rotateOriginX, -rotateOriginY]); + matrix.rotate(m, m, -PI / 2); + matrix.translate(m, m, [rotateOriginX, rotateOriginY]); + viewRect = viewRect.clone(); + viewRect.applyTransform(m); + } + + var viewBound = getBound(viewRect); + var mainBound = getBound(mainGroup.getBoundingRect()); + var labelBound = getBound(labelGroup.getBoundingRect()); + + var mainPosition = mainGroup.position; + var labelsPosition = labelGroup.position; + + labelsPosition[0] = mainPosition[0] = viewBound[0][0]; + + var labelPosOpt = layoutInfo.labelPosOpt; + + if (isNaN(labelPosOpt)) { // '+' or '-' + var mainBoundIdx = labelPosOpt === '+' ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx); + } + else { + var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + labelsPosition[1] = mainPosition[1] + labelPosOpt; + } + + mainGroup.attr('position', mainPosition); + labelGroup.attr('position', labelsPosition); + mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation; + + setOrigin(mainGroup); + setOrigin(labelGroup); + + function setOrigin(targetGroup) { + var pos = targetGroup.position; + targetGroup.origin = [ + viewBound[0][0] - pos[0], + viewBound[1][0] - pos[1] + ]; + } + + function getBound(rect) { + // [[xmin, xmax], [ymin, ymax]] + return [ + [rect.x, rect.x + rect.width], + [rect.y, rect.y + rect.height] + ]; + } + + function toBound(fromPos, from, to, dimIdx, boundIdx) { + fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx]; + } + }, + + _createAxis: function (layoutInfo, timelineModel) { + var data = timelineModel.getData(); + var axisType = timelineModel.get('axisType'); + + var scale = axisHelper.createScaleByModel(timelineModel, axisType); + var dataExtent = data.getDataExtent('value'); + scale.setExtent(dataExtent[0], dataExtent[1]); + this._customizeScale(scale, data); + scale.niceTicks(); + + var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType); + axis.model = timelineModel; + + return axis; + }, + + _customizeScale: function (scale, data) { + + scale.getTicks = function () { + return data.mapArray(['value'], function (value) { + return value; + }); + }; + + scale.getTicksLabels = function () { + return zrUtil.map(this.getTicks(), scale.getLabel, scale); + }; + }, + + _createGroup: function (name) { + var newGroup = this['_' + name] = new graphic.Group(); + this.group.add(newGroup); + return newGroup; + }, + + _renderAxisLine: function (layoutInfo, group, axis, timelineModel) { + var axisExtent = axis.getExtent(); + + if (!timelineModel.get('lineStyle.show')) { + return; + } + + group.add(new graphic.Line({ + shape: { + x1: axisExtent[0], y1: 0, + x2: axisExtent[1], y2: 0 + }, + style: zrUtil.extend( + {lineCap: 'round'}, + timelineModel.getModel('lineStyle').getLineStyle() + ), + silent: true, + z2: 1 + })); + }, + + /** + * @private + */ + _renderAxisTick: function (layoutInfo, group, axis, timelineModel) { + var data = timelineModel.getData(); + var ticks = axis.scale.getTicks(); + + each(ticks, function (value, dataIndex) { + + var tickCoord = axis.dataToCoord(value); + var itemModel = data.getItemModel(dataIndex); + var itemStyleModel = itemModel.getModel('itemStyle.normal'); + var hoverStyleModel = itemModel.getModel('itemStyle.emphasis'); + var symbolOpt = { + position: [tickCoord, 0], + onclick: bind(this._changeTimeline, this, dataIndex) + }; + var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt); + graphic.setHoverStyle(el, hoverStyleModel.getItemStyle()); + + if (itemModel.get('tooltip')) { + el.dataIndex = dataIndex; + el.dataModel = timelineModel; + } + else { + el.dataIndex = el.dataModel = null; + } + + }, this); + }, + + /** + * @private + */ + _renderAxisLabel: function (layoutInfo, group, axis, timelineModel) { + var labelModel = timelineModel.getModel('label.normal'); + + if (!labelModel.get('show')) { + return; + } + + var data = timelineModel.getData(); + var ticks = axis.scale.getTicks(); + var labels = axisHelper.getFormattedLabels( + axis, labelModel.get('formatter') + ); + var labelInterval = axis.getLabelInterval(); + + each(ticks, function (tick, dataIndex) { + if (axis.isLabelIgnored(dataIndex, labelInterval)) { + return; + } + + var itemModel = data.getItemModel(dataIndex); + var itemTextStyleModel = itemModel.getModel('label.normal.textStyle'); + var hoverTextStyleModel = itemModel.getModel('label.emphasis.textStyle'); + var tickCoord = axis.dataToCoord(tick); + var textEl = new graphic.Text({ + style: { + text: labels[dataIndex], + textAlign: layoutInfo.labelAlign, + textVerticalAlign: layoutInfo.labelBaseline, + textFont: itemTextStyleModel.getFont(), + fill: itemTextStyleModel.getTextColor() + }, + position: [tickCoord, 0], + rotation: layoutInfo.labelRotation - layoutInfo.rotation, + onclick: bind(this._changeTimeline, this, dataIndex), + silent: false + }); + + group.add(textEl); + graphic.setHoverStyle(textEl, hoverTextStyleModel.getItemStyle()); + + }, this); + }, + + /** + * @private + */ + _renderControl: function (layoutInfo, group, axis, timelineModel) { + var controlSize = layoutInfo.controlSize; + var rotation = layoutInfo.rotation; + + var itemStyle = timelineModel.getModel('controlStyle.normal').getItemStyle(); + var hoverStyle = timelineModel.getModel('controlStyle.emphasis').getItemStyle(); + var rect = [0, -controlSize / 2, controlSize, controlSize]; + var playState = timelineModel.getPlayState(); + var inverse = timelineModel.get('inverse', true); + + makeBtn( + layoutInfo.nextBtnPosition, + 'controlStyle.nextIcon', + bind(this._changeTimeline, this, inverse ? '-' : '+') + ); + makeBtn( + layoutInfo.prevBtnPosition, + 'controlStyle.prevIcon', + bind(this._changeTimeline, this, inverse ? '+' : '-') + ); + makeBtn( + layoutInfo.playPosition, + 'controlStyle.' + (playState ? 'stopIcon' : 'playIcon'), + bind(this._handlePlayClick, this, !playState), + true + ); + + function makeBtn(position, iconPath, onclick, willRotate) { + if (!position) { + return; + } + var opt = { + position: position, + origin: [controlSize / 2, 0], + rotation: willRotate ? -rotation : 0, + rectHover: true, + style: itemStyle, + onclick: onclick + }; + var btn = makeIcon(timelineModel, iconPath, rect, opt); + group.add(btn); + graphic.setHoverStyle(btn, hoverStyle); + } + }, + + _renderCurrentPointer: function (layoutInfo, group, axis, timelineModel) { + var data = timelineModel.getData(); + var currentIndex = timelineModel.getCurrentIndex(); + var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle'); + var me = this; + + var callback = { + onCreate: function (pointer) { + pointer.draggable = true; + pointer.drift = bind(me._handlePointerDrag, me); + pointer.ondragend = bind(me._handlePointerDragend, me); + pointerMoveTo(pointer, currentIndex, axis, timelineModel, true); + }, + onUpdate: function (pointer) { + pointerMoveTo(pointer, currentIndex, axis, timelineModel); + } + }; + + // Reuse when exists, for animation and drag. + this._currentPointer = giveSymbol( + pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback + ); + }, + + _handlePlayClick: function (nextState) { + this._clearTimer(); + this.api.dispatchAction({ + type: 'timelinePlayChange', + playState: nextState, + from: this.uid + }); + }, + + _handlePointerDrag: function (dx, dy, e) { + this._clearTimer(); + this._pointerChangeTimeline([e.offsetX, e.offsetY]); + }, + + _handlePointerDragend: function (e) { + this._pointerChangeTimeline([e.offsetX, e.offsetY], true); + }, + + _pointerChangeTimeline: function (mousePos, trigger) { + var toCoord = this._toAxisCoord(mousePos)[0]; + + var axis = this._axis; + var axisExtent = numberUtil.asc(axis.getExtent().slice()); + + toCoord > axisExtent[1] && (toCoord = axisExtent[1]); + toCoord < axisExtent[0] && (toCoord = axisExtent[0]); + + this._currentPointer.position[0] = toCoord; + this._currentPointer.dirty(); + + var targetDataIndex = this._findNearestTick(toCoord); + var timelineModel = this.model; + + if (trigger || ( + targetDataIndex !== timelineModel.getCurrentIndex() + && timelineModel.get('realtime') + )) { + this._changeTimeline(targetDataIndex); + } + }, + + _doPlayStop: function () { + this._clearTimer(); + + if (this.model.getPlayState()) { + this._timer = setTimeout( + bind(handleFrame, this), + this.model.get('playInterval') + ); + } + + function handleFrame() { + // Do not cache + var timelineModel = this.model; + this._changeTimeline( + timelineModel.getCurrentIndex() + + (timelineModel.get('rewind', true) ? -1 : 1) + ); + } + }, + + _toAxisCoord: function (vertex) { + var trans = this._mainGroup.getLocalTransform(); + return graphic.applyTransform(vertex, trans, true); + }, + + _findNearestTick: function (axisCoord) { + var data = this.model.getData(); + var dist = Infinity; + var targetDataIndex; + var axis = this._axis; + + data.each(['value'], function (value, dataIndex) { + var coord = axis.dataToCoord(value); + var d = Math.abs(coord - axisCoord); + if (d < dist) { + dist = d; + targetDataIndex = dataIndex; + } + }); + + return targetDataIndex; + }, + + _clearTimer: function () { + if (this._timer) { + clearTimeout(this._timer); + this._timer = null; + } + }, + + _changeTimeline: function (nextIndex) { + var currentIndex = this.model.getCurrentIndex(); + + if (nextIndex === '+') { + nextIndex = currentIndex + 1; + } + else if (nextIndex === '-') { + nextIndex = currentIndex - 1; + } + + this.api.dispatchAction({ + type: 'timelineChange', + currentIndex: nextIndex, + from: this.uid + }); + } + + }); + + function getViewRect(model, api) { + return layout.getLayoutRect( + model.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + }, + model.get('padding') + ); + } + + function makeIcon(timelineModel, objPath, rect, opts) { + var icon = graphic.makePath( + timelineModel.get(objPath).replace(/^path:\/\//, ''), + zrUtil.clone(opts || {}), + new BoundingRect(rect[0], rect[1], rect[2], rect[3]), + 'center' + ); + + return icon; + } + + /** + * Create symbol or update symbol + * opt: basic position and event handlers + */ + function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) { + var color = itemStyleModel.get('color'); + + if (!symbol) { + var symbolType = hostModel.get('symbol'); + symbol = symbolUtil.createSymbol(symbolType, -1, -1, 2, 2, color); + symbol.setStyle('strokeNoScale', true); + group.add(symbol); + callback && callback.onCreate(symbol); + } + else { + symbol.setColor(color); + group.add(symbol); // Group may be new, also need to add. + callback && callback.onUpdate(symbol); + } + + // Style + var itemStyle = itemStyleModel.getItemStyle(['color', 'symbol', 'symbolSize']); + symbol.setStyle(itemStyle); + + // Transform and events. + opt = zrUtil.merge({ + rectHover: true, + z2: 100 + }, opt, true); + + var symbolSize = hostModel.get('symbolSize'); + symbolSize = symbolSize instanceof Array + ? symbolSize.slice() + : [+symbolSize, +symbolSize]; + symbolSize[0] /= 2; + symbolSize[1] /= 2; + opt.scale = symbolSize; + + var symbolOffset = hostModel.get('symbolOffset'); + if (symbolOffset) { + var pos = opt.position = opt.position || [0, 0]; + pos[0] += numberUtil.parsePercent(symbolOffset[0], symbolSize[0]); + pos[1] += numberUtil.parsePercent(symbolOffset[1], symbolSize[1]); + } + + var symbolRotate = hostModel.get('symbolRotate'); + opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + + symbol.attr(opt); + + // FIXME + // (1) When symbol.style.strokeNoScale is true and updateTransform is not performed, + // getBoundingRect will return wrong result. + // (This is supposed to be resolved in zrender, but it is a little difficult to + // leverage performance and auto updateTransform) + // (2) All of ancesters of symbol do not scale, so we can just updateTransform symbol. + symbol.updateTransform(); + + return symbol; + } + + function pointerMoveTo(pointer, dataIndex, axis, timelineModel, noAnimation) { + if (pointer.dragging) { + return; + } + + var pointerModel = timelineModel.getModel('checkpointStyle'); + var toCoord = axis.dataToCoord(timelineModel.getData().get(['value'], dataIndex)); + + if (noAnimation || !pointerModel.get('animation', true)) { + pointer.attr({position: [toCoord, 0]}); + } + else { + pointer.stopAnimation(true); + pointer.animateTo( + {position: [toCoord, 0]}, + pointerModel.get('animationDuration', true), + pointerModel.get('animationEasing', true) + ); + } + } + + + +/***/ }, +/* 410 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Timeline view + */ + + + // var zrUtil = require('zrender/lib/core/util'); + // var graphic = require('../../util/graphic'); + var ComponentView = __webpack_require__(79); + + module.exports = ComponentView.extend({ + + type: 'timeline' + }); + + + +/***/ }, +/* 411 */ +/***/ function(module, exports, __webpack_require__) { + + + + var zrUtil = __webpack_require__(4); + var Axis = __webpack_require__(100); + var axisHelper = __webpack_require__(101); + + /** + * Extend axis 2d + * @constructor module:echarts/coord/cartesian/Axis2D + * @extends {module:echarts/coord/cartesian/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + * @param {string} position + */ + var TimelineAxis = function (dim, scale, coordExtent, axisType) { + + Axis.call(this, dim, scale, coordExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * @private + * @type {number} + */ + this._autoLabelInterval; + + /** + * Axis model + * @param {module:echarts/component/TimelineModel} + */ + this.model = null; + }; + + TimelineAxis.prototype = { + + constructor: TimelineAxis, + + /** + * @public + * @return {number} + */ + getLabelInterval: function () { + var timelineModel = this.model; + var labelModel = timelineModel.getModel('label.normal'); + var labelInterval = labelModel.get('interval'); + + if (labelInterval != null && labelInterval != 'auto') { + return labelInterval; + } + + var labelInterval = this._autoLabelInterval; + + if (!labelInterval) { + labelInterval = this._autoLabelInterval = axisHelper.getAxisLabelInterval( + zrUtil.map(this.scale.getTicks(), this.dataToCoord, this), + axisHelper.getFormattedLabels(this, labelModel.get('formatter')), + labelModel.getModel('textStyle').getFont(), + timelineModel.get('orient') === 'horizontal' + ); + } + + return labelInterval; + }, + + /** + * If label is ignored. + * Automatically used when axis is category and label can not be all shown + * @public + * @param {number} idx + * @return {boolean} + */ + isLabelIgnored: function (idx) { + if (this.type === 'category') { + var labelInterval = this.getLabelInterval(); + return ((typeof labelInterval === 'function') + && !labelInterval(idx, this.scale.getLabel(idx))) + || idx % (labelInterval + 1); + } + } + + }; + + zrUtil.inherits(TimelineAxis, Axis); + + module.exports = TimelineAxis; + + +/***/ }, +/* 412 */ +/***/ function(module, exports, __webpack_require__) { + + + + __webpack_require__(413); + __webpack_require__(414); + + __webpack_require__(415); + __webpack_require__(416); + __webpack_require__(417); + __webpack_require__(418); + __webpack_require__(423); + + +/***/ }, +/* 413 */ +/***/ function(module, exports, __webpack_require__) { + + + + var featureManager = __webpack_require__(357); + var zrUtil = __webpack_require__(4); + + var ToolboxModel = __webpack_require__(1).extendComponentModel({ + + type: 'toolbox', + + layoutMode: { + type: 'box', + ignoreSize: true + }, + + mergeDefaultAndTheme: function (option) { + ToolboxModel.superApply(this, 'mergeDefaultAndTheme', arguments); + + zrUtil.each(this.option.feature, function (featureOpt, featureName) { + var Feature = featureManager.get(featureName); + Feature && zrUtil.merge(featureOpt, Feature.defaultOption); + }); + }, + + defaultOption: { + + show: true, + + z: 6, + + zlevel: 0, + + orient: 'horizontal', + + left: 'right', + + top: 'top', + + // right + // bottom + + backgroundColor: 'transparent', + + borderColor: '#ccc', + + borderWidth: 0, + + padding: 5, + + itemSize: 15, + + itemGap: 8, + + showTitle: true, + + iconStyle: { + normal: { + borderColor: '#666', + color: 'none' + }, + emphasis: { + borderColor: '#3E98C5' + } + } + // textStyle: {}, + + // feature + } + }); + + module.exports = ToolboxModel; + + +/***/ }, +/* 414 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(process) { + + var featureManager = __webpack_require__(357); + var zrUtil = __webpack_require__(4); + var graphic = __webpack_require__(18); + var Model = __webpack_require__(12); + var DataDiffer = __webpack_require__(99); + var listComponentHelper = __webpack_require__(325); + var textContain = __webpack_require__(8); + + module.exports = __webpack_require__(1).extendComponentView({ + + type: 'toolbox', + + render: function (toolboxModel, ecModel, api, payload) { + var group = this.group; + group.removeAll(); + + if (!toolboxModel.get('show')) { + return; + } + + var itemSize = +toolboxModel.get('itemSize'); + var featureOpts = toolboxModel.get('feature') || {}; + var features = this._features || (this._features = {}); + + var featureNames = []; + zrUtil.each(featureOpts, function (opt, name) { + featureNames.push(name); + }); + + (new DataDiffer(this._featureNames || [], featureNames)) + .add(process) + .update(process) + .remove(zrUtil.curry(process, null)) + .execute(); + + // Keep for diff. + this._featureNames = featureNames; + + function process(newIndex, oldIndex) { + var featureName = featureNames[newIndex]; + var oldName = featureNames[oldIndex]; + var featureOpt = featureOpts[featureName]; + var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel); + var feature; + + if (featureName && !oldName) { // Create + if (isUserFeatureName(featureName)) { + feature = { + model: featureModel, + onclick: featureModel.option.onclick, + featureName: featureName + }; + } + else { + var Feature = featureManager.get(featureName); + if (!Feature) { + return; + } + feature = new Feature(featureModel, ecModel, api); + } + features[featureName] = feature; + } + else { + feature = features[oldName]; + // If feature does not exsit. + if (!feature) { + return; + } + feature.model = featureModel; + feature.ecModel = ecModel; + feature.api = api; + } + + if (!featureName && oldName) { + feature.dispose && feature.dispose(ecModel, api); + return; + } + + if (!featureModel.get('show') || feature.unusable) { + feature.remove && feature.remove(ecModel, api); + return; + } + + createIconPaths(featureModel, feature, featureName); + + featureModel.setIconStatus = function (iconName, status) { + var option = this.option; + var iconPaths = this.iconPaths; + option.iconStatus = option.iconStatus || {}; + option.iconStatus[iconName] = status; + // FIXME + iconPaths[iconName] && iconPaths[iconName].trigger(status); + }; + + if (feature.render) { + feature.render(featureModel, ecModel, api, payload); + } + } + + function createIconPaths(featureModel, feature, featureName) { + var iconStyleModel = featureModel.getModel('iconStyle'); + + // If one feature has mutiple icon. they are orginaized as + // { + // icon: { + // foo: '', + // bar: '' + // }, + // title: { + // foo: '', + // bar: '' + // } + // } + var icons = feature.getIcons ? feature.getIcons() : featureModel.get('icon'); + var titles = featureModel.get('title') || {}; + if (typeof icons === 'string') { + var icon = icons; + var title = titles; + icons = {}; + titles = {}; + icons[featureName] = icon; + titles[featureName] = title; + } + var iconPaths = featureModel.iconPaths = {}; + zrUtil.each(icons, function (icon, iconName) { + var normalStyle = iconStyleModel.getModel('normal').getItemStyle(); + var hoverStyle = iconStyleModel.getModel('emphasis').getItemStyle(); + + var style = { + x: -itemSize / 2, + y: -itemSize / 2, + width: itemSize, + height: itemSize + }; + var path = icon.indexOf('image://') === 0 + ? ( + style.image = icon.slice(8), + new graphic.Image({style: style}) + ) + : graphic.makePath( + icon.replace('path://', ''), + { + style: normalStyle, + hoverStyle: hoverStyle, + rectHover: true + }, + style, + 'center' + ); + + graphic.setHoverStyle(path); + + if (toolboxModel.get('showTitle')) { + path.__title = titles[iconName]; + path.on('mouseover', function () { + // Should not reuse above hoverStyle, which might be modified. + var hoverStyle = iconStyleModel.getModel('emphasis').getItemStyle(); + path.setStyle({ + text: titles[iconName], + textPosition: hoverStyle.textPosition || 'bottom', + textFill: hoverStyle.fill || hoverStyle.stroke || '#000', + textAlign: hoverStyle.textAlign || 'center' + }); + }) + .on('mouseout', function () { + path.setStyle({ + textFill: null + }); + }); + } + path.trigger(featureModel.get('iconStatus.' + iconName) || 'normal'); + + group.add(path); + path.on('click', zrUtil.bind( + feature.onclick, feature, ecModel, api, iconName + )); + + iconPaths[iconName] = path; + }); + } + + listComponentHelper.layout(group, toolboxModel, api); + // Render background after group is layout + // FIXME + listComponentHelper.addBackground(group, toolboxModel); + + // Adjust icon title positions to avoid them out of screen + group.eachChild(function (icon) { + var titleText = icon.__title; + var hoverStyle = icon.hoverStyle; + // May be background element + if (hoverStyle && titleText) { + var rect = textContain.getBoundingRect( + titleText, hoverStyle.font + ); + var offsetX = icon.position[0] + group.position[0]; + var offsetY = icon.position[1] + group.position[1] + itemSize; + + var needPutOnTop = false; + if (offsetY + rect.height > api.getHeight()) { + hoverStyle.textPosition = 'top'; + needPutOnTop = true; + } + var topOffset = needPutOnTop ? (-5 - rect.height) : (itemSize + 8); + if (offsetX + rect.width / 2 > api.getWidth()) { + hoverStyle.textPosition = ['100%', topOffset]; + hoverStyle.textAlign = 'right'; + } + else if (offsetX - rect.width / 2 < 0) { + hoverStyle.textPosition = [0, topOffset]; + hoverStyle.textAlign = 'left'; + } + } + }); + }, + + updateView: function (toolboxModel, ecModel, api, payload) { + zrUtil.each(this._features, function (feature) { + feature.updateView && feature.updateView(feature.model, ecModel, api, payload); + }); + }, + + updateLayout: function (toolboxModel, ecModel, api, payload) { + zrUtil.each(this._features, function (feature) { + feature.updateLayout && feature.updateLayout(feature.model, ecModel, api, payload); + }); + }, + + remove: function (ecModel, api) { + zrUtil.each(this._features, function (feature) { + feature.remove && feature.remove(ecModel, api); + }); + this.group.removeAll(); + }, + + dispose: function (ecModel, api) { + zrUtil.each(this._features, function (feature) { + feature.dispose && feature.dispose(ecModel, api); + }); + } + }); + + function isUserFeatureName(featureName) { + return featureName.indexOf('my') === 0; + } + + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(310))) + +/***/ }, +/* 415 */ +/***/ function(module, exports, __webpack_require__) { + + + + var env = __webpack_require__(2); + + function SaveAsImage (model) { + this.model = model; + } + + SaveAsImage.defaultOption = { + show: true, + icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0', + title: '保存为图片', + type: 'png', + // Default use option.backgroundColor + // backgroundColor: '#fff', + name: '', + excludeComponents: ['toolbox'], + pixelRatio: 1, + lang: ['右键另存为图片'] + }; + + SaveAsImage.prototype.unusable = !env.canvasSupported; + + var proto = SaveAsImage.prototype; + + proto.onclick = function (ecModel, api) { + var model = this.model; + var title = model.get('name') || ecModel.get('title.0.text') || 'echarts'; + var $a = document.createElement('a'); + var type = model.get('type', true) || 'png'; + $a.download = title + '.' + type; + $a.target = '_blank'; + var url = api.getConnectedDataURL({ + type: type, + backgroundColor: model.get('backgroundColor', true) + || ecModel.get('backgroundColor') || '#fff', + excludeComponents: model.get('excludeComponents'), + pixelRatio: model.get('pixelRatio') + }); + $a.href = url; + // Chrome and Firefox + if (typeof MouseEvent === 'function' && !env.browser.ie && !env.browser.edge) { + var evt = new MouseEvent('click', { + view: window, + bubbles: true, + cancelable: false + }); + $a.dispatchEvent(evt); + } + // IE + else { + var lang = model.get('lang'); + var html = '' + + '' + + '' + + ''; + var tab = window.open(); + tab.document.write(html); + } + }; + + __webpack_require__(357).register( + 'saveAsImage', SaveAsImage + ); + + module.exports = SaveAsImage; + + +/***/ }, +/* 416 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + + function MagicType(model) { + this.model = model; + } + + MagicType.defaultOption = { + show: true, + type: [], + // Icon group + icon: { + line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4', + bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7', + stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z', // jshint ignore:line + tiled: 'M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z' + }, + title: { + line: '切换为折线图', + bar: '切换为柱状图', + stack: '切换为堆叠', + tiled: '切换为平铺' + }, + option: {}, + seriesIndex: {} + }; + + var proto = MagicType.prototype; + + proto.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon'); + var icons = {}; + zrUtil.each(model.get('type'), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; + }; + + var seriesOptGenreator = { + 'line': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'bar') { + return zrUtil.merge({ + id: seriesId, + type: 'line', + // Preserve data related option + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get('option.line') || {}, true); + } + }, + 'bar': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line') { + return zrUtil.merge({ + id: seriesId, + type: 'bar', + // Preserve data related option + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get('option.bar') || {}, true); + } + }, + 'stack': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line' || seriesType === 'bar') { + return zrUtil.merge({ + id: seriesId, + stack: '__ec_magicType_stack__' + }, model.get('option.stack') || {}, true); + } + }, + 'tiled': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line' || seriesType === 'bar') { + return zrUtil.merge({ + id: seriesId, + stack: '' + }, model.get('option.tiled') || {}, true); + } + } + }; + + var radioTypes = [ + ['line', 'bar'], + ['stack', 'tiled'] + ]; + + proto.onclick = function (ecModel, api, type) { + var model = this.model; + var seriesIndex = model.get('seriesIndex.' + type); + // Not supported magicType + if (!seriesOptGenreator[type]) { + return; + } + var newOption = { + series: [] + }; + var generateNewSeriesTypes = function (seriesModel) { + var seriesType = seriesModel.subType; + var seriesId = seriesModel.id; + var newSeriesOpt = seriesOptGenreator[type]( + seriesType, seriesId, seriesModel, model + ); + if (newSeriesOpt) { + // PENDING If merge original option? + zrUtil.defaults(newSeriesOpt, seriesModel.option); + newOption.series.push(newSeriesOpt); + } + // Modify boundaryGap + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) { + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + if (categoryAxis) { + var axisDim = categoryAxis.dim; + var axisType = axisDim + 'Axis'; + var axisModel = ecModel.queryComponents({ + mainType: axisType, + index: seriesModel.get(name + 'Index'), + id: seriesModel.get(name + 'Id') + })[0]; + var axisIndex = axisModel.componentIndex; + + newOption[axisType] = newOption[axisType] || []; + for (var i = 0; i <= axisIndex; i++) { + newOption[axisType][axisIndex] = newOption[axisType][axisIndex] || {}; + } + newOption[axisType][axisIndex].boundaryGap = type === 'bar' ? true : false; + } + } + }; + + zrUtil.each(radioTypes, function (radio) { + if (zrUtil.indexOf(radio, type) >= 0) { + zrUtil.each(radio, function (item) { + model.setIconStatus(item, 'normal'); + }); + } + }); + + model.setIconStatus(type, 'emphasis'); + + ecModel.eachComponent( + { + mainType: 'series', + query: seriesIndex == null ? null : { + seriesIndex: seriesIndex + } + }, generateNewSeriesTypes + ); + api.dispatchAction({ + type: 'changeMagicType', + currentType: type, + newOption: newOption + }); + }; + + var echarts = __webpack_require__(1); + echarts.registerAction({ + type: 'changeMagicType', + event: 'magicTypeChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + ecModel.mergeOption(payload.newOption); + }); + + __webpack_require__(357).register('magicType', MagicType); + + module.exports = MagicType; + + +/***/ }, +/* 417 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @module echarts/component/toolbox/feature/DataView + */ + + + + var zrUtil = __webpack_require__(4); + var eventTool = __webpack_require__(88); + + + var BLOCK_SPLITER = new Array(60).join('-'); + var ITEM_SPLITER = '\t'; + /** + * Group series into two types + * 1. on category axis, like line, bar + * 2. others, like scatter, pie + * @param {module:echarts/model/Global} ecModel + * @return {Object} + * @inner + */ + function groupSeries(ecModel) { + var seriesGroupByCategoryAxis = {}; + var otherSeries = []; + var meta = []; + ecModel.eachRawSeries(function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && (coordSys.type === 'cartesian2d' || coordSys.type === 'polar')) { + var baseAxis = coordSys.getBaseAxis(); + if (baseAxis.type === 'category') { + var key = baseAxis.dim + '_' + baseAxis.index; + if (!seriesGroupByCategoryAxis[key]) { + seriesGroupByCategoryAxis[key] = { + categoryAxis: baseAxis, + valueAxis: coordSys.getOtherAxis(baseAxis), + series: [] + }; + meta.push({ + axisDim: baseAxis.dim, + axisIndex: baseAxis.index + }); + } + seriesGroupByCategoryAxis[key].series.push(seriesModel); + } + else { + otherSeries.push(seriesModel); + } + } + else { + otherSeries.push(seriesModel); + } + }); + + return { + seriesGroupByCategoryAxis: seriesGroupByCategoryAxis, + other: otherSeries, + meta: meta + }; + } + + /** + * Assemble content of series on cateogory axis + * @param {Array.} series + * @return {string} + * @inner + */ + function assembleSeriesWithCategoryAxis(series) { + var tables = []; + zrUtil.each(series, function (group, key) { + var categoryAxis = group.categoryAxis; + var valueAxis = group.valueAxis; + var valueAxisDim = valueAxis.dim; + + var headers = [' '].concat(zrUtil.map(group.series, function (series) { + return series.name; + })); + var columns = [categoryAxis.model.getCategories()]; + zrUtil.each(group.series, function (series) { + columns.push(series.getRawData().mapArray(valueAxisDim, function (val) { + return val; + })); + }); + // Assemble table content + var lines = [headers.join(ITEM_SPLITER)]; + for (var i = 0; i < columns[0].length; i++) { + var items = []; + for (var j = 0; j < columns.length; j++) { + items.push(columns[j][i]); + } + lines.push(items.join(ITEM_SPLITER)); + } + tables.push(lines.join('\n')); + }); + return tables.join('\n\n' + BLOCK_SPLITER + '\n\n'); + } + + /** + * Assemble content of other series + * @param {Array.} series + * @return {string} + * @inner + */ + function assembleOtherSeries(series) { + return zrUtil.map(series, function (series) { + var data = series.getRawData(); + var lines = [series.name]; + var vals = []; + data.each(data.dimensions, function () { + var argLen = arguments.length; + var dataIndex = arguments[argLen - 1]; + var name = data.getName(dataIndex); + for (var i = 0; i < argLen - 1; i++) { + vals[i] = arguments[i]; + } + lines.push((name ? (name + ITEM_SPLITER) : '') + vals.join(ITEM_SPLITER)); + }); + return lines.join('\n'); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'); + } + + /** + * @param {module:echarts/model/Global} + * @return {string} + * @inner + */ + function getContentFromModel(ecModel) { + + var result = groupSeries(ecModel); + + return { + value: zrUtil.filter([ + assembleSeriesWithCategoryAxis(result.seriesGroupByCategoryAxis), + assembleOtherSeries(result.other) + ], function (str) { + return str.replace(/[\n\t\s]/g, ''); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'), + + meta: result.meta + }; + } + + + function trim(str) { + return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + } + /** + * If a block is tsv format + */ + function isTSVFormat(block) { + // Simple method to find out if a block is tsv format + var firstLine = block.slice(0, block.indexOf('\n')); + if (firstLine.indexOf(ITEM_SPLITER) >= 0) { + return true; + } + } + + var itemSplitRegex = new RegExp('[' + ITEM_SPLITER + ']+', 'g'); + /** + * @param {string} tsv + * @return {Array.} + */ + function parseTSVContents(tsv) { + var tsvLines = tsv.split(/\n+/g); + var headers = trim(tsvLines.shift()).split(itemSplitRegex); + + var categories = []; + var series = zrUtil.map(headers, function (header) { + return { + name: header, + data: [] + }; + }); + for (var i = 0; i < tsvLines.length; i++) { + var items = trim(tsvLines[i]).split(itemSplitRegex); + categories.push(items.shift()); + for (var j = 0; j < items.length; j++) { + series[j] && (series[j].data[i] = items[j]); + } + } + return { + series: series, + categories: categories + }; + } + + /** + * @param {string} str + * @return {Array.} + * @inner + */ + function parseListContents(str) { + var lines = str.split(/\n+/g); + var seriesName = trim(lines.shift()); + + var data = []; + for (var i = 0; i < lines.length; i++) { + var items = trim(lines[i]).split(itemSplitRegex); + var name = ''; + var value; + var hasName = false; + if (isNaN(items[0])) { // First item is name + hasName = true; + name = items[0]; + items = items.slice(1); + data[i] = { + name: name, + value: [] + }; + value = data[i].value; + } + else { + value = data[i] = []; + } + for (var j = 0; j < items.length; j++) { + value.push(+items[j]); + } + if (value.length === 1) { + hasName ? (data[i].value = value[0]) : (data[i] = value[0]); + } + } + + return { + name: seriesName, + data: data + }; + } + + /** + * @param {string} str + * @param {Array.} blockMetaList + * @return {Object} + * @inner + */ + function parseContents(str, blockMetaList) { + var blocks = str.split(new RegExp('\n*' + BLOCK_SPLITER + '\n*', 'g')); + var newOption = { + series: [] + }; + zrUtil.each(blocks, function (block, idx) { + if (isTSVFormat(block)) { + var result = parseTSVContents(block); + var blockMeta = blockMetaList[idx]; + var axisKey = blockMeta.axisDim + 'Axis'; + + if (blockMeta) { + newOption[axisKey] = newOption[axisKey] || []; + newOption[axisKey][blockMeta.axisIndex] = { + data: result.categories + }; + newOption.series = newOption.series.concat(result.series); + } + } + else { + var result = parseListContents(block); + newOption.series.push(result); + } + }); + return newOption; + } + + /** + * @alias {module:echarts/component/toolbox/feature/DataView} + * @constructor + * @param {module:echarts/model/Model} model + */ + function DataView(model) { + + this._dom = null; + + this.model = model; + } + + DataView.defaultOption = { + show: true, + readOnly: false, + optionToContent: null, + contentToOption: null, + + icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28', + title: '数据视图', + lang: ['数据视图', '关闭', '刷新'], + backgroundColor: '#fff', + textColor: '#000', + textareaColor: '#fff', + textareaBorderColor: '#333', + buttonColor: '#c23531', + buttonTextColor: '#fff' + }; + + DataView.prototype.onclick = function (ecModel, api) { + var container = api.getDom(); + var model = this.model; + if (this._dom) { + container.removeChild(this._dom); + } + var root = document.createElement('div'); + root.style.cssText = 'position:absolute;left:5px;top:5px;bottom:5px;right:5px;'; + root.style.backgroundColor = model.get('backgroundColor') || '#fff'; + + // Create elements + var header = document.createElement('h4'); + var lang = model.get('lang') || []; + header.innerHTML = lang[0] || model.get('title'); + header.style.cssText = 'margin: 10px 20px;'; + header.style.color = model.get('textColor'); + + var viewMain = document.createElement('div'); + var textarea = document.createElement('textarea'); + viewMain.style.cssText = 'display:block;width:100%;overflow:auto;'; + + var optionToContent = model.get('optionToContent'); + var contentToOption = model.get('contentToOption'); + var result = getContentFromModel(ecModel); + if (typeof optionToContent === 'function') { + var htmlOrDom = optionToContent(api.getOption()); + if (typeof htmlOrDom === 'string') { + viewMain.innerHTML = htmlOrDom; + } + else if (zrUtil.isDom(htmlOrDom)) { + viewMain.appendChild(htmlOrDom); + } + } + else { + // Use default textarea + viewMain.appendChild(textarea); + textarea.readOnly = model.get('readOnly'); + textarea.style.cssText = 'width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;'; + textarea.style.color = model.get('textColor'); + textarea.style.borderColor = model.get('textareaBorderColor'); + textarea.style.backgroundColor = model.get('textareaColor'); + textarea.value = result.value; + } + + var blockMetaList = result.meta; + + var buttonContainer = document.createElement('div'); + buttonContainer.style.cssText = 'position:absolute;bottom:0;left:0;right:0;'; + + var buttonStyle = 'float:right;margin-right:20px;border:none;' + + 'cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px'; + var closeButton = document.createElement('div'); + var refreshButton = document.createElement('div'); + + buttonStyle += ';background-color:' + model.get('buttonColor'); + buttonStyle += ';color:' + model.get('buttonTextColor'); + + var self = this; + + function close() { + container.removeChild(root); + self._dom = null; + } + eventTool.addEventListener(closeButton, 'click', close); + + eventTool.addEventListener(refreshButton, 'click', function () { + var newOption; + try { + if (typeof contentToOption === 'function') { + newOption = contentToOption(viewMain, api.getOption()); + } + else { + newOption = parseContents(textarea.value, blockMetaList); + } + } + catch (e) { + close(); + throw new Error('Data view format error ' + e); + } + if (newOption) { + api.dispatchAction({ + type: 'changeDataView', + newOption: newOption + }); + } + + close(); + }); + + closeButton.innerHTML = lang[1]; + refreshButton.innerHTML = lang[2]; + refreshButton.style.cssText = buttonStyle; + closeButton.style.cssText = buttonStyle; + + !model.get('readOnly') && buttonContainer.appendChild(refreshButton); + buttonContainer.appendChild(closeButton); + + // http://stackoverflow.com/questions/6637341/use-tab-to-indent-in-textarea + eventTool.addEventListener(textarea, 'keydown', function (e) { + if ((e.keyCode || e.which) === 9) { + // get caret position/selection + var val = this.value; + var start = this.selectionStart; + var end = this.selectionEnd; + + // set textarea value to: text before caret + tab + text after caret + this.value = val.substring(0, start) + ITEM_SPLITER + val.substring(end); + + // put caret at right position again + this.selectionStart = this.selectionEnd = start + 1; + + // prevent the focus lose + eventTool.stop(e); + } + }); + + root.appendChild(header); + root.appendChild(viewMain); + root.appendChild(buttonContainer); + + viewMain.style.height = (container.clientHeight - 80) + 'px'; + + container.appendChild(root); + this._dom = root; + }; + + DataView.prototype.remove = function (ecModel, api) { + this._dom && api.getDom().removeChild(this._dom); + }; + + DataView.prototype.dispose = function (ecModel, api) { + this.remove(ecModel, api); + }; + + /** + * @inner + */ + function tryMergeDataOption(newData, originalData) { + return zrUtil.map(newData, function (newVal, idx) { + var original = originalData && originalData[idx]; + if (zrUtil.isObject(original) && !zrUtil.isArray(original)) { + if (zrUtil.isObject(newVal) && !zrUtil.isArray(newVal)) { + newVal = newVal.value; + } + // Original data has option + return zrUtil.defaults({ + value: newVal + }, original); + } + else { + return newVal; + } + }); + } + + __webpack_require__(357).register('dataView', DataView); + + __webpack_require__(1).registerAction({ + type: 'changeDataView', + event: 'dataViewChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + var newSeriesOptList = []; + zrUtil.each(payload.newOption.series, function (seriesOpt) { + var seriesModel = ecModel.getSeriesByName(seriesOpt.name)[0]; + if (!seriesModel) { + // New created series + // Geuss the series type + newSeriesOptList.push(zrUtil.extend({ + // Default is scatter + type: 'scatter' + }, seriesOpt)); + } + else { + var originalData = seriesModel.get('data'); + newSeriesOptList.push({ + name: seriesOpt.name, + data: tryMergeDataOption(seriesOpt.data, originalData) + }); + } + }); + + ecModel.mergeOption(zrUtil.defaults({ + series: newSeriesOptList + }, payload.newOption)); + }); + + module.exports = DataView; + + +/***/ }, +/* 418 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var zrUtil = __webpack_require__(4); + var BrushController = __webpack_require__(245); + var BrushTargetManager = __webpack_require__(352); + var history = __webpack_require__(419); + var sliderMove = __webpack_require__(239); + + var each = zrUtil.each; + + // Use dataZoomSelect + __webpack_require__(420); + + // Spectial component id start with \0ec\0, see echarts/model/Global.js~hasInnerId + var DATA_ZOOM_ID_BASE = '\0_ec_\0toolbox-dataZoom_'; + + function DataZoom(model, ecModel, api) { + + /** + * @private + * @type {module:echarts/component/helper/BrushController} + */ + (this._brushController = new BrushController(api.getZr())) + .on('brush', zrUtil.bind(this._onBrush, this)) + .mount(); + + /** + * @private + * @type {boolean} + */ + this._isZoomActive; + } + + DataZoom.defaultOption = { + show: true, + // Icon group + icon: { + zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1', + back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26' + }, + title: { + zoom: '区域缩放', + back: '区域缩放还原' + } + }; + + var proto = DataZoom.prototype; + + proto.render = function (featureModel, ecModel, api, payload) { + this.model = featureModel; + this.ecModel = ecModel; + this.api = api; + + updateZoomBtnStatus(featureModel, ecModel, this, payload, api); + updateBackBtnStatus(featureModel, ecModel); + }; + + proto.onclick = function (ecModel, api, type) { + handlers[type].call(this); + }; + + proto.remove = function (ecModel, api) { + this._brushController.unmount(); + }; + + proto.dispose = function (ecModel, api) { + this._brushController.dispose(); + }; + + /** + * @private + */ + var handlers = { + + zoom: function () { + var nextActive = !this._isZoomActive; + + this.api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'dataZoomSelect', + dataZoomSelectActive: nextActive + }); + }, + + back: function () { + this._dispatchZoomAction(history.pop(this.ecModel)); + } + }; + + /** + * @private + */ + proto._onBrush = function (areas, opt) { + if (!opt.isEnd || !areas.length) { + return; + } + var snapshot = {}; + var ecModel = this.ecModel; + + this._brushController.updateCovers([]); // remove cover + + var brushTargetManager = new BrushTargetManager( + retrieveAxisSetting(this.model.option), ecModel, {include: ['grid']} + ); + brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + if (coordSys.type !== 'cartesian2d') { + return; + } + + var brushType = area.brushType; + if (brushType === 'rect') { + setBatch('x', coordSys, coordRange[0]); + setBatch('y', coordSys, coordRange[1]); + } + else { + setBatch(({lineX: 'x', lineY: 'y'})[brushType], coordSys, coordRange); + } + }); + + history.push(ecModel, snapshot); + + this._dispatchZoomAction(snapshot); + + function setBatch(dimName, coordSys, minMax) { + var axis = coordSys.getAxis(dimName); + var axisModel = axis.model; + var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); + + // Restrict range. + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan(); + if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { + minMax = sliderMove( + 0, minMax.slice(), axis.scale.getExtent(), 0, + minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan + ); + } + + dataZoomModel && (snapshot[dataZoomModel.id] = { + dataZoomId: dataZoomModel.id, + startValue: minMax[0], + endValue: minMax[1] + }); + } + + function findDataZoom(dimName, axisModel, ecModel) { + var found; + ecModel.eachComponent({mainType: 'dataZoom', subType: 'select'}, function (dzModel) { + var has = dzModel.getAxisModel(dimName, axisModel.componentIndex); + has && (found = dzModel); + }); + return found; + } + }; + + /** + * @private + */ + proto._dispatchZoomAction = function (snapshot) { + var batch = []; + + // Convert from hash map to array. + each(snapshot, function (batchItem, dataZoomId) { + batch.push(zrUtil.clone(batchItem)); + }); + + batch.length && this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + batch: batch + }); + }; + + function retrieveAxisSetting(option) { + var setting = {}; + // Compatible with previous setting: null => all axis, false => no axis. + zrUtil.each(['xAxisIndex', 'yAxisIndex'], function (name) { + setting[name] = option[name]; + setting[name] == null && (setting[name] = 'all'); + (setting[name] === false || setting[name] === 'none') && (setting[name] = []); + }); + return setting; + } + + function updateBackBtnStatus(featureModel, ecModel) { + featureModel.setIconStatus( + 'back', + history.count(ecModel) > 1 ? 'emphasis' : 'normal' + ); + } + + function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) { + var zoomActive = view._isZoomActive; + + if (payload && payload.type === 'takeGlobalCursor') { + zoomActive = payload.key === 'dataZoomSelect' + ? payload.dataZoomSelectActive : false; + } + + view._isZoomActive = zoomActive; + + featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal'); + + var brushTargetManager = new BrushTargetManager( + retrieveAxisSetting(featureModel.option), ecModel, {include: ['grid']} + ); + + view._brushController + .setPanels(brushTargetManager.makePanelOpts(api, function (targetInfo) { + return (targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared) + ? 'lineX' + : (!targetInfo.xAxisDeclared && targetInfo.yAxisDeclared) + ? 'lineY' + : 'rect'; + })) + .enableBrush( + zoomActive + ? { + brushType: 'auto', + brushStyle: { + // FIXME user customized? + lineWidth: 0, + fill: 'rgba(0,0,0,0.2)' + } + } + : false + ); + } + + + __webpack_require__(357).register('dataZoom', DataZoom); + + + // Create special dataZoom option for select + __webpack_require__(1).registerPreprocessor(function (option) { + if (!option) { + return; + } + + var dataZoomOpts = option.dataZoom || (option.dataZoom = []); + if (!zrUtil.isArray(dataZoomOpts)) { + option.dataZoom = dataZoomOpts = [dataZoomOpts]; + } + + var toolboxOpt = option.toolbox; + if (toolboxOpt) { + // Assume there is only one toolbox + if (zrUtil.isArray(toolboxOpt)) { + toolboxOpt = toolboxOpt[0]; + } + + if (toolboxOpt && toolboxOpt.feature) { + var dataZoomOpt = toolboxOpt.feature.dataZoom; + addForAxis('xAxis', dataZoomOpt); + addForAxis('yAxis', dataZoomOpt); + } + } + + function addForAxis(axisName, dataZoomOpt) { + if (!dataZoomOpt) { + return; + } + + // Try not to modify model, because it is not merged yet. + var axisIndicesName = axisName + 'Index'; + var givenAxisIndices = dataZoomOpt[axisIndicesName]; + if (givenAxisIndices != null + && givenAxisIndices != 'all' + && !zrUtil.isArray(givenAxisIndices) + ) { + givenAxisIndices = (givenAxisIndices === false || givenAxisIndices === 'none') ? [] : [givenAxisIndices]; + } + + forEachComponent(axisName, function (axisOpt, axisIndex) { + if (givenAxisIndices != null + && givenAxisIndices != 'all' + && zrUtil.indexOf(givenAxisIndices, axisIndex) === -1 + ) { + return; + } + var newOpt = { + type: 'select', + $fromToolbox: true, + // Id for merge mapping. + id: DATA_ZOOM_ID_BASE + axisName + axisIndex + }; + // FIXME + // Only support one axis now. + newOpt[axisIndicesName] = axisIndex; + dataZoomOpts.push(newOpt); + }); + } + + function forEachComponent(mainType, cb) { + var opts = option[mainType]; + if (!zrUtil.isArray(opts)) { + opts = opts ? [opts] : []; + } + each(opts, cb); + } + }); + + module.exports = DataZoom; + + +/***/ }, +/* 419 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file History manager. + */ + + + var zrUtil = __webpack_require__(4); + var each = zrUtil.each; + + var ATTR = '\0_ec_hist_store'; + + var history = { + + /** + * @public + * @param {module:echarts/model/Global} ecModel + * @param {Object} newSnapshot {dataZoomId, batch: [payloadInfo, ...]} + */ + push: function (ecModel, newSnapshot) { + var store = giveStore(ecModel); + + // If previous dataZoom can not be found, + // complete an range with current range. + each(newSnapshot, function (batchItem, dataZoomId) { + var i = store.length - 1; + for (; i >= 0; i--) { + var snapshot = store[i]; + if (snapshot[dataZoomId]) { + break; + } + } + if (i < 0) { + // No origin range set, create one by current range. + var dataZoomModel = ecModel.queryComponents( + {mainType: 'dataZoom', subType: 'select', id: dataZoomId} + )[0]; + if (dataZoomModel) { + var percentRange = dataZoomModel.getPercentRange(); + store[0][dataZoomId] = { + dataZoomId: dataZoomId, + start: percentRange[0], + end: percentRange[1] + }; + } + } + }); + + store.push(newSnapshot); + }, + + /** + * @public + * @param {module:echarts/model/Global} ecModel + * @return {Object} snapshot + */ + pop: function (ecModel) { + var store = giveStore(ecModel); + var head = store[store.length - 1]; + store.length > 1 && store.pop(); + + // Find top for all dataZoom. + var snapshot = {}; + each(head, function (batchItem, dataZoomId) { + for (var i = store.length - 1; i >= 0; i--) { + var batchItem = store[i][dataZoomId]; + if (batchItem) { + snapshot[dataZoomId] = batchItem; + break; + } + } + }); + + return snapshot; + }, + + /** + * @public + */ + clear: function (ecModel) { + ecModel[ATTR] = null; + }, + + /** + * @public + * @param {module:echarts/model/Global} ecModel + * @return {number} records. always >= 1. + */ + count: function (ecModel) { + return giveStore(ecModel).length; + } + + }; + + /** + * [{key: dataZoomId, value: {dataZoomId, range}}, ...] + * History length of each dataZoom may be different. + * this._history[0] is used to store origin range. + * @type {Array.} + */ + function giveStore(ecModel) { + var store = ecModel[ATTR]; + if (!store) { + store = ecModel[ATTR] = [{}]; + } + return store; + } + + module.exports = history; + + + +/***/ }, +/* 420 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * DataZoom component entry + */ + + + __webpack_require__(364); + + __webpack_require__(365); + __webpack_require__(368); + + __webpack_require__(421); + __webpack_require__(422); + + __webpack_require__(374); + __webpack_require__(375); + + + +/***/ }, +/* 421 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @file Data zoom model + */ + + + var DataZoomModel = __webpack_require__(365); + + module.exports = DataZoomModel.extend({ + + type: 'dataZoom.select' + + }); + + + +/***/ }, +/* 422 */ +/***/ function(module, exports, __webpack_require__) { + + + + module.exports = __webpack_require__(368).extend({ + + type: 'dataZoom.select' + + }); + + + +/***/ }, +/* 423 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var history = __webpack_require__(419); + + function Restore(model) { + this.model = model; + } + + Restore.defaultOption = { + show: true, + icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5', + title: '还原' + }; + + var proto = Restore.prototype; + + proto.onclick = function (ecModel, api, type) { + history.clear(ecModel); + + api.dispatchAction({ + type: 'restore', + from: this.uid + }); + }; + + + __webpack_require__(357).register('restore', Restore); + + + __webpack_require__(1).registerAction( + {type: 'restore', event: 'restore', update: 'prepareAndUpdate'}, + function (payload, ecModel) { + ecModel.resetOption('recreate'); + } + ); + + module.exports = Restore; + + +/***/ }, +/* 424 */ +/***/ function(module, exports, __webpack_require__) { + + + __webpack_require__(425); + __webpack_require__(82).registerPainter('vml', __webpack_require__(427)); + + +/***/ }, +/* 425 */ +/***/ function(module, exports, __webpack_require__) { + + // http://www.w3.org/TR/NOTE-VML + // TODO Use proxy like svg instead of overwrite brush methods + + + if (!__webpack_require__(2).canvasSupported) { + var vec2 = __webpack_require__(10); + var BoundingRect = __webpack_require__(9); + var CMD = __webpack_require__(36).CMD; + var colorTool = __webpack_require__(31); + var textContain = __webpack_require__(8); + var RectText = __webpack_require__(35); + var Displayable = __webpack_require__(21); + var ZImage = __webpack_require__(49); + var Text = __webpack_require__(50); + var Path = __webpack_require__(20); + var PathProxy = __webpack_require__(36); + + var Gradient = __webpack_require__(66); + + var vmlCore = __webpack_require__(426); + + var round = Math.round; + var sqrt = Math.sqrt; + var abs = Math.abs; + var cos = Math.cos; + var sin = Math.sin; + var mathMax = Math.max; + + var applyTransform = vec2.applyTransform; + + var comma = ','; + var imageTransformPrefix = 'progid:DXImageTransform.Microsoft'; + + var Z = 21600; + var Z2 = Z / 2; + + var ZLEVEL_BASE = 100000; + var Z_BASE = 1000; + + var initRootElStyle = function (el) { + el.style.cssText = 'position:absolute;left:0;top:0;width:1px;height:1px;'; + el.coordsize = Z + ',' + Z; + el.coordorigin = '0,0'; + }; + + var encodeHtmlAttribute = function (s) { + return String(s).replace(/&/g, '&').replace(/"/g, '"'); + }; + + var rgb2Str = function (r, g, b) { + return 'rgb(' + [r, g, b].join(',') + ')'; + }; + + var append = function (parent, child) { + if (child && parent && child.parentNode !== parent) { + parent.appendChild(child); + } + }; + + var remove = function (parent, child) { + if (child && parent && child.parentNode === parent) { + parent.removeChild(child); + } + }; + + var getZIndex = function (zlevel, z, z2) { + // z 的取值范围为 [0, 1000] + return (parseFloat(zlevel) || 0) * ZLEVEL_BASE + (parseFloat(z) || 0) * Z_BASE + z2; + }; + + var parsePercent = function (value, maxValue) { + if (typeof value === 'string') { + if (value.lastIndexOf('%') >= 0) { + return parseFloat(value) / 100 * maxValue; + } + return parseFloat(value); + } + return value; + }; + + /*************************************************** + * PATH + **************************************************/ + + var setColorAndOpacity = function (el, color, opacity) { + var colorArr = colorTool.parse(color); + opacity = +opacity; + if (isNaN(opacity)) { + opacity = 1; + } + if (colorArr) { + el.color = rgb2Str(colorArr[0], colorArr[1], colorArr[2]); + el.opacity = opacity * colorArr[3]; + } + }; + + var getColorAndAlpha = function (color) { + var colorArr = colorTool.parse(color); + return [ + rgb2Str(colorArr[0], colorArr[1], colorArr[2]), + colorArr[3] + ]; + }; + + var updateFillNode = function (el, style, zrEl) { + // TODO pattern + var fill = style.fill; + if (fill != null) { + // Modified from excanvas + if (fill instanceof Gradient) { + var gradientType; + var angle = 0; + var focus = [0, 0]; + // additional offset + var shift = 0; + // scale factor for offset + var expansion = 1; + var rect = zrEl.getBoundingRect(); + var rectWidth = rect.width; + var rectHeight = rect.height; + if (fill.type === 'linear') { + gradientType = 'gradient'; + var transform = zrEl.transform; + var p0 = [fill.x * rectWidth, fill.y * rectHeight]; + var p1 = [fill.x2 * rectWidth, fill.y2 * rectHeight]; + if (transform) { + applyTransform(p0, p0, transform); + applyTransform(p1, p1, transform); + } + var dx = p1[0] - p0[0]; + var dy = p1[1] - p0[1]; + angle = Math.atan2(dx, dy) * 180 / Math.PI; + // The angle should be a non-negative number. + if (angle < 0) { + angle += 360; + } + + // Very small angles produce an unexpected result because they are + // converted to a scientific notation string. + if (angle < 1e-6) { + angle = 0; + } + } + else { + gradientType = 'gradientradial'; + var p0 = [fill.x * rectWidth, fill.y * rectHeight]; + var transform = zrEl.transform; + var scale = zrEl.scale; + var width = rectWidth; + var height = rectHeight; + focus = [ + // Percent in bounding rect + (p0[0] - rect.x) / width, + (p0[1] - rect.y) / height + ]; + if (transform) { + applyTransform(p0, p0, transform); + } + + width /= scale[0] * Z; + height /= scale[1] * Z; + var dimension = mathMax(width, height); + shift = 2 * 0 / dimension; + expansion = 2 * fill.r / dimension - shift; + } + + // We need to sort the color stops in ascending order by offset, + // otherwise IE won't interpret it correctly. + var stops = fill.colorStops.slice(); + stops.sort(function(cs1, cs2) { + return cs1.offset - cs2.offset; + }); + + var length = stops.length; + // Color and alpha list of first and last stop + var colorAndAlphaList = []; + var colors = []; + for (var i = 0; i < length; i++) { + var stop = stops[i]; + var colorAndAlpha = getColorAndAlpha(stop.color); + colors.push(stop.offset * expansion + shift + ' ' + colorAndAlpha[0]); + if (i === 0 || i === length - 1) { + colorAndAlphaList.push(colorAndAlpha); + } + } + + if (length >= 2) { + var color1 = colorAndAlphaList[0][0]; + var color2 = colorAndAlphaList[1][0]; + var opacity1 = colorAndAlphaList[0][1] * style.opacity; + var opacity2 = colorAndAlphaList[1][1] * style.opacity; + + el.type = gradientType; + el.method = 'none'; + el.focus = '100%'; + el.angle = angle; + el.color = color1; + el.color2 = color2; + el.colors = colors.join(','); + // When colors attribute is used, the meanings of opacity and o:opacity2 + // are reversed. + el.opacity = opacity2; + // FIXME g_o_:opacity ? + el.opacity2 = opacity1; + } + if (gradientType === 'radial') { + el.focusposition = focus.join(','); + } + } + else { + // FIXME Change from Gradient fill to color fill + setColorAndOpacity(el, fill, style.opacity); + } + } + }; + + var updateStrokeNode = function (el, style) { + // if (style.lineJoin != null) { + // el.joinstyle = style.lineJoin; + // } + // if (style.miterLimit != null) { + // el.miterlimit = style.miterLimit * Z; + // } + // if (style.lineCap != null) { + // el.endcap = style.lineCap; + // } + if (style.lineDash != null) { + el.dashstyle = style.lineDash.join(' '); + } + if (style.stroke != null && !(style.stroke instanceof Gradient)) { + setColorAndOpacity(el, style.stroke, style.opacity); + } + }; + + var updateFillAndStroke = function (vmlEl, type, style, zrEl) { + var isFill = type == 'fill'; + var el = vmlEl.getElementsByTagName(type)[0]; + // Stroke must have lineWidth + if (style[type] != null && style[type] !== 'none' && (isFill || (!isFill && style.lineWidth))) { + vmlEl[isFill ? 'filled' : 'stroked'] = 'true'; + // FIXME Remove before updating, or set `colors` will throw error + if (style[type] instanceof Gradient) { + remove(vmlEl, el); + } + if (!el) { + el = vmlCore.createNode(type); + } + + isFill ? updateFillNode(el, style, zrEl) : updateStrokeNode(el, style); + append(vmlEl, el); + } + else { + vmlEl[isFill ? 'filled' : 'stroked'] = 'false'; + remove(vmlEl, el); + } + }; + + var points = [[], [], []]; + var pathDataToString = function (data, m) { + var M = CMD.M; + var C = CMD.C; + var L = CMD.L; + var A = CMD.A; + var Q = CMD.Q; + + var str = []; + var nPoint; + var cmdStr; + var cmd; + var i; + var xi; + var yi; + for (i = 0; i < data.length;) { + cmd = data[i++]; + cmdStr = ''; + nPoint = 0; + switch (cmd) { + case M: + cmdStr = ' m '; + nPoint = 1; + xi = data[i++]; + yi = data[i++]; + points[0][0] = xi; + points[0][1] = yi; + break; + case L: + cmdStr = ' l '; + nPoint = 1; + xi = data[i++]; + yi = data[i++]; + points[0][0] = xi; + points[0][1] = yi; + break; + case Q: + case C: + cmdStr = ' c '; + nPoint = 3; + var x1 = data[i++]; + var y1 = data[i++]; + var x2 = data[i++]; + var y2 = data[i++]; + var x3; + var y3; + if (cmd === Q) { + // Convert quadratic to cubic using degree elevation + x3 = x2; + y3 = y2; + x2 = (x2 + 2 * x1) / 3; + y2 = (y2 + 2 * y1) / 3; + x1 = (xi + 2 * x1) / 3; + y1 = (yi + 2 * y1) / 3; + } + else { + x3 = data[i++]; + y3 = data[i++]; + } + points[0][0] = x1; + points[0][1] = y1; + points[1][0] = x2; + points[1][1] = y2; + points[2][0] = x3; + points[2][1] = y3; + + xi = x3; + yi = y3; + break; + case A: + var x = 0; + var y = 0; + var sx = 1; + var sy = 1; + var angle = 0; + if (m) { + // Extract SRT from matrix + x = m[4]; + y = m[5]; + sx = sqrt(m[0] * m[0] + m[1] * m[1]); + sy = sqrt(m[2] * m[2] + m[3] * m[3]); + angle = Math.atan2(-m[1] / sy, m[0] / sx); + } + + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++] + angle; + var endAngle = data[i++] + startAngle + angle; + // FIXME + // var psi = data[i++]; + i++; + var clockwise = data[i++]; + + var x0 = cx + cos(startAngle) * rx; + var y0 = cy + sin(startAngle) * ry; + + var x1 = cx + cos(endAngle) * rx; + var y1 = cy + sin(endAngle) * ry; + + var type = clockwise ? ' wa ' : ' at '; + if (Math.abs(x0 - x1) < 1e-4) { + // IE won't render arches drawn counter clockwise if x0 == x1. + if (Math.abs(endAngle - startAngle) > 1e-2) { + // Offset x0 by 1/80 of a pixel. Use something + // that can be represented in binary + if (clockwise) { + x0 += 270 / Z; + } + } + else { + // Avoid case draw full circle + if (Math.abs(y0 - cy) < 1e-4) { + if ((clockwise && x0 < cx) || (!clockwise && x0 > cx)) { + y1 -= 270 / Z; + } + else { + y1 += 270 / Z; + } + } + else if ((clockwise && y0 < cy) || (!clockwise && y0 > cy)) { + x1 += 270 / Z; + } + else { + x1 -= 270 / Z; + } + } + } + str.push( + type, + round(((cx - rx) * sx + x) * Z - Z2), comma, + round(((cy - ry) * sy + y) * Z - Z2), comma, + round(((cx + rx) * sx + x) * Z - Z2), comma, + round(((cy + ry) * sy + y) * Z - Z2), comma, + round((x0 * sx + x) * Z - Z2), comma, + round((y0 * sy + y) * Z - Z2), comma, + round((x1 * sx + x) * Z - Z2), comma, + round((y1 * sy + y) * Z - Z2) + ); + + xi = x1; + yi = y1; + break; + case CMD.R: + var p0 = points[0]; + var p1 = points[1]; + // x0, y0 + p0[0] = data[i++]; + p0[1] = data[i++]; + // x1, y1 + p1[0] = p0[0] + data[i++]; + p1[1] = p0[1] + data[i++]; + + if (m) { + applyTransform(p0, p0, m); + applyTransform(p1, p1, m); + } + + p0[0] = round(p0[0] * Z - Z2); + p1[0] = round(p1[0] * Z - Z2); + p0[1] = round(p0[1] * Z - Z2); + p1[1] = round(p1[1] * Z - Z2); + str.push( + // x0, y0 + ' m ', p0[0], comma, p0[1], + // x1, y0 + ' l ', p1[0], comma, p0[1], + // x1, y1 + ' l ', p1[0], comma, p1[1], + // x0, y1 + ' l ', p0[0], comma, p1[1] + ); + break; + case CMD.Z: + // FIXME Update xi, yi + str.push(' x '); + } + + if (nPoint > 0) { + str.push(cmdStr); + for (var k = 0; k < nPoint; k++) { + var p = points[k]; + + m && applyTransform(p, p, m); + // 不 round 会非常慢 + str.push( + round(p[0] * Z - Z2), comma, round(p[1] * Z - Z2), + k < nPoint - 1 ? comma : '' + ); + } + } + } + + return str.join(''); + }; + + // Rewrite the original path method + Path.prototype.brushVML = function (vmlRoot) { + var style = this.style; + + var vmlEl = this._vmlEl; + if (!vmlEl) { + vmlEl = vmlCore.createNode('shape'); + initRootElStyle(vmlEl); + + this._vmlEl = vmlEl; + } + + updateFillAndStroke(vmlEl, 'fill', style, this); + updateFillAndStroke(vmlEl, 'stroke', style, this); + + var m = this.transform; + var needTransform = m != null; + var strokeEl = vmlEl.getElementsByTagName('stroke')[0]; + if (strokeEl) { + var lineWidth = style.lineWidth; + // Get the line scale. + // Determinant of this.m_ means how much the area is enlarged by the + // transformation. So its square root can be used as a scale factor + // for width. + if (needTransform && !style.strokeNoScale) { + var det = m[0] * m[3] - m[1] * m[2]; + lineWidth *= sqrt(abs(det)); + } + strokeEl.weight = lineWidth + 'px'; + } + + var path = this.path || (this.path = new PathProxy()); + if (this.__dirtyPath) { + path.beginPath(); + this.buildPath(path, this.shape); + path.toStatic(); + this.__dirtyPath = false; + } + + vmlEl.path = pathDataToString(path.data, this.transform); + + vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); + + // Append to root + append(vmlRoot, vmlEl); + + // Text + if (style.text != null) { + this.drawRectText(vmlRoot, this.getBoundingRect()); + } + else { + this.removeRectText(vmlRoot); + } + }; + + Path.prototype.onRemove = function (vmlRoot) { + remove(vmlRoot, this._vmlEl); + this.removeRectText(vmlRoot); + }; + + Path.prototype.onAdd = function (vmlRoot) { + append(vmlRoot, this._vmlEl); + this.appendRectText(vmlRoot); + }; + + /*************************************************** + * IMAGE + **************************************************/ + var isImage = function (img) { + // FIXME img instanceof Image 如果 img 是一个字符串的时候,IE8 下会报错 + return (typeof img === 'object') && img.tagName && img.tagName.toUpperCase() === 'IMG'; + // return img instanceof Image; + }; + + // Rewrite the original path method + ZImage.prototype.brushVML = function (vmlRoot) { + var style = this.style; + var image = style.image; + + // Image original width, height + var ow; + var oh; + + if (isImage(image)) { + var src = image.src; + if (src === this._imageSrc) { + ow = this._imageWidth; + oh = this._imageHeight; + } + else { + var imageRuntimeStyle = image.runtimeStyle; + var oldRuntimeWidth = imageRuntimeStyle.width; + var oldRuntimeHeight = imageRuntimeStyle.height; + imageRuntimeStyle.width = 'auto'; + imageRuntimeStyle.height = 'auto'; + + // get the original size + ow = image.width; + oh = image.height; + + // and remove overides + imageRuntimeStyle.width = oldRuntimeWidth; + imageRuntimeStyle.height = oldRuntimeHeight; + + // Caching image original width, height and src + this._imageSrc = src; + this._imageWidth = ow; + this._imageHeight = oh; + } + image = src; + } + else { + if (image === this._imageSrc) { + ow = this._imageWidth; + oh = this._imageHeight; + } + } + if (!image) { + return; + } + + var x = style.x || 0; + var y = style.y || 0; + + var dw = style.width; + var dh = style.height; + + var sw = style.sWidth; + var sh = style.sHeight; + var sx = style.sx || 0; + var sy = style.sy || 0; + + var hasCrop = sw && sh; + + var vmlEl = this._vmlEl; + if (!vmlEl) { + // FIXME 使用 group 在 left, top 都不是 0 的时候就无法显示了。 + // vmlEl = vmlCore.createNode('group'); + vmlEl = vmlCore.doc.createElement('div'); + initRootElStyle(vmlEl); + + this._vmlEl = vmlEl; + } + + var vmlElStyle = vmlEl.style; + var hasRotation = false; + var m; + var scaleX = 1; + var scaleY = 1; + if (this.transform) { + m = this.transform; + scaleX = sqrt(m[0] * m[0] + m[1] * m[1]); + scaleY = sqrt(m[2] * m[2] + m[3] * m[3]); + + hasRotation = m[1] || m[2]; + } + if (hasRotation) { + // If filters are necessary (rotation exists), create them + // filters are bog-slow, so only create them if abbsolutely necessary + // The following check doesn't account for skews (which don't exist + // in the canvas spec (yet) anyway. + // From excanvas + var p0 = [x, y]; + var p1 = [x + dw, y]; + var p2 = [x, y + dh]; + var p3 = [x + dw, y + dh]; + applyTransform(p0, p0, m); + applyTransform(p1, p1, m); + applyTransform(p2, p2, m); + applyTransform(p3, p3, m); + + var maxX = mathMax(p0[0], p1[0], p2[0], p3[0]); + var maxY = mathMax(p0[1], p1[1], p2[1], p3[1]); + + var transformFilter = []; + transformFilter.push('M11=', m[0] / scaleX, comma, + 'M12=', m[2] / scaleY, comma, + 'M21=', m[1] / scaleX, comma, + 'M22=', m[3] / scaleY, comma, + 'Dx=', round(x * scaleX + m[4]), comma, + 'Dy=', round(y * scaleY + m[5])); + + vmlElStyle.padding = '0 ' + round(maxX) + 'px ' + round(maxY) + 'px 0'; + // FIXME DXImageTransform 在 IE11 的兼容模式下不起作用 + vmlElStyle.filter = imageTransformPrefix + '.Matrix(' + + transformFilter.join('') + ', SizingMethod=clip)'; + + } + else { + if (m) { + x = x * scaleX + m[4]; + y = y * scaleY + m[5]; + } + vmlElStyle.filter = ''; + vmlElStyle.left = round(x) + 'px'; + vmlElStyle.top = round(y) + 'px'; + } + + var imageEl = this._imageEl; + var cropEl = this._cropEl; + + if (!imageEl) { + imageEl = vmlCore.doc.createElement('div'); + this._imageEl = imageEl; + } + var imageELStyle = imageEl.style; + if (hasCrop) { + // Needs know image original width and height + if (! (ow && oh)) { + var tmpImage = new Image(); + var self = this; + tmpImage.onload = function () { + tmpImage.onload = null; + ow = tmpImage.width; + oh = tmpImage.height; + // Adjust image width and height to fit the ratio destinationSize / sourceSize + imageELStyle.width = round(scaleX * ow * dw / sw) + 'px'; + imageELStyle.height = round(scaleY * oh * dh / sh) + 'px'; + + // Caching image original width, height and src + self._imageWidth = ow; + self._imageHeight = oh; + self._imageSrc = image; + }; + tmpImage.src = image; + } + else { + imageELStyle.width = round(scaleX * ow * dw / sw) + 'px'; + imageELStyle.height = round(scaleY * oh * dh / sh) + 'px'; + } + + if (! cropEl) { + cropEl = vmlCore.doc.createElement('div'); + cropEl.style.overflow = 'hidden'; + this._cropEl = cropEl; + } + var cropElStyle = cropEl.style; + cropElStyle.width = round((dw + sx * dw / sw) * scaleX); + cropElStyle.height = round((dh + sy * dh / sh) * scaleY); + cropElStyle.filter = imageTransformPrefix + '.Matrix(Dx=' + + (-sx * dw / sw * scaleX) + ',Dy=' + (-sy * dh / sh * scaleY) + ')'; + + if (! cropEl.parentNode) { + vmlEl.appendChild(cropEl); + } + if (imageEl.parentNode != cropEl) { + cropEl.appendChild(imageEl); + } + } + else { + imageELStyle.width = round(scaleX * dw) + 'px'; + imageELStyle.height = round(scaleY * dh) + 'px'; + + vmlEl.appendChild(imageEl); + + if (cropEl && cropEl.parentNode) { + vmlEl.removeChild(cropEl); + this._cropEl = null; + } + } + + var filterStr = ''; + var alpha = style.opacity; + if (alpha < 1) { + filterStr += '.Alpha(opacity=' + round(alpha * 100) + ') '; + } + filterStr += imageTransformPrefix + '.AlphaImageLoader(src=' + image + ', SizingMethod=scale)'; + + imageELStyle.filter = filterStr; + + vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); + + // Append to root + append(vmlRoot, vmlEl); + + // Text + if (style.text != null) { + this.drawRectText(vmlRoot, this.getBoundingRect()); + } + }; + + ZImage.prototype.onRemove = function (vmlRoot) { + remove(vmlRoot, this._vmlEl); + + this._vmlEl = null; + this._cropEl = null; + this._imageEl = null; + + this.removeRectText(vmlRoot); + }; + + ZImage.prototype.onAdd = function (vmlRoot) { + append(vmlRoot, this._vmlEl); + this.appendRectText(vmlRoot); + }; + + + /*************************************************** + * TEXT + **************************************************/ + + var DEFAULT_STYLE_NORMAL = 'normal'; + + var fontStyleCache = {}; + var fontStyleCacheCount = 0; + var MAX_FONT_CACHE_SIZE = 100; + var fontEl = document.createElement('div'); + + var getFontStyle = function (fontString) { + var fontStyle = fontStyleCache[fontString]; + if (!fontStyle) { + // Clear cache + if (fontStyleCacheCount > MAX_FONT_CACHE_SIZE) { + fontStyleCacheCount = 0; + fontStyleCache = {}; + } + + var style = fontEl.style; + var fontFamily; + try { + style.font = fontString; + fontFamily = style.fontFamily.split(',')[0]; + } + catch (e) { + } + + fontStyle = { + style: style.fontStyle || DEFAULT_STYLE_NORMAL, + variant: style.fontVariant || DEFAULT_STYLE_NORMAL, + weight: style.fontWeight || DEFAULT_STYLE_NORMAL, + size: parseFloat(style.fontSize || 12) | 0, + family: fontFamily || 'Microsoft YaHei' + }; + + fontStyleCache[fontString] = fontStyle; + fontStyleCacheCount++; + } + return fontStyle; + }; + + var textMeasureEl; + // Overwrite measure text method + textContain.measureText = function (text, textFont) { + var doc = vmlCore.doc; + if (!textMeasureEl) { + textMeasureEl = doc.createElement('div'); + textMeasureEl.style.cssText = 'position:absolute;top:-20000px;left:0;' + + 'padding:0;margin:0;border:none;white-space:pre;'; + vmlCore.doc.body.appendChild(textMeasureEl); + } + + try { + textMeasureEl.style.font = textFont; + } catch (ex) { + // Ignore failures to set to invalid font. + } + textMeasureEl.innerHTML = ''; + // Don't use innerHTML or innerText because they allow markup/whitespace. + textMeasureEl.appendChild(doc.createTextNode(text)); + return { + width: textMeasureEl.offsetWidth + }; + }; + + var tmpRect = new BoundingRect(); + + var drawRectText = function (vmlRoot, rect, textRect, fromTextEl) { + + var style = this.style; + var text = style.text; + // Convert to string + text != null && (text += ''); + if (!text) { + return; + } + + var x; + var y; + var align = style.textAlign; + var fontStyle = getFontStyle(style.textFont); + // FIXME encodeHtmlAttribute ? + var font = fontStyle.style + ' ' + fontStyle.variant + ' ' + fontStyle.weight + ' ' + + fontStyle.size + 'px "' + fontStyle.family + '"'; + + var baseline = style.textBaseline; + var verticalAlign = style.textVerticalAlign; + + textRect = textRect || textContain.getBoundingRect(text, font, align, baseline); + + // Transform rect to view space + var m = this.transform; + // Ignore transform for text in other element + if (m && !fromTextEl) { + tmpRect.copy(rect); + tmpRect.applyTransform(m); + rect = tmpRect; + } + + if (!fromTextEl) { + var textPosition = style.textPosition; + var distance = style.textDistance; + // Text position represented by coord + if (textPosition instanceof Array) { + x = rect.x + parsePercent(textPosition[0], rect.width); + y = rect.y + parsePercent(textPosition[1], rect.height); + + align = align || 'left'; + baseline = baseline || 'top'; + } + else { + var res = textContain.adjustTextPositionOnRect( + textPosition, rect, textRect, distance + ); + x = res.x; + y = res.y; + + // Default align and baseline when has textPosition + align = align || res.textAlign; + baseline = baseline || res.textBaseline; + } + } + else { + x = rect.x; + y = rect.y; + } + if (verticalAlign) { + switch (verticalAlign) { + case 'middle': + y -= textRect.height / 2; + break; + case 'bottom': + y -= textRect.height; + break; + // 'top' + } + // Ignore baseline + baseline = 'top'; + } + + var fontSize = fontStyle.size; + // 1.75 is an arbitrary number, as there is no info about the text baseline + switch (baseline) { + case 'hanging': + case 'top': + y += fontSize / 1.75; + break; + case 'middle': + break; + default: + // case null: + // case 'alphabetic': + // case 'ideographic': + // case 'bottom': + y -= fontSize / 2.25; + break; + } + switch (align) { + case 'left': + break; + case 'center': + x -= textRect.width / 2; + break; + case 'right': + x -= textRect.width; + break; + // case 'end': + // align = elementStyle.direction == 'ltr' ? 'right' : 'left'; + // break; + // case 'start': + // align = elementStyle.direction == 'rtl' ? 'right' : 'left'; + // break; + // default: + // align = 'left'; + } + + var createNode = vmlCore.createNode; + + var textVmlEl = this._textVmlEl; + var pathEl; + var textPathEl; + var skewEl; + if (!textVmlEl) { + textVmlEl = createNode('line'); + pathEl = createNode('path'); + textPathEl = createNode('textpath'); + skewEl = createNode('skew'); + + // FIXME Why here is not cammel case + // Align 'center' seems wrong + textPathEl.style['v-text-align'] = 'left'; + + initRootElStyle(textVmlEl); + + pathEl.textpathok = true; + textPathEl.on = true; + + textVmlEl.from = '0 0'; + textVmlEl.to = '1000 0.05'; + + append(textVmlEl, skewEl); + append(textVmlEl, pathEl); + append(textVmlEl, textPathEl); + + this._textVmlEl = textVmlEl; + } + else { + // 这里是在前面 appendChild 保证顺序的前提下 + skewEl = textVmlEl.firstChild; + pathEl = skewEl.nextSibling; + textPathEl = pathEl.nextSibling; + } + + var coords = [x, y]; + var textVmlElStyle = textVmlEl.style; + // Ignore transform for text in other element + if (m && fromTextEl) { + applyTransform(coords, coords, m); + + skewEl.on = true; + + skewEl.matrix = m[0].toFixed(3) + comma + m[2].toFixed(3) + comma + + m[1].toFixed(3) + comma + m[3].toFixed(3) + ',0,0'; + + // Text position + skewEl.offset = (round(coords[0]) || 0) + ',' + (round(coords[1]) || 0); + // Left top point as origin + skewEl.origin = '0 0'; + + textVmlElStyle.left = '0px'; + textVmlElStyle.top = '0px'; + } + else { + skewEl.on = false; + textVmlElStyle.left = round(x) + 'px'; + textVmlElStyle.top = round(y) + 'px'; + } + + textPathEl.string = encodeHtmlAttribute(text); + // TODO + try { + textPathEl.style.font = font; + } + // Error font format + catch (e) {} + + updateFillAndStroke(textVmlEl, 'fill', { + fill: fromTextEl ? style.fill : style.textFill, + opacity: style.opacity + }, this); + updateFillAndStroke(textVmlEl, 'stroke', { + stroke: fromTextEl ? style.stroke : style.textStroke, + opacity: style.opacity, + lineDash: style.lineDash + }, this); + + textVmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); + + // Attached to root + append(vmlRoot, textVmlEl); + }; + + var removeRectText = function (vmlRoot) { + remove(vmlRoot, this._textVmlEl); + this._textVmlEl = null; + }; + + var appendRectText = function (vmlRoot) { + append(vmlRoot, this._textVmlEl); + }; + + var list = [RectText, Displayable, ZImage, Path, Text]; + + // In case Displayable has been mixed in RectText + for (var i = 0; i < list.length; i++) { + var proto = list[i].prototype; + proto.drawRectText = drawRectText; + proto.removeRectText = removeRectText; + proto.appendRectText = appendRectText; + } + + Text.prototype.brushVML = function (vmlRoot) { + var style = this.style; + if (style.text != null) { + this.drawRectText(vmlRoot, { + x: style.x || 0, y: style.y || 0, + width: 0, height: 0 + }, this.getBoundingRect(), true); + } + else { + this.removeRectText(vmlRoot); + } + }; + + Text.prototype.onRemove = function (vmlRoot) { + this.removeRectText(vmlRoot); + }; + + Text.prototype.onAdd = function (vmlRoot) { + this.appendRectText(vmlRoot); + }; + } + + +/***/ }, +/* 426 */ +/***/ function(module, exports, __webpack_require__) { + + + + if (!__webpack_require__(2).canvasSupported) { + var urn = 'urn:schemas-microsoft-com:vml'; + + var createNode; + var win = window; + var doc = win.document; + + var vmlInited = false; + + try { + !doc.namespaces.zrvml && doc.namespaces.add('zrvml', urn); + createNode = function (tagName) { + return doc.createElement(''); + }; + } + catch (e) { + createNode = function (tagName) { + return doc.createElement('<' + tagName + ' xmlns="' + urn + '" class="zrvml">'); + }; + } + + // From raphael + var initVML = function () { + if (vmlInited) { + return; + } + vmlInited = true; + + var styleSheets = doc.styleSheets; + if (styleSheets.length < 31) { + doc.createStyleSheet().addRule('.zrvml', 'behavior:url(#default#VML)'); + } + else { + // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx + styleSheets[0].addRule('.zrvml', 'behavior:url(#default#VML)'); + } + }; + + // Not useing return to avoid error when converting to CommonJS module + module.exports = { + doc: doc, + initVML: initVML, + createNode: createNode + }; + } + + +/***/ }, +/* 427 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * VML Painter. + * + * @module zrender/vml/Painter + */ + + + + var zrLog = __webpack_require__(33); + var vmlCore = __webpack_require__(426); + + function parseInt10(val) { + return parseInt(val, 10); + } + + /** + * @alias module:zrender/vml/Painter + */ + function VMLPainter(root, storage) { + + vmlCore.initVML(); + + this.root = root; + + this.storage = storage; + + var vmlViewport = document.createElement('div'); + + var vmlRoot = document.createElement('div'); + + vmlViewport.style.cssText = 'display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;'; + + vmlRoot.style.cssText = 'position:absolute;left:0;top:0;'; + + root.appendChild(vmlViewport); + + this._vmlRoot = vmlRoot; + this._vmlViewport = vmlViewport; + + this.resize(); + + // Modify storage + var oldDelFromStorage = storage.delFromStorage; + var oldAddToStorage = storage.addToStorage; + storage.delFromStorage = function (el) { + oldDelFromStorage.call(storage, el); + + if (el) { + el.onRemove && el.onRemove(vmlRoot); + } + }; + + storage.addToStorage = function (el) { + // Displayable already has a vml node + el.onAdd && el.onAdd(vmlRoot); + + oldAddToStorage.call(storage, el); + }; + + this._firstPaint = true; + } + + VMLPainter.prototype = { + + constructor: VMLPainter, + + /** + * @return {HTMLDivElement} + */ + getViewportRoot: function () { + return this._vmlViewport; + }, + + /** + * 刷新 + */ + refresh: function () { + + var list = this.storage.getDisplayList(true, true); + + this._paintList(list); + }, + + _paintList: function (list) { + var vmlRoot = this._vmlRoot; + for (var i = 0; i < list.length; i++) { + var el = list[i]; + if (el.invisible || el.ignore) { + if (!el.__alreadyNotVisible) { + el.onRemove(vmlRoot); + } + // Set as already invisible + el.__alreadyNotVisible = true; + } + else { + if (el.__alreadyNotVisible) { + el.onAdd(vmlRoot); + } + el.__alreadyNotVisible = false; + if (el.__dirty) { + el.beforeBrush && el.beforeBrush(); + (el.brushVML || el.brush).call(el, vmlRoot); + el.afterBrush && el.afterBrush(); + } + } + el.__dirty = false; + } + + if (this._firstPaint) { + // Detached from document at first time + // to avoid page refreshing too many times + + // FIXME 如果每次都先 removeChild 可能会导致一些填充和描边的效果改变 + this._vmlViewport.appendChild(vmlRoot); + this._firstPaint = false; + } + }, + + resize: function (width, height) { + var width = width == null ? this._getWidth() : width; + var height = height == null ? this._getHeight() : height; + + if (this._width != width || this._height != height) { + this._width = width; + this._height = height; + + var vmlViewportStyle = this._vmlViewport.style; + vmlViewportStyle.width = width + 'px'; + vmlViewportStyle.height = height + 'px'; + } + }, + + dispose: function () { + this.root.innerHTML = ''; + + this._vmlRoot = + this._vmlViewport = + this.storage = null; + }, + + getWidth: function () { + return this._width; + }, + + getHeight: function () { + return this._height; + }, + + clear: function () { + if (this._vmlViewport) { + this.root.removeChild(this._vmlViewport); + } + }, + + _getWidth: function () { + var root = this.root; + var stl = root.currentStyle; + + return ((root.clientWidth || parseInt10(stl.width)) + - parseInt10(stl.paddingLeft) + - parseInt10(stl.paddingRight)) | 0; + }, + + _getHeight: function () { + var root = this.root; + var stl = root.currentStyle; + + return ((root.clientHeight || parseInt10(stl.height)) + - parseInt10(stl.paddingTop) + - parseInt10(stl.paddingBottom)) | 0; + } + }; + + // Not supported methods + function createMethodNotSupport(method) { + return function () { + zrLog('In IE8.0 VML mode painter not support method "' + method + '"'); + }; + } + + var notSupportedMethods = [ + 'getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer', 'eachOtherLayer', 'getLayers', + 'modLayer', 'delLayer', 'clearLayer', 'toDataURL', 'pathToImage' + ]; + + for (var i = 0; i < notSupportedMethods.length; i++) { + var name = notSupportedMethods[i]; + VMLPainter.prototype[name] = createMethodNotSupport(name); + } + + module.exports = VMLPainter; + + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/worldmap/static/js/glbg.js b/worldmap/static/js/glbg.js new file mode 100644 index 0000000..36ee42b --- /dev/null +++ b/worldmap/static/js/glbg.js @@ -0,0 +1,135 @@ +function glInitialize() { + var earth = new WE.map('canvas'); + WE.tileLayer('http://tileserver.maptiler.com/nasa/{z}/{x}/{y}.jpg', { + minZoom: 0, + maxZoom: 5, + attribution: 'NASA' + }).addTo(earth); + // Start a simple rotation animation + var before = null; + requestAnimationFrame(function animate(now) { + var c = earth.getPosition(); + var elapsed = before? now - before: 0; + before = now; + earth.setCenter([c[0], c[1] + 0.1*(elapsed/30)]); + requestAnimationFrame(animate); + }); + } + + var canvas = document.getElementById("canvas"); + var ctx = canvas.getContext("2d"); + + resize(); + window.onresize = resize; + + function resize() { + canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + } + + var RAF = (function() { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { + window.setTimeout(callback, 1000 / 60); + }; + })(); + + // 鼠标活动时,获取鼠标坐标 + var warea = {x: null, y: null, max: 20000}; + window.onmousemove = function(e) { + e = e || window.event; + + warea.x = e.clientX; + warea.y = e.clientY; + }; + window.onmouseout = function(e) { + warea.x = null; + warea.y = null; + }; + + // 添加粒子 + // x,y为粒子坐标,xa, ya为粒子xy轴加速度,max为连线的最大距离 + var dots = []; + for (var i = 0; i < 300; i++) { + var x = Math.random() * canvas.width; + var y = Math.random() * canvas.height; + var xa = Math.random() * 2 - 1; + var ya = Math.random() * 2 - 1; + + dots.push({ + x: x, + y: y, + xa: xa, + ya: ya, + max: 6000 + }) + } + + // 延迟100秒开始执行动画,如果立即执行有时位置计算会出错 + setTimeout(function() { + animate(); + }, 100); + + // 每一帧循环的逻辑 + function animate() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // 将鼠标坐标添加进去,产生一个用于比对距离的点数组 + var ndots = [warea].concat(dots); + + dots.forEach(function(dot) { + + // 粒子位移 + dot.x += dot.xa; + dot.y += dot.ya; + + // 遇到边界将加速度反向 + dot.xa *= (dot.x > canvas.width || dot.x < 0) ? -1 : 1; + dot.ya *= (dot.y > canvas.height || dot.y < 0) ? -1 : 1; + + // 绘制点 + ctx.fillStyle="#dcdcef"; + ctx.fillRect(dot.x - 0.5, dot.y - 0.5, 2, 2); + + // 循环比对粒子间的距离 + for (var i = 0; i < ndots.length; i++) { + var d2 = ndots[i]; + + if (dot === d2 || d2.x === null || d2.y === null) continue; + + var xc = dot.x - d2.x; + var yc = dot.y - d2.y; + + // 两个粒子之间的距离 + var dis = xc * xc + yc * yc; + + // 距离比 + var ratio; + + // 如果两个粒子之间的距离小于粒子对象的max值,则在两个粒子间画线 + if (dis < d2.max) { + + // 如果是鼠标,则让粒子向鼠标的位置移动 + /*if (d2 === warea && dis > (d2.max / 2)) { + dot.x -= xc * 0.03; + dot.y -= yc * 0.03; + }*/ + + // 计算距离比 + ratio = (d2.max - dis) / d2.max; + + // 画线 + ctx.beginPath(); + ctx.lineWidth = ratio; + ctx.strokeStyle = 'rgba(187,185,240,' + (ratio + 0.2) + ')'; + ctx.moveTo(dot.x, dot.y); + ctx.lineTo(d2.x, d2.y); + ctx.stroke(); + } + } + + // 将已经计算过的粒子从数组中删除 + ndots.splice(ndots.indexOf(dot), 1); + }); + + RAF(animate); + } diff --git a/worldmap/static/js/layertree.js b/worldmap/static/js/layertree.js new file mode 100644 index 0000000..66d674c --- /dev/null +++ b/worldmap/static/js/layertree.js @@ -0,0 +1,804 @@ +var layerTreeJson = [{ + "id": 0, + "text": "new map", + "type":"map" +}]; +function openChangeName() { + $('#changeName').find('#nameForChange').val(myMapMana.mapname); + $('#changeName').find('input[name="accessType"]').removeAttr("checked"); + $('#changeName').find('input[name="accessType"][value="'+myMapMana.mapaccess+'"]').prop("checked", true); + $('#changeName').find('#maptype').combobox( + { + valueField:'id', + textField:'text', + data:[ + {id:0,text:"综合"}, + {id:1,text:"人文"}, + {id:2,text:"历史"}, + {id:3,text:"经济"}, + {id:4,text:"政治"} + ] + } + ); + $('#changeName').find('#maptype').val(myMapMana.maptype); + $('#changeName').window('open'); +} +function changeName() { + $('#changeName').window('close'); + + myMapMana.mapname = $('#changeName').find('#nameForChange').val(); + myMapMana.mapaccess = $('#changeName').find('input[name="accessType"]:checked').val(); + + layerTreeJson[0].text=myMapMana.mapname; + $("#layerTree").tree({ + dataType: "json", + data: layerTreeJson + }); + $('.accordion').find('.panel-header').find('.panel-title').html(myMapMana.mapname); + myMapMana.maptype= $('#changeName').find('#maptype').val(); + redraw(); +} + +function initLayertree(mapid,mapname) { + // + $('.accordion').find('.panel-header').find('.panel-title').html(myMapMana.mapname);//not save TODO find a save way to change title name. + // + $('.accordion').find('.panel-header').bind("contextmenu", function () { + return false; + }); + $('.accordion').find('.panel-header').mousedown(function (e) { + //右键为3 + if (1 == e.which) { + openChangeName(myMapMana.mapname,myMapMana.mapaccess); + ; + } + }); + if(!has(myMapMana.layertree)) + { + layerTreeJson[0].id=mapid; + layerTreeJson[0].text=mapname; + } + else + { + layerTreeJson = myMapMana.layertree; + layerTreeJson[0].id=mapid; + layerTreeJson[0].text=mapname; + } + $("#layerTree").tree({ + dataType: "json", + data: layerTreeJson, + //是否显示复选框 + checkbox: function (node) { + if (node.type == "map") { + return false; + } else { + return true; + } + }, + //这是拖动前的检查事件 如果returnfalse 则会停止拖动事件 + onBeforeDrop: function (target, source, point) { + //Father不能被拖动 + if (source.type === 'map') { + return false; + }; + //append:移动为子节点 + if (point === 'append') { + //有些node不能添加子node,即不能拖图层到其他图层下级            + var targetNode = $(this).tree('getNode', target); + if (targetNode.type === 'layer') { + return false; + }; + /* + //图层不能移动到别的父节点下 + var parentNode = $(this).tree('getParent', source.target); + if (parentNode.id != targetNode.id) { + return false; + }; + */ + } + //point == 'top' OR 'bottom':移动到目标节点的上/下方 + else { + var targetNode = $(this).tree('getNode', target); + if (targetNode.type === 'map') { + return false; + }; + } + }, + //选中复选框后触发 + onCheck: function (node, checked) { + onLayerCheck(node, checked); + //修改为级联勾选之后 还需要写一个函数来判断树的父节点们的勾选情况 只要不是全选 就应该判断为未勾选 + }, + //DONE 拖动结束放置好节点后触发 + onDrop: function (target, source, point) { + var roots = $(this).tree('getRoots'); + nodeOrders = new Array(); + getOrders(roots); + setLayerOverlay(nodeOrders); + }, + //右键节点弹出菜单,用于各种操作 + + onContextMenu: function (e, node) { + e.preventDefault(); + // select the node + //这里要根据右键点击的是图层节点还是地图根节点还是说子地图(submap)也就是layergroup 这样三类 + $('#layerTree').tree('select', node.target); + var menuType = node.type; + // display context menu + if(menuType=="map"){ + $('#mapMenu').menu('show', { + left: e.pageX, + top: e.pageY + }); + } + else if(menuType=="submap"){ + $('#submapMenu').menu('show', { + left: e.pageX, + top: e.pageY + }); + } + else + $('#layerMenu').menu('show', { + left: e.pageX, + top: e.pageY + }); + }, + onBeforeEdit: function (node){ + $(node.target).css("color","#000000"); + }, + onAfterEdit: function (node){ + function updateTreeJson(treejson) + { + if(treejson.type=="submap"&&node.id==treejson.id) treejson.text=node.text; + } + + $(node.target).css("color",""); + travelTree(layerTreeJson,updateTreeJson); + }, + onCancelEdit:function(node) + { + $(node.target).css("color",""); + } + }); +} +//======================== 图层树节点操作 ========================// +function addsubtree(subtree){ + if (layerTreeJson[0]["children"] == null) { + layerTreeJson[0]["children"] = new Array(); + }; + //这里需要先处理下subtree里面的id问题 + for(var i=0;i= 0; i--) { + if(node.type=="submap"&&treeJson[i].type=="submap"&& + treeJson[i].id == node.id){ + treeJson.splice(i, 1); + $("#layerTree").tree({ + dataType: "json", + data: layerTreeJson + }); + return; + }else + if (treeJson[i].index!=null&&treeJson[i].index == node.index) { + treeJson.splice(i, 1); + //有待重构 这里只删除分层设色图层的根节点是不是不太合适? 不过总之功能实现的挺好 + + //刷新图层树 + $("#layerTree").tree({ + dataType: "json", + data: layerTreeJson + }); + return; + } else if (treeJson[i].children != null) + removeTreeNode(node, treeJson[i].children); + }; +}; + + +//====================== 图层树相关图层操作 ======================// +//DONE 添加图层后集中保存//layerpanel.js以及yukimap.js里面的相关函数取代 +function addLayertoSilo(lname, ltype) { + var newLayer = { + name: lname, + type: ltype, + checked: true + }; + layerSilo.push(newLayer); +}; + +function clearMap() { + //TODO 清除地图内容 +} + +function removeLayer() { + function removeMapLayer(node){ + if(node.type=="layer" && myMapMana.maplayerlist[node.index]!=null && has(myMapMana.maplayerlist[node.index].mapv)) + myMapMana.maplayerlist[node.index].mapv.hide(); + myMapMana.maplayerlist[node.index]=null; + } + var t = $('#layerTree'); + var node = t.tree('getSelected'); + + travelTree(node,removeMapLayer); + + removeTreeNode(node, layerTreeJson); + redraw(); +}; + +//TODO layertreejson的遍历(这里姑且用 children这个默认的成员标签来写一个深度搜索的递归。 +//这里直接也兼容了easyui里面内建的树的遍历 +function travelTree(treejson,nodeupdate) +{ + if(has(treejson.length)){ + for(var i=0;i= 0; i--) { + if (roots[i].children == null) { + if (roots[i].checked == true) + nodeOrders.push({ + "id": roots[i].index, + "checked": 1 + }); + else + nodeOrders.push({ + "id": roots[i].index, + "checked": 0 + }); + } else if (roots[i].children != null) { + getOrders(roots[i].children); + } + }; +}; + +//DONE 更新图层叠放次序 +var setLayerOverlay = function () { + + for (var j = nodeOrders.length - 1; j >= 0; j--) { + + myMapMana.maplayerlist[nodeOrders[j].id].zIndex = j; + } + + + + redraw(); + //重绘所有被勾选的分层图 + // +}; + +// +//以下是一堆自用函数 有待封装 (按理说应该单独起一个color.js的 +// +//别人家的代码begin 修改自http://www.zhangxinxu.com/study/js/zxx.color_exchange.js +/*RGBto16进制*/ +var colorHex = function (colorS) { + var reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; + var that = colorS; + if (/^(rgb|RGB)/.test(that)) { + var aColor = that.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); + var strHex = "#"; + for (var i = 0; i < aColor.length; i++) { + var hex = Number(aColor[i]).toString(16); + if (hex === "0") { + hex += hex; + } + strHex += hex; + } + if (strHex.length !== 7) { + strHex = that; + } + return strHex; + } else if (reg.test(that)) { + var aNum = that.replace(/#/, "").split(""); + if (aNum.length === 6) { + return that; + } else if (aNum.length === 3) { + var numHex = "#"; + for (var i = 0; i < aNum.length; i += 1) { + numHex += (aNum[i] + aNum[i]); + } + return numHex; + } + } else { + return that; + } +}; +//------------------------------------------------- +/*16进制转RGB*/ +var colorRgb = function (colorH) { + var reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; + var sColor = colorH.toLowerCase(); + if (sColor && reg.test(sColor)) { + if (sColor.length === 4) { + var sColorNew = "#"; + for (var i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + //澶勭悊鍏綅鐨勯鑹插€� + var sColorChange = []; + for (var i = 1; i < 7; i += 2) { + sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2))); + } + return "RGB(" + sColorChange.join(",") + ")"; + } else { + return sColor; + } +}; +//别人家的代码over +// +//yuki又造轮子啦 +// +//16进制转RGB数组 +function HexToColorArray(hColor) { + var colorArray = []; + for (var i = 1; i < 7; i += 2) { + colorArray.push(parseInt("0x" + hColor.slice(i, i + 2))); + } + return { r: colorArray[0], g: colorArray[1], b: colorArray[2] } +} +//RGB数组转16进制 +function ColorArrayToHex(colorArray) { + function OctToHex(Oct) { + var hexString = ""; + if (Oct < 0) return '00'; + if (Oct > 255) return 'ff'; + hexString = Oct.toString(16); + if (hexString.length == 1) + hexString = "0" + hexString; + return hexString; + } + return '#' + OctToHex(colorArray.r) + OctToHex(colorArray.g) + OctToHex(colorArray.b); +} +/** + * HSL颜色值转换为RGB. + * 换算公式改编自 http://en.wikipedia.org/wiki/HSL_color_space. + * h, s, 和 l 设定在 [0, 1] 之间 + * 返回的 r, g, 和 b 在 [0, 255]之间 + * + * @param Number h 色相 + * @param Number s 饱和度 + * @param Number l 亮度 + * @return Array RGB色值数值 + */ +function hslToRgb(h, s, l){ + var r, g, b; + + if(s == 0){ + r = g = b = l; // achromatic + }else{ + var hue2rgb = function hue2rgb(p, q, t){ + while(t < 0) t += 1; + while(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; +} +/** + * RGB 颜色值转换为 HSL. + * 转换公式参考自 http://en.wikipedia.org/wiki/HSL_color_space. + * r, g, 和 b 需要在 [0, 255] 范围内 + * 返回的 h, s, 和 l 在 [0, 1] 之间 + * + * @param Number r 红色色值 + * @param Number g 绿色色值 + * @param Number b 蓝色色值 + * @return Array HSL各值数组 + */ +function rgbToHsl(r, g, b){ + r /= 255, g /= 255, b /= 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min){ + h = s = 0; // achromatic + }else{ + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + + return [h, s, l]; +} +// +////**yukiToolBegin +//雪家色彩映射器 +//2017.7.25 +//yukiColorMap(数值 最小值, +//数值 最大值, +//色彩字符串 最小值颜色, +//色彩字符串 最大值颜色, +//字符串 分段数, +//字符串类型 暂时只有linear) +//有待重构... 需要分离数值映射和色彩映射,以便精简代码,色彩映射也应该提供rgb(特点是色彩跨度大的时候从灰色过度)和hsl(特点是色彩跨度大的时候从色相环过度)两种空间的渐变方案 暂时是写死的hsl色彩过渡方案 +function yukiColorMapper(min, max, minColor, maxColor, num, style) { + var ColorMaps = new Array(); + ColorMaps = []; + //确保格式 + var yminColor = colorHex(minColor); + var ymaxColor = colorHex(maxColor); + var valueColor = HexToColorArray(yminColor); + var endColor = HexToColorArray(ymaxColor); + var valueColorhsl = rgbToHsl(valueColor.r,valueColor.g,valueColor.b); + var endColorhsl = rgbToHsl(endColor.r,endColor.g,endColor.b); + if((endColorhsl[0]-valueColorhsl[0])>0.5) endColorhsl[0]=endColorhsl[0]-1; + else if((valueColorhsl[0]-endColorhsl[0])>0.5) valueColorhsl[0] = valueColorhsl[0]-1; + //线性映射 + if (style == "linear") { + var step = (max - min) / num; + var hstep = (endColorhsl[0] - valueColorhsl[0]) / num; + var sstep = (endColorhsl[1] - valueColorhsl[1]) / num; + var lstep = (endColorhsl[2] - valueColorhsl[2]) / num; + var nowstart = min - 1; + var nowend = min + step; + var nowColor = { + r: parseInt(valueColor.r), + g: parseInt(valueColor.g), + b: parseInt(valueColor.b) + }; + while (nowend < max) { + ColorMaps.push({ start: parseInt(nowstart), end: parseInt(nowend), value: ColorArrayToHex(nowColor) }); + // + valueColorhsl[0]+=hstep; + valueColorhsl[1]+=sstep; + valueColorhsl[2]+=lstep; + var nowRgb = hslToRgb(valueColorhsl[0],valueColorhsl[1],valueColorhsl[2]); + // + valueColor = { + r: nowRgb[0], + g: nowRgb[1], + b: nowRgb[2] + }; + nowstart = nowend; + nowend = nowend + step; + nowColor = { + r: parseInt(valueColor.r), + g: parseInt(valueColor.g), + b: parseInt(valueColor.b) + }; + } + ColorMaps.push({ start: parseInt(nowstart), value: ColorArrayToHex(nowColor) }) + } + else if (style == "log") { + var offset=1; + if(min<0) offset = -min+1; + var step = (Math.log(max+offset) - Math.log(min+offset)) / num; + var hstep = (endColorhsl[0] - valueColorhsl[0]) / num; + var sstep = (endColorhsl[1] - valueColorhsl[1]) / num; + var lstep = (endColorhsl[2] - valueColorhsl[2]) / num; + var nowstart = min - 1; + var nowstartLog = Math.log(min + offset); + var nowendLog = nowstartLog+step; + var nowend = Math.exp(nowendLog)-offset; + var nowColor = { + r: parseInt(valueColor.r), + g: parseInt(valueColor.g), + b: parseInt(valueColor.b) + }; + while (nowend < max) { + ColorMaps.push({ start: parseInt(nowstart), end: parseInt(nowend), value: ColorArrayToHex(nowColor) }); + // + valueColorhsl[0]+=hstep; + valueColorhsl[1]+=sstep; + valueColorhsl[2]+=lstep; + var nowRgb = hslToRgb(valueColorhsl[0],valueColorhsl[1],valueColorhsl[2]); + // + valueColor = { + r: nowRgb[0], + g: nowRgb[1], + b: nowRgb[2] + }; + nowstart = nowend; + nowendLog = nowendLog + step; + nowend = Math.exp(nowendLog)-offset; + nowColor = { + r: parseInt(valueColor.r), + g: parseInt(valueColor.g), + b: parseInt(valueColor.b) + }; + } + ColorMaps.push({ start: parseInt(nowstart), value: ColorArrayToHex(nowColor) }) + } + else if (style == "square") { + var offset=0; + if(min<0) offset = -min; + var step = (max*max - min*min) / num; + var hstep = (endColorhsl[0] - valueColorhsl[0]) / num; + var sstep = (endColorhsl[1] - valueColorhsl[1]) / num; + var lstep = (endColorhsl[2] - valueColorhsl[2]) / num; + var nowstart = min - 1; + var nowstartSquare = nowstart*nowstart; + var nowendSquare = nowstartSquare+step; + var nowend = Math.sqrt(nowendSquare)-offset; + var nowColor = { + r: parseInt(valueColor.r), + g: parseInt(valueColor.g), + b: parseInt(valueColor.b) + }; + while (nowend < max) { + ColorMaps.push({ start: parseInt(nowstart), end: parseInt(nowend), value: ColorArrayToHex(nowColor) }); + // + valueColorhsl[0]+=hstep; + valueColorhsl[1]+=sstep; + valueColorhsl[2]+=lstep; + var nowRgb = hslToRgb(valueColorhsl[0],valueColorhsl[1],valueColorhsl[2]); + // + valueColor = { + r: nowRgb[0], + g: nowRgb[1], + b: nowRgb[2] + }; + nowstart = nowend; + nowendSquare = nowendSquare + step; + nowend = Math.sqrt(nowendSquare)-offset; + nowColor = { + r: parseInt(valueColor.r), + g: parseInt(valueColor.g), + b: parseInt(valueColor.b) + }; + } + ColorMaps.push({ start: parseInt(nowstart), value: ColorArrayToHex(nowColor) }) + } + return ColorMaps; +} + +////**yukiToolEnd + + +//修改样式弹出框 +function changstyle() { + var t = $('#layerTree'); + var node = t.tree('getSelected'); + var menuType = node.type; + + if(menuType=="map"){ + var div = '地图选项框 施工ing'; + $('#stylediv').html(div); + + } + else if(menuType=="submap"){ + if (node){ + t.tree('beginEdit',node.target + ); + } + } + else{ + var i =node.index; + $('#styleWin').window('open'); + if (myMapMana.maplayerlist[i].type == 1) {//如果是等级符号图 + var div = '
点基本颜色映射:
'+ + '最大值:   
'+ + '最小值:   
'+ + '高亮颜色:  
点样式:   '+ + '
点尺寸映射:
'+ + '最大值:'+ + '
最小值:'+ + '
映射方式 :  '; + $('#stylediv').html(div); + $("#color1max")[0].value = myMapMana.maplayerlist[i].style.append.maxColor; + $("#color1min")[0].value = myMapMana.maplayerlist[i].style.append.minColor; + $("#color2")[0].value = myMapMana.maplayerlist[i].style.series.itemStyle.emphasis.color; + $("#mapperType").val(myMapMana.maplayerlist[i].style.append.mapperType); + $("#levelPointStyle").val(myMapMana.maplayerlist[i].style.series.symbol); + } + else if (myMapMana.maplayerlist[i].type == 2) {//如果是点图 + var div = '

点基本颜色:    

点高亮颜色:    

点样式 :    ' + + '

点大小:'; + $('#stylediv').html(div); + $("#color1")[0].value = myMapMana.maplayerlist[i].style.series.itemStyle.normal.color; + $("#color2")[0].value = myMapMana.maplayerlist[i].style.series.itemStyle.emphasis.color; + $("#pointStyle").val(myMapMana.maplayerlist[i].style.series.symbol); + } + else if (myMapMana.maplayerlist[i].type == 3) {//如果是轨迹图 + var div = '
 
轨迹起点颜色:    

轨迹终点颜色:    

轨迹方向点颜色 :
' + + '
轨迹方向样式 :    '; + $('#stylediv').html(div); + $("#color1")[0].value = myMapMana.maplayerlist[i].style.lineStyle.normal.color.colorStops[0].color; + $("#color2")[0].value = myMapMana.maplayerlist[i].style.lineStyle.normal.color.colorStops[1].color; + $("#color3")[0].value = myMapMana.maplayerlist[i].style.effect.color; + if (myMapMana.maplayerlist[i].style.effect.show == 'false') + $("#cBoxDirection").val("none"); + else { + $("#cBoxDirection").val(myMapMana.maplayerlist[i].style.effect.symbol); + } + if (myMapMana.maplayerlist[i].style.lineStyle.normal.curveness == 0) { + $('input:radio[name="curvevalue"][value="str"]').attr("checked", true); + } + else { + $('input:radio[name="curvevalue"][value="cur"]').attr("checked", true); + } + } + else if (myMapMana.maplayerlist[i].type == '0') { + var div = '
最大值颜色:

最小值颜色:' + + '

高光颜色: ' + + '

分段数:
' + + '
颜色映射方式 :    '; + $('#stylediv').html(div); + var nowSplitList = myMapMana.maplayerlist[i].mapv.options.splitList; + $("#mincolor")[0].value = nowSplitList[0].value; + $("#maxcolor")[0].value = nowSplitList[nowSplitList.length - 1].value; + $('#highcolor')[0].value = myMapMana.maplayerlist[i].style.options.highlight; + $("#splitType").val(myMapMana.maplayerlist[i].mapv.options.splitType); + } + } + +} +//更改样式并保存 +function savestyle() { + var t = $('#layerTree'); + var node = t.tree('getSelected'); + $('#styleWin').window('open'); // open a window + var menuType = node.type; + // display context menu + if(menuType=="map"){ + //尚未整合进来 + } + else if(menuType=="submap"){ + + } + else + { + var i =node.index; + if (myMapMana.maplayerlist[i].type == '1') {//等级符号图 + myMapMana.maplayerlist[i].style.append.maxColor = $("#color1max")[0].value; + myMapMana.maplayerlist[i].style.append.minColor = $("#color1min")[0].value; + myMapMana.maplayerlist[i].style.series.itemStyle.emphasis.color = $("#color2")[0].value; + myMapMana.maplayerlist[i].style.append.maxSize = parseInt($('#pointMaxSize').val()); + myMapMana.maplayerlist[i].style.append.minSize = parseInt($('#pointMinSize').val()); + myMapMana.maplayerlist[i].style.append.mapperType = $('#mapperType').val(); + myMapMana.maplayerlist[i].style.series.symbol = $("#levelPointStyle").val(); + } + if (myMapMana.maplayerlist[i].type == '2') {//点图 + myMapMana.maplayerlist[i].style.series.itemStyle.normal.color = $("#color1")[0].value; + myMapMana.maplayerlist[i].style.series.itemStyle.emphasis.color = $("#color2")[0].value; + myMapMana.maplayerlist[i].style.series.symbolSize = $('#pointSize').val(); + myMapMana.maplayerlist[i].style.series.symbol = $("#pointStyle").val(); + } + if (myMapMana.maplayerlist[i].type == '3') {//轨迹图 + var checkValue = $('input:radio[name="curvevalue"]:checked').val(); + if (checkValue == "str")//直线轨迹图 + myMapMana.maplayerlist[i].style.lineStyle.normal.curveness = '0'; + else if (checkValue == "cur")//曲线轨迹图 + myMapMana.maplayerlist[i].style.lineStyle.normal.curveness = '0.15'; + myMapMana.maplayerlist[i].style.lineStyle.normal.color.colorStops[0].color = $("#color1")[0].value; + myMapMana.maplayerlist[i].style.lineStyle.normal.color.colorStops[1].color = $("#color2")[0].value; + myMapMana.maplayerlist[i].style.effect.color = $("#color3")[0].value; + var show = $("#cBoxDirection").val(); + if(show=="none") + myMapMana.maplayerlist[i].style.effect.show = 'false'; + else + myMapMana.maplayerlist[i].style.effect.show = 'true'; + myMapMana.maplayerlist[i].style.effect.symbol = show; + } + if (myMapMana.maplayerlist[i].type == '0') {//分层设色图 + var minColor = $("#mincolor")[0].value; + var maxColor = $("#maxcolor")[0].value; + var min = myMapMana.maplayerlist[i].style.options.min; + var max = myMapMana.maplayerlist[i].style.options.max; + var splitNum = $('#splitNum').val(); + var splitType = $('#splitType').val(); + var newSplitList = yukiColorMapper(min, max, minColor, maxColor, splitNum, splitType); + myMapMana.maplayerlist[i].style.options.splitNum = splitNum; + myMapMana.maplayerlist[i].style.options.splitType = splitType; + myMapMana.maplayerlist[i].style.options.highlight = $("#highcolor")[0].value;; + myMapMana.maplayerlist[i].style.options.splitList= newSplitList; + myMapMana.maplayerlist[i].mapv.refresh(); + } + redraw(); + + } + +} + +function closeStyleWin() { + $('#styleWin').window('close'); +} diff --git a/worldmap/static/js/load.js b/worldmap/static/js/load.js new file mode 100644 index 0000000..790ebfb --- /dev/null +++ b/worldmap/static/js/load.js @@ -0,0 +1,21 @@ +//获取浏览器页面可见高度和宽度 +var _PageHeight = document.documentElement.clientHeight, +_PageWidth = document.documentElement.clientWidth; +//计算loading框距离顶部和左部的距离(loading框的宽度为215px,高度为61px) +var _LoadingTop = _PageHeight > 41 ? (_PageHeight - 41) / 2 : 0, +_LoadingLeft = _PageWidth > 215 ? (_PageWidth - 215) / 2 : 0; +//加载gif地址 +var Loadimagerul=""; +//在页面未加载完毕之前显示的loading Html自定义内容 +var _LoadingHtml = '
载入中...
'; +//呈现loading效果 +document.write(_LoadingHtml); +//监听加载状态改变 +document.onreadystatechange = completeLoading; +//加载状态为complete时移除loading效果 +function completeLoading() { +if (document.readyState == "complete") { +var loadingMask = document.getElementById('loadingDiv'); +loadingMask.parentNode.removeChild(loadingMask); +} +} \ No newline at end of file diff --git a/worldmap/static/js/main.js b/worldmap/static/js/main.js new file mode 100644 index 0000000..dd53b94 --- /dev/null +++ b/worldmap/static/js/main.js @@ -0,0 +1,751 @@ +//main.jsp的页面的初始化 +//TODO 整理全局变量 +var disopen = false; +// 打开测距 +function mydisFunc() { + if(disopen){ + measureOver(); + disopen=false; + } + else{ + measureStart(); + disopen=true; + } +} +function closeAllPanel(){ + $('#sharePanel').css('display', 'none'); + $('#mapPanel').css('display', 'none'); + $('#searchBox').css('display', 'none'); + if(has(mySearchMarker)) + mySearchMarker.hide(); +} +// 打开分享 +function myshareFunc() { + if ($('#sharePanel').css('display') == 'none') + { + closeAllPanel(); + $('#sharePanel').css('display', 'inline'); + } + else + $('#sharePanel').css('display', 'none'); +} + +// 打开搜索窗 +function showSearchPanel() { + if ($('#searchBox').css('display') == 'none'){ + closeAllPanel(); + $('#searchBox').css('display', 'inline'); + } + else + closeSearchPanel(); +} + +// 关闭搜索窗 +function closeSearchPanel() +{ + $('#searchBox').css('display', 'none'); + if(has(mySearchMarker)) mySearchMarker.hide(); +} + +// 打开地图框 +function showMapPanel() { + if ($('#mapPanel').css('display') == 'none') { + var mapsName = new Array(); + var username; + var userid; + $.ajax({ + url: "./getActiveUser.action", + async: false, + type: "POST", + dataType: "text", + data: { + },success: function (result) { + username = $.parseJSON(result).username; + userid = $.parseJSON(result).userid; + }}); + $.ajax({ + url: "./getMapList.action", + async: false, + type: "POST", + dataType: "text", + data: { + userid: userid + }, + success: function (result) { + var resultobj = $.parseJSON(result); + for (var i = 0; i < resultobj.length; i++) { + var temp = { + id: resultobj[i].id, + name: resultobj[i].mapname + } + mapsName.push(temp); + } + } + }) + $('#selectMapName').combobox({ + + valueField: 'id', + textField: 'name', + data: mapsName, + onSelect: function (param) { + getMap(param.id); + } + }); + closeAllPanel(); + $('#mapPanel').css('display', 'inline'); + } + else + $('#mapPanel').css('display', 'none'); +} + +// 获取地图 +function getMap(varmapid) { + + addMapToMap(varmapid); +} + +// 添加地图至地图 +function addMapToMap(varmapid) +{ + var newlayerlist; + var submaptree; + $.ajax({ + url: "./getMapLayerList.action", + async: false, + type: "POST", + dataType: "text", + data: { + mapid:varmapid + },success: function (result) { + newlayerlist = layeranaly($.parseJSON(result)); + }}); + $.ajax({ + url: "./getMapInfo.action", + async: false, + type: "POST", + dataType: "text", + data: { + mapid:varmapid + },success: function (result) { + var submap = $.parseJSON(result); + submaptree = $.parseJSON(submap.layertree); + }}); + function insertLayer(treejson){ + if(treejson.type=="layer"){ + myMapMana.maplayerlist.push(newlayerlist[treejson.index]); + treejson.index=myMapMana.maplayerlist.length-1; + } + } + travelTree(submaptree,insertLayer); + submaptree[0].type="submap"; + submaptree[0].id=varmapid; + addsubtree(submaptree); + redraw(); +} + +function screenShot(){ + html2canvas($('#map'), { + onrendered: function(canvas) { + canvas.id = "mycanvas"; + // document.body.appendChild(canvas); + // 生成base64图片数据 + var dataUrl = canvas.toDataURL(); + var newImg = document.createElement("img"); + newImg.src = dataUrl; + newImg.width = 320; + newImg.height = 180; + // document.body.appendChild(newImg); + } + }); +} + +// 打开查询结果框 +function showResultPanel(resultSet) { + var gridDataSet=""; + for (var i = 0; i < resultSet.length; i++) { + gridDataSet=gridDataSet+''+ + ''+resultSet[i].layername+''+ + ''+resultSet[i].name+''+ + ''+resultSet[i].count+''+ + ''+resultSet[i].type+''+ + '' + } + $('#resultSet').html(gridDataSet); + $(".tr").click(function(){ + $('#resultPanel').window('close'); + zoomMapTo(resultSet[$(this).attr('id')]); + }); + + $('#resultPanel').window('open'); +} + +function openMarkBoard(data){ + $('#MarkBoard').css('display','inline'); + var html="

查询结果

"; + //通过判断是否很有bound属性来判别是否是面要素 + if(data.hasOwnProperty("bound")){//面要素成员属性独特、单独处理 + for(index in data) + { + var label = index; + if(index=="gid") { + label="GID"; + html=html+''+label+':'+data[index]+'
'; + } + if(index=="count") { + label="数量"; + html=html+''+label+':'+data[index]+'
'; + } + if(index=="name") { + label="地名"; + html=html+''+label+':'+data[index]+'
'; + } + else if(index=="geometry") { + label="要素类型"; + html=html+''+label+':'+data[index].type+'
'; + } + else if(index=="name_py") { + label="英文名"; + html=html+''+label+':'+data[index]+'
'; + } + } + } + else{//不是面要素 + for(index in data) + { + var label = index; + if(index=="name") label="地名"; + if(index=="value") { + label="数据内容"; + var len = data[index].length; + if(len>=3) + html=html+''+label+':'+data[index][len-3]+'
'; + } + else + html=html+''+label+':'+data[index]+'
'; + } + var len = data.value.length; + html=html+'ID:'+""+data.value[len-1]+','+data.value[len-2]+'
'; + html=html+'详细信息'; + $('.detailLink').click(function(){ + var id = $('#MarkBoard').find('.ID').html(); + $.ajax({ + url: "./getFeaturesDetail.action", + async: false, + type: "POST", + dataType: "text", + data: { + index:"["+id+"]" + },success: function (result) { + ShowDetailInfoPanel($.parseJSON(result)); + }}); + }) + } + + $('#MarkBoard').find('#res').html(html); +} +function closeMarkBoard() +{ + $('#MarkBoard').css('display','none'); + $('#MarkBoard').find('#res').html(""); +} +function setMarkBoardPos(tx,ty) +{ + var topOffSet = $('#headInterval').height(); + var mapW = $('#map').width(); + var mapH = $('#map').height(); + var boardH = parseInt($('#MarkBoard').css('height')); + $('#MarkBoard').css('left',mapW/2-48+'px'); // here the 48 is set in + // olpopup.css + $('#MarkBoard').css('top',mapH/2-boardH-7+'px'); // here the 7 is + // set in + // olpopup.css + // sqrt(10) +} +// 缩放地图至 (按照对象的情况确定缩放层级 +function zoomMapTo(obj) +{ + var layer = myMapMana.maplayerlist[obj.index.layer]; + var index = obj.index.feature; + switch(layer.type) + { + case 0: + var data = layer.style.dataSet._data; + var feature = data[index]; + var BB = feature.bound; + + var dx = BB.maxX-BB.minX; + var dy = BB.maxY-BB.minY; + var tx = (BB.minX+BB.maxX)/2; + var ty = (BB.minY+BB.maxY)/2; + var avgDis = dx>dy?dx:dy; + if(avgDis){ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + resolution:avgDis*100// here 100 is a magic number + // (setsumei:lonlat to Mercator(100k) to + // pixel(1k*1k)) + }) + mymap.setView(newView); + } + else{ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + resolution:myMapMana.zoomlevel + }) + mymap.setView(newView); + } + openMarkBoard(feature); + setMarkBoardPos(); + break; + case 1: + var data = layer.style.series.data; + var feature=data[index]; + var tx=feature.lonlat[0]; + var ty=feature.lonlat[1]; + var dx=layer.style.append.avgDis.dx; + var dy=layer.style.append.avgDis.dy; + var avgDis = dx>dy?dx:dy; + if(avgDis){ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + resolution:avgDis*100// here 100 is a magic number + // (setsumei:lonlat to Mercator(100k) to + // pixel(1k*1k)) + }) + mymap.setView(newView); + } + else{ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + zoom:myMapMana.zoomlevel + }) + mymap.setView(newView); + } + openMarkBoard(feature); + setMarkBoardPos(); + break; + case 2: + var data = layer.style.series.data; + var feature = data[index]; + var tx=data[index].lonlat[0]; + var ty=data[index].lonlat[1]; + var dx=layer.style.append.avgDis.dx; + var dy=layer.style.append.avgDis.dy; + var avgDis = dx>dy?dx:dy; + if(avgDis){ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + resolution:avgDis*100// here 100 is a magic number + }) + mymap.setView(newView); + } + else{ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + zoom:myMapMana.zoomlevel + }) + mymap.setView(newView); + } + openMarkBoard(feature); + setMarkBoardPos(); + break; + case 3: + var data = layer.style.data; + var feature = data[index]; + var coorda = data[index].lonlat[0]; + var coordb = data[index].lonlat[1]; + var dx=Math.abs(coorda[0]-coordb[0]); + var dy=Math.abs(coorda[1]-coordb[1]); + var tx = (data[index].lonlat[0][0]+data[index].lonlat[1][0])/2; + var ty = (data[index].lonlat[0][1]+data[index].lonlat[1][1])/2; + var avgDis = dx>dy?dx:dy; + if(avgDis){ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + resolution:avgDis*100// here 100 is a magic number + }) + mymap.setView(newView); + } + else{ + var newView= new ol.View({ + center: ol.proj.fromLonLat([tx, ty]), + zoom:myMapMana.zoomlevel + }) + mymap.setView(newView); + } + openMarkBoard(feature); + setMarkBoardPos(); + break; + } +} + function showLayerPanel() { + $("#layerPanel").window('open'); + getLayerData(0,10); + } + + function mouseMove(ev) { + Ev = ev || window.event; + mousePos = mouseCoords(ev); + } + function mouseCoords(ev) { + if (ev.pageX || ev.pageY) { + return { x: ev.pageX, y: ev.pageY }; + } + return { + x: ev.clientX + document.body.scrollLeft - document.body.clientLeft, + y: ev.clientY + document.body.scrollTop - document.body.clientTop + }; + } + function initMouseFunc(){ + document.onmousemove = mouseMove; + } + // 原layerpanel.js + function diappearText(obj) { + if(obj.value == ""){ + obj.removeAttribute('placeholder'); + } + } + + function showText(obj,text) { + if(obj.value == ""){ + obj.setAttribute("placeholder",text); + } + } + + var jsonData; + var selected; + function getLayerData(offset,limit) { // 这里的逻辑需要修改 + $.ajax({ + url:"./searchLayers.action", + async:true, + type:"POST", + dataType:"json", + data:{ + keyword:$("#keyword").val(), + type:$("#type").val(), + offset:offset, + limit:limit + }, + success:function(result){ + if(result == null || result == ""){ + var table = $("#table"); + var nodes = table.children(); + for(var i = 0 ;i < nodes.length;i++){ + nodes.remove(); + } + $("#databorder").html("无查询结果"); + $("#table").append("无查询结果"); + $("#count").html("0"); + }else{ + addDataColum(result); + } + } + }) + } + + // 锟斤拷锟斤拷锟斤拷锟斤拷锟? + function addDataColum(result){ + offset = result["offset"]; + var limit = result["limit"]; + var totalCount = result["totalCount"]; + var lastPage; + if(totalCount%10==0 && totalCount!=0) + lastPage = Math.floor(totalCount/10 - 1) * 10; + else + lastPage = Math.floor(totalCount/10) * 10; + if(offset == 0) + $("#li2").hide(); + else + $("#li2").show(); + $("#li2").attr("href", "javascript:getLayerData("+ (offset-10) +",10)"); + if(offset == lastPage) + $("#li3").hide(); + else + $("#li3").show(); + $("#li3").attr("href", "javascript:getLayerData("+ (offset+10) +",10)"); + $("#li4").attr("href", "javascript:getLayerData("+ lastPage +",10)"); + var jsonData = result["layers"]; + // jsonData = JSON.parse(res);//锟斤拷锟斤拷锟斤拷转锟斤拷锟斤拷json + var table = $("#table"); + // 锟斤拷删锟斤拷锟斤拷锟斤拷锟接节碉拷 + var nodes = table.children(); + for(var i = 0 ;i < nodes.length;i++){ + nodes.remove(); + } + + for(var i = 0 ; i"; + if(field == "type"){ + switch(jsonEachData[field]){ + case 0: + elementString += "" + "分层设色图" +""; + break; + case 1: + elementString += "" + "等级符号图" +""; + break; + case 2: + elementString += "" + "点图" +""; + break; + case 3: + elementString += "" + "轨迹图" +""; + break; + default: + break; + } + } + if(field == "userid") + elementString += "" + jsonEachData[field] +""; + + if(field == "datacontent"){ + var obj = jsonEachData[field]; + elementString += "" + JSON.stringify(obj) + ""; + } + if(field == "id"){ + elementString += "" + jsonEachData[field] + ""; + } + + } + elementString += ""; + table.append(elementString); + } + + + + $("#count").html($("#table tr").length); + // 为table提供tr回调函数 + $(".tr").click(function(){ + if($(this).hasClass("select")){ + $(this).removeClass("select"); + var contentDateBorder = ""; + $("#table").find("tr").each(function () { + if($(this).hasClass("select")){ + // contentDateBorder += + // $(this).children('td:eq(4)').text() + // +"

"; + } + }); + $("#databorder").html(contentDateBorder); + } + else{ + $(this).addClass("select"); + var contentDateBorder = ""; + $("#table").find("tr").each(function () { + if($(this).hasClass("select")){ + // contentDateBorder += + // $(this).children('td:eq(4)').text() + // +"

"; + } + }); + $("#databorder").html(contentDateBorder); + } + }) + // 为table锟斤拷每一锟斤拷tr锟斤拷一锟斤拷mouseover/mouseout锟铰硷拷 + $(".tr").mouseover(function() { + $(this).addClass("over"); + var contentDateBorder = ""; + $("#table").find("tr").each(function () { + if($(this).hasClass("select") || $(this).hasClass("over")){ + // contentDateBorder += + // $(this).children('td:eq(4)').text() +"

"; + } + }); + $("#databorder").html(contentDateBorder); + }) + $(".tr").mouseout(function() { + $(this).removeClass("over"); + var contentDateBorder = ""; + $("#table").find("tr").each(function () { + if($(this).hasClass("select") || $(this).hasClass("over")){ + // contentDateBorder += + // $(this).children('td:eq(4)').text() +"

"; + } + }); + $("#databorder").html(contentDateBorder); + }) + } + +// 这里可以重新发送请求来获得图层数据,用以优化 +function addLayerToMap() +{ + var selectedset = new Array(); + $(".tr.select").each(function(){ + selectedset.push(parseInt(($(this).find(".layerid").html()))); + }); + var newJsonData=null; + $.ajax({ + url: "./getLayerByIdlist.action", + async: false, + type: "GET", + dataType: "text", + data: { + idlist: "["+selectedset+"]" + },success: function (result) { + newJsonData = JSON.parse(result); + }}); + var temp = new Array(); + for(var i=0; i"; + html+=""+data[index]+""; + } + html+="" + $('#DetailInfoPanel').find('#detail').html(html); + $('#DetailInfoPanel').window({ + shadow:false, + }); + $('#DetailInfoPanel').window('open'); + $('#DetailInfoPanel').window('center'); +} + + +// 页面初始化 +$(document).ready(function () { + initMouseFunc();// 绑定tooltip的鼠标跟随事件 + // getLayerData();//获取图层数据(这里要重写(这里的具体代码见layerpanel.js + yukiInit();// 初始化(这里的代码见yukimap) + createAutoComplete();// 建立查询数据组(这里的代码见AttrSearch + checkAuthority(); + measureInit(); + Dragging(getDraggingDialog).enable(); + $("#myChangeBaseMap").parent().css({"left":"", "right":"5px"}); + var node = $('#baseMapTree').tree('find', basemapid);//找到id为”tt“这个树的节点id为”1“的对象 + $('#baseMapTree').tree('select', node.target); + switch(basemapid) { + case 0: { + addLayer2Bottom(tianditu_annotation); + addLayer2Bottom(tianditu_road_layer); + break; + } + case 1: { + addLayer2Bottom(tianditu_image_annotation); + addLayer2Bottom(tianditu_image_layer); + break; + } + case 2: { + addLayer2Bottom(qing_layer); + break; + } + case 3: { + addLayer2Bottom(yuan_layer); + break; + } + } + $("#baseMapTree").tree({ + onSelect: function(node){ + switch(basemapid){ + case 0:{ + mymap.removeLayer(tianditu_road_layer); + mymap.removeLayer(tianditu_annotation); + break; + } + case 1:{ + mymap.removeLayer(tianditu_image_layer); + mymap.removeLayer(tianditu_image_annotation); + break; + } + case 2:{ + mymap.removeLayer(qing_layer); + break; + } + case 3:{ + mymap.removeLayer(yuan_layer); + break; + } + } + switch(node.text) { + case "地图": { + addLayer2Bottom(tianditu_annotation); + addLayer2Bottom(tianditu_road_layer); + basemapid = 0; + break; + } + case "影像": { + addLayer2Bottom(tianditu_image_annotation); + addLayer2Bottom(tianditu_image_layer); + basemapid = 1; + break; + } + case "清代": { + addLayer2Bottom(qing_layer); + basemapid = 2; + break; + } + case "元代": { + addLayer2Bottom(yuan_layer); + basemapid = 3; + break; + } + } + } + }); +}); + +function addLayer2Bottom(layer){ + var layers = mymap.getLayers(); + layers.insertAt(0, layer); +} + diff --git a/worldmap/static/js/md5.js b/worldmap/static/js/md5.js new file mode 100644 index 0000000..7cc1ed5 --- /dev/null +++ b/worldmap/static/js/md5.js @@ -0,0 +1,375 @@ +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_md5(s) { + return rstr2hex(rstr_md5(str2rstr_utf8(s))); +} +function b64_md5(s) { + return rstr2b64(rstr_md5(str2rstr_utf8(s))); +} +function any_md5(s, e) { + return rstr2any(rstr_md5(str2rstr_utf8(s)), e); +} +function hex_hmac_md5(k, d) { + return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); +} +function b64_hmac_md5(k, d) { + return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); +} +function any_hmac_md5(k, d, e) { + return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); +} + +/* + * Perform a simple self-test to see if the VM is working + */ +function md5_vm_test() { + return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72"; +} + +/* + * Calculate the MD5 of a raw string + */ +function rstr_md5(s) { + return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); +} + +/* + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ +function rstr_hmac_md5(key, data) { + var bkey = rstr2binl(key); + if (bkey.length > 16) + bkey = binl_md5(bkey, key.length * 8); + + var ipad = Array(16), + opad = Array(16); + for (var i = 0; i < 16; i++) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); +} + +/* + * Convert a raw string to a hex string + */ +function rstr2hex(input) { + try { + hexcase + } catch (e) { + hexcase = 0; + } + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var output = ""; + var x; + for (var i = 0; i < input.length; i++) { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + + hex_tab.charAt(x & 0x0F); + } + return output; +} + +/* + * Convert a raw string to a base-64 string + */ +function rstr2b64(input) { + try { + b64pad + } catch (e) { + b64pad = ''; + } + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var output = ""; + var len = input.length; + for (var i = 0; i < len; i += 3) { + var triplet = (input.charCodeAt(i) << 16) + | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) + | (i + 2 < len ? input.charCodeAt(i + 2) : 0); + for (var j = 0; j < 4; j++) { + if (i * 8 + j * 6 > input.length * 8) + output += b64pad; + else + output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + } + return output; +} + +/* + * Convert a raw string to an arbitrary string encoding + */ +function rstr2any(input, encoding) { + var divisor = encoding.length; + var i, + j, + q, + x, + quotient; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + var dividend = Array(Math.ceil(input.length / 2)); + for (i = 0; i < dividend.length; i++) { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /* + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. All remainders are stored for later + * use. + */ + var full_length = Math.ceil(input.length * 8 / + (Math.log(encoding.length) / Math.log(2))); + var remainders = Array(full_length); + for (j = 0; j < full_length; j++) { + quotient = Array(); + x = 0; + for (i = 0; i < dividend.length; i++) { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if (quotient.length > 0 || q > 0) + quotient[quotient.length] = q; + } + remainders[j] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + var output = ""; + for (i = remainders.length - 1; i >= 0; i--) + output += encoding.charAt(remainders[i]); + + return output; +} + +/* + * Encode a string as utf-8. + * For efficiency, this assumes the input is valid utf-16. + */ +function str2rstr_utf8(input) { + var output = ""; + var i = -1; + var x, + y; + while (++i < input.length) { + /* Decode utf-16 surrogate pairs */ + x = input.charCodeAt(i); + y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; + if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i++; + } + + /* Encode output as utf-8 */ + if (x <= 0x7F) + output += String.fromCharCode(x); + else if (x <= 0x7FF) + output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F), + 0x80 | (x & 0x3F)); + else if (x <= 0xFFFF) + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + else if (x <= 0x1FFFFF) + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + } + return output; +} + +/* + * Encode a string as utf-16 + */ +function str2rstr_utf16le(input) { + var output = ""; + for (var i = 0; i < input.length; i++) + output += String.fromCharCode(input.charCodeAt(i) & 0xFF, + (input.charCodeAt(i) >>> 8) & 0xFF); + return output; +} + +function str2rstr_utf16be(input) { + var output = ""; + for (var i = 0; i < input.length; i++) + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, + input.charCodeAt(i) & 0xFF); + return output; +} + +/* + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ +function rstr2binl(input) { + var output = Array(input.length >> 2); + for (var i = 0; i < output.length; i++) + output[i] = 0; + for (var i = 0; i < input.length * 8; i += 8) + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); + return output; +} + +/* + * Convert an array of little-endian words to a string + */ +function binl2rstr(input) { + var output = ""; + for (var i = 0; i < input.length * 32; i += 8) + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + return output; +} + +/* + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ +function binl_md5(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for (var i = 0; i < x.length; i += 16) { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); +} + +/* + * These functions implement the four basic operations the algorithm uses. + */ +function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); +} +function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} +function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); +} diff --git a/worldmap/static/js/measure.js b/worldmap/static/js/measure.js new file mode 100644 index 0000000..3c8f8a6 --- /dev/null +++ b/worldmap/static/js/measure.js @@ -0,0 +1,277 @@ +//这个js需要封装成一个class +var source = new ol.source.Vector(); + + var vector = new ol.layer.Vector({ + source: source, + style: new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new ol.style.Stroke({ + color: '#ffcc33', + width: 2 + }), + image: new ol.style.Circle({ + radius: 7, + fill: new ol.style.Fill({ + color: '#ffcc33' + }) + }) + }) + }); + + + /** + * Currently drawn feature. + * @type {ol.Feature} + */ + var sketch; + + + /** + * The help tooltip element. + * @type {Element} + */ + var helpTooltipElement; + + + /** + * Overlay to show the help messages. + * @type {ol.Overlay} + */ + var helpTooltip; + + + /** + * The measure tooltip element. + * @type {Element} + */ + var measureTooltipElement; + + + /** + * Overlay to show the measurement. + * @type {ol.Overlay} + */ + var measureTooltip; + + + /** + * Message to show when the user is drawing a polygon. + * @type {string} + */ + var continuePolygonMsg = 'Click to continue drawing the polygon'; + + + /** + * Message to show when the user is drawing a line. + * @type {string} + */ + var continueLineMsg = 'Click to continue drawing the line'; + + + /** + * Handle pointer move. + * @param {ol.MapBrowserEvent} evt The event. + */ + var pointerMoveHandler = function(evt) { + if (evt.dragging) { + return; + } + /** @type {string} */ + var helpMsg = 'Click to start drawing'; + + if (sketch) { + var geom = (sketch.getGeometry()); + if (geom instanceof ol.geom.Polygon) { + helpMsg = continuePolygonMsg; + } else if (geom instanceof ol.geom.LineString) { + helpMsg = continueLineMsg; + } + } + + helpTooltipElement.innerHTML = helpMsg; + helpTooltip.setPosition(evt.coordinate); + + helpTooltipElement.classList.remove('hidden'); + }; + + + + var draw; // global so we can remove it later + + + /** + * Format length output. + * @param {ol.geom.LineString} line The line. + * @return {string} The formatted length. + */ + var formatLength = function(line) { + var length = ol.Sphere.getLength(line); + var output; + if (length > 100) { + output = (Math.round(length / 1000 * 100) / 100) + + ' ' + 'km'; + } else { + output = (Math.round(length * 100) / 100) + + ' ' + 'm'; + } + return output; + }; + + + /** + * Format area output. + * @param {ol.geom.Polygon} polygon The polygon. + * @return {string} Formatted area. + */ + var formatArea = function(polygon) { + var area = ol.Sphere.getArea(polygon); + var output; + if (area > 10000) { + output = (Math.round(area / 1000000 * 100) / 100) + + ' ' + 'km2'; + } else { + output = (Math.round(area * 100) / 100) + + ' ' + 'm2'; + } + return output; + }; + + function addInteraction() { + mymap.addLayer(vector); + var type = 'LineString'; + draw = new ol.interaction.Draw({ + source: source, + type: /** @type {ol.geom.GeometryType} */ (type), + style: new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.5)', + lineDash: [10, 10], + width: 2 + }), + image: new ol.style.Circle({ + radius: 5, + stroke: new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.7)' + }), + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }) + }) + }) + }); + mymap.addInteraction(draw); + + createMeasureTooltip(); + createHelpTooltip(); + + var listener; + draw.on('drawstart', + function(evt) { + // set sketch + sketch = evt.feature; + + /** @type {ol.Coordinate|undefined} */ + var tooltipCoord = evt.coordinate; + + listener = sketch.getGeometry().on('change', function(evt) { + var geom = evt.target; + var output; + if (geom instanceof ol.geom.Polygon) { + output = formatArea(geom); + tooltipCoord = geom.getInteriorPoint().getCoordinates(); + } else if (geom instanceof ol.geom.LineString) { + output = formatLength(geom); + tooltipCoord = geom.getLastCoordinate(); + } + measureTooltipElement.innerHTML = output; + measureTooltip.setPosition(tooltipCoord); + }); + }, this); + + draw.on('drawend', + function() { + measureTooltipElement.className = 'mstooltip mstooltip-static'; + measureTooltip.setOffset([0, -7]); + // unset sketch + sketch = null; + // unset tooltip so that a new one can be created + measureTooltipElement = null; + createMeasureTooltip(); + ol.Observable.unByKey(listener); + }, this); + } + + + /** + * Creates a new help tooltip + */ + function createHelpTooltip() { + if (helpTooltipElement) { + helpTooltipElement.parentNode.removeChild(helpTooltipElement); + } + helpTooltipElement = document.createElement('div'); + helpTooltipElement.className = 'mstooltip hidden'; + helpTooltip = new ol.Overlay({ + element: helpTooltipElement, + offset: [15, 0], + positioning: 'center-left' + }); + mymap.addOverlay(helpTooltip); + } + + + /** + * Creates a new measure tooltip + */ + function createMeasureTooltip() { + if (measureTooltipElement) { + measureTooltipElement.parentNode.removeChild(measureTooltipElement); + } + measureTooltipElement = document.createElement('div'); + measureTooltipElement.className = 'mstooltip mstooltip-measure'; + measureTooltip = new ol.Overlay({ + element: measureTooltipElement, + offset: [0, -15], + positioning: 'bottom-center' + }); + mymap.addOverlay(measureTooltip); + } + + + /** + * Let user change the geometry type. + */ + var measureOver = function(){ + mymap.removeInteraction(draw); + + mymap.removeOverlay(helpTooltip); + var res = $('.mstooltip'); + for(var i=0;i=splitList[splitList.length-1].start) color = splitList[splitList.length-1].value; + break; + } + } + return new ol.style.Style({ + fill: new ol.style.Fill({ + color: color + }), + stroke: new ol.style.Stroke({ + color: highlight, + width: 1 + })/*, 效果不是很理想 也找不到通过这个的函数回调的文本设置方案 + text: new ol.style.Text({ + text:name + })*/ + }); + return stylefuntion; +}; +/* clone array a To b */ +OlvLayer.prototype.clone = function(a){ + b = new Array(); + for(var i=0;i' + + '

' + + info["mapname"] + + '

' + + '
' + + info["userid"] + + '
'; + } + }); + + if(strHtml!=""){ + mes.push(strHtml); + } + list.html(mes[curPage]); + var pager = $("#pager"); + pager.html("当前"+(curPage+1)+"//"+(page+1)+"页"); + });//ready + + + function search(){ + var key = $("#searchInput").val(); + var data; + $.ajax({ + url: "./getActiveUser.action", + async: false, + type: "POST", + dataType: "text", + data: { + },success: function (result) { + username = $.parseJSON(result).username; + userid = $.parseJSON(result).userid; + }}); + //发一个同步请求,得到地图json + $.ajax({ + url: "./getMapList.action", + async: false, + type: "POST", + dataType: "text", + data: { + userid: userid + }, + success: function (result) { + + data = $.parseJSON(result); + } + }); + var list = $("#resultList"); + var strHtml = ""; //存储数据的变量 + var count = 0; + page = 0; + list.empty(); + mes.splice(0,mes.length); //清空数组 + $.each(data,function(infoIndex,info){ + var mapname = info["mapname"]; + if(mapname.indexOf(key)>=0){ //判断地图名中是否包含关键词 + if(info["accessibility"]=="0"&&(info["userid"]!=userid)){} //判断地图对于用户是否可见 + else{ + count = count + 1; + if(count==4){ //每页显示3条记录 + mes.push(strHtml); + strHtml=""; + page=page+1; + count=1; + } + strHtml += ''; + } + } + else{} + }); + if(strHtml!=""){ + mes.push(strHtml); + } + list.html(mes[0]); + var pager = $("#pager"); + pager.html("当前"+(curPage+1)+"//"+(page+1)+"页"); + } + + //点击地图信息条目后执行的函数 + function openMap(mapid){ + //TODO 改成ajax的重定向 + location.href = "http://localhost:8080/AncientMap/main.action?mapid=" + mapid; + } + + //向前翻页 + function prevPage(){ + if(curPage>0){ + curPage-=1; + var list = $("#resultList"); + list.empty(); + list.html(mes[curPage]); + var pager = $("#pager"); + pager.html("当前"+(curPage+1)+"//"+(page+1)+"页"); + } + } + //向后翻页 + function nextPage(){ + if(curPage 0) { + t = false;//每次执行滑动前将t设置为false,以免在执行window.scroll函数时不断调用滑动函数 + y = y + heig; + $("body").animate({scrollTop: y}, 1000, function () { + beforescroll = y; + t = true;//在animate的回调函数中将t设置为true,即在每次动画完成后才能够再次调用roll函数 + }); + return false; + } + else if (delta < 0) { + t = false; + y = y - heig; + $("body").animate({scrollTop: y}, 1000, function () { + beforescroll = y; + t = true; + }); + return false; + } + } + } + } + $(window).scroll(roll); +}) diff --git a/worldmap/static/js/uplayerPage.js b/worldmap/static/js/uplayerPage.js new file mode 100644 index 0000000..f313771 --- /dev/null +++ b/worldmap/static/js/uplayerPage.js @@ -0,0 +1,144 @@ +//jQuery time +var current_fs, next_fs, previous_fs; //fieldsets +var left, opacity, scale; //fieldset properties which we will animate + +$(".next1").click(function(){ + current_fs = $(this).parent(); + next_fs = $(this).parent().next(); + var index; + for(var i=0;i<4;i++) + { + if($(this).siblings("div").eq(i).hasClass("border")){ + index = i; + $("#content").css("height","1200px"); + $("#msform fieldset").css("height","1000px"); + } + } + if(index == undefined){ + $('#warnModalLabel').html("错误提示"); + $('#warnMessage').html("请先选择模板"); + $('#warnModal').modal('show'); + } + else { + //先以index为标记向session里面设定图层类型……以便前端整合上传界面 + $.ajax({ + url: "./setLayerType.action", + async: false, + type: "POST", + dataType: "text", + data: { + LayerType:index + },success: function (result) { + console.log(result); + }}); + // + next_fs = $(this).parent().siblings("fieldset").eq(index); + console.log(next_fs); + //activate next step on progressbar using the index of next_fs + $("#progressbar li").eq(1).addClass("active"); + + //show the next fieldset + next_fs.show(); + //hide the current fieldset with style + current_fs.animate({opacity: 0}, { + step: function (now, mx) { + //as the opacity of current_fs reduces to 0 - stored in "now" + //1. scale current_fs down to 80% + scale = 1 - (1 - now) * 0.2; + //2. bring next_fs from the right(50%) + left = (now * 50) + "%"; + //3. increase opacity of next_fs to 1 as it moves in + opacity = 1 - now; + current_fs.css({'transform': 'scale(' + scale + ')'}); + next_fs.css({'left': left, 'opacity': opacity}); + }, + duration: 800, + complete: function () { + current_fs.hide(); + animating = false; + }, + //this comes from the custom easing plugin + easing: 'easeInOutBack' + }); + } +}); +$(".next2").click(function(){ + if($(".uploadInfo")[0].innerHTML=="上传成功"){ + $("#content").css("height","650px"); + $("#msform fieldset").css("height","450px"); + //current fieldset + current_fs = $(this).parent(); + //next fieldset 下一个要打开的fieldset——图层制作成功 + next_fs = $(this).parent().siblings("fieldset").eq(4); + //activate next step on progressbar using the index of next_fs + $("#progressbar li").eq(2).addClass("active"); + + //show the next fieldset + next_fs.show(); + //hide the current fieldset with style + current_fs.animate({opacity: 0}, { + step: function (now, mx) { + //as the opacity of current_fs reduces to 0 - stored in "now" + //1. scale current_fs down to 80% + scale = 1 - (1 - now) * 0.2; + //2. bring next_fs from the right(50%) + left = (now * 50) + "%"; + //3. increase opacity of next_fs to 1 as it moves in + opacity = 1 - now; + current_fs.css({'transform': 'scale(' + scale + ')'}); + next_fs.css({'left': left, 'opacity': opacity}); + }, + duration: 800, + complete: function () { + current_fs.hide(); + animating = false; + }, + //this comes from the custom easing plugin + easing: 'easeInOutBack' + }); + } + else{ + $('#warnModalLabel').html("错误提示"); + $('#warnMessage').html("请先正确上传数据"); + $('#warnModal').modal('show'); + } +}); +$(".previous1").click(function(){ + if(animating) return false; + animating = true; + $("#content").css("height","650px"); + $("#msform fieldset").css("height","450px"); + + current_fs = $(this).parent(); + // previous_fs = $(this).parent().prev(); + previous_fs = $(this).parent().siblings("fieldset").eq(0); + //de-activate current step on progressbar + $("#progressbar li").eq(1).removeClass("active"); + + //show the previous fieldset + previous_fs.show(); + //hide the current fieldset with style + current_fs.animate({opacity: 0}, { + step: function(now, mx) { + //as the opacity of current_fs reduces to 0 - stored in "now" + //1. scale previous_fs from 80% to 100% + scale = 0.8 + (1 - now) * 0.2; + //2. take current_fs to the right(50%) - from 0% + left = ((1-now) * 50)+"%"; + //3. increase opacity of previous_fs to 1 as it moves in + opacity = 1 - now; + current_fs.css({'left': left}); + previous_fs.css({'transform': 'scale('+scale+')', 'opacity': opacity}); + }, + duration: 800, + complete: function(){ + current_fs.hide(); + animating = false; + }, + //this comes from the custom easing plugin + easing: 'easeInOutBack' + }); +}); +$(".submit").click(function(){ + return false; +}) \ No newline at end of file diff --git a/worldmap/static/js/userCenter.js b/worldmap/static/js/userCenter.js new file mode 100644 index 0000000..ee4240b --- /dev/null +++ b/worldmap/static/js/userCenter.js @@ -0,0 +1,200 @@ +$(function () { + //1.初始化Table + var oTable = new TableInit(); + oTable.Init(); + + //2.初始化Button的点击事件 + var oButtonInit = new ButtonInit(); + oButtonInit.Init(); + +}); + + +var TableInit = function () { + var oTableInit = new Object(); + //初始化Table + oTableInit.Init = function () { + $('#tb_layers').bootstrapTable({ + url: './getLayerList.action', //请求后台的URL(*) + method: 'get', //请求方式(*) + //toolbar: '#toolbar', //工具按钮用哪个容器 + striped: true, //是否显示行间隔色 + cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*) + pagination: true, //是否显示分页(*) + sortable: false, //是否启用排序 + sortOrder: "asc", //排序方式 + queryParams: oTableInit.layerQueryParams,//传递参数(*) + sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*) + pageNumber:1, //初始化加载第一页,默认第一页 + pageSize: 10, //每页的记录行数(*) + pageList: [10, 25, 50, 100], //可供选择的每页的行数(*) + search: false, //是否显示表格搜索,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大 + strictSearch: true, + showColumns: true, //是否显示所有的列 + showRefresh: true, //是否显示刷新按钮 + minimumCountColumns: 2, //最少允许的列数 + clickToSelect: false, //是否启用点击选中行 + height: 500, //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度 + uniqueId: "ID", //每一行的唯一标识,一般为主键列 + showToggle:true, //是否显示详细视图和列表视图的切换按钮 + cardView: false, //是否显示详细视图 + detailView: false, //是否显示父子表 + columns: [{ + checkbox: true + }, { + field: 'id', + title: 'ID' + }, { + field: 'layername', + title: '图层名' + },{ + field: 'type', + title: '图层类型' + }, { + field: 'appendDataSrc', + title: '附加文件' + }, + { + field: 'storelocation', + title: '源文件' + }, + { + field:'course', + title:'学科' + }] + }); + + $('#tb_maps').bootstrapTable({ + url: './getMapList3.action', //请求后台的URL(*) + method: 'get', //请求方式(*) + //toolbar: '#toolbar', //工具按钮用哪个容器 + striped: true, //是否显示行间隔色 + cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*) + pagination: true, //是否显示分页(*) + sortable: false, //是否启用排序 + sortOrder: "asc", //排序方式 + queryParams: oTableInit.mapQueryParams,//传递参数(*) + sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*) + pageNumber:1, //初始化加载第一页,默认第一页 + pageSize: 10, //每页的记录行数(*) + pageList: [10, 25, 50, 100], //可供选择的每页的行数(*) + search: false, //是否显示表格搜索,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大 + strictSearch: true, + showColumns: true, //是否显示所有的列 + showRefresh: true, //是否显示刷新按钮 + minimumCountColumns: 2, //最少允许的列数 + clickToSelect: false, //是否启用点击选中行 + height: 500, //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度 + uniqueId: "ID", //每一行的唯一标识,一般为主键列 + showToggle:true, //是否显示详细视图和列表视图的切换按钮 + cardView: false, //是否显示详细视图 + detailView: false, //是否显示父子表 + columns: [{ + checkbox: true + }, { + field: 'id', + title: 'ID' + }, { + field: 'mapname', + title: '地图名' + }, { + field: 'userid', + title: '建立地图用户id' + }, { + field: 'accessibility', + title: '地图公开性' + }, { + field: 'addable', + title: '审核状态' + }], + onClickRow: function (item, $element) { + window.open("http://localhost:8080/AncientMap/main.action?mapid="+item.id); + return false; + } + }); + }; + + //得到查询的参数 + oTableInit.layerQueryParams = function (params) { + var temp = { + limit: params.limit, //页面大小 + offset: params.offset, //页码 + layername: $("#layer_txt_layername").val().trim() + }; + return temp; + }; + + oTableInit.mapQueryParams = function (params) { + var temp = { + limit: params.limit, //页面大小 + offset: params.offset, //页码 + mapname: $("#map_txt_mapname").val().trim() + }; + return temp; + }; + + return oTableInit; +}; + +var ButtonInit = function () { + var oInit = new Object(); + var postdata = {}; + + oInit.Init = function () { + $('#layer_btn_query').click( + function(){ + $('#tb_layers').bootstrapTable('refresh'); + }); + $('#map_btn_query').click( + function(){ + $('#tb_maps').bootstrapTable('refresh'); + }); + $('#map_btn_open').click( + function(){ + var mapList = getSelectMapIdList(); + $.ajax({ + url: "./openMap.action", + async: true, + type: "POST", + dataType: "text", + data: { + mapList: JSON.stringify(mapList) + }, + success: function (result) { + $('#tb_maps').bootstrapTable('refresh'); + } + }) + + }); + $('#map_btn_close').click( + function(){ + var mapList = getSelectMapIdList(); + $.ajax({ + url: "./closeMap.action", + async: true, + type: "POST", + dataType: "text", + data: { + mapList: JSON.stringify(mapList) + }, + success: function (result) { + $('#tb_maps').bootstrapTable('refresh'); + } + }) + + }); + }; + + return oInit; +}; + +function getSelectMapIdList() +{ + var selections = $('#tb_maps').bootstrapTable('getSelections'); + var mapList = new Array(); + for (var i=0;imaxX) maxX=tx; + if(txmaxY) maxY=ty; + if(tymaxX) maxX=tx; + if(txmaxY) maxY=ty; + if(ty maxC) { + maxC = item.count; + } + if (item.count < minC) { + minC = item.count; + } + return true; + } + } + + return false; + } + }); + + splitList = yukiColorMapper(minC, maxC, '#ffddee', '#aa4466', splitNum, splitType); + dataSet = new mapv.DataSet(data); + }); + $.ajaxSettings.async = true; + }/* + dataSet = layer.data; + minC = maxC = Number(dataSet[0].value); + + for (var i = 0; i < dataSet.length; i++) { + var count = Number(dataSet[i].value); + //item.bound = getBoundBox(item.geometry.coordinates); + if (count > maxC) { + maxC = count; + continue; + } + if (count < minC) { + minC = count; + } + } + + maxC = maxC; + minC = minC; + splitList = yukiColorMapper(minC, maxC, '#ffddee', '#aa4466', splitNum, splitType); +*/ + { + var options = { + draw: 'choropleth', + max: maxC, + min: minC, + zIndex:myMapMana.maplayerlist[layerindex].zIndex, + highlight:highlight, + splitNum: splitNum, + splitType: splitType, + splitList: splitList, + shadowColor: 'rgba(0, 0, 0, 0.5)', // 投影颜色 + shadowBlur: 10, // 投影模糊级数 + /*methods: { + click: function (item) { + if (tooltipPub.flag == 0) { + $('#QueryBoard').window('open'); + $('#QueryBoard').window('expand'); + $('#layerL0').text(layer.layername); + $('#nameL0').text(item.name); + $('#countL0').text(item.count); + $('#typeL0').text('面'); + } + }, + mousemove: function (item) { + item = item || {}; + var flag = 0; + var data = dataSet.get(); + for (var i = 0; i < data.length; i++) { + var a,b; + if(has(item.id)) {a=item.id;b=data[i].id;} + else if(has(item.gid)) {a=item.gid;b=data[i].gid;} + + if (has(a)&&a==b) {//这里也是 geojson里面是gid 总之item的下面的东西的类型都要注意和geojson里面得对应字段的匹配问题 + data[i].fillStyle = layer.style.options.highlight; + flag = 1; + if (tooltipPub.flag == 0) { + $("#mytooltip").html(layer.layername+':'+item.name+':'+item.count); + $("#mytooltip").css("top", (mousePos.y - 40) + "px"); + $("#mytooltip").css("left", (mousePos.x + 10) + "px"); + $("#mytooltip").css("display", "inline"); + } + } else { + data[i].fillStyle = null; + } + } + if (flag == 0) { $("#mytooltip").css("display", "none") }; + dataSet.set(data); + } + },*/ + globalAlpha: 0.9, + draw: 'choropleth', + appendsrc:appendsrc + } + //完成设定 进行绘图 + myMapMana.maplayerlist[layerindex].style = { "options": options, "dataSet": dataSet }; + myMapMana.maplayerlist[layerindex].mapv = new OlvLayer(mymap, options.appendsrc,dataSet, options,layerindex); + //myMapMana.maplayerlist[layerindex].mapv.destroy(); + } + return true; +} +function drawL1(layer, layerindex) {//等级符号图 (打算后面全用mapv重构 + if (has(myMapMana.maplayerlist[layerindex].style)) { + //同步zIndex值之后重绘 + //对已有style做修改后没反应就在此重设 + //回调函数必须在此重设...这里就有个问题 如何在字符串和回调函数之间转换 + myMapMana.maplayerlist[layerindex].style.series.symbolSize + = function (val, param) { + var temp = myMapMana.maplayerlist[layerindex].style.append; + //需要用类似模板的函数重构,就是把计算函数作为参数传入的那种... + if (temp.mapperType == "linear") + return (val[2] - temp.min) / (temp.max - temp.min) * (temp.maxSize - temp.minSize) + temp.minSize; + else if (temp.mapperType == "log") { + //确保取对数之前不出现负数 + var offset = 1; + if (temp.min < 0) offset = -temp.min + 1; + return (Math.log(val[2] + offset) - Math.log(temp.min + offset)) / (Math.log(temp.max + offset) - Math.log(temp.min + offset)) * (temp.maxSize - temp.minSize) + temp.minSize; + } + else if (temp.mapperType == "square") { + var offset = 0; + if (temp.min < 0) offset = -temp.min; + return ((val[2] + offset) + (temp.min + offset)) * ((val[2] + offset) - (temp.min + offset)) / ((temp.max + offset) - (temp.min + offset)) / ((temp.max + offset) + (temp.min + offset)) * (temp.maxSize - temp.minSize) + temp.minSize; + } + else return val[2]; + } + myMapMana.maplayerlist[layerindex].style.series.itemStyle.normal.color + = function (param) { + var temp = myMapMana.maplayerlist[layerindex].style.append; + var maxrgb = HexToColorArray(temp.maxColor); + var minrgb = HexToColorArray(temp.minColor); + var dvalue; + if (temp.mapperType == "log") { + //确保取对数之前不出现负数 + var offset = 1; + if (temp.min < 0) offset = -temp.min + 1; + dvalue = (Math.log(param.value[2] + offset) - Math.log(temp.min + offset)) / (Math.log(temp.max + offset) - Math.log(temp.min + offset)); + } + else if (temp.mapperType == "square") { + var offset = 0; + if (temp.min < 0) offset = -temp.min; + dvalue = (param.value[2] - temp.min) * (param.value[2] + temp.min) / (temp.max - temp.min) / (temp.max + temp.min) + } + else + { dvalue = (param.value[2] - temp.min) / (temp.max - temp.min); } + var dr = parseInt(dvalue * (maxrgb.r - minrgb.r)); + var dg = parseInt(dvalue * (maxrgb.g - minrgb.g)); + var db = parseInt(dvalue * (maxrgb.b - minrgb.b)); + var dycolor = { + r: minrgb.r + dr, + g: minrgb.g + dg, + b: minrgb.b + db + }; + return ColorArrayToHex(dycolor); + } + myMapMana.maplayerlist[layerindex].style.series.z = myMapMana.maplayerlist[layerindex].zIndex; + return myMapMana.maplayerlist[layerindex].style.series; + } + var data = layer.data; + var maxvalue = Number(data[0].value); + var minvalue = Number(data[0].value); + var maxsize = 20; + var minsize = 5; + var maxcolor = "#5784ef"; + var mincolor = "#aad3ff"; + var mappertype = "linear"; + var res = []; + for (var i = 0; i < data.length; i++) { + res.push({ + name: data[i].name, + lonlat:[Number(data[i].x), Number(data[i].y)], + value: [0, 0, Number(data[i].value),data[i].featureid,data[i].layerid] + }); + if (res[i].value[2] > maxvalue) maxvalue = res[i].value[2]; + if (res[i].value[2] < minvalue) minvalue = res[i].value[2]; + } + var item = { + name: layer.layername, + type: 'scatter', + coordinateSystem: 'geo', + data: res, + z: layer.zIndex, + symbol: 'circle', + symbolSize: function (val, param) { + return (val[2] - minvalue) / (maxvalue - minvalue) * (maxsize - minsize) + minsize; + }, + label: { + normal: { + formatter: '{b}', + position: 'right', + show: false + }, + emphasis: { + textStyle: { + fontStyle: 'normal', + fontWeight: 'bold ', + fontFamily: 'sans-serif', + fontSize: 15, + }, + show: true + } + }, + itemStyle: { + normal: { + color: function (param) { + var maxrgb = HexToColorArray(maxcolor); + var minrgb = HexToColorArray(mincolor); + var dvalue = (param.value[2] - minvalue) / (maxvalue - minvalue); + var dr = parseInt(dvalue * (maxrgb.r - minrgb.r)); + var dg = parseInt(dvalue * (maxrgb.g - minrgb.g)); + var db = parseInt(dvalue * (maxrgb.b - minrgb.b)); + var dycolor = { + r: minrgb.r + dr, + g: minrgb.g + dg, + b: minrgb.b + db + }; + return ColorArrayToHex(dycolor); + } + }, + emphasis: { + color: '#333399' + } + } + } + var avgDis = getAverageDistance(res); + myMapMana.maplayerlist[layerindex].style = { + series: item, append: { + max: maxvalue, + min: minvalue, + maxSize: maxsize, + minSize: minsize, + maxColor: maxcolor, + minColor: mincolor, + mapperType: mappertype, + avgDis: avgDis + } + }; + return item; +} +function drawL2(layer, layerindex) {//点图 (打算后面全用mapv重构 + if (has(myMapMana.maplayerlist[layerindex].style)) { + //同步zIndex值之后重绘 + //对已有style做修改后没反应就在此重设 + //回调函数必须在此重设 + myMapMana.maplayerlist[layerindex].style.series.z = myMapMana.maplayerlist[layerindex].zIndex; + return myMapMana.maplayerlist[layerindex].style.series; + } + var data = layer.data; + var res = []; + for (var i = 0; i < data.length; i++) { + res.push({ + name: data[i].name, + lonlat:[Number(data[i].x), Number(data[i].y)], + value: [0, 0, data[i].value,data[i].featureid,data[i].layerid] + }); + } + var item = { + name: layer.layername, + type: 'scatter', + coordinateSystem: 'geo', + data: res, + z: layer.zIndex, + symbol: 'circle', + symbolSize: 5, + label: { + normal: { + formatter: '{b}', + position: 'right', + show: false + }, + emphasis: { + formatter: '{b}', + textStyle: { + fontStyle: 'normal', + fontWeight: 'bold ', + fontFamily: 'sans-serif', + fontSize: 15, + }, + show: true + } + }, + itemStyle: { + normal: { + color: '#5376EE' + }, + emphasis: { + color: '#333399' + } + } + } + var avgDis = getAverageDistance(res); + myMapMana.maplayerlist[layerindex].style = + {series: item, append: { + avgDis: avgDis + } +}; + return item; +} +function drawL3(layer, layerindex) {//轨迹图 (打算后面全用mapv重构 + if (has(myMapMana.maplayerlist[layerindex].style)) { + //同步zIndex值之后重绘 + //对已有style做修改后没反应就在此重设 + //回调函数必须在此重设 + myMapMana.maplayerlist[layerindex].style.z = myMapMana.maplayerlist[layerindex].zIndex; + return myMapMana.maplayerlist[layerindex].style; + } + var data = layer.data; + var res = []; + //TODO 完善线图层的多字段处理 + for (var i = 0; i < data.length; i++) { + res.push({ + ID: data[i].name, + lonlat:$.parseJSON(data[i].linegeom), + coords: [[0,0],[0,0]], + value:[data[i].value,data[i].featureid,data[i].layerid] + }); + } + var item = + { + name: layer.layername, + type: 'lines', + coordinateSystem: 'geo', + z: layer.zIndex, + large: true, + effect: { + show: false, + constantSpeed: 10, + symbol: 'pin',//ECharts 提供的标记类型包括 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow' + symbolSize: 6, + trailLength: 0, + color: '#eee955' + }, + lineStyle: { + normal: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#eee955' }, { offset: 1, color: '#f6082d' }], false), //轨迹线颜色 + width: 1.5, + opacity: 1, + curveness: 0 //轨迹线弯曲度 + } + }, + data: res + } + myMapMana.maplayerlist[layerindex].style = item; + return item; +} +function redrawLegend() +{ + var legendContent="图例
"; + for(var i=0;i'; + var styleInfo = layer.style.options; + var colorlen = styleInfo.splitList.length; + var maxcolor = styleInfo.splitList[colorlen-1].value; + var mincolor = styleInfo.splitList[0].value; + var maxval = styleInfo.max; + var minval = styleInfo.min; + legendContent+='
'; + legendContent+=' '+maxval+'
'; + legendContent+='
'; + legendContent+=' '+minval+'
'; + break; + case 1://等级符号图 + legendContent+=layer.layername+'
'; + var styleInfo = layer.style.append; + var maxcolor = styleInfo.maxColor; + var mincolor = styleInfo.minColor; + var maxval = styleInfo.max; + var minval = styleInfo.min; + var symbol = layer.style.series.symbol; + if(symbol=="arrow" || symbol=="triangle"){ + legendContent+='
'; + legendContent+=' '+maxval+'
'; + legendContent+='
'; + legendContent+=' '+minval+'
'; + } + else{ + legendContent+='
'; + legendContent+=' '+maxval+'
'; + legendContent+='
'; + legendContent+=' '+minval+'
'; + } + break; + case 2://点图 + var pointcolor = layer.style.series.itemStyle.normal.color; + var symbol = layer.style.series.symbol; + if(symbol=="arrow" || symbol=="triangle") + legendContent+='
'; + else + legendContent+='
'; + legendContent+=' '+layer.layername+'
'; + break; + case 3://轨迹图 + var colors = layer.style.lineStyle.normal.color.colorStops; + var begincolor = colors[0].color; + var endcolor = colors[1].color; + legendContent+='
'; + legendContent+=' '+layer.layername+'
'; + break; + } + } + $('#mylegend').html(legendContent); + $('#mylegend').css("display","inline"); +} + + +var tooltipPub = { + flag: 0, + nowIndex:0 +} +function display() { + echartsoption = { + tooltip: { + trigger: 'none' + }, + geo:{} + , + // visualMap:{type: 'continuous', + // min: 0, + // max: 40, + // bottom: 50, + // calculable: true, + // inRange: { + // color: ['#50a3ba', '#eac736', '#d94e5d'], + // symbolSize: [1, 30] + // }, + // textStyle: { + // color: '#44e' + // }}, + series: [] + }; + + mymap = new ol.Map({ + controls: ol.control.defaults({ + attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + collapsible: false + }) + }).extend([ + new ol.control.ScaleLine({units:'metric'}) + ]),view: new ol.View({ + center: ol.proj.fromLonLat([myMapMana.centerx, myMapMana.centery]), + zoom:myMapMana.zoomlevel + }), + target: 'map', + logo : false + }); + // 天地图 + tianditu_road_layer = new ol.layer.Tile({ + title: "天地图路网", + source: new ol.source.XYZ({ + url: "http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}" + }) + }); + tianditu_annotation = new ol.layer.Tile({ + title: "天地图文字标注", + source: new ol.source.XYZ({ + url: 'http://t3.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}' + }) + }); + // 天地图影像 + tianditu_image_layer = new ol.layer.Tile({ + title: "天地图影像", + source: new ol.source.XYZ({ + url: "http://t4.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}" + }) + }); + tianditu_image_annotation = new ol.layer.Tile({ + title: "天地图影像文字标注", + source: new ol.source.XYZ({ + url: "http://t4.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}" + }) + }); + // 清代 + qing_layer = new ol.layer.Vector({ + source: new ol.source.Vector({ + url: "./geoJson/new_qing_prov.json", + format: new ol.format.GeoJSON() + }) + }); + // 元代 + yuan_layer = new ol.layer.Vector({ + source: new ol.source.Vector({ + url: "./geoJson/yuan_t.json", + format: new ol.format.GeoJSON() + }) + }); + + //local google +/* var google_source = new ol.source.XYZ({ + url : 'http://202.121.180.132/TerrainWithLabel/{z}/{x}/{y}.jpg' + }); + var google_layer = new ol.layer.Tile({ + name : "google_layer", + chName : "谷歌地图", + source : google_source + }); + mymap.addLayer(google_layer);*/ + + mymap.once('postrender', function (e) { + if (myecharts !== undefined) + return; + myecharts = new OpenLayer3Ext(mymap, echarts); + var container = myecharts.getEchartsContainer(); + var mec = myecharts.initECharts(container); + window.onresize = myecharts.resize; + myecharts.setOption(echartsoption,true); + myecharts.bindEvent(); + mec.on('mouseover', function (params) { + tooltipPub.flag = 1; + var tooltipHtml=""; + var data = params.value; + var len = params.value.length; + switch(params.seriesType){ + case "lines": + tooltipHtml = params.seriesName+':'+data[len-3]; + break; + case "scatter": + tooltipHtml = params.seriesName+':'+params.name+','+data[len-3]; + } + $("#mytooltip").html(tooltipHtml); + $("#mytooltip").css("top", (mousePos.y - 40) + "px"); + $("#mytooltip").css("left", (mousePos.x + 10) + "px"); + $("#mytooltip").css("display", "inline"); + }); + mec.on('mouseout', function (params) { + tooltipPub.flag = 0; + $("#mytooltip").css("display", "none"); + }); + mec.on('click', function (params) { + $('#QueryBoard').window({ + shadow:false + }); + $('#QueryBoard').window('open'); + var html="ID图层地名基本数值"; + var count=0; + html+=""; + for(var i = 0 ; i< params.length;i++) + { + html+=""; + var len = params[i].value.length; + html+=""+params[i].value[len-1]+","+params[i].value[len-2]+""; + html+=""+params[i].seriesName+""; + html+=""+params[i].name+""; + html+=""+params[i].value[len-3]+""; + html+=""; + } + html=html+'' + html=html+'记录数:'+count+'条'; + $('#QueryBoard').find('#res').html(html); + $('#QueryBoard').window('center'); + $('.rows').click(function(){ + var id = $(this).find('.ID').html(); + $.ajax({ + url: "./getFeaturesDetail.action", + async: false, + type: "POST", + dataType: "text", + data: { + index:"["+id+"]" + },success: function (result) { + ShowDetailInfoPanel($.parseJSON(result)); + }}); + }) + }); + var featureOverlay = new ol.layer.Vector({ + source: new ol.source.Vector(), + map: mymap, + style: new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: '#f00', + width: 1 + }), + fill: new ol.style.Fill({ + color: 'rgba(255,0,0,0.1)' + }) + }) + }); + + var highlight; + var displayFeatureInfo = function(pixel) { + + var feature = mymap.forEachFeatureAtPixel(pixel, function(feature) { + return feature; + }); + var flag = 0; + if(feature){ + flag = 1; + if (tooltipPub.flag == 0) { + $("#mytooltip").html(feature.values_.name); + $("#mytooltip").css("top", (mousePos.y - 40) + "px"); + $("#mytooltip").css("left", (mousePos.x + 10) + "px"); + $("#mytooltip").css("display", "inline"); + } + } + if (flag == 0) { $("#mytooltip").css("display", "none"); return;} + + if (feature !== highlight) { + if (highlight) { + featureOverlay.getSource().removeFeature(highlight); + } + if (feature) { + featureOverlay.getSource().addFeature(feature); + } + highlight = feature; + } + + }; + + mymap.on('pointermove', function(evt) { + if (evt.dragging) { + return; + } + var pixel = mymap.getEventPixel(evt.originalEvent); + displayFeatureInfo(pixel); + }); + + mymap.on('click', function(evt) { + displayFeatureInfo(evt.pixel); + }); + redraw(); + }); + +} +//保存数据的结构 +function Icelayer(YKlayer) { + this.mlid = YKlayer.mlid; + this.layerid = YKlayer.layerid; + this.state = YKlayer.state; + //TODO 拆分style为具体设定 + this.style = JSON.stringify(YKlayer.style); + this.zIndex = YKlayer.zIndex; +} +function Icemap(YKmap) { + var mapstyle = { + centerx: YKmap.centerx, + centery: YKmap.centery, + zoomlevel: YKmap.zoomlevel, + mapmode: YKmap.mapmode + } + this.id = YKmap.mapid; + this.userid = YKmap.mapuserid; + this.mapname = YKmap.mapname; + this.accessibility = YKmap.mapaccess; + this.mapstyle = JSON.stringify(mapstyle); + this.maptype = YKmap.maptype; + this.basemapid = YKmap.basemapid; +} + +function savemap() { + var userid; + $.ajax({ + url: "./getActiveUser.action", + async: false, + type: "POST", + dataType: "text", + data: { + },success: function (result) { + userid = $.parseJSON(result).userid; + }}); + if(userid==0) { + $('#alertModalLabel').html('错误提示'); + $('#alertMessage').html('请先登录或注册再保存地图'); + $('#alertModal').modal('show'); + return; + } + if(userid!=myMapMana.mapuserid) + { + myMapMana.mapid=0; + myMapMana.mapuserid=userid; + for(var i=0;i提示'); + if(parseInt(result)>0){ + myMapMana.mapid=parseInt(result);//更新新建的地图的ID + $('#alertMessage').html('保存成功!'); + $('#alertModal').modal('show'); + } + else + { + myMapMana.mapid=parseInt(result);//更新新建的地图的ID + $('#alertMessage').html('保存失败!'); + $('#alertModal').modal('show'); + } + } + }) + +} diff --git a/worldmap/static/plugin/bmap.js b/worldmap/static/plugin/bmap.js new file mode 100644 index 0000000..e19bb47 --- /dev/null +++ b/worldmap/static/plugin/bmap.js @@ -0,0 +1,424 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("echarts")); + else if(typeof define === 'function' && define.amd) + define(["echarts"], factory); + else if(typeof exports === 'object') + exports["bmap"] = factory(require("echarts")); + else + root["echarts"] = root["echarts"] || {}, root["echarts"]["bmap"] = factory(root["echarts"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/** + * BMap component extension + */ + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + __webpack_require__(1).registerCoordinateSystem( + 'bmap', __webpack_require__(2) + ); + __webpack_require__(3); + __webpack_require__(4); + + // Action + __webpack_require__(1).registerAction({ + type: 'bmapRoam', + event: 'bmapRoam', + update: 'updateLayout' + }, function (payload, ecModel) { + ecModel.eachComponent('bmap', function (bMapModel) { + var bmap = bMapModel.getBMap(); + var center = bmap.getCenter(); + bMapModel.setCenterAndZoom([center.lng, center.lat], bmap.getZoom()); + }); + }); + + return { + version: '1.0.0' + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 1 */ +/***/ function(module, exports) { + + module.exports = __WEBPACK_EXTERNAL_MODULE_1__; + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + var echarts = __webpack_require__(1); + var zrUtil = echarts.util; + + function BMapCoordSys(bmap, api) { + this._bmap = bmap; + this.dimensions = ['lng', 'lat']; + this._mapOffset = [0, 0]; + + this._api = api; + + this._projection = new BMap.MercatorProjection(); + } + + BMapCoordSys.prototype.dimensions = ['lng', 'lat']; + + BMapCoordSys.prototype.setZoom = function (zoom) { + this._zoom = zoom; + }; + + BMapCoordSys.prototype.setCenter = function (center) { + this._center = this._projection.lngLatToPoint(new BMap.Point(center[0], center[1])); + }; + + BMapCoordSys.prototype.setMapOffset = function (mapOffset) { + this._mapOffset = mapOffset; + }; + + BMapCoordSys.prototype.getBMap = function () { + return this._bmap; + }; + + BMapCoordSys.prototype.dataToPoint = function (data) { + var point = new BMap.Point(data[0], data[1]); + // TODO mercator projection is toooooooo slow + // var mercatorPoint = this._projection.lngLatToPoint(point); + + // var width = this._api.getZr().getWidth(); + // var height = this._api.getZr().getHeight(); + // var divider = Math.pow(2, 18 - 10); + // return [ + // Math.round((mercatorPoint.x - this._center.x) / divider + width / 2), + // Math.round((this._center.y - mercatorPoint.y) / divider + height / 2) + // ]; + var px = this._bmap.pointToOverlayPixel(point); + var mapOffset = this._mapOffset; + return [px.x - mapOffset[0], px.y - mapOffset[1]]; + }; + + BMapCoordSys.prototype.pointToData = function (pt) { + var mapOffset = this._mapOffset; + var pt = this._bmap.overlayPixelToPoint({ + x: pt[0] + mapOffset[0], + y: pt[1] + mapOffset[1] + }); + return [pt.lng, pt.lat]; + }; + + BMapCoordSys.prototype.getViewRect = function () { + var api = this._api; + return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()); + }; + + BMapCoordSys.prototype.getRoamTransform = function () { + return echarts.matrix.create(); + }; + + BMapCoordSys.prototype.prepareCustoms = function (data) { + var rect = this.getViewRect(); + return { + coordSys: { + // The name exposed to user is always 'cartesian2d' but not 'grid'. + type: 'bmap', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: zrUtil.bind(this.dataToPoint, this), + size: zrUtil.bind(dataToCoordSize, this) + } + }; + }; + + function dataToCoordSize(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return zrUtil.map([0, 1], function (dimIdx) { + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var p1 = []; + var p2 = []; + p1[dimIdx] = val - halfSize; + p2[dimIdx] = val + halfSize; + p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; + return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); + }, this); + } + + var Overlay; + + // For deciding which dimensions to use when creating list data + BMapCoordSys.dimensions = BMapCoordSys.prototype.dimensions; + + function createOverlayCtor() { + function Overlay(root) { + this._root = root; + } + + Overlay.prototype = new BMap.Overlay(); + /** + * 鍒濆鍖� + * + * @param {BMap.Map} map + * @override + */ + Overlay.prototype.initialize = function (map) { + map.getPanes().labelPane.appendChild(this._root); + return this._root; + }; + /** + * @override + */ + Overlay.prototype.draw = function () {}; + + return Overlay; + } + + BMapCoordSys.create = function (ecModel, api) { + var bmapCoordSys; + var root = api.getDom(); + + // TODO Dispose + ecModel.eachComponent('bmap', function (bmapModel) { + var viewportRoot = api.getZr().painter.getViewportRoot(); + if (typeof BMap === 'undefined') { + throw new Error('BMap api is not loaded'); + } + Overlay = Overlay || createOverlayCtor(); + if (bmapCoordSys) { + throw new Error('Only one bmap component can exist'); + } + if (!bmapModel.__bmap) { + // Not support IE8 + var bmapRoot = root.querySelector('.ec-extension-bmap'); + if (bmapRoot) { + // Reset viewport left and top, which will be changed + // in moving handler in BMapView + viewportRoot.style.left = '0px'; + viewportRoot.style.top = '0px'; + root.removeChild(bmapRoot); + } + bmapRoot = document.createElement('div'); + bmapRoot.style.cssText = 'width:100%;height:100%'; + // Not support IE8 + bmapRoot.classList.add('ec-extension-bmap'); + root.appendChild(bmapRoot); + var bmap = bmapModel.__bmap = new BMap.Map(bmapRoot); + + var overlay = new Overlay(viewportRoot); + bmap.addOverlay(overlay); + } + var bmap = bmapModel.__bmap; + + // Set bmap options + // centerAndZoom before layout and render + var center = bmapModel.get('center'); + var zoom = bmapModel.get('zoom'); + if (center && zoom) { + var pt = new BMap.Point(center[0], center[1]); + bmap.centerAndZoom(pt, zoom); + } + + bmapCoordSys = new BMapCoordSys(bmap, api); + bmapCoordSys.setMapOffset(bmapModel.__mapOffset || [0, 0]); + bmapCoordSys.setZoom(zoom); + bmapCoordSys.setCenter(center); + + bmapModel.coordinateSystem = bmapCoordSys; + }); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'bmap') { + seriesModel.coordinateSystem = bmapCoordSys; + } + }); + }; + + return BMapCoordSys; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + function v2Equal(a, b) { + return a && b && a[0] === b[0] && a[1] === b[1]; + } + + return __webpack_require__(1).extendComponentModel({ + type: 'bmap', + + getBMap: function () { + // __bmap is injected when creating BMapCoordSys + return this.__bmap; + }, + + setCenterAndZoom: function (center, zoom) { + this.option.center = center; + this.option.zoom = zoom; + }, + + centerOrZoomChanged: function (center, zoom) { + var option = this.option; + return !(v2Equal(center, option.center) && zoom === option.zoom); + }, + + defaultOption: { + + center: [104.114129, 37.550339], + + zoom: 5, + + mapStyle: {}, + + roam: false + } + }); + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { + + return __webpack_require__(1).extendComponentView({ + type: 'bmap', + + render: function (bMapModel, ecModel, api) { + var rendering = true; + + var bmap = bMapModel.getBMap(); + var viewportRoot = api.getZr().painter.getViewportRoot(); + var coordSys = bMapModel.coordinateSystem; + var moveHandler = function (type, target) { + if (rendering) { + return; + } + var offsetEl = viewportRoot.parentNode.parentNode.parentNode; + var mapOffset = [ + -parseInt(offsetEl.style.left, 10) || 0, + -parseInt(offsetEl.style.top, 10) || 0 + ]; + viewportRoot.style.left = mapOffset[0] + 'px'; + viewportRoot.style.top = mapOffset[1] + 'px'; + + coordSys.setMapOffset(mapOffset); + bMapModel.__mapOffset = mapOffset; + + api.dispatchAction({ + type: 'bmapRoam' + }); + }; + + function zoomEndHandler() { + if (rendering) { + return; + } + api.dispatchAction({ + type: 'bmapRoam' + }); + } + + bmap.removeEventListener('moving', this._oldMoveHandler); + // FIXME + // Moveend may be triggered by centerAndZoom method when creating coordSys next time + // bmap.removeEventListener('moveend', this._oldMoveHandler); + bmap.removeEventListener('zoomend', this._oldZoomEndHandler); + bmap.addEventListener('moving', moveHandler); + // bmap.addEventListener('moveend', moveHandler); + bmap.addEventListener('zoomend', zoomEndHandler); + + this._oldMoveHandler = moveHandler; + this._oldZoomEndHandler = zoomEndHandler; + + var roam = bMapModel.get('roam'); + if (roam && roam !== 'scale') { + bmap.enableDragging(); + } + else { + bmap.disableDragging(); + } + if (roam && roam !== 'move') { + bmap.enableScrollWheelZoom(); + bmap.enableDoubleClickZoom(); + bmap.enablePinchToZoom(); + } + else { + bmap.disableScrollWheelZoom(); + bmap.disableDoubleClickZoom(); + bmap.disablePinchToZoom(); + } + + var originalStyle = bMapModel.__mapStyle; + + var newMapStyle = bMapModel.get('mapStyle') || {}; + // FIXME, Not use JSON methods + var mapStyleStr = JSON.stringify(newMapStyle); + if (JSON.stringify(originalStyle) !== mapStyleStr) { + // FIXME May have blank tile when dragging if setMapStyle + if (Object.keys(newMapStyle).length) { + bmap.setMapStyle(newMapStyle); + } + bMapModel.__mapStyle = JSON.parse(mapStyleStr); + } + + rendering = false; + } + }); + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.css b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.css new file mode 100644 index 0000000..31d8882 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.css @@ -0,0 +1,587 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); +} +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-default.disabled, +.btn-primary.disabled, +.btn-success.disabled, +.btn-info.disabled, +.btn-warning.disabled, +.btn-danger.disabled, +.btn-default[disabled], +.btn-primary[disabled], +.btn-success[disabled], +.btn-info[disabled], +.btn-warning[disabled], +.btn-danger[disabled], +fieldset[disabled] .btn-default, +fieldset[disabled] .btn-primary, +fieldset[disabled] .btn-success, +fieldset[disabled] .btn-info, +fieldset[disabled] .btn-warning, +fieldset[disabled] .btn-danger { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default .badge, +.btn-primary .badge, +.btn-success .badge, +.btn-info .badge, +.btn-warning .badge, +.btn-danger .badge { + text-shadow: none; +} +.btn:active, +.btn.active { + background-image: none; +} +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); + background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #dbdbdb; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus { + background-color: #e0e0e0; + background-position: 0 -15px; +} +.btn-default:active, +.btn-default.active { + background-color: #e0e0e0; + border-color: #dbdbdb; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #e0e0e0; + background-image: none; +} +.btn-primary { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); + background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #245580; +} +.btn-primary:hover, +.btn-primary:focus { + background-color: #265a88; + background-position: 0 -15px; +} +.btn-primary:active, +.btn-primary.active { + background-color: #265a88; + border-color: #245580; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #265a88; + background-image: none; +} +.btn-success { + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); + background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #3e8f3e; +} +.btn-success:hover, +.btn-success:focus { + background-color: #419641; + background-position: 0 -15px; +} +.btn-success:active, +.btn-success.active { + background-color: #419641; + border-color: #3e8f3e; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #419641; + background-image: none; +} +.btn-info { + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); + background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #28a4c9; +} +.btn-info:hover, +.btn-info:focus { + background-color: #2aabd2; + background-position: 0 -15px; +} +.btn-info:active, +.btn-info.active { + background-color: #2aabd2; + border-color: #28a4c9; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #2aabd2; + background-image: none; +} +.btn-warning { + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #e38d13; +} +.btn-warning:hover, +.btn-warning:focus { + background-color: #eb9316; + background-position: 0 -15px; +} +.btn-warning:active, +.btn-warning.active { + background-color: #eb9316; + border-color: #e38d13; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #eb9316; + background-image: none; +} +.btn-danger { + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); + background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #b92c28; +} +.btn-danger:hover, +.btn-danger:focus { + background-color: #c12e2a; + background-position: 0 -15px; +} +.btn-danger:active, +.btn-danger.active { + background-color: #c12e2a; + border-color: #b92c28; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #c12e2a; + background-image: none; +} +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + background-color: #e8e8e8; + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #2e6da4; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; +} +.navbar-default { + background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); + background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .active > a { + background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); + background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); + background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); +} +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); +} +.navbar-inverse { + background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-radius: 4px; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .active > a { + background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); + background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); + background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); +} +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); +} +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} +@media (max-width: 767px) { + .navbar .navbar-nav .open .dropdown-menu > .active > a, + .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; + } +} +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); +} +.alert-success { + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); + background-repeat: repeat-x; + border-color: #b2dba1; +} +.alert-info { + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); + background-repeat: repeat-x; + border-color: #9acfea; +} +.alert-warning { + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); + background-repeat: repeat-x; + border-color: #f5e79e; +} +.alert-danger { + background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); + background-repeat: repeat-x; + border-color: #dca7a7; +} +.progress { + background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); + background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-success { + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-info { + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-warning { + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-danger { + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #286090; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); + background-repeat: repeat-x; + border-color: #2b669a; +} +.list-group-item.active .badge, +.list-group-item.active:hover .badge, +.list-group-item.active:focus .badge { + text-shadow: none; +} +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: 0 1px 2px rgba(0, 0, 0, .05); +} +.panel-default > .panel-heading { + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; +} +.panel-primary > .panel-heading { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; +} +.panel-success > .panel-heading { + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); + background-repeat: repeat-x; +} +.panel-info > .panel-heading { + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); + background-repeat: repeat-x; +} +.panel-warning > .panel-heading { + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); + background-repeat: repeat-x; +} +.panel-danger > .panel-heading { + background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); + background-repeat: repeat-x; +} +.well { + background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; + border-color: #dcdcdc; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); +} +/*# sourceMappingURL=bootstrap-theme.css.map */ diff --git a/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.css.map b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.css.map new file mode 100644 index 0000000..d876f60 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAAA;;;;GAIG;ACeH;;;;;;EAME,yCAAA;EC2CA,4FAAA;EACQ,oFAAA;CFvDT;ACgBC;;;;;;;;;;;;ECsCA,yDAAA;EACQ,iDAAA;CFxCT;ACMC;;;;;;;;;;;;;;;;;;ECiCA,yBAAA;EACQ,iBAAA;CFnBT;AC/BD;;;;;;EAuBI,kBAAA;CDgBH;ACyBC;;EAEE,uBAAA;CDvBH;AC4BD;EErEI,sEAAA;EACA,iEAAA;EACA,2FAAA;EAAA,oEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;EAuC2C,0BAAA;EAA2B,mBAAA;CDjBvE;ACpBC;;EAEE,0BAAA;EACA,6BAAA;CDsBH;ACnBC;;EAEE,0BAAA;EACA,sBAAA;CDqBH;ACfG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6BL;ACbD;EEtEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8DD;AC5DC;;EAEE,0BAAA;EACA,6BAAA;CD8DH;AC3DC;;EAEE,0BAAA;EACA,sBAAA;CD6DH;ACvDG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqEL;ACpDD;EEvEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsGD;ACpGC;;EAEE,0BAAA;EACA,6BAAA;CDsGH;ACnGC;;EAEE,0BAAA;EACA,sBAAA;CDqGH;AC/FG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6GL;AC3FD;EExEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ID;AC5IC;;EAEE,0BAAA;EACA,6BAAA;CD8IH;AC3IC;;EAEE,0BAAA;EACA,sBAAA;CD6IH;ACvIG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqJL;AClID;EEzEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsLD;ACpLC;;EAEE,0BAAA;EACA,6BAAA;CDsLH;ACnLC;;EAEE,0BAAA;EACA,sBAAA;CDqLH;AC/KG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6LL;ACzKD;EE1EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ND;AC5NC;;EAEE,0BAAA;EACA,6BAAA;CD8NH;AC3NC;;EAEE,0BAAA;EACA,sBAAA;CD6NH;ACvNG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqOL;AC1MD;;EClCE,mDAAA;EACQ,2CAAA;CFgPT;ACrMD;;EE3FI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF0FF,0BAAA;CD2MD;ACzMD;;;EEhGI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFgGF,0BAAA;CD+MD;ACtMD;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EH+HA,mBAAA;ECjEA,4FAAA;EACQ,oFAAA;CF8QT;ACjND;;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,yDAAA;EACQ,iDAAA;CFwRT;AC9MD;;EAEE,+CAAA;CDgND;AC5MD;EEhII,sEAAA;EACA,iEAAA;EACA,2FAAA;EAAA,oEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EHkJA,mBAAA;CDkND;ACrND;;EEhII,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,wDAAA;EACQ,gDAAA;CF+ST;AC/ND;;EAYI,0CAAA;CDuNH;AClND;;;EAGE,iBAAA;CDoND;AC/LD;EAfI;;;IAGE,YAAA;IE7JF,yEAAA;IACA,oEAAA;IACA,8FAAA;IAAA,uEAAA;IACA,4BAAA;IACA,uHAAA;GH+WD;CACF;AC3MD;EACE,8CAAA;EC3HA,2FAAA;EACQ,mFAAA;CFyUT;ACnMD;EEtLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+MD;AC1MD;EEvLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuND;ACjND;EExLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+ND;ACxND;EEzLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuOD;ACxND;EEjMI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH4ZH;ACrND;EE3MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHmaH;AC3ND;EE5MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH0aH;ACjOD;EE7MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHibH;ACvOD;EE9MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHwbH;AC7OD;EE/MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH+bH;AChPD;EElLI,8MAAA;EACA,yMAAA;EACA,sMAAA;CHqaH;AC5OD;EACE,mBAAA;EC9KA,mDAAA;EACQ,2CAAA;CF6ZT;AC7OD;;;EAGE,8BAAA;EEnOE,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFiOF,sBAAA;CDmPD;ACxPD;;;EAQI,kBAAA;CDqPH;AC3OD;ECnME,kDAAA;EACQ,0CAAA;CFibT;ACrOD;EE5PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHoeH;AC3OD;EE7PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH2eH;ACjPD;EE9PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHkfH;ACvPD;EE/PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHyfH;AC7PD;EEhQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHggBH;ACnQD;EEjQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHugBH;ACnQD;EExQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFsQF,sBAAA;EC3NA,0FAAA;EACQ,kFAAA;CFqeT","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.min.css b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.min.css new file mode 100644 index 0000000..5e39401 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} +/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.min.css.map b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.min.css.map new file mode 100644 index 0000000..94813e9 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap-theme.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":";;;;AAmBA,YAAA,aAAA,UAAA,aAAA,aAAA,aAME,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBDvCR,mBAAA,mBAAA,oBAAA,oBAAA,iBAAA,iBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBDlCR,qBAAA,sBAAA,sBAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,uBAAA,sBAAA,uBAAA,+BAAA,gCAAA,6BAAA,gCAAA,gCAAA,gCCiCA,mBAAA,KACQ,WAAA,KDlDV,mBAAA,oBAAA,iBAAA,oBAAA,oBAAA,oBAuBI,YAAA,KAyCF,YAAA,YAEE,iBAAA,KAKJ,aErEI,YAAA,EAAA,IAAA,EAAA,KACA,iBAAA,iDACA,iBAAA,4CAAA,iBAAA,qEAEA,iBAAA,+CCnBF,OAAA,+GH4CA,OAAA,0DACA,kBAAA,SAuC2C,aAAA,QAA2B,aAAA,KArCtE,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAgBN,aEtEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAiBN,aEvEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAkBN,UExEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,gBAAA,gBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,iBAAA,iBAEE,iBAAA,QACA,aAAA,QAMA,mBAAA,0BAAA,yBAAA,0BAAA,yBAAA,yBAAA,oBAAA,2BAAA,0BAAA,2BAAA,0BAAA,0BAAA,6BAAA,oCAAA,mCAAA,oCAAA,mCAAA,mCAME,iBAAA,QACA,iBAAA,KAmBN,aEzEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAoBN,YE1EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,kBAAA,kBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAMA,qBAAA,4BAAA,2BAAA,4BAAA,2BAAA,2BAAA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,+BAAA,sCAAA,qCAAA,sCAAA,qCAAA,qCAME,iBAAA,QACA,iBAAA,KA2BN,eAAA,WClCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBD2CV,0BAAA,0BE3FI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GF0FF,kBAAA,SAEF,yBAAA,+BAAA,+BEhGI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GFgGF,kBAAA,SASF,gBE7GI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SH+HA,cAAA,ICjEA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBD6DV,sCAAA,oCE7GI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD0EV,cAAA,iBAEE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEhII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SHkJA,cAAA,IAHF,sCAAA,oCEhII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDgFV,8BAAA,iCAYI,YAAA,EAAA,KAAA,EAAA,gBAKJ,qBAAA,kBAAA,mBAGE,cAAA,EAqBF,yBAfI,mDAAA,yDAAA,yDAGE,MAAA,KE7JF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UFqKJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC3HA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBDsIV,eEtLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAKF,YEvLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAMF,eExLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAOF,cEzLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAeF,UEjMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuMJ,cE3MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFwMJ,sBE5MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyMJ,mBE7MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0MJ,sBE9MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2MJ,qBE/MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,sBElLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKFyLJ,YACE,cAAA,IC9KA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDgLV,wBAAA,8BAAA,8BAGE,YAAA,EAAA,KAAA,EAAA,QEnOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiOF,aAAA,QALF,+BAAA,qCAAA,qCAQI,YAAA,KAUJ,OCnME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBD4MV,8BE5PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyPJ,8BE7PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0PJ,8BE9PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2PJ,2BE/PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4PJ,8BEhQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6PJ,6BEjQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoQJ,MExQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsQF,aAAA,QC3NA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap.css b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap.css new file mode 100644 index 0000000..6167622 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap.css @@ -0,0 +1,6757 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 46px; + line-height: 46px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 11px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; +} +.btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: middle; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + padding-right: 15px; + padding-left: 15px; + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success, +button.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info, +button.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + filter: alpha(opacity=0); + opacity: 0; + + line-break: auto; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + + line-break: auto; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + background-color: rgba(0, 0, 0, 0); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + margin-top: -10px; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap.css.map b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap.css.map new file mode 100644 index 0000000..f010c82 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-3.3.7/css/bootstrap.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4EAA4E;ACG5E;EACE,wBAAA;EACA,2BAAA;EACA,+BAAA;CDDD;ACQD;EACE,UAAA;CDND;ACmBD;;;;;;;;;;;;;EAaE,eAAA;CDjBD;ACyBD;;;;EAIE,sBAAA;EACA,yBAAA;CDvBD;AC+BD;EACE,cAAA;EACA,UAAA;CD7BD;ACqCD;;EAEE,cAAA;CDnCD;AC6CD;EACE,8BAAA;CD3CD;ACmDD;;EAEE,WAAA;CDjDD;AC2DD;EACE,0BAAA;CDzDD;ACgED;;EAEE,kBAAA;CD9DD;ACqED;EACE,mBAAA;CDnED;AC2ED;EACE,eAAA;EACA,iBAAA;CDzED;ACgFD;EACE,iBAAA;EACA,YAAA;CD9ED;ACqFD;EACE,eAAA;CDnFD;AC0FD;;EAEE,eAAA;EACA,eAAA;EACA,mBAAA;EACA,yBAAA;CDxFD;AC2FD;EACE,YAAA;CDzFD;AC4FD;EACE,gBAAA;CD1FD;ACoGD;EACE,UAAA;CDlGD;ACyGD;EACE,iBAAA;CDvGD;ACiHD;EACE,iBAAA;CD/GD;ACsHD;EACE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,UAAA;CDpHD;AC2HD;EACE,eAAA;CDzHD;ACgID;;;;EAIE,kCAAA;EACA,eAAA;CD9HD;ACgJD;;;;;EAKE,eAAA;EACA,cAAA;EACA,UAAA;CD9ID;ACqJD;EACE,kBAAA;CDnJD;AC6JD;;EAEE,qBAAA;CD3JD;ACsKD;;;;EAIE,2BAAA;EACA,gBAAA;CDpKD;AC2KD;;EAEE,gBAAA;CDzKD;ACgLD;;EAEE,UAAA;EACA,WAAA;CD9KD;ACsLD;EACE,oBAAA;CDpLD;AC+LD;;EAEE,+BAAA;KAAA,4BAAA;UAAA,uBAAA;EACA,WAAA;CD7LD;ACsMD;;EAEE,aAAA;CDpMD;AC4MD;EACE,8BAAA;EACA,gCAAA;KAAA,6BAAA;UAAA,wBAAA;CD1MD;ACmND;;EAEE,yBAAA;CDjND;ACwND;EACE,0BAAA;EACA,cAAA;EACA,+BAAA;CDtND;AC8ND;EACE,UAAA;EACA,WAAA;CD5ND;ACmOD;EACE,eAAA;CDjOD;ACyOD;EACE,kBAAA;CDvOD;ACiPD;EACE,0BAAA;EACA,kBAAA;CD/OD;ACkPD;;EAEE,WAAA;CDhPD;AACD,qFAAqF;AElFrF;EA7FI;;;IAGI,mCAAA;IACA,uBAAA;IACA,oCAAA;YAAA,4BAAA;IACA,6BAAA;GFkLL;EE/KC;;IAEI,2BAAA;GFiLL;EE9KC;IACI,6BAAA;GFgLL;EE7KC;IACI,8BAAA;GF+KL;EE1KC;;IAEI,YAAA;GF4KL;EEzKC;;IAEI,uBAAA;IACA,yBAAA;GF2KL;EExKC;IACI,4BAAA;GF0KL;EEvKC;;IAEI,yBAAA;GFyKL;EEtKC;IACI,2BAAA;GFwKL;EErKC;;;IAGI,WAAA;IACA,UAAA;GFuKL;EEpKC;;IAEI,wBAAA;GFsKL;EEhKC;IACI,cAAA;GFkKL;EEhKC;;IAGQ,kCAAA;GFiKT;EE9JC;IACI,uBAAA;GFgKL;EE7JC;IACI,qCAAA;GF+JL;EEhKC;;IAKQ,kCAAA;GF+JT;EE5JC;;IAGQ,kCAAA;GF6JT;CACF;AGnPD;EACE,oCAAA;EACA,sDAAA;EACA,gYAAA;CHqPD;AG7OD;EACE,mBAAA;EACA,SAAA;EACA,sBAAA;EACA,oCAAA;EACA,mBAAA;EACA,oBAAA;EACA,eAAA;EACA,oCAAA;EACA,mCAAA;CH+OD;AG3OmC;EAAW,iBAAA;CH8O9C;AG7OmC;EAAW,iBAAA;CHgP9C;AG9OmC;;EAAW,iBAAA;CHkP9C;AGjPmC;EAAW,iBAAA;CHoP9C;AGnPmC;EAAW,iBAAA;CHsP9C;AGrPmC;EAAW,iBAAA;CHwP9C;AGvPmC;EAAW,iBAAA;CH0P9C;AGzPmC;EAAW,iBAAA;CH4P9C;AG3PmC;EAAW,iBAAA;CH8P9C;AG7PmC;EAAW,iBAAA;CHgQ9C;AG/PmC;EAAW,iBAAA;CHkQ9C;AGjQmC;EAAW,iBAAA;CHoQ9C;AGnQmC;EAAW,iBAAA;CHsQ9C;AGrQmC;EAAW,iBAAA;CHwQ9C;AGvQmC;EAAW,iBAAA;CH0Q9C;AGzQmC;EAAW,iBAAA;CH4Q9C;AG3QmC;EAAW,iBAAA;CH8Q9C;AG7QmC;EAAW,iBAAA;CHgR9C;AG/QmC;EAAW,iBAAA;CHkR9C;AGjRmC;EAAW,iBAAA;CHoR9C;AGnRmC;EAAW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;EAAW,iBAAA;CH4tB9C;AG3tBmC;EAAW,iBAAA;CH8tB9C;AG7tBmC;EAAW,iBAAA;CHguB9C;AG/tBmC;EAAW,iBAAA;CHkuB9C;AGjuBmC;EAAW,iBAAA;CHouB9C;AGnuBmC;EAAW,iBAAA;CHsuB9C;AGruBmC;EAAW,iBAAA;CHwuB9C;AGvuBmC;EAAW,iBAAA;CH0uB9C;AGzuBmC;EAAW,iBAAA;CH4uB9C;AG3uBmC;EAAW,iBAAA;CH8uB9C;AG7uBmC;EAAW,iBAAA;CHgvB9C;AIthCD;ECgEE,+BAAA;EACG,4BAAA;EACK,uBAAA;CLy9BT;AIxhCD;;EC6DE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL+9BT;AIthCD;EACE,gBAAA;EACA,8CAAA;CJwhCD;AIrhCD;EACE,4DAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;CJuhCD;AInhCD;;;;EAIE,qBAAA;EACA,mBAAA;EACA,qBAAA;CJqhCD;AI/gCD;EACE,eAAA;EACA,sBAAA;CJihCD;AI/gCC;;EAEE,eAAA;EACA,2BAAA;CJihCH;AI9gCC;EEnDA,2CAAA;EACA,qBAAA;CNokCD;AIvgCD;EACE,UAAA;CJygCD;AIngCD;EACE,uBAAA;CJqgCD;AIjgCD;;;;;EGvEE,eAAA;EACA,gBAAA;EACA,aAAA;CP+kCD;AIrgCD;EACE,mBAAA;CJugCD;AIjgCD;EACE,aAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;EC6FA,yCAAA;EACK,oCAAA;EACG,iCAAA;EEvLR,sBAAA;EACA,gBAAA;EACA,aAAA;CP+lCD;AIjgCD;EACE,mBAAA;CJmgCD;AI7/BD;EACE,iBAAA;EACA,oBAAA;EACA,UAAA;EACA,8BAAA;CJ+/BD;AIv/BD;EACE,mBAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,iBAAA;EACA,uBAAA;EACA,UAAA;CJy/BD;AIj/BC;;EAEE,iBAAA;EACA,YAAA;EACA,aAAA;EACA,UAAA;EACA,kBAAA;EACA,WAAA;CJm/BH;AIx+BD;EACE,gBAAA;CJ0+BD;AQjoCD;;;;;;;;;;;;EAEE,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;CR6oCD;AQlpCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,oBAAA;EACA,eAAA;EACA,eAAA;CRmqCH;AQ/pCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRoqCD;AQxqCD;;;;;;;;;;;;EAQI,eAAA;CR8qCH;AQ3qCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRgrCD;AQprCD;;;;;;;;;;;;EAQI,eAAA;CR0rCH;AQtrCD;;EAAU,gBAAA;CR0rCT;AQzrCD;;EAAU,gBAAA;CR6rCT;AQ5rCD;;EAAU,gBAAA;CRgsCT;AQ/rCD;;EAAU,gBAAA;CRmsCT;AQlsCD;;EAAU,gBAAA;CRssCT;AQrsCD;;EAAU,gBAAA;CRysCT;AQnsCD;EACE,iBAAA;CRqsCD;AQlsCD;EACE,oBAAA;EACA,gBAAA;EACA,iBAAA;EACA,iBAAA;CRosCD;AQ/rCD;EAwOA;IA1OI,gBAAA;GRqsCD;CACF;AQ7rCD;;EAEE,eAAA;CR+rCD;AQ5rCD;;EAEE,0BAAA;EACA,cAAA;CR8rCD;AQ1rCD;EAAuB,iBAAA;CR6rCtB;AQ5rCD;EAAuB,kBAAA;CR+rCtB;AQ9rCD;EAAuB,mBAAA;CRisCtB;AQhsCD;EAAuB,oBAAA;CRmsCtB;AQlsCD;EAAuB,oBAAA;CRqsCtB;AQlsCD;EAAuB,0BAAA;CRqsCtB;AQpsCD;EAAuB,0BAAA;CRusCtB;AQtsCD;EAAuB,2BAAA;CRysCtB;AQtsCD;EACE,eAAA;CRwsCD;AQtsCD;ECrGE,eAAA;CT8yCD;AS7yCC;;EAEE,eAAA;CT+yCH;AQ1sCD;ECxGE,eAAA;CTqzCD;ASpzCC;;EAEE,eAAA;CTszCH;AQ9sCD;EC3GE,eAAA;CT4zCD;AS3zCC;;EAEE,eAAA;CT6zCH;AQltCD;EC9GE,eAAA;CTm0CD;ASl0CC;;EAEE,eAAA;CTo0CH;AQttCD;ECjHE,eAAA;CT00CD;ASz0CC;;EAEE,eAAA;CT20CH;AQttCD;EAGE,YAAA;EE3HA,0BAAA;CVk1CD;AUj1CC;;EAEE,0BAAA;CVm1CH;AQxtCD;EE9HE,0BAAA;CVy1CD;AUx1CC;;EAEE,0BAAA;CV01CH;AQ5tCD;EEjIE,0BAAA;CVg2CD;AU/1CC;;EAEE,0BAAA;CVi2CH;AQhuCD;EEpIE,0BAAA;CVu2CD;AUt2CC;;EAEE,0BAAA;CVw2CH;AQpuCD;EEvIE,0BAAA;CV82CD;AU72CC;;EAEE,0BAAA;CV+2CH;AQnuCD;EACE,oBAAA;EACA,oBAAA;EACA,iCAAA;CRquCD;AQ7tCD;;EAEE,cAAA;EACA,oBAAA;CR+tCD;AQluCD;;;;EAMI,iBAAA;CRkuCH;AQ3tCD;EACE,gBAAA;EACA,iBAAA;CR6tCD;AQztCD;EALE,gBAAA;EACA,iBAAA;EAMA,kBAAA;CR4tCD;AQ9tCD;EAKI,sBAAA;EACA,kBAAA;EACA,mBAAA;CR4tCH;AQvtCD;EACE,cAAA;EACA,oBAAA;CRytCD;AQvtCD;;EAEE,wBAAA;CRytCD;AQvtCD;EACE,kBAAA;CRytCD;AQvtCD;EACE,eAAA;CRytCD;AQhsCD;EA6EA;IAvFM,YAAA;IACA,aAAA;IACA,YAAA;IACA,kBAAA;IGtNJ,iBAAA;IACA,wBAAA;IACA,oBAAA;GXq6CC;EQ7nCH;IAhFM,mBAAA;GRgtCH;CACF;AQvsCD;;EAGE,aAAA;EACA,kCAAA;CRwsCD;AQtsCD;EACE,eAAA;EA9IqB,0BAAA;CRu1CtB;AQpsCD;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,+BAAA;CRssCD;AQjsCG;;;EACE,iBAAA;CRqsCL;AQ/sCD;;;EAmBI,eAAA;EACA,eAAA;EACA,wBAAA;EACA,eAAA;CRisCH;AQ/rCG;;;EACE,uBAAA;CRmsCL;AQ3rCD;;EAEE,oBAAA;EACA,gBAAA;EACA,gCAAA;EACA,eAAA;EACA,kBAAA;CR6rCD;AQvrCG;;;;;;EAAW,YAAA;CR+rCd;AQ9rCG;;;;;;EACE,uBAAA;CRqsCL;AQ/rCD;EACE,oBAAA;EACA,mBAAA;EACA,wBAAA;CRisCD;AYv+CD;;;;EAIE,+DAAA;CZy+CD;AYr+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CZu+CD;AYn+CD;EACE,iBAAA;EACA,eAAA;EACA,YAAA;EACA,uBAAA;EACA,mBAAA;EACA,uDAAA;UAAA,+CAAA;CZq+CD;AY3+CD;EASI,WAAA;EACA,gBAAA;EACA,kBAAA;EACA,yBAAA;UAAA,iBAAA;CZq+CH;AYh+CD;EACE,eAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,sBAAA;EACA,sBAAA;EACA,eAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;CZk+CD;AY7+CD;EAeI,WAAA;EACA,mBAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,iBAAA;CZi+CH;AY59CD;EACE,kBAAA;EACA,mBAAA;CZ89CD;AaxhDD;ECHE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;Cd8hDD;AaxhDC;EAqEF;IAvEI,aAAA;Gb8hDD;CACF;Aa1hDC;EAkEF;IApEI,aAAA;GbgiDD;CACF;Aa5hDD;EA+DA;IAjEI,cAAA;GbkiDD;CACF;AazhDD;ECvBE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;CdmjDD;AathDD;ECvBE,mBAAA;EACA,oBAAA;CdgjDD;AehjDG;EACE,mBAAA;EAEA,gBAAA;EAEA,mBAAA;EACA,oBAAA;CfgjDL;AehiDG;EACE,YAAA;CfkiDL;Ae3hDC;EACE,YAAA;Cf6hDH;Ae9hDC;EACE,oBAAA;CfgiDH;AejiDC;EACE,oBAAA;CfmiDH;AepiDC;EACE,WAAA;CfsiDH;AeviDC;EACE,oBAAA;CfyiDH;Ae1iDC;EACE,oBAAA;Cf4iDH;Ae7iDC;EACE,WAAA;Cf+iDH;AehjDC;EACE,oBAAA;CfkjDH;AenjDC;EACE,oBAAA;CfqjDH;AetjDC;EACE,WAAA;CfwjDH;AezjDC;EACE,oBAAA;Cf2jDH;Ae5jDC;EACE,mBAAA;Cf8jDH;AehjDC;EACE,YAAA;CfkjDH;AenjDC;EACE,oBAAA;CfqjDH;AetjDC;EACE,oBAAA;CfwjDH;AezjDC;EACE,WAAA;Cf2jDH;Ae5jDC;EACE,oBAAA;Cf8jDH;Ae/jDC;EACE,oBAAA;CfikDH;AelkDC;EACE,WAAA;CfokDH;AerkDC;EACE,oBAAA;CfukDH;AexkDC;EACE,oBAAA;Cf0kDH;Ae3kDC;EACE,WAAA;Cf6kDH;Ae9kDC;EACE,oBAAA;CfglDH;AejlDC;EACE,mBAAA;CfmlDH;Ae/kDC;EACE,YAAA;CfilDH;AejmDC;EACE,WAAA;CfmmDH;AepmDC;EACE,mBAAA;CfsmDH;AevmDC;EACE,mBAAA;CfymDH;Ae1mDC;EACE,UAAA;Cf4mDH;Ae7mDC;EACE,mBAAA;Cf+mDH;AehnDC;EACE,mBAAA;CfknDH;AennDC;EACE,UAAA;CfqnDH;AetnDC;EACE,mBAAA;CfwnDH;AeznDC;EACE,mBAAA;Cf2nDH;Ae5nDC;EACE,UAAA;Cf8nDH;Ae/nDC;EACE,mBAAA;CfioDH;AeloDC;EACE,kBAAA;CfooDH;AehoDC;EACE,WAAA;CfkoDH;AepnDC;EACE,kBAAA;CfsnDH;AevnDC;EACE,0BAAA;CfynDH;Ae1nDC;EACE,0BAAA;Cf4nDH;Ae7nDC;EACE,iBAAA;Cf+nDH;AehoDC;EACE,0BAAA;CfkoDH;AenoDC;EACE,0BAAA;CfqoDH;AetoDC;EACE,iBAAA;CfwoDH;AezoDC;EACE,0BAAA;Cf2oDH;Ae5oDC;EACE,0BAAA;Cf8oDH;Ae/oDC;EACE,iBAAA;CfipDH;AelpDC;EACE,0BAAA;CfopDH;AerpDC;EACE,yBAAA;CfupDH;AexpDC;EACE,gBAAA;Cf0pDH;Aa1pDD;EElCI;IACE,YAAA;Gf+rDH;EexrDD;IACE,YAAA;Gf0rDD;Ee3rDD;IACE,oBAAA;Gf6rDD;Ee9rDD;IACE,oBAAA;GfgsDD;EejsDD;IACE,WAAA;GfmsDD;EepsDD;IACE,oBAAA;GfssDD;EevsDD;IACE,oBAAA;GfysDD;Ee1sDD;IACE,WAAA;Gf4sDD;Ee7sDD;IACE,oBAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,WAAA;GfqtDD;EettDD;IACE,oBAAA;GfwtDD;EeztDD;IACE,mBAAA;Gf2tDD;Ee7sDD;IACE,YAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,oBAAA;GfqtDD;EettDD;IACE,WAAA;GfwtDD;EeztDD;IACE,oBAAA;Gf2tDD;Ee5tDD;IACE,oBAAA;Gf8tDD;Ee/tDD;IACE,WAAA;GfiuDD;EeluDD;IACE,oBAAA;GfouDD;EeruDD;IACE,oBAAA;GfuuDD;EexuDD;IACE,WAAA;Gf0uDD;Ee3uDD;IACE,oBAAA;Gf6uDD;Ee9uDD;IACE,mBAAA;GfgvDD;Ee5uDD;IACE,YAAA;Gf8uDD;Ee9vDD;IACE,WAAA;GfgwDD;EejwDD;IACE,mBAAA;GfmwDD;EepwDD;IACE,mBAAA;GfswDD;EevwDD;IACE,UAAA;GfywDD;Ee1wDD;IACE,mBAAA;Gf4wDD;Ee7wDD;IACE,mBAAA;Gf+wDD;EehxDD;IACE,UAAA;GfkxDD;EenxDD;IACE,mBAAA;GfqxDD;EetxDD;IACE,mBAAA;GfwxDD;EezxDD;IACE,UAAA;Gf2xDD;Ee5xDD;IACE,mBAAA;Gf8xDD;Ee/xDD;IACE,kBAAA;GfiyDD;Ee7xDD;IACE,WAAA;Gf+xDD;EejxDD;IACE,kBAAA;GfmxDD;EepxDD;IACE,0BAAA;GfsxDD;EevxDD;IACE,0BAAA;GfyxDD;Ee1xDD;IACE,iBAAA;Gf4xDD;Ee7xDD;IACE,0BAAA;Gf+xDD;EehyDD;IACE,0BAAA;GfkyDD;EenyDD;IACE,iBAAA;GfqyDD;EetyDD;IACE,0BAAA;GfwyDD;EezyDD;IACE,0BAAA;Gf2yDD;Ee5yDD;IACE,iBAAA;Gf8yDD;Ee/yDD;IACE,0BAAA;GfizDD;EelzDD;IACE,yBAAA;GfozDD;EerzDD;IACE,gBAAA;GfuzDD;CACF;Aa/yDD;EE3CI;IACE,YAAA;Gf61DH;Eet1DD;IACE,YAAA;Gfw1DD;Eez1DD;IACE,oBAAA;Gf21DD;Ee51DD;IACE,oBAAA;Gf81DD;Ee/1DD;IACE,WAAA;Gfi2DD;Eel2DD;IACE,oBAAA;Gfo2DD;Eer2DD;IACE,oBAAA;Gfu2DD;Eex2DD;IACE,WAAA;Gf02DD;Ee32DD;IACE,oBAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,WAAA;Gfm3DD;Eep3DD;IACE,oBAAA;Gfs3DD;Eev3DD;IACE,mBAAA;Gfy3DD;Ee32DD;IACE,YAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,oBAAA;Gfm3DD;Eep3DD;IACE,WAAA;Gfs3DD;Eev3DD;IACE,oBAAA;Gfy3DD;Ee13DD;IACE,oBAAA;Gf43DD;Ee73DD;IACE,WAAA;Gf+3DD;Eeh4DD;IACE,oBAAA;Gfk4DD;Een4DD;IACE,oBAAA;Gfq4DD;Eet4DD;IACE,WAAA;Gfw4DD;Eez4DD;IACE,oBAAA;Gf24DD;Ee54DD;IACE,mBAAA;Gf84DD;Ee14DD;IACE,YAAA;Gf44DD;Ee55DD;IACE,WAAA;Gf85DD;Ee/5DD;IACE,mBAAA;Gfi6DD;Eel6DD;IACE,mBAAA;Gfo6DD;Eer6DD;IACE,UAAA;Gfu6DD;Eex6DD;IACE,mBAAA;Gf06DD;Ee36DD;IACE,mBAAA;Gf66DD;Ee96DD;IACE,UAAA;Gfg7DD;Eej7DD;IACE,mBAAA;Gfm7DD;Eep7DD;IACE,mBAAA;Gfs7DD;Eev7DD;IACE,UAAA;Gfy7DD;Ee17DD;IACE,mBAAA;Gf47DD;Ee77DD;IACE,kBAAA;Gf+7DD;Ee37DD;IACE,WAAA;Gf67DD;Ee/6DD;IACE,kBAAA;Gfi7DD;Eel7DD;IACE,0BAAA;Gfo7DD;Eer7DD;IACE,0BAAA;Gfu7DD;Eex7DD;IACE,iBAAA;Gf07DD;Ee37DD;IACE,0BAAA;Gf67DD;Ee97DD;IACE,0BAAA;Gfg8DD;Eej8DD;IACE,iBAAA;Gfm8DD;Eep8DD;IACE,0BAAA;Gfs8DD;Eev8DD;IACE,0BAAA;Gfy8DD;Ee18DD;IACE,iBAAA;Gf48DD;Ee78DD;IACE,0BAAA;Gf+8DD;Eeh9DD;IACE,yBAAA;Gfk9DD;Een9DD;IACE,gBAAA;Gfq9DD;CACF;Aa18DD;EE9CI;IACE,YAAA;Gf2/DH;Eep/DD;IACE,YAAA;Gfs/DD;Eev/DD;IACE,oBAAA;Gfy/DD;Ee1/DD;IACE,oBAAA;Gf4/DD;Ee7/DD;IACE,WAAA;Gf+/DD;EehgED;IACE,oBAAA;GfkgED;EengED;IACE,oBAAA;GfqgED;EetgED;IACE,WAAA;GfwgED;EezgED;IACE,oBAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,WAAA;GfihED;EelhED;IACE,oBAAA;GfohED;EerhED;IACE,mBAAA;GfuhED;EezgED;IACE,YAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,oBAAA;GfihED;EelhED;IACE,WAAA;GfohED;EerhED;IACE,oBAAA;GfuhED;EexhED;IACE,oBAAA;Gf0hED;Ee3hED;IACE,WAAA;Gf6hED;Ee9hED;IACE,oBAAA;GfgiED;EejiED;IACE,oBAAA;GfmiED;EepiED;IACE,WAAA;GfsiED;EeviED;IACE,oBAAA;GfyiED;Ee1iED;IACE,mBAAA;Gf4iED;EexiED;IACE,YAAA;Gf0iED;Ee1jED;IACE,WAAA;Gf4jED;Ee7jED;IACE,mBAAA;Gf+jED;EehkED;IACE,mBAAA;GfkkED;EenkED;IACE,UAAA;GfqkED;EetkED;IACE,mBAAA;GfwkED;EezkED;IACE,mBAAA;Gf2kED;Ee5kED;IACE,UAAA;Gf8kED;Ee/kED;IACE,mBAAA;GfilED;EellED;IACE,mBAAA;GfolED;EerlED;IACE,UAAA;GfulED;EexlED;IACE,mBAAA;Gf0lED;Ee3lED;IACE,kBAAA;Gf6lED;EezlED;IACE,WAAA;Gf2lED;Ee7kED;IACE,kBAAA;Gf+kED;EehlED;IACE,0BAAA;GfklED;EenlED;IACE,0BAAA;GfqlED;EetlED;IACE,iBAAA;GfwlED;EezlED;IACE,0BAAA;Gf2lED;Ee5lED;IACE,0BAAA;Gf8lED;Ee/lED;IACE,iBAAA;GfimED;EelmED;IACE,0BAAA;GfomED;EermED;IACE,0BAAA;GfumED;EexmED;IACE,iBAAA;Gf0mED;Ee3mED;IACE,0BAAA;Gf6mED;Ee9mED;IACE,yBAAA;GfgnED;EejnED;IACE,gBAAA;GfmnED;CACF;AgBvrED;EACE,8BAAA;ChByrED;AgBvrED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChByrED;AgBvrED;EACE,iBAAA;ChByrED;AgBnrED;EACE,YAAA;EACA,gBAAA;EACA,oBAAA;ChBqrED;AgBxrED;;;;;;EAWQ,aAAA;EACA,wBAAA;EACA,oBAAA;EACA,2BAAA;ChBqrEP;AgBnsED;EAoBI,uBAAA;EACA,8BAAA;ChBkrEH;AgBvsED;;;;;;EA8BQ,cAAA;ChBirEP;AgB/sED;EAoCI,2BAAA;ChB8qEH;AgBltED;EAyCI,uBAAA;ChB4qEH;AgBrqED;;;;;;EAOQ,aAAA;ChBsqEP;AgB3pED;EACE,uBAAA;ChB6pED;AgB9pED;;;;;;EAQQ,uBAAA;ChB8pEP;AgBtqED;;EAeM,yBAAA;ChB2pEL;AgBjpED;EAEI,0BAAA;ChBkpEH;AgBzoED;EAEI,0BAAA;ChB0oEH;AgBjoED;EACE,iBAAA;EACA,YAAA;EACA,sBAAA;ChBmoED;AgB9nEG;;EACE,iBAAA;EACA,YAAA;EACA,oBAAA;ChBioEL;AiB7wEC;;;;;;;;;;;;EAOI,0BAAA;CjBoxEL;AiB9wEC;;;;;EAMI,0BAAA;CjB+wEL;AiBlyEC;;;;;;;;;;;;EAOI,0BAAA;CjByyEL;AiBnyEC;;;;;EAMI,0BAAA;CjBoyEL;AiBvzEC;;;;;;;;;;;;EAOI,0BAAA;CjB8zEL;AiBxzEC;;;;;EAMI,0BAAA;CjByzEL;AiB50EC;;;;;;;;;;;;EAOI,0BAAA;CjBm1EL;AiB70EC;;;;;EAMI,0BAAA;CjB80EL;AiBj2EC;;;;;;;;;;;;EAOI,0BAAA;CjBw2EL;AiBl2EC;;;;;EAMI,0BAAA;CjBm2EL;AgBjtED;EACE,iBAAA;EACA,kBAAA;ChBmtED;AgBtpED;EACA;IA3DI,YAAA;IACA,oBAAA;IACA,mBAAA;IACA,6CAAA;IACA,uBAAA;GhBotED;EgB7pEH;IAnDM,iBAAA;GhBmtEH;EgBhqEH;;;;;;IA1CY,oBAAA;GhBktET;EgBxqEH;IAlCM,UAAA;GhB6sEH;EgB3qEH;;;;;;IAzBY,eAAA;GhB4sET;EgBnrEH;;;;;;IArBY,gBAAA;GhBgtET;EgB3rEH;;;;IARY,iBAAA;GhBysET;CACF;AkBn6ED;EACE,WAAA;EACA,UAAA;EACA,UAAA;EAIA,aAAA;ClBk6ED;AkB/5ED;EACE,eAAA;EACA,YAAA;EACA,WAAA;EACA,oBAAA;EACA,gBAAA;EACA,qBAAA;EACA,eAAA;EACA,UAAA;EACA,iCAAA;ClBi6ED;AkB95ED;EACE,sBAAA;EACA,gBAAA;EACA,mBAAA;EACA,kBAAA;ClBg6ED;AkBr5ED;Eb4BE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL43ET;AkBr5ED;;EAEE,gBAAA;EACA,mBAAA;EACA,oBAAA;ClBu5ED;AkBp5ED;EACE,eAAA;ClBs5ED;AkBl5ED;EACE,eAAA;EACA,YAAA;ClBo5ED;AkBh5ED;;EAEE,aAAA;ClBk5ED;AkB94ED;;;EZrEE,2CAAA;EACA,qBAAA;CNw9ED;AkB74ED;EACE,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;ClB+4ED;AkBr3ED;EACE,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;EbxDA,yDAAA;EACQ,iDAAA;EAyHR,uFAAA;EACK,0EAAA;EACG,uEAAA;CLwzET;AmBh8EC;EACE,sBAAA;EACA,WAAA;EdUF,uFAAA;EACQ,+EAAA;CLy7ET;AKx5EC;EACE,YAAA;EACA,WAAA;CL05EH;AKx5EC;EAA0B,YAAA;CL25E3B;AK15EC;EAAgC,YAAA;CL65EjC;AkBj4EC;EACE,UAAA;EACA,8BAAA;ClBm4EH;AkB33EC;;;EAGE,0BAAA;EACA,WAAA;ClB63EH;AkB13EC;;EAEE,oBAAA;ClB43EH;AkBx3EC;EACE,aAAA;ClB03EH;AkB92ED;EACE,yBAAA;ClBg3ED;AkBx0ED;EAtBI;;;;IACE,kBAAA;GlBo2EH;EkBj2EC;;;;;;;;IAEE,kBAAA;GlBy2EH;EkBt2EC;;;;;;;;IAEE,kBAAA;GlB82EH;CACF;AkBp2ED;EACE,oBAAA;ClBs2ED;AkB91ED;;EAEE,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,oBAAA;ClBg2ED;AkBr2ED;;EAQI,iBAAA;EACA,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,gBAAA;ClBi2EH;AkB91ED;;;;EAIE,mBAAA;EACA,mBAAA;EACA,mBAAA;ClBg2ED;AkB71ED;;EAEE,iBAAA;ClB+1ED;AkB31ED;;EAEE,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;ClB61ED;AkB31ED;;EAEE,cAAA;EACA,kBAAA;ClB61ED;AkBp1EC;;;;;;EAGE,oBAAA;ClBy1EH;AkBn1EC;;;;EAEE,oBAAA;ClBu1EH;AkBj1EC;;;;EAGI,oBAAA;ClBo1EL;AkBz0ED;EAEE,iBAAA;EACA,oBAAA;EAEA,iBAAA;EACA,iBAAA;ClBy0ED;AkBv0EC;;EAEE,gBAAA;EACA,iBAAA;ClBy0EH;AkB5zED;ECnQE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnBkkFD;AmBhkFC;EACE,aAAA;EACA,kBAAA;CnBkkFH;AmB/jFC;;EAEE,aAAA;CnBikFH;AkBx0ED;EAEI,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;ClBy0EH;AkB/0ED;EASI,aAAA;EACA,kBAAA;ClBy0EH;AkBn1ED;;EAcI,aAAA;ClBy0EH;AkBv1ED;EAiBI,aAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;ClBy0EH;AkBr0ED;EC/RE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBumFD;AmBrmFC;EACE,aAAA;EACA,kBAAA;CnBumFH;AmBpmFC;;EAEE,aAAA;CnBsmFH;AkBj1ED;EAEI,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;ClBk1EH;AkBx1ED;EASI,aAAA;EACA,kBAAA;ClBk1EH;AkB51ED;;EAcI,aAAA;ClBk1EH;AkBh2ED;EAiBI,aAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;ClBk1EH;AkBz0ED;EAEE,mBAAA;ClB00ED;AkB50ED;EAMI,sBAAA;ClBy0EH;AkBr0ED;EACE,mBAAA;EACA,OAAA;EACA,SAAA;EACA,WAAA;EACA,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,mBAAA;EACA,qBAAA;ClBu0ED;AkBr0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBu0ED;AkBr0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBu0ED;AkBn0ED;;;;;;;;;;EC1ZI,eAAA;CnByuFH;AkB/0ED;ECtZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CL0rFT;AmBxuFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL+rFT;AkBz1ED;EC5YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBwuFH;AkB91ED;ECtYI,eAAA;CnBuuFH;AkB91ED;;;;;;;;;;EC7ZI,eAAA;CnBuwFH;AkB12ED;ECzZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLwtFT;AmBtwFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL6tFT;AkBp3ED;EC/YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBswFH;AkBz3ED;ECzYI,eAAA;CnBqwFH;AkBz3ED;;;;;;;;;;EChaI,eAAA;CnBqyFH;AkBr4ED;EC5ZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLsvFT;AmBpyFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL2vFT;AkB/4ED;EClZI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBoyFH;AkBp5ED;EC5YI,eAAA;CnBmyFH;AkBh5EC;EACE,UAAA;ClBk5EH;AkBh5EC;EACE,OAAA;ClBk5EH;AkBx4ED;EACE,eAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;ClB04ED;AkBvzED;EAwEA;IAtIM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlBy3EH;EkBrvEH;IA/HM,sBAAA;IACA,YAAA;IACA,uBAAA;GlBu3EH;EkB1vEH;IAxHM,sBAAA;GlBq3EH;EkB7vEH;IApHM,sBAAA;IACA,uBAAA;GlBo3EH;EkBjwEH;;;IA9GQ,YAAA;GlBo3EL;EkBtwEH;IAxGM,YAAA;GlBi3EH;EkBzwEH;IApGM,iBAAA;IACA,uBAAA;GlBg3EH;EkB7wEH;;IA5FM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlB62EH;EkBpxEH;;IAtFQ,gBAAA;GlB82EL;EkBxxEH;;IAjFM,mBAAA;IACA,eAAA;GlB62EH;EkB7xEH;IA3EM,OAAA;GlB22EH;CACF;AkBj2ED;;;;EASI,cAAA;EACA,iBAAA;EACA,iBAAA;ClB81EH;AkBz2ED;;EAiBI,iBAAA;ClB41EH;AkB72ED;EJthBE,mBAAA;EACA,oBAAA;Cds4FD;AkB10EC;EAyBF;IAnCM,kBAAA;IACA,iBAAA;IACA,iBAAA;GlBw1EH;CACF;AkBx3ED;EAwCI,YAAA;ClBm1EH;AkBr0EC;EAUF;IAdQ,kBAAA;IACA,gBAAA;GlB60EL;CACF;AkBn0EC;EAEF;IANQ,iBAAA;IACA,gBAAA;GlB20EL;CACF;AoBp6FD;EACE,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;EACA,uBAAA;EACA,+BAAA;MAAA,2BAAA;EACA,gBAAA;EACA,uBAAA;EACA,8BAAA;EACA,oBAAA;EC0CA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,mBAAA;EhB+JA,0BAAA;EACG,uBAAA;EACC,sBAAA;EACI,kBAAA;CL+tFT;AoBv6FG;;;;;;EdnBF,2CAAA;EACA,qBAAA;CNk8FD;AoB16FC;;;EAGE,YAAA;EACA,sBAAA;CpB46FH;AoBz6FC;;EAEE,WAAA;EACA,uBAAA;Ef2BF,yDAAA;EACQ,iDAAA;CLi5FT;AoBz6FC;;;EAGE,oBAAA;EE7CF,cAAA;EAGA,0BAAA;EjB8DA,yBAAA;EACQ,iBAAA;CL05FT;AoBz6FG;;EAEE,qBAAA;CpB26FL;AoBl6FD;EC3DE,YAAA;EACA,uBAAA;EACA,mBAAA;CrBg+FD;AqB99FC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBg+FP;AqB99FC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBg+FP;AqB99FC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBg+FP;AqB99FG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBs+FT;AqBn+FC;;;EAGE,uBAAA;CrBq+FH;AqBh+FG;;;;;;;;;EAGE,uBAAA;EACI,mBAAA;CrBw+FT;AoBv9FD;ECZI,YAAA;EACA,uBAAA;CrBs+FH;AoBx9FD;EC9DE,YAAA;EACA,0BAAA;EACA,sBAAA;CrByhGD;AqBvhGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrByhGP;AqBvhGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrByhGP;AqBvhGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrByhGP;AqBvhGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB+hGT;AqB5hGC;;;EAGE,uBAAA;CrB8hGH;AqBzhGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBiiGT;AoB7gGD;ECfI,eAAA;EACA,uBAAA;CrB+hGH;AoB7gGD;EClEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBklGD;AqBhlGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBklGP;AqBhlGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBklGP;AqBhlGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBklGP;AqBhlGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBwlGT;AqBrlGC;;;EAGE,uBAAA;CrBulGH;AqBllGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrB0lGT;AoBlkGD;ECnBI,eAAA;EACA,uBAAA;CrBwlGH;AoBlkGD;ECtEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB2oGD;AqBzoGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB2oGP;AqBzoGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB2oGP;AqBzoGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB2oGP;AqBzoGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBipGT;AqB9oGC;;;EAGE,uBAAA;CrBgpGH;AqB3oGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBmpGT;AoBvnGD;ECvBI,eAAA;EACA,uBAAA;CrBipGH;AoBvnGD;EC1EE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBosGD;AqBlsGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBosGP;AqBlsGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBosGP;AqBlsGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBosGP;AqBlsGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB0sGT;AqBvsGC;;;EAGE,uBAAA;CrBysGH;AqBpsGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrB4sGT;AoB5qGD;EC3BI,eAAA;EACA,uBAAA;CrB0sGH;AoB5qGD;EC9EE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB6vGD;AqB3vGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB6vGP;AqB3vGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB6vGP;AqB3vGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB6vGP;AqB3vGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBmwGT;AqBhwGC;;;EAGE,uBAAA;CrBkwGH;AqB7vGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBqwGT;AoBjuGD;EC/BI,eAAA;EACA,uBAAA;CrBmwGH;AoB5tGD;EACE,eAAA;EACA,oBAAA;EACA,iBAAA;CpB8tGD;AoB5tGC;;;;;EAKE,8BAAA;EfnCF,yBAAA;EACQ,iBAAA;CLkwGT;AoB7tGC;;;;EAIE,0BAAA;CpB+tGH;AoB7tGC;;EAEE,eAAA;EACA,2BAAA;EACA,8BAAA;CpB+tGH;AoB3tGG;;;;EAEE,eAAA;EACA,sBAAA;CpB+tGL;AoBttGD;;ECxEE,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CrBkyGD;AoBztGD;;EC5EE,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrByyGD;AoB5tGD;;EChFE,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrBgzGD;AoB3tGD;EACE,eAAA;EACA,YAAA;CpB6tGD;AoBztGD;EACE,gBAAA;CpB2tGD;AoBptGC;;;EACE,YAAA;CpBwtGH;AuBl3GD;EACE,WAAA;ElBoLA,yCAAA;EACK,oCAAA;EACG,iCAAA;CLisGT;AuBr3GC;EACE,WAAA;CvBu3GH;AuBn3GD;EACE,cAAA;CvBq3GD;AuBn3GC;EAAY,eAAA;CvBs3Gb;AuBr3GC;EAAY,mBAAA;CvBw3Gb;AuBv3GC;EAAY,yBAAA;CvB03Gb;AuBv3GD;EACE,mBAAA;EACA,UAAA;EACA,iBAAA;ElBuKA,gDAAA;EACQ,2CAAA;KAAA,wCAAA;EAOR,mCAAA;EACQ,8BAAA;KAAA,2BAAA;EAGR,yCAAA;EACQ,oCAAA;KAAA,iCAAA;CL2sGT;AwBr5GD;EACE,sBAAA;EACA,SAAA;EACA,UAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,yBAAA;EACA,oCAAA;EACA,mCAAA;CxBu5GD;AwBn5GD;;EAEE,mBAAA;CxBq5GD;AwBj5GD;EACE,WAAA;CxBm5GD;AwB/4GD;EACE,mBAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,sCAAA;EACA,mBAAA;EnBsBA,oDAAA;EACQ,4CAAA;EmBrBR,qCAAA;UAAA,6BAAA;CxBk5GD;AwB74GC;EACE,SAAA;EACA,WAAA;CxB+4GH;AwBx6GD;ECzBE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBo8GD;AwB96GD;EAmCI,eAAA;EACA,kBAAA;EACA,YAAA;EACA,oBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxB84GH;AwBx4GC;;EAEE,sBAAA;EACA,eAAA;EACA,0BAAA;CxB04GH;AwBp4GC;;;EAGE,YAAA;EACA,sBAAA;EACA,WAAA;EACA,0BAAA;CxBs4GH;AwB73GC;;;EAGE,eAAA;CxB+3GH;AwB33GC;;EAEE,sBAAA;EACA,8BAAA;EACA,uBAAA;EE3GF,oEAAA;EF6GE,oBAAA;CxB63GH;AwBx3GD;EAGI,eAAA;CxBw3GH;AwB33GD;EAQI,WAAA;CxBs3GH;AwB92GD;EACE,WAAA;EACA,SAAA;CxBg3GD;AwBx2GD;EACE,QAAA;EACA,YAAA;CxB02GD;AwBt2GD;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxBw2GD;AwBp2GD;EACE,gBAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;CxBs2GD;AwBl2GD;EACE,SAAA;EACA,WAAA;CxBo2GD;AwB51GD;;EAII,cAAA;EACA,0BAAA;EACA,4BAAA;EACA,YAAA;CxB41GH;AwBn2GD;;EAWI,UAAA;EACA,aAAA;EACA,mBAAA;CxB41GH;AwBv0GD;EAXE;IApEA,WAAA;IACA,SAAA;GxB05GC;EwBv1GD;IA1DA,QAAA;IACA,YAAA;GxBo5GC;CACF;A2BpiHD;;EAEE,mBAAA;EACA,sBAAA;EACA,uBAAA;C3BsiHD;A2B1iHD;;EAMI,mBAAA;EACA,YAAA;C3BwiHH;A2BtiHG;;;;;;;;EAIE,WAAA;C3B4iHL;A2BtiHD;;;;EAKI,kBAAA;C3BuiHH;A2BliHD;EACE,kBAAA;C3BoiHD;A2BriHD;;;EAOI,YAAA;C3BmiHH;A2B1iHD;;;EAYI,iBAAA;C3BmiHH;A2B/hHD;EACE,iBAAA;C3BiiHD;A2B7hHD;EACE,eAAA;C3B+hHD;A2B9hHC;EClDA,8BAAA;EACG,2BAAA;C5BmlHJ;A2B7hHD;;EC/CE,6BAAA;EACG,0BAAA;C5BglHJ;A2B5hHD;EACE,YAAA;C3B8hHD;A2B5hHD;EACE,iBAAA;C3B8hHD;A2B5hHD;;ECnEE,8BAAA;EACG,2BAAA;C5BmmHJ;A2B3hHD;ECjEE,6BAAA;EACG,0BAAA;C5B+lHJ;A2B1hHD;;EAEE,WAAA;C3B4hHD;A2B3gHD;EACE,kBAAA;EACA,mBAAA;C3B6gHD;A2B3gHD;EACE,mBAAA;EACA,oBAAA;C3B6gHD;A2BxgHD;EtB/CE,yDAAA;EACQ,iDAAA;CL0jHT;A2BxgHC;EtBnDA,yBAAA;EACQ,iBAAA;CL8jHT;A2BrgHD;EACE,eAAA;C3BugHD;A2BpgHD;EACE,wBAAA;EACA,uBAAA;C3BsgHD;A2BngHD;EACE,wBAAA;C3BqgHD;A2B9/GD;;;EAII,eAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;C3B+/GH;A2BtgHD;EAcM,YAAA;C3B2/GL;A2BzgHD;;;;EAsBI,iBAAA;EACA,eAAA;C3By/GH;A2Bp/GC;EACE,iBAAA;C3Bs/GH;A2Bp/GC;EC3KA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5B4pHF;A2Bt/GC;EC/KA,2BAAA;EACC,0BAAA;EAOD,gCAAA;EACC,+BAAA;C5BkqHF;A2Bv/GD;EACE,iBAAA;C3By/GD;A2Bv/GD;;EC/KE,8BAAA;EACC,6BAAA;C5B0qHF;A2Bt/GD;EC7LE,2BAAA;EACC,0BAAA;C5BsrHF;A2Bl/GD;EACE,eAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;C3Bo/GD;A2Bx/GD;;EAOI,YAAA;EACA,oBAAA;EACA,UAAA;C3Bq/GH;A2B9/GD;EAYI,YAAA;C3Bq/GH;A2BjgHD;EAgBI,WAAA;C3Bo/GH;A2Bn+GD;;;;EAKM,mBAAA;EACA,uBAAA;EACA,qBAAA;C3Bo+GL;A6B9sHD;EACE,mBAAA;EACA,eAAA;EACA,0BAAA;C7BgtHD;A6B7sHC;EACE,YAAA;EACA,gBAAA;EACA,iBAAA;C7B+sHH;A6BxtHD;EAeI,mBAAA;EACA,WAAA;EAKA,YAAA;EAEA,YAAA;EACA,iBAAA;C7BusHH;A6BrsHG;EACE,WAAA;C7BusHL;A6B7rHD;;;EV0BE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBwqHD;AmBtqHC;;;EACE,aAAA;EACA,kBAAA;CnB0qHH;AmBvqHC;;;;;;EAEE,aAAA;CnB6qHH;A6B/sHD;;;EVqBE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnB+rHD;AmB7rHC;;;EACE,aAAA;EACA,kBAAA;CnBisHH;AmB9rHC;;;;;;EAEE,aAAA;CnBosHH;A6B7tHD;;;EAGE,oBAAA;C7B+tHD;A6B7tHC;;;EACE,iBAAA;C7BiuHH;A6B7tHD;;EAEE,UAAA;EACA,oBAAA;EACA,uBAAA;C7B+tHD;A6B1tHD;EACE,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;C7B4tHD;A6BztHC;EACE,kBAAA;EACA,gBAAA;EACA,mBAAA;C7B2tHH;A6BztHC;EACE,mBAAA;EACA,gBAAA;EACA,mBAAA;C7B2tHH;A6B/uHD;;EA0BI,cAAA;C7BytHH;A6BptHD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;C5Bi0HJ;A6BrtHD;EACE,gBAAA;C7ButHD;A6BrtHD;;;;;;;EDxGE,6BAAA;EACG,0BAAA;C5Bs0HJ;A6BttHD;EACE,eAAA;C7BwtHD;A6BntHD;EACE,mBAAA;EAGA,aAAA;EACA,oBAAA;C7BmtHD;A6BxtHD;EAUI,mBAAA;C7BitHH;A6B3tHD;EAYM,kBAAA;C7BktHL;A6B/sHG;;;EAGE,WAAA;C7BitHL;A6B5sHC;;EAGI,mBAAA;C7B6sHL;A6B1sHC;;EAGI,WAAA;EACA,kBAAA;C7B2sHL;A8B12HD;EACE,iBAAA;EACA,gBAAA;EACA,iBAAA;C9B42HD;A8B/2HD;EAOI,mBAAA;EACA,eAAA;C9B22HH;A8Bn3HD;EAWM,mBAAA;EACA,eAAA;EACA,mBAAA;C9B22HL;A8B12HK;;EAEE,sBAAA;EACA,0BAAA;C9B42HP;A8Bv2HG;EACE,eAAA;C9By2HL;A8Bv2HK;;EAEE,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,oBAAA;C9By2HP;A8Bl2HG;;;EAGE,0BAAA;EACA,sBAAA;C9Bo2HL;A8B74HD;ELHE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBm5HD;A8Bn5HD;EA0DI,gBAAA;C9B41HH;A8Bn1HD;EACE,8BAAA;C9Bq1HD;A8Bt1HD;EAGI,YAAA;EAEA,oBAAA;C9Bq1HH;A8B11HD;EASM,kBAAA;EACA,wBAAA;EACA,8BAAA;EACA,2BAAA;C9Bo1HL;A8Bn1HK;EACE,mCAAA;C9Bq1HP;A8B/0HK;;;EAGE,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,iCAAA;EACA,gBAAA;C9Bi1HP;A8B50HC;EAqDA,YAAA;EA8BA,iBAAA;C9B6vHD;A8Bh1HC;EAwDE,YAAA;C9B2xHH;A8Bn1HC;EA0DI,mBAAA;EACA,mBAAA;C9B4xHL;A8Bv1HC;EAgEE,UAAA;EACA,WAAA;C9B0xHH;A8B9wHD;EA0DA;IAjEM,oBAAA;IACA,UAAA;G9ByxHH;E8BztHH;IA9DQ,iBAAA;G9B0xHL;CACF;A8Bp2HC;EAuFE,gBAAA;EACA,mBAAA;C9BgxHH;A8Bx2HC;;;EA8FE,uBAAA;C9B+wHH;A8BjwHD;EA2BA;IApCM,8BAAA;IACA,2BAAA;G9B8wHH;E8B3uHH;;;IA9BM,0BAAA;G9B8wHH;CACF;A8B/2HD;EAEI,YAAA;C9Bg3HH;A8Bl3HD;EAMM,mBAAA;C9B+2HL;A8Br3HD;EASM,iBAAA;C9B+2HL;A8B12HK;;;EAGE,YAAA;EACA,0BAAA;C9B42HP;A8Bp2HD;EAEI,YAAA;C9Bq2HH;A8Bv2HD;EAIM,gBAAA;EACA,eAAA;C9Bs2HL;A8B11HD;EACE,YAAA;C9B41HD;A8B71HD;EAII,YAAA;C9B41HH;A8Bh2HD;EAMM,mBAAA;EACA,mBAAA;C9B61HL;A8Bp2HD;EAYI,UAAA;EACA,WAAA;C9B21HH;A8B/0HD;EA0DA;IAjEM,oBAAA;IACA,UAAA;G9B01HH;E8B1xHH;IA9DQ,iBAAA;G9B21HL;CACF;A8Bn1HD;EACE,iBAAA;C9Bq1HD;A8Bt1HD;EAKI,gBAAA;EACA,mBAAA;C9Bo1HH;A8B11HD;;;EAYI,uBAAA;C9Bm1HH;A8Br0HD;EA2BA;IApCM,8BAAA;IACA,2BAAA;G9Bk1HH;E8B/yHH;;;IA9BM,0BAAA;G9Bk1HH;CACF;A8Bz0HD;EAEI,cAAA;C9B00HH;A8B50HD;EAKI,eAAA;C9B00HH;A8Bj0HD;EAEE,iBAAA;EF3OA,2BAAA;EACC,0BAAA;C5B8iIF;A+BxiID;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,8BAAA;C/B0iID;A+BliID;EA8nBA;IAhoBI,mBAAA;G/BwiID;CACF;A+BzhID;EAgnBA;IAlnBI,YAAA;G/B+hID;CACF;A+BjhID;EACE,oBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,2DAAA;UAAA,mDAAA;EAEA,kCAAA;C/BkhID;A+BhhIC;EACE,iBAAA;C/BkhIH;A+Bt/HD;EA6jBA;IArlBI,YAAA;IACA,cAAA;IACA,yBAAA;YAAA,iBAAA;G/BkhID;E+BhhIC;IACE,0BAAA;IACA,wBAAA;IACA,kBAAA;IACA,6BAAA;G/BkhIH;E+B/gIC;IACE,oBAAA;G/BihIH;E+B5gIC;;;IAGE,gBAAA;IACA,iBAAA;G/B8gIH;CACF;A+B1gID;;EAGI,kBAAA;C/B2gIH;A+BtgIC;EAmjBF;;IArjBM,kBAAA;G/B6gIH;CACF;A+BpgID;;;;EAII,oBAAA;EACA,mBAAA;C/BsgIH;A+BhgIC;EAgiBF;;;;IAniBM,gBAAA;IACA,eAAA;G/B0gIH;CACF;A+B9/HD;EACE,cAAA;EACA,sBAAA;C/BggID;A+B3/HD;EA8gBA;IAhhBI,iBAAA;G/BigID;CACF;A+B7/HD;;EAEE,gBAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;C/B+/HD;A+Bz/HD;EAggBA;;IAlgBI,iBAAA;G/BggID;CACF;A+B9/HD;EACE,OAAA;EACA,sBAAA;C/BggID;A+B9/HD;EACE,UAAA;EACA,iBAAA;EACA,sBAAA;C/BggID;A+B1/HD;EACE,YAAA;EACA,mBAAA;EACA,gBAAA;EACA,kBAAA;EACA,aAAA;C/B4/HD;A+B1/HC;;EAEE,sBAAA;C/B4/HH;A+BrgID;EAaI,eAAA;C/B2/HH;A+Bl/HD;EALI;;IAEE,mBAAA;G/B0/HH;CACF;A+Bh/HD;EACE,mBAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;EC9LA,gBAAA;EACA,mBAAA;ED+LA,8BAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;C/Bm/HD;A+B/+HC;EACE,WAAA;C/Bi/HH;A+B//HD;EAmBI,eAAA;EACA,YAAA;EACA,YAAA;EACA,mBAAA;C/B++HH;A+BrgID;EAyBI,gBAAA;C/B++HH;A+Bz+HD;EAqbA;IAvbI,cAAA;G/B++HD;CACF;A+Bt+HD;EACE,oBAAA;C/Bw+HD;A+Bz+HD;EAII,kBAAA;EACA,qBAAA;EACA,kBAAA;C/Bw+HH;A+B58HC;EA2YF;IAjaM,iBAAA;IACA,YAAA;IACA,YAAA;IACA,cAAA;IACA,8BAAA;IACA,UAAA;IACA,yBAAA;YAAA,iBAAA;G/Bs+HH;E+B3kHH;;IAxZQ,2BAAA;G/Bu+HL;E+B/kHH;IArZQ,kBAAA;G/Bu+HL;E+Bt+HK;;IAEE,uBAAA;G/Bw+HP;CACF;A+Bt9HD;EA+XA;IA1YI,YAAA;IACA,UAAA;G/Bq+HD;E+B5lHH;IAtYM,YAAA;G/Bq+HH;E+B/lHH;IApYQ,kBAAA;IACA,qBAAA;G/Bs+HL;CACF;A+B39HD;EACE,mBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,qCAAA;E1B9NA,6FAAA;EACQ,qFAAA;E2B/DR,gBAAA;EACA,mBAAA;ChC4vID;AkBtuHD;EAwEA;IAtIM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlBwyHH;EkBpqHH;IA/HM,sBAAA;IACA,YAAA;IACA,uBAAA;GlBsyHH;EkBzqHH;IAxHM,sBAAA;GlBoyHH;EkB5qHH;IApHM,sBAAA;IACA,uBAAA;GlBmyHH;EkBhrHH;;;IA9GQ,YAAA;GlBmyHL;EkBrrHH;IAxGM,YAAA;GlBgyHH;EkBxrHH;IApGM,iBAAA;IACA,uBAAA;GlB+xHH;EkB5rHH;;IA5FM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlB4xHH;EkBnsHH;;IAtFQ,gBAAA;GlB6xHL;EkBvsHH;;IAjFM,mBAAA;IACA,eAAA;GlB4xHH;EkB5sHH;IA3EM,OAAA;GlB0xHH;CACF;A+BpgIC;EAmWF;IAzWM,mBAAA;G/B8gIH;E+B5gIG;IACE,iBAAA;G/B8gIL;CACF;A+B7/HD;EAoVA;IA5VI,YAAA;IACA,UAAA;IACA,eAAA;IACA,gBAAA;IACA,eAAA;IACA,kBAAA;I1BzPF,yBAAA;IACQ,iBAAA;GLmwIP;CACF;A+BngID;EACE,cAAA;EHpUA,2BAAA;EACC,0BAAA;C5B00IF;A+BngID;EACE,iBAAA;EHzUA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5By0IF;A+B//HD;EChVE,gBAAA;EACA,mBAAA;ChCk1ID;A+BhgIC;ECnVA,iBAAA;EACA,oBAAA;ChCs1ID;A+BjgIC;ECtVA,iBAAA;EACA,oBAAA;ChC01ID;A+B3/HD;EChWE,iBAAA;EACA,oBAAA;ChC81ID;A+Bv/HD;EAsSA;IA1SI,YAAA;IACA,kBAAA;IACA,mBAAA;G/B+/HD;CACF;A+Bl+HD;EAhBE;IExWA,uBAAA;GjC81IC;E+Br/HD;IE5WA,wBAAA;IF8WE,oBAAA;G/Bu/HD;E+Bz/HD;IAKI,gBAAA;G/Bu/HH;CACF;A+B9+HD;EACE,0BAAA;EACA,sBAAA;C/Bg/HD;A+Bl/HD;EAKI,YAAA;C/Bg/HH;A+B/+HG;;EAEE,eAAA;EACA,8BAAA;C/Bi/HL;A+B1/HD;EAcI,YAAA;C/B++HH;A+B7/HD;EAmBM,YAAA;C/B6+HL;A+B3+HK;;EAEE,YAAA;EACA,8BAAA;C/B6+HP;A+Bz+HK;;;EAGE,YAAA;EACA,0BAAA;C/B2+HP;A+Bv+HK;;;EAGE,YAAA;EACA,8BAAA;C/By+HP;A+BjhID;EA8CI,mBAAA;C/Bs+HH;A+Br+HG;;EAEE,uBAAA;C/Bu+HL;A+BxhID;EAoDM,uBAAA;C/Bu+HL;A+B3hID;;EA0DI,sBAAA;C/Bq+HH;A+B99HK;;;EAGE,0BAAA;EACA,YAAA;C/Bg+HP;A+B/7HC;EAoKF;IA7LU,YAAA;G/B49HP;E+B39HO;;IAEE,YAAA;IACA,8BAAA;G/B69HT;E+Bz9HO;;;IAGE,YAAA;IACA,0BAAA;G/B29HT;E+Bv9HO;;;IAGE,YAAA;IACA,8BAAA;G/By9HT;CACF;A+B3jID;EA8GI,YAAA;C/Bg9HH;A+B/8HG;EACE,YAAA;C/Bi9HL;A+BjkID;EAqHI,YAAA;C/B+8HH;A+B98HG;;EAEE,YAAA;C/Bg9HL;A+B58HK;;;;EAEE,YAAA;C/Bg9HP;A+Bx8HD;EACE,uBAAA;EACA,sBAAA;C/B08HD;A+B58HD;EAKI,eAAA;C/B08HH;A+Bz8HG;;EAEE,YAAA;EACA,8BAAA;C/B28HL;A+Bp9HD;EAcI,eAAA;C/By8HH;A+Bv9HD;EAmBM,eAAA;C/Bu8HL;A+Br8HK;;EAEE,YAAA;EACA,8BAAA;C/Bu8HP;A+Bn8HK;;;EAGE,YAAA;EACA,0BAAA;C/Bq8HP;A+Bj8HK;;;EAGE,YAAA;EACA,8BAAA;C/Bm8HP;A+B3+HD;EA+CI,mBAAA;C/B+7HH;A+B97HG;;EAEE,uBAAA;C/Bg8HL;A+Bl/HD;EAqDM,uBAAA;C/Bg8HL;A+Br/HD;;EA2DI,sBAAA;C/B87HH;A+Bx7HK;;;EAGE,0BAAA;EACA,YAAA;C/B07HP;A+Bn5HC;EAwBF;IAvDU,sBAAA;G/Bs7HP;E+B/3HH;IApDU,0BAAA;G/Bs7HP;E+Bl4HH;IAjDU,eAAA;G/Bs7HP;E+Br7HO;;IAEE,YAAA;IACA,8BAAA;G/Bu7HT;E+Bn7HO;;;IAGE,YAAA;IACA,0BAAA;G/Bq7HT;E+Bj7HO;;;IAGE,YAAA;IACA,8BAAA;G/Bm7HT;CACF;A+B3hID;EA+GI,eAAA;C/B+6HH;A+B96HG;EACE,YAAA;C/Bg7HL;A+BjiID;EAsHI,eAAA;C/B86HH;A+B76HG;;EAEE,YAAA;C/B+6HL;A+B36HK;;;;EAEE,YAAA;C/B+6HP;AkCzjJD;EACE,kBAAA;EACA,oBAAA;EACA,iBAAA;EACA,0BAAA;EACA,mBAAA;ClC2jJD;AkChkJD;EAQI,sBAAA;ClC2jJH;AkCnkJD;EAWM,kBAAA;EACA,eAAA;EACA,YAAA;ClC2jJL;AkCxkJD;EAkBI,eAAA;ClCyjJH;AmC7kJD;EACE,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,mBAAA;CnC+kJD;AmCnlJD;EAOI,gBAAA;CnC+kJH;AmCtlJD;;EAUM,mBAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,sBAAA;EACA,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,kBAAA;CnCglJL;AmC9kJG;;EAGI,eAAA;EPXN,+BAAA;EACG,4BAAA;C5B2lJJ;AmC7kJG;;EPvBF,gCAAA;EACG,6BAAA;C5BwmJJ;AmCxkJG;;;;EAEE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CnC4kJL;AmCtkJG;;;;;;EAGE,WAAA;EACA,YAAA;EACA,0BAAA;EACA,sBAAA;EACA,gBAAA;CnC2kJL;AmCloJD;;;;;;EAkEM,eAAA;EACA,uBAAA;EACA,mBAAA;EACA,oBAAA;CnCwkJL;AmC/jJD;;EC3EM,mBAAA;EACA,gBAAA;EACA,uBAAA;CpC8oJL;AoC5oJG;;ERKF,+BAAA;EACG,4BAAA;C5B2oJJ;AoC3oJG;;ERTF,gCAAA;EACG,6BAAA;C5BwpJJ;AmC1kJD;;EChFM,kBAAA;EACA,gBAAA;EACA,iBAAA;CpC8pJL;AoC5pJG;;ERKF,+BAAA;EACG,4BAAA;C5B2pJJ;AoC3pJG;;ERTF,gCAAA;EACG,6BAAA;C5BwqJJ;AqC3qJD;EACE,gBAAA;EACA,eAAA;EACA,iBAAA;EACA,mBAAA;CrC6qJD;AqCjrJD;EAOI,gBAAA;CrC6qJH;AqCprJD;;EAUM,sBAAA;EACA,kBAAA;EACA,uBAAA;EACA,uBAAA;EACA,oBAAA;CrC8qJL;AqC5rJD;;EAmBM,sBAAA;EACA,0BAAA;CrC6qJL;AqCjsJD;;EA2BM,aAAA;CrC0qJL;AqCrsJD;;EAkCM,YAAA;CrCuqJL;AqCzsJD;;;;EA2CM,eAAA;EACA,uBAAA;EACA,oBAAA;CrCoqJL;AsCltJD;EACE,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,mBAAA;EACA,oBAAA;EACA,yBAAA;EACA,qBAAA;CtCotJD;AsChtJG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CtCktJL;AsC7sJC;EACE,cAAA;CtC+sJH;AsC3sJC;EACE,mBAAA;EACA,UAAA;CtC6sJH;AsCtsJD;ECtCE,0BAAA;CvC+uJD;AuC5uJG;;EAEE,0BAAA;CvC8uJL;AsCzsJD;EC1CE,0BAAA;CvCsvJD;AuCnvJG;;EAEE,0BAAA;CvCqvJL;AsC5sJD;EC9CE,0BAAA;CvC6vJD;AuC1vJG;;EAEE,0BAAA;CvC4vJL;AsC/sJD;EClDE,0BAAA;CvCowJD;AuCjwJG;;EAEE,0BAAA;CvCmwJL;AsCltJD;ECtDE,0BAAA;CvC2wJD;AuCxwJG;;EAEE,0BAAA;CvC0wJL;AsCrtJD;EC1DE,0BAAA;CvCkxJD;AuC/wJG;;EAEE,0BAAA;CvCixJL;AwCnxJD;EACE,sBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,YAAA;EACA,eAAA;EACA,uBAAA;EACA,oBAAA;EACA,mBAAA;EACA,0BAAA;EACA,oBAAA;CxCqxJD;AwClxJC;EACE,cAAA;CxCoxJH;AwChxJC;EACE,mBAAA;EACA,UAAA;CxCkxJH;AwC/wJC;;EAEE,OAAA;EACA,iBAAA;CxCixJH;AwC5wJG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CxC8wJL;AwCzwJC;;EAEE,eAAA;EACA,uBAAA;CxC2wJH;AwCxwJC;EACE,aAAA;CxC0wJH;AwCvwJC;EACE,kBAAA;CxCywJH;AwCtwJC;EACE,iBAAA;CxCwwJH;AyCl0JD;EACE,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,eAAA;EACA,0BAAA;CzCo0JD;AyCz0JD;;EASI,eAAA;CzCo0JH;AyC70JD;EAaI,oBAAA;EACA,gBAAA;EACA,iBAAA;CzCm0JH;AyCl1JD;EAmBI,0BAAA;CzCk0JH;AyC/zJC;;EAEE,mBAAA;EACA,mBAAA;EACA,oBAAA;CzCi0JH;AyC31JD;EA8BI,gBAAA;CzCg0JH;AyC9yJD;EACA;IAfI,kBAAA;IACA,qBAAA;GzCg0JD;EyC9zJC;;IAEE,mBAAA;IACA,oBAAA;GzCg0JH;EyCvzJH;;IAJM,gBAAA;GzC+zJH;CACF;A0C52JD;EACE,eAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;ErCiLA,4CAAA;EACK,uCAAA;EACG,oCAAA;CL8rJT;A0Cx3JD;;EAaI,kBAAA;EACA,mBAAA;C1C+2JH;A0C32JC;;;EAGE,sBAAA;C1C62JH;A0Cl4JD;EA0BI,aAAA;EACA,eAAA;C1C22JH;A2Cp4JD;EACE,cAAA;EACA,oBAAA;EACA,8BAAA;EACA,mBAAA;C3Cs4JD;A2C14JD;EAQI,cAAA;EAEA,eAAA;C3Co4JH;A2C94JD;EAeI,kBAAA;C3Ck4JH;A2Cj5JD;;EAqBI,iBAAA;C3Cg4JH;A2Cr5JD;EAyBI,gBAAA;C3C+3JH;A2Cv3JD;;EAEE,oBAAA;C3Cy3JD;A2C33JD;;EAMI,mBAAA;EACA,UAAA;EACA,aAAA;EACA,eAAA;C3Cy3JH;A2Cj3JD;ECvDE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C26JD;A2Ct3JD;EClDI,0BAAA;C5C26JH;A2Cz3JD;EC/CI,eAAA;C5C26JH;A2Cx3JD;EC3DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Cs7JD;A2C73JD;ECtDI,0BAAA;C5Cs7JH;A2Ch4JD;ECnDI,eAAA;C5Cs7JH;A2C/3JD;EC/DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Ci8JD;A2Cp4JD;EC1DI,0BAAA;C5Ci8JH;A2Cv4JD;ECvDI,eAAA;C5Ci8JH;A2Ct4JD;ECnEE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C48JD;A2C34JD;EC9DI,0BAAA;C5C48JH;A2C94JD;EC3DI,eAAA;C5C48JH;A6C98JD;EACE;IAAQ,4BAAA;G7Ci9JP;E6Ch9JD;IAAQ,yBAAA;G7Cm9JP;CACF;A6Ch9JD;EACE;IAAQ,4BAAA;G7Cm9JP;E6Cl9JD;IAAQ,yBAAA;G7Cq9JP;CACF;A6Cx9JD;EACE;IAAQ,4BAAA;G7Cm9JP;E6Cl9JD;IAAQ,yBAAA;G7Cq9JP;CACF;A6C98JD;EACE,iBAAA;EACA,aAAA;EACA,oBAAA;EACA,0BAAA;EACA,mBAAA;ExCsCA,uDAAA;EACQ,+CAAA;CL26JT;A6C78JD;EACE,YAAA;EACA,UAAA;EACA,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,YAAA;EACA,mBAAA;EACA,0BAAA;ExCyBA,uDAAA;EACQ,+CAAA;EAyHR,oCAAA;EACK,+BAAA;EACG,4BAAA;CL+zJT;A6C18JD;;ECCI,8MAAA;EACA,yMAAA;EACA,sMAAA;EDAF,mCAAA;UAAA,2BAAA;C7C88JD;A6Cv8JD;;ExC5CE,2DAAA;EACK,sDAAA;EACG,mDAAA;CLu/JT;A6Cp8JD;EErEE,0BAAA;C/C4gKD;A+CzgKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C49JH;A6Cx8JD;EEzEE,0BAAA;C/CohKD;A+CjhKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9Co+JH;A6C58JD;EE7EE,0BAAA;C/C4hKD;A+CzhKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C4+JH;A6Ch9JD;EEjFE,0BAAA;C/CoiKD;A+CjiKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9Co/JH;AgD5iKD;EAEE,iBAAA;ChD6iKD;AgD3iKC;EACE,cAAA;ChD6iKH;AgDziKD;;EAEE,QAAA;EACA,iBAAA;ChD2iKD;AgDxiKD;EACE,eAAA;ChD0iKD;AgDviKD;EACE,eAAA;ChDyiKD;AgDtiKC;EACE,gBAAA;ChDwiKH;AgDpiKD;;EAEE,mBAAA;ChDsiKD;AgDniKD;;EAEE,oBAAA;ChDqiKD;AgDliKD;;;EAGE,oBAAA;EACA,oBAAA;ChDoiKD;AgDjiKD;EACE,uBAAA;ChDmiKD;AgDhiKD;EACE,uBAAA;ChDkiKD;AgD9hKD;EACE,cAAA;EACA,mBAAA;ChDgiKD;AgD1hKD;EACE,gBAAA;EACA,iBAAA;ChD4hKD;AiDnlKD;EAEE,oBAAA;EACA,gBAAA;CjDolKD;AiD5kKD;EACE,mBAAA;EACA,eAAA;EACA,mBAAA;EAEA,oBAAA;EACA,uBAAA;EACA,uBAAA;CjD6kKD;AiD1kKC;ErB3BA,6BAAA;EACC,4BAAA;C5BwmKF;AiD3kKC;EACE,iBAAA;ErBvBF,gCAAA;EACC,+BAAA;C5BqmKF;AiDpkKD;;EAEE,YAAA;CjDskKD;AiDxkKD;;EAKI,YAAA;CjDukKH;AiDnkKC;;;;EAEE,sBAAA;EACA,YAAA;EACA,0BAAA;CjDukKH;AiDnkKD;EACE,YAAA;EACA,iBAAA;CjDqkKD;AiDhkKC;;;EAGE,0BAAA;EACA,eAAA;EACA,oBAAA;CjDkkKH;AiDvkKC;;;EASI,eAAA;CjDmkKL;AiD5kKC;;;EAYI,eAAA;CjDqkKL;AiDhkKC;;;EAGE,WAAA;EACA,YAAA;EACA,0BAAA;EACA,sBAAA;CjDkkKH;AiDxkKC;;;;;;;;;EAYI,eAAA;CjDukKL;AiDnlKC;;;EAeI,eAAA;CjDykKL;AkD3qKC;EACE,eAAA;EACA,0BAAA;ClD6qKH;AkD3qKG;;EAEE,eAAA;ClD6qKL;AkD/qKG;;EAKI,eAAA;ClD8qKP;AkD3qKK;;;;EAEE,eAAA;EACA,0BAAA;ClD+qKP;AkD7qKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDkrKP;AkDxsKC;EACE,eAAA;EACA,0BAAA;ClD0sKH;AkDxsKG;;EAEE,eAAA;ClD0sKL;AkD5sKG;;EAKI,eAAA;ClD2sKP;AkDxsKK;;;;EAEE,eAAA;EACA,0BAAA;ClD4sKP;AkD1sKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD+sKP;AkDruKC;EACE,eAAA;EACA,0BAAA;ClDuuKH;AkDruKG;;EAEE,eAAA;ClDuuKL;AkDzuKG;;EAKI,eAAA;ClDwuKP;AkDruKK;;;;EAEE,eAAA;EACA,0BAAA;ClDyuKP;AkDvuKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD4uKP;AkDlwKC;EACE,eAAA;EACA,0BAAA;ClDowKH;AkDlwKG;;EAEE,eAAA;ClDowKL;AkDtwKG;;EAKI,eAAA;ClDqwKP;AkDlwKK;;;;EAEE,eAAA;EACA,0BAAA;ClDswKP;AkDpwKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDywKP;AiDxqKD;EACE,cAAA;EACA,mBAAA;CjD0qKD;AiDxqKD;EACE,iBAAA;EACA,iBAAA;CjD0qKD;AmDpyKD;EACE,oBAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;E9C0DA,kDAAA;EACQ,0CAAA;CL6uKT;AmDnyKD;EACE,cAAA;CnDqyKD;AmDhyKD;EACE,mBAAA;EACA,qCAAA;EvBpBA,6BAAA;EACC,4BAAA;C5BuzKF;AmDtyKD;EAMI,eAAA;CnDmyKH;AmD9xKD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,eAAA;CnDgyKD;AmDpyKD;;;;;EAWI,eAAA;CnDgyKH;AmD3xKD;EACE,mBAAA;EACA,0BAAA;EACA,2BAAA;EvBxCA,gCAAA;EACC,+BAAA;C5Bs0KF;AmDrxKD;;EAGI,iBAAA;CnDsxKH;AmDzxKD;;EAMM,oBAAA;EACA,iBAAA;CnDuxKL;AmDnxKG;;EAEI,cAAA;EvBvEN,6BAAA;EACC,4BAAA;C5B61KF;AmDjxKG;;EAEI,iBAAA;EvBvEN,gCAAA;EACC,+BAAA;C5B21KF;AmD1yKD;EvB1DE,2BAAA;EACC,0BAAA;C5Bu2KF;AmD7wKD;EAEI,oBAAA;CnD8wKH;AmD3wKD;EACE,oBAAA;CnD6wKD;AmDrwKD;;;EAII,iBAAA;CnDswKH;AmD1wKD;;;EAOM,mBAAA;EACA,oBAAA;CnDwwKL;AmDhxKD;;EvBzGE,6BAAA;EACC,4BAAA;C5B63KF;AmDrxKD;;;;EAmBQ,4BAAA;EACA,6BAAA;CnDwwKP;AmD5xKD;;;;;;;;EAwBU,4BAAA;CnD8wKT;AmDtyKD;;;;;;;;EA4BU,6BAAA;CnDoxKT;AmDhzKD;;EvBjGE,gCAAA;EACC,+BAAA;C5Bq5KF;AmDrzKD;;;;EAyCQ,+BAAA;EACA,gCAAA;CnDkxKP;AmD5zKD;;;;;;;;EA8CU,+BAAA;CnDwxKT;AmDt0KD;;;;;;;;EAkDU,gCAAA;CnD8xKT;AmDh1KD;;;;EA2DI,2BAAA;CnD2xKH;AmDt1KD;;EA+DI,cAAA;CnD2xKH;AmD11KD;;EAmEI,UAAA;CnD2xKH;AmD91KD;;;;;;;;;;;;EA0EU,eAAA;CnDkyKT;AmD52KD;;;;;;;;;;;;EA8EU,gBAAA;CnD4yKT;AmD13KD;;;;;;;;EAuFU,iBAAA;CnD6yKT;AmDp4KD;;;;;;;;EAgGU,iBAAA;CnD8yKT;AmD94KD;EAsGI,UAAA;EACA,iBAAA;CnD2yKH;AmDjyKD;EACE,oBAAA;CnDmyKD;AmDpyKD;EAKI,iBAAA;EACA,mBAAA;CnDkyKH;AmDxyKD;EASM,gBAAA;CnDkyKL;AmD3yKD;EAcI,iBAAA;CnDgyKH;AmD9yKD;;EAkBM,2BAAA;CnDgyKL;AmDlzKD;EAuBI,cAAA;CnD8xKH;AmDrzKD;EAyBM,8BAAA;CnD+xKL;AmDxxKD;EC1PE,mBAAA;CpDqhLD;AoDnhLC;EACE,eAAA;EACA,0BAAA;EACA,mBAAA;CpDqhLH;AoDxhLC;EAMI,uBAAA;CpDqhLL;AoD3hLC;EASI,eAAA;EACA,0BAAA;CpDqhLL;AoDlhLC;EAEI,0BAAA;CpDmhLL;AmDvyKD;EC7PE,sBAAA;CpDuiLD;AoDriLC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CpDuiLH;AoD1iLC;EAMI,0BAAA;CpDuiLL;AoD7iLC;EASI,eAAA;EACA,uBAAA;CpDuiLL;AoDpiLC;EAEI,6BAAA;CpDqiLL;AmDtzKD;EChQE,sBAAA;CpDyjLD;AoDvjLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDyjLH;AoD5jLC;EAMI,0BAAA;CpDyjLL;AoD/jLC;EASI,eAAA;EACA,0BAAA;CpDyjLL;AoDtjLC;EAEI,6BAAA;CpDujLL;AmDr0KD;ECnQE,sBAAA;CpD2kLD;AoDzkLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD2kLH;AoD9kLC;EAMI,0BAAA;CpD2kLL;AoDjlLC;EASI,eAAA;EACA,0BAAA;CpD2kLL;AoDxkLC;EAEI,6BAAA;CpDykLL;AmDp1KD;ECtQE,sBAAA;CpD6lLD;AoD3lLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD6lLH;AoDhmLC;EAMI,0BAAA;CpD6lLL;AoDnmLC;EASI,eAAA;EACA,0BAAA;CpD6lLL;AoD1lLC;EAEI,6BAAA;CpD2lLL;AmDn2KD;ECzQE,sBAAA;CpD+mLD;AoD7mLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD+mLH;AoDlnLC;EAMI,0BAAA;CpD+mLL;AoDrnLC;EASI,eAAA;EACA,0BAAA;CpD+mLL;AoD5mLC;EAEI,6BAAA;CpD6mLL;AqD7nLD;EACE,mBAAA;EACA,eAAA;EACA,UAAA;EACA,WAAA;EACA,iBAAA;CrD+nLD;AqDpoLD;;;;;EAYI,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,aAAA;EACA,YAAA;EACA,UAAA;CrD+nLH;AqD1nLD;EACE,uBAAA;CrD4nLD;AqDxnLD;EACE,oBAAA;CrD0nLD;AsDrpLD;EACE,iBAAA;EACA,cAAA;EACA,oBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EjDwDA,wDAAA;EACQ,gDAAA;CLgmLT;AsD/pLD;EASI,mBAAA;EACA,kCAAA;CtDypLH;AsDppLD;EACE,cAAA;EACA,mBAAA;CtDspLD;AsDppLD;EACE,aAAA;EACA,mBAAA;CtDspLD;AuD5qLD;EACE,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,0BAAA;EjCRA,aAAA;EAGA,0BAAA;CtBqrLD;AuD7qLC;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;EjCfF,aAAA;EAGA,0BAAA;CtB6rLD;AuDzqLC;EACE,WAAA;EACA,gBAAA;EACA,wBAAA;EACA,UAAA;EACA,yBAAA;CvD2qLH;AwDhsLD;EACE,iBAAA;CxDksLD;AwD9rLD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,kCAAA;EAIA,WAAA;CxD6rLD;AwD1rLC;EnD+GA,sCAAA;EACI,kCAAA;EACC,iCAAA;EACG,8BAAA;EAkER,oDAAA;EAEK,0CAAA;EACG,oCAAA;CL6gLT;AwDhsLC;EnD2GA,mCAAA;EACI,+BAAA;EACC,8BAAA;EACG,2BAAA;CLwlLT;AwDpsLD;EACE,mBAAA;EACA,iBAAA;CxDssLD;AwDlsLD;EACE,mBAAA;EACA,YAAA;EACA,aAAA;CxDosLD;AwDhsLD;EACE,mBAAA;EACA,uBAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EnDaA,iDAAA;EACQ,yCAAA;EmDZR,qCAAA;UAAA,6BAAA;EAEA,WAAA;CxDksLD;AwD9rLD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,uBAAA;CxDgsLD;AwD9rLC;ElCrEA,WAAA;EAGA,yBAAA;CtBowLD;AwDjsLC;ElCtEA,aAAA;EAGA,0BAAA;CtBwwLD;AwDhsLD;EACE,cAAA;EACA,iCAAA;CxDksLD;AwD9rLD;EACE,iBAAA;CxDgsLD;AwD5rLD;EACE,UAAA;EACA,wBAAA;CxD8rLD;AwDzrLD;EACE,mBAAA;EACA,cAAA;CxD2rLD;AwDvrLD;EACE,cAAA;EACA,kBAAA;EACA,8BAAA;CxDyrLD;AwD5rLD;EAQI,iBAAA;EACA,iBAAA;CxDurLH;AwDhsLD;EAaI,kBAAA;CxDsrLH;AwDnsLD;EAiBI,eAAA;CxDqrLH;AwDhrLD;EACE,mBAAA;EACA,aAAA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;CxDkrLD;AwDhqLD;EAZE;IACE,aAAA;IACA,kBAAA;GxD+qLD;EwD7qLD;InDvEA,kDAAA;IACQ,0CAAA;GLuvLP;EwD5qLD;IAAY,aAAA;GxD+qLX;CACF;AwD1qLD;EAFE;IAAY,aAAA;GxDgrLX;CACF;AyD/zLD;EACE,mBAAA;EACA,cAAA;EACA,eAAA;ECRA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;EDHA,gBAAA;EnCVA,WAAA;EAGA,yBAAA;CtBs1LD;AyD30LC;EnCdA,aAAA;EAGA,0BAAA;CtB01LD;AyD90LC;EAAW,iBAAA;EAAmB,eAAA;CzDk1L/B;AyDj1LC;EAAW,iBAAA;EAAmB,eAAA;CzDq1L/B;AyDp1LC;EAAW,gBAAA;EAAmB,eAAA;CzDw1L/B;AyDv1LC;EAAW,kBAAA;EAAmB,eAAA;CzD21L/B;AyDv1LD;EACE,iBAAA;EACA,iBAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,mBAAA;CzDy1LD;AyDr1LD;EACE,mBAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;CzDu1LD;AyDn1LC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,uBAAA;CzDq1LH;AyDn1LC;EACE,UAAA;EACA,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzDq1LH;AyDn1LC;EACE,UAAA;EACA,UAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzDq1LH;AyDn1LC;EACE,SAAA;EACA,QAAA;EACA,iBAAA;EACA,4BAAA;EACA,yBAAA;CzDq1LH;AyDn1LC;EACE,SAAA;EACA,SAAA;EACA,iBAAA;EACA,4BAAA;EACA,wBAAA;CzDq1LH;AyDn1LC;EACE,OAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,0BAAA;CzDq1LH;AyDn1LC;EACE,OAAA;EACA,WAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzDq1LH;AyDn1LC;EACE,OAAA;EACA,UAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzDq1LH;A2Dl7LD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EDXA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;ECAA,gBAAA;EAEA,uBAAA;EACA,qCAAA;UAAA,6BAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EtD8CA,kDAAA;EACQ,0CAAA;CLk5LT;A2D77LC;EAAY,kBAAA;C3Dg8Lb;A2D/7LC;EAAY,kBAAA;C3Dk8Lb;A2Dj8LC;EAAY,iBAAA;C3Do8Lb;A2Dn8LC;EAAY,mBAAA;C3Ds8Lb;A2Dn8LD;EACE,UAAA;EACA,kBAAA;EACA,gBAAA;EACA,0BAAA;EACA,iCAAA;EACA,2BAAA;C3Dq8LD;A2Dl8LD;EACE,kBAAA;C3Do8LD;A2D57LC;;EAEE,mBAAA;EACA,eAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;C3D87LH;A2D37LD;EACE,mBAAA;C3D67LD;A2D37LD;EACE,mBAAA;EACA,YAAA;C3D67LD;A2Dz7LC;EACE,UAAA;EACA,mBAAA;EACA,uBAAA;EACA,0BAAA;EACA,sCAAA;EACA,cAAA;C3D27LH;A2D17LG;EACE,aAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,uBAAA;C3D47LL;A2Dz7LC;EACE,SAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,4BAAA;EACA,wCAAA;C3D27LH;A2D17LG;EACE,aAAA;EACA,UAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;C3D47LL;A2Dz7LC;EACE,UAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;EACA,yCAAA;EACA,WAAA;C3D27LH;A2D17LG;EACE,aAAA;EACA,SAAA;EACA,mBAAA;EACA,oBAAA;EACA,0BAAA;C3D47LL;A2Dx7LC;EACE,SAAA;EACA,aAAA;EACA,kBAAA;EACA,sBAAA;EACA,2BAAA;EACA,uCAAA;C3D07LH;A2Dz7LG;EACE,aAAA;EACA,WAAA;EACA,sBAAA;EACA,wBAAA;EACA,cAAA;C3D27LL;A4DpjMD;EACE,mBAAA;C5DsjMD;A4DnjMD;EACE,mBAAA;EACA,iBAAA;EACA,YAAA;C5DqjMD;A4DxjMD;EAMI,cAAA;EACA,mBAAA;EvD6KF,0CAAA;EACK,qCAAA;EACG,kCAAA;CLy4LT;A4D/jMD;;EAcM,eAAA;C5DqjML;A4D3hMC;EA4NF;IvD3DE,uDAAA;IAEK,6CAAA;IACG,uCAAA;IA7JR,oCAAA;IAEQ,4BAAA;IA+GR,4BAAA;IAEQ,oBAAA;GL86LP;E4DzjMG;;IvDmHJ,2CAAA;IACQ,mCAAA;IuDjHF,QAAA;G5D4jML;E4D1jMG;;IvD8GJ,4CAAA;IACQ,oCAAA;IuD5GF,QAAA;G5D6jML;E4D3jMG;;;IvDyGJ,wCAAA;IACQ,gCAAA;IuDtGF,QAAA;G5D8jML;CACF;A4DpmMD;;;EA6CI,eAAA;C5D4jMH;A4DzmMD;EAiDI,QAAA;C5D2jMH;A4D5mMD;;EAsDI,mBAAA;EACA,OAAA;EACA,YAAA;C5D0jMH;A4DlnMD;EA4DI,WAAA;C5DyjMH;A4DrnMD;EA+DI,YAAA;C5DyjMH;A4DxnMD;;EAmEI,QAAA;C5DyjMH;A4D5nMD;EAuEI,YAAA;C5DwjMH;A4D/nMD;EA0EI,WAAA;C5DwjMH;A4DhjMD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EtC9FA,aAAA;EAGA,0BAAA;EsC6FA,gBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;EACA,mCAAA;C5DmjMD;A4D9iMC;EdnGE,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9CopMH;A4DljMC;EACE,WAAA;EACA,SAAA;EdxGA,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9C6pMH;A4DpjMC;;EAEE,WAAA;EACA,YAAA;EACA,sBAAA;EtCvHF,aAAA;EAGA,0BAAA;CtB4qMD;A4DtlMD;;;;EAuCI,mBAAA;EACA,SAAA;EACA,kBAAA;EACA,WAAA;EACA,sBAAA;C5DqjMH;A4DhmMD;;EA+CI,UAAA;EACA,mBAAA;C5DqjMH;A4DrmMD;;EAoDI,WAAA;EACA,oBAAA;C5DqjMH;A4D1mMD;;EAyDI,YAAA;EACA,aAAA;EACA,eAAA;EACA,mBAAA;C5DqjMH;A4DhjMG;EACE,iBAAA;C5DkjML;A4D9iMG;EACE,iBAAA;C5DgjML;A4DtiMD;EACE,mBAAA;EACA,aAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;C5DwiMD;A4DjjMD;EAYI,sBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,oBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;EAWA,0BAAA;EACA,mCAAA;C5D8hMH;A4D7jMD;EAkCI,UAAA;EACA,YAAA;EACA,aAAA;EACA,uBAAA;C5D8hMH;A4DvhMD;EACE,mBAAA;EACA,UAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;C5DyhMD;A4DxhMC;EACE,kBAAA;C5D0hMH;A4Dj/LD;EAhCE;;;;IAKI,YAAA;IACA,aAAA;IACA,kBAAA;IACA,gBAAA;G5DmhMH;E4D3hMD;;IAYI,mBAAA;G5DmhMH;E4D/hMD;;IAgBI,oBAAA;G5DmhMH;E4D9gMD;IACE,UAAA;IACA,WAAA;IACA,qBAAA;G5DghMD;E4D5gMD;IACE,aAAA;G5D8gMD;CACF;A6D7wMC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,aAAA;EACA,eAAA;C7D6yMH;A6D3yMC;;;;;;;;;;;;;;;;EACE,YAAA;C7D4zMH;AiCp0MD;E6BRE,eAAA;EACA,kBAAA;EACA,mBAAA;C9D+0MD;AiCt0MD;EACE,wBAAA;CjCw0MD;AiCt0MD;EACE,uBAAA;CjCw0MD;AiCh0MD;EACE,yBAAA;CjCk0MD;AiCh0MD;EACE,0BAAA;CjCk0MD;AiCh0MD;EACE,mBAAA;CjCk0MD;AiCh0MD;E8BzBE,YAAA;EACA,mBAAA;EACA,kBAAA;EACA,8BAAA;EACA,UAAA;C/D41MD;AiC9zMD;EACE,yBAAA;CjCg0MD;AiCzzMD;EACE,gBAAA;CjC2zMD;AgE51MD;EACE,oBAAA;ChE81MD;AgEx1MD;;;;ECdE,yBAAA;CjE42MD;AgEv1MD;;;;;;;;;;;;EAYE,yBAAA;ChEy1MD;AgEl1MD;EA6IA;IC7LE,0BAAA;GjEs4MC;EiEr4MD;IAAU,0BAAA;GjEw4MT;EiEv4MD;IAAU,8BAAA;GjE04MT;EiEz4MD;;IACU,+BAAA;GjE44MT;CACF;AgE51MD;EAwIA;IA1II,0BAAA;GhEk2MD;CACF;AgE51MD;EAmIA;IArII,2BAAA;GhEk2MD;CACF;AgE51MD;EA8HA;IAhII,iCAAA;GhEk2MD;CACF;AgE31MD;EAwHA;IC7LE,0BAAA;GjEo6MC;EiEn6MD;IAAU,0BAAA;GjEs6MT;EiEr6MD;IAAU,8BAAA;GjEw6MT;EiEv6MD;;IACU,+BAAA;GjE06MT;CACF;AgEr2MD;EAmHA;IArHI,0BAAA;GhE22MD;CACF;AgEr2MD;EA8GA;IAhHI,2BAAA;GhE22MD;CACF;AgEr2MD;EAyGA;IA3GI,iCAAA;GhE22MD;CACF;AgEp2MD;EAmGA;IC7LE,0BAAA;GjEk8MC;EiEj8MD;IAAU,0BAAA;GjEo8MT;EiEn8MD;IAAU,8BAAA;GjEs8MT;EiEr8MD;;IACU,+BAAA;GjEw8MT;CACF;AgE92MD;EA8FA;IAhGI,0BAAA;GhEo3MD;CACF;AgE92MD;EAyFA;IA3FI,2BAAA;GhEo3MD;CACF;AgE92MD;EAoFA;IAtFI,iCAAA;GhEo3MD;CACF;AgE72MD;EA8EA;IC7LE,0BAAA;GjEg+MC;EiE/9MD;IAAU,0BAAA;GjEk+MT;EiEj+MD;IAAU,8BAAA;GjEo+MT;EiEn+MD;;IACU,+BAAA;GjEs+MT;CACF;AgEv3MD;EAyEA;IA3EI,0BAAA;GhE63MD;CACF;AgEv3MD;EAoEA;IAtEI,2BAAA;GhE63MD;CACF;AgEv3MD;EA+DA;IAjEI,iCAAA;GhE63MD;CACF;AgEt3MD;EAyDA;ICrLE,yBAAA;GjEs/MC;CACF;AgEt3MD;EAoDA;ICrLE,yBAAA;GjE2/MC;CACF;AgEt3MD;EA+CA;ICrLE,yBAAA;GjEggNC;CACF;AgEt3MD;EA0CA;ICrLE,yBAAA;GjEqgNC;CACF;AgEn3MD;ECnJE,yBAAA;CjEygND;AgEh3MD;EA4BA;IC7LE,0BAAA;GjEqhNC;EiEphND;IAAU,0BAAA;GjEuhNT;EiEthND;IAAU,8BAAA;GjEyhNT;EiExhND;;IACU,+BAAA;GjE2hNT;CACF;AgE93MD;EACE,yBAAA;ChEg4MD;AgE33MD;EAqBA;IAvBI,0BAAA;GhEi4MD;CACF;AgE/3MD;EACE,yBAAA;ChEi4MD;AgE53MD;EAcA;IAhBI,2BAAA;GhEk4MD;CACF;AgEh4MD;EACE,yBAAA;ChEk4MD;AgE73MD;EAOA;IATI,iCAAA;GhEm4MD;CACF;AgE53MD;EACA;ICrLE,yBAAA;GjEojNC;CACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on
"),e.push("")}}),this.$tableFooter.find("tr").html(e.join("")),this.$tableFooter.show(),clearTimeout(this.timeoutFooter_),this.timeoutFooter_=setTimeout(a.proxy(this.fitFooter,this),this.$el.is(":hidden")?100:0))},o.prototype.fitFooter=function(){var b,c,d;return clearTimeout(this.timeoutFooter_),this.$el.is(":hidden")?void(this.timeoutFooter_=setTimeout(a.proxy(this.fitFooter,this),100)):(c=this.$el.css("width"),d=c>this.$tableBody.width()?g():0,this.$tableFooter.css({"margin-right":d}).find("table").css("width",c).attr("class",this.$el.attr("class")),b=this.$tableFooter.find("td"),void this.$body.find(">tr:first-child:not(.no-records-found) > *").each(function(c){var d=a(this);b.eq(c).find(".fht-cell").width(d.innerWidth())}))},o.prototype.toggleColumn=function(a,b,d){if(-1!==a&&(this.columns[a].visible=b,this.initHeader(),this.initSearch(),this.initPagination(),this.initBody(),this.options.showColumns)){var e=this.$toolbar.find(".keep-open input").prop("disabled",!1);d&&e.filter(c('[value="%s"]',a)).prop("checked",b),e.filter(":checked").length<=this.options.minimumCountColumns&&e.filter(":checked").prop("disabled",!0)}},o.prototype.getVisibleFields=function(){var b=this,c=[];return a.each(this.header.fields,function(a,d){var f=b.columns[e(b.columns,d)];f.visible&&c.push(d)}),c},o.prototype.resetView=function(a){var b=0;if(a&&a.height&&(this.options.height=a.height),this.$selectAll.prop("checked",this.$selectItem.length>0&&this.$selectItem.length===this.$selectItem.filter(":checked").length),this.options.height){var c=this.$toolbar.outerHeight(!0),d=this.$pagination.outerHeight(!0),e=this.options.height-c-d;this.$tableContainer.css("height",e+"px")}return this.options.cardView?(this.$el.css("margin-top","0"),this.$tableContainer.css("padding-bottom","0"),void this.$tableFooter.hide()):(this.options.showHeader&&this.options.height?(this.$tableHeader.show(),this.resetHeader(),b+=this.$header.outerHeight()):(this.$tableHeader.hide(),this.trigger("post-header")),this.options.showFooter&&(this.resetFooter(),this.options.height&&(b+=this.$tableFooter.outerHeight()+1)),this.getCaret(),this.$tableContainer.css("padding-bottom",b+"px"),void this.trigger("reset-view"))},o.prototype.getData=function(b){return!this.searchText&&a.isEmptyObject(this.filterColumns)&&a.isEmptyObject(this.filterColumnsPartial)?b?this.options.data.slice(this.pageFrom-1,this.pageTo):this.options.data:b?this.data.slice(this.pageFrom-1,this.pageTo):this.data},o.prototype.load=function(b){var c=!1;"server"===this.options.sidePagination?(this.options.totalRows=b[this.options.totalField],c=b.fixedScroll,b=b[this.options.dataField]):a.isArray(b)||(c=b.fixedScroll,b=b.data),this.initData(b),this.initSearch(),this.initPagination(),this.initBody(c)},o.prototype.append=function(a){this.initData(a,"append"),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},o.prototype.prepend=function(a){this.initData(a,"prepend"),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},o.prototype.remove=function(b){var c,d,e=this.options.data.length;if(b.hasOwnProperty("field")&&b.hasOwnProperty("values")){for(c=e-1;c>=0;c--)d=this.options.data[c],d.hasOwnProperty(b.field)&&-1!==a.inArray(d[b.field],b.values)&&(this.options.data.splice(c,1),"server"===this.options.sidePagination&&(this.options.totalRows-=1));e!==this.options.data.length&&(this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0))}},o.prototype.removeAll=function(){this.options.data.length>0&&(this.options.data.splice(0,this.options.data.length),this.initSearch(),this.initPagination(),this.initBody(!0))},o.prototype.getRowByUniqueId=function(a){var b,c,d,e=this.options.uniqueId,f=this.options.data.length,g=null;for(b=f-1;b>=0;b--){if(c=this.options.data[b],c.hasOwnProperty(e))d=c[e];else{if(!c._data.hasOwnProperty(e))continue;d=c._data[e]}if("string"==typeof d?a=a.toString():"number"==typeof d&&(Number(d)===d&&d%1===0?a=parseInt(a):d===Number(d)&&0!==d&&(a=parseFloat(a))),d===a){g=c;break}}return g},o.prototype.removeByUniqueId=function(a){var b=this.options.data.length,c=this.getRowByUniqueId(a);c&&this.options.data.splice(this.options.data.indexOf(c),1),b!==this.options.data.length&&(this.initSearch(),this.initPagination(),this.initBody(!0))},o.prototype.updateByUniqueId=function(b){var c=this,d=a.isArray(b)?b:[b];a.each(d,function(b,d){var e;d.hasOwnProperty("id")&&d.hasOwnProperty("row")&&(e=a.inArray(c.getRowByUniqueId(d.id),c.options.data),-1!==e&&a.extend(c.options.data[e],d.row))}),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},o.prototype.insertRow=function(a){a.hasOwnProperty("index")&&a.hasOwnProperty("row")&&(this.data.splice(a.index,0,a.row),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0))},o.prototype.updateRow=function(b){var c=this,d=a.isArray(b)?b:[b];a.each(d,function(b,d){d.hasOwnProperty("index")&&d.hasOwnProperty("row")&&a.extend(c.options.data[d.index],d.row)}),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},o.prototype.initHiddenRows=function(){this.hiddenRows=[]},o.prototype.showRow=function(a){this.toggleRow(a,!0)},o.prototype.hideRow=function(a){this.toggleRow(a,!1)},o.prototype.toggleRow=function(b,c){var d,e;b.hasOwnProperty("index")?d=this.getData()[b.index]:b.hasOwnProperty("uniqueId")&&(d=this.getRowByUniqueId(b.uniqueId)),d&&(e=a.inArray(d,this.hiddenRows),c||-1!==e?c&&e>-1&&this.hiddenRows.splice(e,1):this.hiddenRows.push(d),this.initBody(!0))},o.prototype.getHiddenRows=function(){var b=this,c=this.getData(),d=[];return a.each(c,function(c,e){a.inArray(e,b.hiddenRows)>-1&&d.push(e)}),this.hiddenRows=d,d},o.prototype.mergeCells=function(b){var c,d,e,f=b.index,g=a.inArray(b.field,this.getVisibleFields()),h=b.rowspan||1,i=b.colspan||1,j=this.$body.find(">tr");if(this.options.detailView&&!this.options.cardView&&(g+=1),e=j.eq(f).find(">td").eq(g),!(0>f||0>g||f>=this.data.length)){for(c=f;f+h>c;c++)for(d=g;g+i>d;d++)j.eq(c).find(">td").eq(d).hide();e.attr("rowspan",h).attr("colspan",i).show()}},o.prototype.updateCell=function(a){a.hasOwnProperty("index")&&a.hasOwnProperty("field")&&a.hasOwnProperty("value")&&(this.data[a.index][a.field]=a.value,a.reinit!==!1&&(this.initSort(),this.initBody(!0)))},o.prototype.getOptions=function(){return this.options},o.prototype.getSelections=function(){var b=this;return a.grep(this.options.data,function(a){return a[b.header.stateField]===!0})},o.prototype.getAllSelections=function(){var b=this;return a.grep(this.options.data,function(a){return a[b.header.stateField]})},o.prototype.checkAll=function(){this.checkAll_(!0)},o.prototype.uncheckAll=function(){this.checkAll_(!1)},o.prototype.checkInvert=function(){var b=this,c=b.$selectItem.filter(":enabled"),d=c.filter(":checked");c.each(function(){a(this).prop("checked",!a(this).prop("checked"))}),b.updateRows(),b.updateSelected(),b.trigger("uncheck-some",d),d=b.getSelections(),b.trigger("check-some",d)},o.prototype.checkAll_=function(a){var b;a||(b=this.getSelections()),this.$selectAll.add(this.$selectAll_).prop("checked",a),this.$selectItem.filter(":enabled").prop("checked",a),this.updateRows(),a&&(b=this.getSelections()),this.trigger(a?"check-all":"uncheck-all",b)},o.prototype.check=function(a){this.check_(!0,a)},o.prototype.uncheck=function(a){this.check_(!1,a)},o.prototype.check_=function(a,b){var d=this.$selectItem.filter(c('[data-index="%s"]',b)).prop("checked",a);this.data[b][this.header.stateField]=a,this.updateSelected(),this.trigger(a?"check":"uncheck",this.data[b],d)},o.prototype.checkBy=function(a){this.checkBy_(!0,a)},o.prototype.uncheckBy=function(a){this.checkBy_(!1,a)},o.prototype.checkBy_=function(b,d){if(d.hasOwnProperty("field")&&d.hasOwnProperty("values")){var e=this,f=[];a.each(this.options.data,function(g,h){if(!h.hasOwnProperty(d.field))return!1;if(-1!==a.inArray(h[d.field],d.values)){var i=e.$selectItem.filter(":enabled").filter(c('[data-index="%s"]',g)).prop("checked",b);h[e.header.stateField]=b,f.push(h),e.trigger(b?"check":"uncheck",h,i)}}),this.updateSelected(),this.trigger(b?"check-some":"uncheck-some",f)}},o.prototype.destroy=function(){this.$el.insertBefore(this.$container),a(this.options.toolbar).insertBefore(this.$el),this.$container.next().remove(),this.$container.remove(),this.$el.html(this.$el_.html()).css("margin-top","0").attr("class",this.$el_.attr("class")||"")},o.prototype.showLoading=function(){this.$tableLoading.show()},o.prototype.hideLoading=function(){this.$tableLoading.hide()},o.prototype.togglePagination=function(){this.options.pagination=!this.options.pagination;var a=this.$toolbar.find('button[name="paginationSwitch"] i');this.options.pagination?a.attr("class",this.options.iconsPrefix+" "+this.options.icons.paginationSwitchDown):a.attr("class",this.options.iconsPrefix+" "+this.options.icons.paginationSwitchUp),this.updatePagination()},o.prototype.refresh=function(a){a&&a.url&&(this.options.url=a.url),a&&a.pageNumber&&(this.options.pageNumber=a.pageNumber),a&&a.pageSize&&(this.options.pageSize=a.pageSize),this.initServer(a&&a.silent,a&&a.query,a&&a.url),this.trigger("refresh",a)},o.prototype.resetWidth=function(){this.options.showHeader&&this.options.height&&this.fitHeader(),this.options.showFooter&&this.fitFooter()},o.prototype.showColumn=function(a){this.toggleColumn(e(this.columns,a),!0,!0)},o.prototype.hideColumn=function(a){this.toggleColumn(e(this.columns,a),!1,!0)},o.prototype.getHiddenColumns=function(){return a.grep(this.columns,function(a){return!a.visible})},o.prototype.getVisibleColumns=function(){return a.grep(this.columns,function(a){return a.visible})},o.prototype.toggleAllColumns=function(b){if(a.each(this.columns,function(a){this.columns[a].visible=b}),this.initHeader(),this.initSearch(),this.initPagination(),this.initBody(),this.options.showColumns){var c=this.$toolbar.find(".keep-open input").prop("disabled",!1);c.filter(":checked").length<=this.options.minimumCountColumns&&c.filter(":checked").prop("disabled",!0)}},o.prototype.showAllColumns=function(){this.toggleAllColumns(!0)},o.prototype.hideAllColumns=function(){this.toggleAllColumns(!1)},o.prototype.filterBy=function(b){this.filterColumns=a.isEmptyObject(b)?{}:b,this.options.pageNumber=1,this.initSearch(),this.updatePagination()},o.prototype.scrollTo=function(a){return"string"==typeof a&&(a="bottom"===a?this.$tableBody[0].scrollHeight:0),"number"==typeof a&&this.$tableBody.scrollTop(a),"undefined"==typeof a?this.$tableBody.scrollTop():void 0},o.prototype.getScrollPosition=function(){return this.scrollTo()},o.prototype.selectPage=function(a){a>0&&a<=this.options.totalPages&&(this.options.pageNumber=a,this.updatePagination())},o.prototype.prevPage=function(){this.options.pageNumber>1&&(this.options.pageNumber--,this.updatePagination())},o.prototype.nextPage=function(){this.options.pageNumber tr[data-index="%s"]',b));d.next().is("tr.detail-view")===(a?!1:!0)&&d.find("> td > .detail-icon").click()},o.prototype.expandRow=function(a){this.expandRow_(!0,a)},o.prototype.collapseRow=function(a){this.expandRow_(!1,a)},o.prototype.expandAllRows=function(b){if(b){var d=this.$body.find(c('> tr[data-index="%s"]',0)),e=this,f=null,g=!1,h=-1;if(d.next().is("tr.detail-view")?d.next().next().is("tr.detail-view")||(d.next().find(".detail-icon").click(),g=!0):(d.find("> td > .detail-icon").click(),g=!0),g)try{h=setInterval(function(){f=e.$body.find("tr.detail-view").last().find(".detail-icon"),f.length>0?f.click():clearInterval(h)},1)}catch(i){clearInterval(h)}}else for(var j=this.$body.children(),k=0;k.btn-group'); + var $btnAutoRefresh = $btnGroup.find('.auto-refresh'); + + if (!$btnAutoRefresh.length) { + $btnAutoRefresh = $([ + sprintf('' + ].join('')).appendTo($btnGroup); + + $btnAutoRefresh.on('click', $.proxy(this.toggleAutoRefresh, this)); + } + } + }; + + BootstrapTable.prototype.toggleAutoRefresh = function() { + if (this.options.autoRefresh) { + if (this.options.autoRefreshStatus) { + clearInterval(this.options.autoRefreshFunction); + this.$toolbar.find('>.btn-group').find('.auto-refresh').removeClass('enabled'); + } else { + var that = this; + this.options.autoRefreshFunction = setInterval(function () { + that.refresh({silent: that.options.autoRefreshSilent}); + }, this.options.autoRefreshInterval*1000); + this.$toolbar.find('>.btn-group').find('.auto-refresh').addClass('enabled'); + } + this.options.autoRefreshStatus = !this.options.autoRefreshStatus; + } + }; + +})(jQuery); diff --git a/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js b/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js new file mode 100644 index 0000000..bb7f595 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.11.1 - 2017-02-22 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2017 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{autoRefresh:!1,autoRefreshInterval:60,autoRefreshSilent:!0,autoRefreshStatus:!0,autoRefreshFunction:null}),a.extend(a.fn.bootstrapTable.defaults.icons,{autoRefresh:"glyphicon-time icon-time"}),a.extend(a.fn.bootstrapTable.locales,{formatAutoRefresh:function(){return"Auto Refresh"}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var b=a.fn.bootstrapTable.Constructor,c=b.prototype.init,d=b.prototype.initToolbar,e=a.fn.bootstrapTable.utils.sprintf;b.prototype.init=function(){if(c.apply(this,Array.prototype.slice.apply(arguments)),this.options.autoRefresh&&this.options.autoRefreshStatus){var a=this;this.options.autoRefreshFunction=setInterval(function(){a.refresh({silent:a.options.autoRefreshSilent})},1e3*this.options.autoRefreshInterval)}},b.prototype.initToolbar=function(){if(d.apply(this,Array.prototype.slice.apply(arguments)),this.options.autoRefresh){var b=this.$toolbar.find(">.btn-group"),c=b.find(".auto-refresh");c.length||(c=a([e('"].join("")).appendTo(b),c.on("click",a.proxy(this.toggleAutoRefresh,this)))}},b.prototype.toggleAutoRefresh=function(){if(this.options.autoRefresh){if(this.options.autoRefreshStatus)clearInterval(this.options.autoRefreshFunction),this.$toolbar.find(">.btn-group").find(".auto-refresh").removeClass("enabled");else{var a=this;this.options.autoRefreshFunction=setInterval(function(){a.refresh({silent:a.options.autoRefreshSilent})},1e3*this.options.autoRefreshInterval),this.$toolbar.find(">.btn-group").find(".auto-refresh").addClass("enabled")}this.options.autoRefreshStatus=!this.options.autoRefreshStatus}}}(jQuery); \ No newline at end of file diff --git a/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/click-edit-row/bootstrap-table-click-edit-row.css b/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/click-edit-row/bootstrap-table-click-edit-row.css new file mode 100644 index 0000000..85c3645 --- /dev/null +++ b/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/click-edit-row/bootstrap-table-click-edit-row.css @@ -0,0 +1,21 @@ +#tooling{ + float: right; +} +.clear{ + display: block; + width: 13px; + height: 13px; + position: absolute; + opacity: 0.6; + z-index: 100; + top: 50%; + right: 26px; + margin-top: -10px; + cursor: pointer; +} +.clear > i{ + font-size: 1.5em; +} +.clear > i:hover{ + color: hsl(0, 0%, 75%); +} \ No newline at end of file diff --git a/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/click-edit-row/bootstrap-table-click-edit-row.js b/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/click-edit-row/bootstrap-table-click-edit-row.js new file mode 100644 index 0000000..3af4e5c --- /dev/null +++ b/worldmap/static/plugin/bootstrap-table-1.11.1/extensions/click-edit-row/bootstrap-table-click-edit-row.js @@ -0,0 +1,142 @@ +/** + * @author horken wong + * @version: v1.0.0 + * https://github.com/horkenw/bootstrap-table + * Click to edit row for bootstrap-table + */ + +(function ($) { + 'use strict'; + + $.extend($.fn.bootstrapTable.defaults, { + clickEdit: false + }); + + function setDivision(node, options){ + var $option = $('